Overview of Authorization and Authentication with GraphQL
Dgraph’s GraphQL implementation comes with built-in authorization. This lets you annotate your schema with rules that determine who can query and mutate your data.
First, let’s get some concepts defined. There are two important concepts included in what’s often called auth:
- Authorization: access permissions (what are you allowed to do)
- Authentication: establishment of identity (who you are)
Dgraph lets you use your GraphQL schema to manage both authorization and authentication:
- You set authorization rules by annotating your schema with the
@auth
directive - You configure authentication methods by providing those settings to Dgraph in the last
line of your schema, in a commented-out
Dgraph.Authorization
object.
Establishing identity and managing identity-based permissions are closely related, so this page covers both Dgraph’s authorization capabilities, and how Dgraph works with various authentication methods.
Authorization
You can add authorization rules to your schema using the @auth
directive. But,
you also need to configure the Dgraph.Authorization
object (which handles
authentication) on the last line of your schema for the @auth
directive to
work (as described below).
When authentication and authorization are complete, your schema should look similar to the following:
type A @auth(...) {
...
}
type B @auth(...) {
...
}
# Dgraph.Authorization {"VerificationKey":"","Header":"","Namespace":"","Algo":"","Audience":[]}
Authentication
You can authenticate your users using the following methods:
- A cloud service like OneGraph, Firebase, or Auth0
- Social sign-in options (such as Google authentication)
- Your own custom authentication code
Dgraph’s GraphQL implementation is completely flexible about how your app does authentication; instead, Dgraph focuses on authorization.
Dgraph’s GraphQL endpoint supports both symmetric (secret-based) and asymmetric (public key) encryption. The connection between Dgraph and your authentication mechanism can be a JSON Web Key (JWK) URL or a signed JSON Web Token (JWT). So, you can provide Dgraph with the public key of the JWT signer (such as Firebase or Auth0) and Dgraph trusts JWTs signed by the corresponding private key.
Dgraph.Authorization
parameters
To define the authentication connection method, Dgraph uses a commented-out
Dgraph.Authorization
object that you should add as the last line of your schema.
You can only use one authentication connection method, either JWT, a single JWK
URL, or multiple JWK URLs.
The Dgraph.Authorization
object uses the following syntax:
{"Header":"", "Namespace":"", "Algo":"", "VerificationKey":"", "JWKURL":"", "Audience":[], "ClosedByDefault": false}
This object contains the following values:
Header
is the header that requests use to store the signed JWT.Namespace
is the key inside the JWT that contains the claims relevant to Dgraph authorization.Algo
is the JWT verification algorithm which can be eitherHS256
orRS256
.VerificationKey
is the string value of the key, with newlines replaced with\n
and the key string wrapped in""
:- For asymmetric encryption:
VerificationKey
contains the public key string - For symmetric (secret-based) encryption:
VerificationKey
is the secret key; this can be any secret string you choose, such as one that you generate using a tool like OpenSSL
- For asymmetric encryption:
JWKURL
/JWKURLs
is the URL for the JSON Web Key sets. If you want to pass multiple URLs, useJWKURLs
as an array of multiple JWK URLs for the JSON Web Key sets.Audience
is used to verify theaud
field of a JWT, which is used by certain providers to indicate the intended audience for the JWT. When doing authentication withJWKURL
, this field is mandatory as identity providers share JWKs among multiple tenants.ClosedByDefault
, if set totrue
, requires authorization for all requests even if the type does not specify the@auth
directive. If omitted, the default setting isfalse
.
JWKURLs
as an array of multiple JWK URLs for the JSON Web Key sets.
To set the authentication connection method, do the following:
- To use a JWT: On the last line of your schema, specify a verification key (
VerificationKey
) and encryption algorithm (Algo
) in theDgraph.Authorization
object. Dgraph verifies the JWT against the providedVerificationKey
. So, your schema should end with a line like the following:
# Dgraph.Authorization {"VerificationKey":"<verification-key-here>","Header":"X-My-App-Auth","Namespace":"https://my.app.io/jwt/claims","Algo":"HS256","Audience":["aud1","aud5"]}
- To use a single JWK URL: Specify the
JWKURL
andAudience
arguments in theDgraph.Authorization
object. Dgraph fetches the JWK and verifies the token against it. So, your schema should end with a line like the following:
# Dgraph.Authorization {"VerificationKey":"","Header":"X-My-App-Auth", "jwkurl":"https://www.googleapis.com/service_accounts/v1/jwk/securetoken@system.gserviceaccount.com", "Namespace":"https://xyz.io/jwt/claims","Algo":"","Audience":["fir-project1-259e7", "HhaXkQVRBn5e0K3DmMp2zbjI8i1wcv2e"]}
- To use multiple JWK URLs: Specify the
JWKURLs
andAudience
arguments in theDgraph.Authorization
object. Dgraph fetches all of the JWKs and verifies the token against one of the JWKs, based on the JWK’s kind. So, your schema should end with a line like the following:
# Dgraph.Authorization {"VerificationKey":"","Header":"X-My-App-Auth","jwkurls":["https://www.googleapis.com/service_accounts/v1/jwk/securetoken@system.gserviceaccount.com","https://dev-hr2kugfp.us.auth0.com/.well-known/jwks.json"], "Namespace":"https://xyz.io/jwt/claims","Algo":"","Audience":["fir-project1-259e7", "HhaXkQVRBn5e0K3DmMp2zbjI8i1wcv2e"]}
Using JWTs and authorization claims
In addition to the examples shown above, you can configure Dgraph.Authorization
as follows
to use the X-My-App-Auth
header and use namespace-based authorization claims:
- HMAC-SHA256 JWT with symmetric cryptography (the signing key and verification key are the same):
# Dgraph.Authorization {"VerificationKey":"secretkey","Header":"X-My-App-Auth","Namespace":"https://my.app.io/jwt/claims","Algo":"HS256"}
- RSA Signature with SHA-256 asymmetric cryptography (the JWT is signed with the private key and Dgraph checks with the public key):
# 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"}
Authorization with custom claims
In both of the examples above, the header X-My-App-Auth
is required and the
JWT is expected to contain a custom claims object (in this case, "https://my.app.io/jwt/claims": { ... }
) with the claims used in authorization rules.
The value of the X-My-App-Auth
header is expected to be in one of the following forms:
-
Just the JWT token. For example:
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyLCJodHRwczovL215LmFwcC5pby9qd3QvY2xhaW1zIjp7fX0.Pjlxpf-3FhH61EtHBRo2g1amQPRi0pNwoLUooGbxIho
-
A Bearer token, e.g., a JWT prepended with
Bearer
prefix (including space). For example:Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyLCJodHRwczovL215LmFwcC5pby9qd3QvY2xhaW1zIjp7fX0.Pjlxpf-3FhH61EtHBRo2g1amQPRi0pNwoLUooGbxIho
Authorization with standard claims
Apart from the custom claims belonging to a given namespace, you can use standard claims in the authorization rules, as shown in the following example:
{
"https://xyz.io/jwt/claims": [
....
],
"ROLE": "ADMIN",
"USERROLE": "user1",
"email": "random@example.com",
"email_verified": true,
"sub": "1234567890",
"aud": "63do0q16n6ebjgkumu05kkeian",
"iat": 1611694692,
"exp": 2611730692
}
The authorization variables include the rest of the given claims along with the claims provided under namespace https://xyz.io/jwt/claims
.