Configuration
|
This is the documentation of the GraphQL Library version 7. 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
tokenfield of the request context. -
Decoded JWTs in the
jwtfield 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 |