Configuration
This is the documentation of the GraphQL Library version 6. For the long-term support (LTS) version 5, refer to GraphQL Library version 5 LTS. |
The Neo4j GraphQL Library uses JSON Web Token (JWT) authentication. JWTs are tokens containing claims or statements about the user or client making the request. These claims can include information such as the user’s ID or roles.
A JWT can be obtained from an authentication service and then be included in an API request. The API verifies the JWT and returns the requested data if the JWT is valid.
Instantiation
The Neo4j GraphQL Library can accept two types of JWTs:
-
Encoded JWTs in the
token
field of the request context. -
Decoded JWTs in the
jwt
field of the request context.
Encoded JWTs
In order to use encoded JWTs, configure the library with a key to decode and verify the tokens.
The following code block uses Apollo Server.
It extracts the Authorization
header from the request and puts it in the appropriate context field:
const server = new ApolloServer({
schema, // schema from Neo4jGraphQL.getSchema()
});
const { url } = await startStandaloneServer(server, {
listen: { port: 4000 },
context: async ({ req }) => ({
token: req.headers.authorization,
}),
});
Optionally, if a custom decoding mechanism is required, that same header can be decoded and the resulting JWT payload put into the jwt
field of the context.
Alternatively, you can decode a token via a JWKS endpoint.
Symmetric secret
To configure the library with a symmetric secret (e.g. "secret"), the following instantiation is required:
new Neo4jGraphQL({
typeDefs,
features: {
authorization: {
key: "secret",
},
},
});
JWKS endpoint
To configure the library to verify tokens against a JSON Web Key Set (JWKS) endpoint, for example "https://www.example.com/.well-known/jwks.json", the following instantiation is required:
new Neo4jGraphQL({
typeDefs,
features: {
authorization: {
key: {
url: "https://www.myapplication.com/.well-known/jwks.json"
},
},
},
});
Passing in encoded JWTs
To pass in an encoded JWT, use the token field of the context. When using Apollo Server, extract the authorization header into the token property of the context:
const server = new ApolloServer({
schema,
});
await startStandaloneServer(server, {
context: async ({ req }) => ({ token: req.headers.authorization }),
});
For example, a HTTP request with the following authorization
header should look like this:
POST / HTTP/1.1
authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyLCJyb2xlcyI6WyJ1c2VyX2FkbWluIiwicG9zdF9hZG1pbiIsImdyb3VwX2FkbWluIl19.IY0LWqgHcjEtOsOw60mqKazhuRFKroSXFQkpCtWpgQI
content-type: application/json
Alternatively, you can pass a key jwt
of type JwtPayload
into the context, which has the following definition:
// standard claims https://datatracker.ietf.org/doc/html/rfc7519#section-4.1
interface JwtPayload {
[key: string]: any;
iss?: string | undefined;
sub?: string | undefined;
aud?: string | string[] | undefined;
exp?: number | undefined;
nbf?: number | undefined;
iat?: number | undefined;
jti?: string | undefined;
}
Do not pass in the header or the signature. |
Decoded JWTs
A decoded JWT is passed to the context in a similar way that an encoded JWT is.
However, instead of using a token, it uses the jwt
field:
const jwt = customImplementation();
const { url } = await startStandaloneServer(server, {
listen: { port: 4000 },
context: async ({ req }) => ({
jwt: jwt,
}),
});
customImplementation
is a placeholder for a function that provides a decoded JWT.
Using jwt
instead of token
in the context
informs the Neo4j GraphQL Library that it doesn’t need to decode it.
Adding JWT claims
By default, filtering is available on the registered claim names in the JWT specification.
Filtering can be configured for additional JWT claims using the @jwt
directive and, in some circumstances, the @jwtClaim
directive.
@jwt
Definition
"""
Instructs @neo4j/graphql that the flagged object represents the relevant JWT payload
"""
directive @jwt on OBJECT
Usage
If you configure an additional roles
claim, which is an array of strings located at the root of the JWT payload, add the following to the type definitions:
type JWT @jwt {
roles: [String!]!
}
The type name |
@jwtClaim
Definition
"""
Instructs @neo4j/graphql that the flagged field has a mapped path within the JWT Payload.
"""
directive @jwtClaim(
"""
The path of the field in the real JWT as mapped within the JWT Payload.
"""
path: String!
) on FIELD_DEFINITION
Usage
A roles
claim is not necessarily located at the JWT payload root.
It can instead be in a nested location, for example under myApplication
:
{
"sub": "user1234",
"myApplication": {
"roles": ["user", "admin"]
}
}
In this case, use the @jwtClaim
directive alongside the @jwt
directive:
type JWT @jwt {
roles: [String!]! @jwtClaim(path: "myApplication.roles")
}
Additionally, the nested location may contain .
characters in the path, for example:
{
"sub": "user1234",
"http://www.myapplication.com": {
"roles": ["user", "admin"]
}
}
These characters must be escaped:
type JWT @jwt {
roles: [String!]! @jwtClaim(path: "http://www\\\\.myapplication\\\\.com.roles")
}
The |