auth0 / express-jwt

connect/express middleware that validates a JsonWebToken (JWT) and set the req.user with the attributes
MIT License
4.49k stars 444 forks source link

UnauthorizedError: No authorization token was found – despite valid token #269

Open axhl opened 3 years ago

axhl commented 3 years ago

express-jwt refuses to parse a valid token, and I cannot for the life of me understand why :

Reproduction

The following client-side code uses graphql-ws to include a token in a request via Relay:

const subscriptionsClient = createClient({
      url: process.env.REACT_APP_GRAPHQL_API || "string",
      retryAttempts: 10,
      connectionParams: () => {
          return {
              headers: {
                  "Content-Type": "application/json",
                  authorization: token ? `Bearer ${token}` : "auth-header not defined",
              },
          };
      },
});

The token is visible in the network requests when there is an open express-server on the other end.

On the server-side, the request is then parsed as follows:

var jwtCheck = jwt({
    secret: jwksRsa.expressJwtSecret({
        cache: false,
        rateLimit: true,
        jwksRequestsPerMinute: 5,
        jwksUri: "CORRECT",
    }),
    audience: "CORRECT",
    issuer: "CORRECT",
    algorithms: ["RS256"],

app.use("/graphql", jwtCheck);

});

This renders a UnauthorizedError: No authorization token was found error message.

Grateful for any community input

relevant dependencies

"dependencies": {
    "express": "^4.17.1",
    "express-jwt": "^6.1.0",
    "jwks-rsa": "^2.0.5"}   
adamjmcgrath commented 3 years ago

👋 @axhl

You don't need to provide a custom getToken option to express-jwt (your custom implementation is wrong, it needs to split out the bearer string from the authorization header).

For your reference, the default implementation is here https://github.com/auth0/express-jwt/blob/master/lib/index.js#L58-L74

axhl commented 3 years ago

@adamjmcgrath many thanks for replying so far. Unfortunately I made a mistake when pasting the code:

getToken: function (req) {
        if (req.headers.authorization) return req.headers.authorization;
    },

has already been removed and the error persists. (I've updated the code above to reflect that for later arrivals to the thread). Any thoughts what could be up apart from the getToken?

adamjmcgrath commented 3 years ago

Hi @axhl - can't see anything wrong with your code.

Happy to debug a sample project if you can share a minimal reproduction of the issue

axhl commented 3 years ago

Hi @axhl - can't see anything wrong with your code.

Happy to debug a sample project if you can share a minimal reproduction of the issue

Huge thanks @adamjmcgrath for offering to be so generous with your time. I think I've made progress:

As graphql-ws runs all its connections via websocket, the server's middleware for the incoming client request needs to wrap thews:// / wss:// endpoints and have access to the socket equivalent of the http req object; app.use won't work. So if I can figure out how to use postgraphile's websocketMiddlewares option correctly, it should work.

Any thoughts on how to best wrap wrap sockets with jwt-verification?

adamjmcgrath commented 3 years ago

@axhl - no problem

It doesn't sound like you need express-jwt for that.

Any thoughts on how to best wrap wrap sockets with jwt-verification?

I'm not sure about graph-ql specifically, but this looks like the sort of thing I'd do for authenticating Web Sockets with JWTs https://gist.github.com/jfromaniello/8418116