Prisma1: Authentication

Created on 4 Dec 2017  路  11Comments  路  Source: prisma/prisma1

In Graphcool 1.0 we are streamlining the authentication mechanism. There are two different parts of the system that requires authentication:

Database API

This is your GraphQL API where you can query and modify your data.

This API is protected by an secret that you specify in the graphcool.yml file when deploying the service.

The secret is used to sign a jwt that can then be used in the Authorization header:

Authorization: Bearer ${jwt}

The jwt must contain the following claims:

  • exp the expiration time.
  • service name and stage of the service
  • roles a list of roles granting access to the service. Currently ['admin'] is supported

For example:

{
  "exp": 1300819380,
  "service": "my-service@prod",
  "roles": ["admin"]
}

In the future we might support more fine grained roles such as ["write:Log", "read:*"]

A node server could create a signed jwt like this:

var jwt = require('jsonwebtoken');

jwt.sign({
  data: {
    "service": "my-service@prod",
    "roles": ["admin"]
  }
}, process.env.GRAPHCOOL_SECRET, { expiresIn: '1h' });

JWT verification

The Graphcool Database will verify the following aspect of the jwt:

  • It must be signed with a secret configured for the service as described in #1328
  • It must contain an exp claim with a value in the future
  • It must contain a service claim with service and stage matching the current request
  • It must contain a roles claim that provides access to the current operation

Cluster API

This is the API you use to deploy and migrate services on a cluster. When using the Graphcool CLI you need to be in posession of a valid Cluster Token. There are two ways to obtain this token:

Cluster Secret

When you set up a Graphcool cluster you specify a cluster secret. The CLI can use the cluster secret to sign a Cluster Token with full access to all services on the cluster, as well as various cluster management tasks.

This method can be used with the open source release of Graphcool without connecting to the Graphcool Platform.

Graphcool Platform

The Graphcool Platform allows you to manage teams of developers and grant access to specific services and clusters.

You might want to grant a development team access to deploy services to a dev cluster, but restrict deploy access to the production cluster to the CI user and a few senior engineers.

When a cluster is connected to the Graphcool Platform, the CLI can obtain a Cluster Token from the Platform that provides scoped access to the cluster according to the rules configured by the manager of the workspace that cluster belongs to.

JWT claims

exp

A Cluster Token must include an exp claim containing a timestamp in the future. The Graphcool Platform will issue short lived tokens with 1 hour expiration

grants

A list of target/action pairs that grant permission to perform certain actions on certain resources.

Examples

deploy a specific stage of a service to a cluster that is not connected to Graphcool Cloud:

[{"target": "service/stage", "action": "deploy"}]

create and deploy to services and stages in specific workspace:

[{"target": "workspace/*/*", "action": "*"}]

multiple grants:

[{"target": "workspace/service-1/dev", "action": "deploy"}, {"target": "workspace/service-1/prod", "action": "deploy"}]
target

Target must take one of the following forms:

For clusters managed by Graphcool Cloud: workspace/service/stage

For clusters not managed by Graphcool Cloud: service/stage

All components can be replaced by a wildcard. Typically only right most components will be a wildcard.

action

At present only deploy is a valid action. We might introduce more actions in the future.

Open Questions

  • [ ] Deployment token
rf1-draft

Most helpful comment

Hi, i found it very good overall. How are Third party Auth providers ( google, facebook, Auth0) integration work with Graphcool 1.0 ?

All 11 comments

@dpetrick and i discussed this issue this evening. Here's a summary of the solution we came up with.

Generally access to our APIs (deploy and database) is based upon the validation of JWT tokens. A request to an API is always performed with a JWT token. This token must contain references to services it is valid for. An API processes a given request if the JWT token contains the service that the request is sent for.

Deploy API

The CLI can perform a login for a given Graphcool Service against an Auth Service. This can be either the Auth Service of the Graphcool Platform or a simplified one for local development. After login this Auth Service returns a JWT token to the CLI. This token can be used to send requests to the Deploy API of Graphcool. The Auth Service and the Deploy API share a JWT secret.

Database API

Each Graphcool service must be associated with one ore more JWT secrets. A CLI with access to the Deploy API can query those secrets. One of those secrets can then be injected (e.g. env var) into an application (e.g. a Gateway). This application can then use this secret to construct a JWT token in order to send an authenticated request to the Database API.

Why multiple secrets?
There may be multiple JWT secrets associated with a given service to enable secret rotation.

Authenticated Introspection

Until now, Graphcool didn't require authentication for the introspection query.
However, if you want to have a secured endpoint with secret types/field names that already contain business information just on the type level, you may want to secure the introspection by the authentication mechanism, too.

This can concretely be implemented by enabling/disabling the top-level field __schema, as that field is used for the introspection query. You also may want to enable/disable __type to mitigate the risk of lookup attacks.

Advantages

  • Having a more secure endpoint, not leaking business information

Disadvantages

  • You can't just look at the schema anymore, now you need to hold a token. This may make your workflows more complicated

Setting

The fact if the introspection needs auth or not could be configurable through the graphcool.yml.

Open Questions

  • [ ] Should introspection require authentication?
  • [ ] If yes, should it be a setting?

Hi, i found it very good overall. How are Third party Auth providers ( google, facebook, Auth0) integration work with Graphcool 1.0 ?

Correct header name should be Authori z ation (see MDN). It's probably just a typo in here, but want to make sure it doesn't go further than that ;)

@timsuchanek Regarding authenticated introspection. This should be an explicit setting. Messing around with the __schema field is definitely not a good solution for this.

Thanks @FredyC - fixed the typo :-)

@kbrandwijk I suggest the introspection query always (or at least by default) require authentication if authentication is enabled for the service. Do you disagree?

@sorenbs I would like it to be an explicit setting.

I have a few questions about authentication in the Database API.

  • Apart from reading (queries, mutation payload) and writing (mutations), what other operations are available?

    • The original post mentiones write:Log, is this a fictional operation?

    • How do subscriptions tie into this?

I don't know anything about JWT, but just sharing PAST which touts itself as more secure than JWT (just saw it on GitHub Trending).

As an end user, having the opportunity to choose a setting to secure the endpoint access and introspection would definitively be the right move and introspection always requiring authentication would be great.
Why not add a permission to enable/disable public playground as well ?

This has been implemented in Prisma 1.0. Read more about service authentication in the documentation.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

nikolasburk picture nikolasburk  路  3Comments

schickling picture schickling  路  3Comments

hoodsy picture hoodsy  路  3Comments

sorenbs picture sorenbs  路  3Comments

thomaswright picture thomaswright  路  3Comments