Monday - Friday 10:00 - 21:00
+44 208 123 2413

IaM: Understanding what can be protected

In a previous post IaM post we introduced IaM in Hypi. The post described that there are a few distinct categories of things that can be protected with the Hypi platform.

  1. GraphQL functions on a per app basis, this protection is Type based
  2. Records created by these functions, this protection is Type:ID based
  3. Non-record assets e.g. images/files, this protection is HTTP URI based

In this post, we will explore the first of these and explain how to go about making use of this. When creating an App, you can create one or more models that Hypi will generate a GraphQL API for. For example:

1
2
3
4
5
type Post {
  title: String!
  body: String!
  slug: String!
}

In doing so Hypi will generate several GraphQL functions for you to use to work with Post types.

-- Query:
findPost(filter: String): [Post!]
-- Mutation:
createPost(..)
updatePost(..)
trashPost(..)
deletePost(..)

On its own, these operations are unprotected i.e. anyone with access to the generated API can call them. In most cases, that is not ideal. 

Thankfully, Hypi makes protecting them very easy. In your app definition, simply add a dependency on the Hypi hypi:iam:latest App. If you’re unfamiliar with the syntax, hypi is the publisher realm, iam is the name of the App and latestis the release name (or version) that you’re adding a dependency to.

How does this solve the authorisation problem?
Hypi has support for scripting which takes on two forms

  • Hypi Prime – The Hypi Prime version enables the submissions of JavaScript or Java code that is executed locally to the data
  • Hypi Gamma – Full blown serverless functions that you can package into a Docker container, using any language or framework you want and Hypi will call out to it, passing the appropriate data

Authorisation is implemented with Hypi Prime. Being a core functionality, the platform has builtin support specifically for this.

When the IaM app is added as a dependency of your app, it brings into scope a Hypi Prime function called iam-auth.fn which is a Java_Function defined by the IaM app as a pre-script. Functions in Hypi can be executed as pre or post scripts i.e. before or after any generated function, or in the case of custom GraphQL functions, any script can be called to be executed as the logic behind that GraphQL function.

So that explains a little of how authorisation can be added very simply. Once it’s added, what does it do, what is it authorising?

Before we answer that, Hypi’s authorisation is done with OAuth 2, behind the scenes when an operation is performed, various OAuth 2 actions are performed implicitly, in some cases it is explicit where it needs to be.

A thorough treatment of OAuth 2 is outside the scope of this guide, an introduction to OAuth can be found here, the relevant concepts are

  1. Resource Server – Hosts the protected resources (The Hypi API is the resource server)
  2. Authorisation Server – Verifies the identity and checks if they can do what they’re trying to. To you this is also the Hypi API but internally it is delegated to a dedicated authorisation server.
  3. Resource Owner – Owns the protected resources (e.g. a Post record)
  4. Client – An agent trying to access the protected resource e.g. the browser or a mobile app 
  5. Scope – A “bounded context” which limits what can be accessed

Requests to the Hypi generated API uses the standard Authorization header to pass an access token. The script will take this token and ask the authorisation server if that token is allowed to execute the GraphQL function, if the server says yes, the script returns true and the GraphQL function is executed as if nothing had happened, if the server says no, the script raises an exception and returns immediately, nothing else is executed.

How does the authorisation server know if the user the token belongs to is authorised or not?
In the introduction to IaM post, Scope based protection is mentioned.

What Hypi does is, it treats every GraphQL function (that includes fields outside of Query and Mutation objects) as a Scope. From the example above, If your Hypi realm is called publisher and the app is called blog the following scopes are created

publisher:blog:Post:title
publisher:blog:Post:content
publisher:blog:Post:slug
publisher:blog:Query:findPost
publisher:blog:Mutation:createPost
publisher:blog:Mutation:updatePost
publisher:blog:Mutation:trashPost
publisher:blog:Mutation:deletePost

Hypi creates a resource server for every app. Any and all resources created are owned by this resource server. Hypi also creates a default clients, one in particular is called web

To the point, how does Hypi know if access should be granted or not? Recall from the introduction to IaM post that Hypi allows you to define one or more Policy and Permission. A permission binds a policy to either a scope or to a resource.

Hypi creates an “owner” based policy which checks if the user querying the resource is the owner, in which case, access is granted.

A policy does not work on its own however, so there is an associated scope based permission which includes all of the scopes listed above.

With all of that, we’ve finally covered all of the pieces of how Hypi knows whether access should be granted or denied by simply adding the IaM app as a dependency. All it does is check that the user is the owner.

This post covers the simple case, in a follow up post we will explain how this check can be extended to use other policies e.g. if a resource has been shared with another user, they will not be the owner, in which case access would be denied based on what has been described here, however, a composite policy can be created which includes the owner based policy described here and another policy which checks if permission has been granted to the user or not.