Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Provide a better way to use JWT with asymmetric key algorithms such as RS256 for authentication #1251

Closed
petersaints opened this issue Mar 18, 2019 · 3 comments

Comments

@petersaints
Copy link

petersaints commented Mar 18, 2019

I recently tried to move my authentication system from HS256-based JWTs to RS256-based ones and it has been more difficult than it should.

First, we are told that the "secret" under the "authentication" can be set to a symmetric shared secret (the default) or to a private key. Well, that's easier said than done because you can't just put PEM encoded strings into the JSON file and be done with it. My solution for that has been the following:

"authentication": {
   "secret": null,
    ...
   "jwt": {
      ...
      "algorithm": "RS256",
      ...
    }
}

And then on "authentication.js" I load the key from a file before setting things up:

...
const privateKey = fs.readFileSync(path.join(__dirname,'..','keys','combined.pem'), 'utf8');
config.secret = privateKey;
app.configure(authentication(config));
app.configure(jwt());
app.configure(local());
...

This solved the problem of issuing RS256 signed tokens. However, I noticed that I could not authenticate using the issued tokens because I was getting a "NotAuthenticated" with a "PEM_read_bio_PUBKEY" message.

I than realized that I hadn't set where my public key was and that there was no documented way of doing it. I fiddled with the source code and with lots of break points to find if there was any way to easily set the public key, but I didn't find any way of doing it.

I ended up thinking that I had no other choice other than fork "@feathersjs/authentication-jwt" and force it to use the public key I provided it other than the private key that it was getting directly from my "standardized" feathers app configuration.

However, before that and out of desperation, I tried to run "cat private.pem public.pem > combined.pem" to create a file with both my private and public keys. I passed it as the "secret", instead of the private key alone and it seems that both the token issuing (the "create" method of the @feathersjs/authentication service) and the token verification (@feathersjs/authentication-jwt, which uses passport-jwt) are able to read and use the correct key from this combined file, i.e., the private key is used only for issuing, whereas the public key is used for verification and authentication, respectively.

I believe that this is undocumented behavior but it works and it's an easy fix for now. It would be nice to have RS256 (and other asymmetric JWT algorithms) as officially supported by feathers by making some changes to the previously mentioned components and by documenting how to use public and private key files instead of a boring symmetric shared secret.

At the very least, if this combined file behavior is something that is supposed to continue to work and to be supported, we should add a note about that in the official documentation.

What do you guys think?

I think I'm use the latest stable version of all feathers components and I'm using using the latest Node.js LTS. But I leave all the details below anyway:

Module versions:
"@feathersjs/authentication-client": "^1.0.11",
"@feathersjs/errors": "^3.3.6",
"@feathersjs/feathers": "^3.3.1",
"@feathersjs/socketio-client": "^1.2.1",

NodeJS version:
10.13.5

Operating System:
Ubuntu 18.10 64-bit

@petersaints petersaints changed the title Provide a better way to use asymmetric key algorithms such RS256 for authentication Provide a better way to use asymmetric key algorithms such as RS256 for authentication Mar 18, 2019
@petersaints petersaints changed the title Provide a better way to use asymmetric key algorithms such as RS256 for authentication Provide a better way to use JWT with asymmetric key algorithms such as RS256 for authentication Mar 18, 2019
petersaints added a commit to YanuX-Framework/YanuX-Broker that referenced this issue Mar 18, 2019
Check this report for more information about the issue mentioned above: feathersjs/feathers#1251
@daffl
Copy link
Member

daffl commented Mar 25, 2019

This should be addressed by the next authentication version (#1045) which removes the dependency on PassportJS and allows to fully customize any aspect of the JWT generation and verification in one place by extending the base service (in progress documentation example can be found here).

@petersaints
Copy link
Author

Ok. Nice to see that you're actively working on improving feathers authentication. For the time being the solution I have found seems to be working fine and it's mostly acceptable. It's just a shame that it wasn't documented on feathers or any of its dependencies, so I had to find out about it the hard way.

Meanwhile, once the authentication system arrives I will probably have some issue migrating because I use a custom authentication strategy (besides jwt and local). It receives a token that has previously been issued by a separate project to another application and my feathers project makes an HTTP request to the project that issued it to verify if it is indeed valid (I do intend to replace this verification endpoint with a proper JWT to avoid constant HTTP request and database lookups).

From what I've read in #1045 it will still be possible to implement this type of custom authentication in the new version, but the class structure will be different. Am I correct? I really hope that it will still be possible and that it will not be very hard to convert from the "old format" to the new one.

@daffl
Copy link
Member

daffl commented Jun 6, 2019

That is correct and this has now been implemented in Feathers v4 authentication which allows to more easily customize the authentication service and JWT strategy. See the Migration guide for more information on how to upgrade.

@daffl daffl closed this as completed Jun 6, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants