feathersjs / feathers

The API and real-time application framework
https://feathersjs.com
MIT License
15.03k stars 748 forks source link

header.toLowerCase is not a function local jwt authentication #1554

Closed AmitJoki closed 4 years ago

AmitJoki commented 5 years ago

I cloned https://github.com/leob/feathers-next and wanted to migrate to the latest version so did a yarn upgrade --latest.

I also migrated all the files using the latest boilerplate code generated by the feathers-cli. I've been getting this error:

{"name":"GeneralError","message":"header.toLowerCase is not a function","code":500,"className":"general-error","data":{},"errors":{}}

And it is frustrating because there's no stacktrace information at all to see where the error is arising from.

Also, when I do this on a Nextjs client, I keep getting "Timeout of 5000ms exceeded on create" error.

Steps to reproduce

Here's a minimal code that reproduces the said bug:

https://drive.google.com/file/d/1TDYD4DkVT4KjvGZ6HheAflJfaQidICcx/view?usp=sharing

Run yarn to install dependencies and do yarn start and try authenticating via cURL or Postman as is shown in the docs.

subodhpareek18 commented 5 years ago

I would recommend running the code without upgrading first, and then upgrade important dependencies one by one keeping in mind that major upgrades can have breaking fixes.

Not a good idea to upgrade everything at once if you can't figure out the errors.

jasonk commented 4 years ago

For anyone else who stumbles across this like I did and wished there was an answer here...

This can happen after upgrading from v3 to v4 if you were previously customizing the JWT payload with a configuration like this:

  authentication: {
    jwt: {
      header: { audience: 'foo', issuer: 'bar' },

If you don't update this (or you just change authentication.jwt to authentication.jwtOptions) then you will get this error, because you end up with the JWT Strategy having a config that looks something like this:

{
  entity: 'user',
  service: 'users',
  header: { audience: 'foo', issuer: 'bar' },
  schemes: [ 'Bearer', 'JWT' ]
}

The JWT Strategy then tries to call header.toLowerCase() on that object while it's attempting to parse the headers, and you get this error.

The solution is to hoist the options from that header object up one level, so your configuration ends up like this instead:

  authentication: {
    jwtOptions: {
      audience: 'foo',
      issuer: 'bar',
   },
  }

One thing that threw me off while trying to debug this is that the default jwtOptions (in @feathrsjs/authentication/src/options.ts) has configuration that would not actually work either:

export default {
  authStrategies: [],
  jwtOptions: {
    header: { typ: 'access' }, // by default is an access token but can be any type
    audience: 'https://yourdomain.com', // The resource server where the token is processed
    issuer: 'feathers', // The issuing server, application or resource
    algorithm: 'HS256',
    expiresIn: '1d'
  }
};

But, because the JWT implementation provides it's own default value for that (header: 'Authorization'), the incorrect value in options.ts never gets applied.

daffl commented 4 years ago

These are two different configurations:

https://github.com/feathersjs/feathers/pull/1844 has a fix with a better error message when verifying the configuration.