I'm trying to get Neo4J + graphQL lib 4.0.0 + authentication/authorization via JWT. I managed to do it with graphQL 3.0.0 but can't now update to 4.0.0.
My base code relates on the documentation OGM/Examples/Custom Resolvers
I get the following error:
"message": "Type mismatch for parameter 'jwt': expected Map, Node, Relationship, Point, Duration, Date, Time, LocalTime, LocalDateTime or DateTime but was String (line 3, column 87 (offset: 113))\n\"WHERE apoc.util.validatePredicate(NOT ($isAuthenticated = true AND this.id = coalesce($jwt.sub, $jwtDefault)), \"@neo4j/graphql/FORBIDDEN\", [0])\"\
This seems to be related to APOC translation.
I have the following in my schema:
type JWT @jwt {
roles: [String!]!
}
My base type for User is:
type User {
id: ID @id
username: String!
password: String! @private
roles: [String!]
}
I tried different simple things in the schema:
type User @authorization(validate: [{ when: [BEFORE], where: {node: {id: "$jwt.sub" } } }]){
# or
type User @authorization(validate: [
{ where: { node: { id: "$jwt.sub" } } }
{ where: { jwt: { roles_INCLUDES: "admin" } } }
]) {
# or
type User @authentication(operations: [DELETE], jwt: { roles_INCLUDES: "admin" }){
When querying
query Users {
users {
username
roles
}
}
with header
{
"Authorization" : "Bearer <jwt>"
}
I get the following error:
"message": "Type mismatch for parameter 'jwt': expected Map, Node, Relationship, Point, Duration, Date, Time, LocalTime, LocalDateTime or DateTime but was String (line 3, column 87 (offset: 113))\n\"WHERE apoc.util.validatePredicate(NOT ($isAuthenticated = true AND this.id = coalesce($jwt.sub, $jwtDefault)), \"@neo4j/graphql/FORBIDDEN\", [0])\"\
This seems to be related to APOC translation.
My server is as follows:
const neoSchema = new Neo4jGraphQL({
typeDefs,
driver,
resolvers,
features: {
authorization: {
key: signingKey,
}
}
});
Promise.all([neoSchema.getSchema(), ogm.init()]).then(([schema]) => {
const server = new ApolloServer({
schema,
});
startStandaloneServer(server, {
context: async ({ req }) => {
//console.log(req.headers);
return { jwt: req.headers.authorization }},
}).then(({ url }) => {
console.log(`🚀 Server ready at ${url}`);
});
});
Any help would be greatly appreciated!
I looks like you're trying to decode the JWT with the GraphQL library since you have the below in the library config.
features: {
authorization: {
key: signingKey,
}
}
Also, if the token you're setting to the jwt
field on the request context is encoded, that would explain why the error gets thrown about it being a string.
The documentation here https://neo4j.com/docs/graphql-manual/current/authentication-and-authorization/configuration/ says
The Neo4j GraphQL Library can accept JSON Web Tokens via two mechanisms:
- Encoded JWTs in the token field of the request context.
- Decoded JWTs in the jwt field of the request context.
If using the former, the library will need to be configured with a key to decode and verify the token.
You should pass the encoded token into the request context on the token
field.
Try setting the request context with return { token: req.headers.authorization }}
instead.