Can't manage to use JWT authentication/authorization with Neo4J-GraphQL

205 Views Asked by At

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!

1

There are 1 best solutions below

2
On BEST ANSWER

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.