Overview - Graphql

Dgraph GraphQL comes with inbuilt authorization. It allows you to annotate your schema with rules that determine who can access or mutate what data.

Firstly, let’s get some concepts defined. There are two important concepts in what’s often called ‘auth’.

  • authentication : who are you; and
  • authorization : what are you allowed to do.

Dgraph GraphQL deals with authorization, but is completely flexible about how your app does authentication. You could authenticate your users with a cloud service like OneGraph or Auth0, use some social sign in options, or write bespoke code. The connection between Dgraph and your authentication mechanism is a signed JWT - you tell Dgraph, for example, the public key of the JWT signer and Dgraph trusts JWTs signed by the corresponding private key.

With an authentication mechanism set up, you then annotate your schema with the @auth directive to define your authorization rules, attach details of your authentication provider to the last line of the schema, and pass the schema to Dgraph. So your schema will follow this pattern.

type A @auth(...) {
    ...
}
type B @auth(...) {
    ...
}
# Dgraph.Authorization {"VerificationKey":"","Header":"","Namespace":"","Algo":"","Audience":[]}
  • Header is the header in which requests will send the signed JWT
  • Namespace is the key inside the JWT that contains the claims relevant to Dgraph auth
  • Algo is JWT verification algorithm which can be either HS256 or RS256, and
  • VerificationKey is the string value of the key (newlines replaced with \n) wrapped in ""
  • Audience is used to verify aud field of JWT which might be set by certain providers. It indicates the intended audience for the JWT. This is an optional field.

Valid examples look like

# Dgraph.Authorization {"VerificationKey":"verificationkey","Header":"X-My-App-Auth","Namespace":"https://my.app.io/jwt/claims","Algo":"HS256","Audience":["aud1","aud5"]}

Without audience field

# Dgraph.Authorization {"VerificationKey":"secretkey","Header":"X-My-App-Auth","Namespace":"https://my.app.io/jwt/claims","Algo":"HS256"}

for HMAC-SHA256 JWT with symmetric cryptography (the signing key and verification key are the same), and like

# Dgraph.Authorization {"VerificationKey":"-----BEGIN PUBLIC KEY-----\n...\n-----END PUBLIC KEY-----","Header":"X-My-App-Auth","Namespace":"https://my.app.io/jwt/claims","Algo":"RS256"}

for RSA Signature with SHA-256 asymmetric cryptography (the JWT is signed with the private key and Dgraph checks with the public key).

Both cases expect the JWT to be in a header X-My-App-Auth and expect the JWT to contain custom claims object "https://my.app.io/jwt/claims": { ... } with the claims used in authorization rules.

Note: authorization is in beta and some aspects may change - for example, it’s possible that the method to specify the header, key, etc. will move into the /admin updateGQLSchema mutation that sets the schema. Some features are also in active improvement and development - for example, auth is supported an on types, but interfaces (and the types that implement them) don’t correctly support auth in the current beta.


This is a companion discussion topic for the original entry at https://dgraph.io/docs/graphql/authorization/authorization-overview/

How to invalidate JWT tokens ?
That’s a well known JWT issue:
when an authenticated user logs out before token expiration, that token should become unusable.
a bunch of strategies may be adopted for this use case, each one with its own tradeoffs
But my question is, how to apply a middleware for token management?

I have concerns about authorization. “Public by default” seems very dangerous, and being forced to copy-paste identical queries for every crud operation feels fragile and error-prone. As an example, I just now decided to change my “user” field to “author” and had to edit thirty-six different auth rules.

Hey @aleclofabbro, the recommended way is to keep the expiry of access tokens short. We are also releasing Custom JS resolvers soon which would allow you to add business logic on top of your pre-existing auto-generated resolvers.

@dusty-phillips 20.11 release would have an option to change the default to Closed by default instead of the current public by default. This would mean that a JWT must be supplied to access any of the resources. We are getting the docs up for this right now.

2 Likes

Hi :slight_smile:
20.11 release would have an option to change the default to Closed by default instead of the current public by default
Has this been documented yet? If so, where?