feathersjs / feathers

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

Add support for refresh tokens #1337

Open marshallswain opened 8 years ago

marshallswain commented 8 years ago

We currently allow getting a new token by posting a valid auth token to <loginEndpoint>/refresh. Refresh tokens have a slightly different workflow as explained here: https://auth0.com/learn/refresh-tokens

sarkistlt commented 4 years ago

@bwgjoseph I would suggest to use regular express session, and store all tokens there, instead of client side. That's what I do and works perfectly fine with all types of apps including SPA

bwgjoseph commented 4 years ago

@sarkistlt You mean to say to store all client JWT token on server-side? Any reference/article material for that? I'm not exactly sure how the process would be like. So what does client sent, when they request for data (CRUD)?

sarkistlt commented 4 years ago

@bwgjoseph same as always, cookie, just add middlewere before registerring your services:

app.use('* | [or specific rout]', session(sess), (req, res, next) => {
      req.feathers.session = req.session || {};
      next();
    });

then in your server, for let's say customer login service, when customer is authenticated, you just store token in the session like ctx.params.session.token = token, where token is your JWT access or refresh token, depends on your application logic. And with any new request from client you will check if token exist in the session and will use it for authentication. This is much safer and secure approach, since none of the tokens are exposed on the client side at all.

I'll just add that this works best for client (browser) - server applications. When communicating internally between servers, or worker/server, you don't need session.

daffl commented 4 years ago

This has been discussed a lot before (I also added an entry to the FAQ) and it is not necessarily more secure to store a token in a session. If someone gets access to your page to be able to execute scripts they have also hijacked the session and can make authenticated requests anyway.

Hence it is usually ok to store a token in e.g. localStorage (which only the current page has access to as well) and it also works seamlessly with other non-browser platforms (like native mobile apps, server-to-server etc.) and websockets (I can't stress enough how painful it is to make websockets work seamlessly and securely with HTTP cookies - my life has been a lot easier since we stopped trying to do so). In general, a refresh token should be revokable though since it is usually a lot more long lived.

Either way, a pull request for this would be very welcome, I find it makes ironing out the details a lot easier.

TheSinding commented 4 years ago

@jackywxd - Great job, took a brief look at it and it seems like some great additions. Is there anyway of making it easier for the developer implementing this? Like integrating the hooks you've created into the library, so we wouldn't need to add the hooks later ?

I think you should create a pull request and we could have the discussion there.

sarkistlt commented 4 years ago

@daffl yes agree, especially with WS. And if both client and backend build by you or your team, yes it's best to just use JWT and avoid extra dependancies and complexity in your application. But in some cases, for example when building storefront REST-API that will be used by 3rd party companies / developers, it's easier to use regular session, and ask developers to include credentials with their requests then to describe how to retrieve access (and refresh) tokens, store it, and pass it with each requests. Which handled perfectly by feathers client, but in most cases when developer is not familiar with how backend built, they will use request, superagent, fetch or axios to connect their application to the backend. At least in my case this was the main reason to move storefront part of API to work with regular sessions instead of JWT directly.

TheSinding commented 4 years ago

But wouldn't that be the design decision and responsibility, of the maker of said storefront, to implement into their own API and then properly document this feature, instead of "forcing" this decision onto the community ?

sarkistlt commented 4 years ago

@TheSinding I think we can say 'forcing' about less commonly used approach, not about cookie which have been (and still is) most commonly used approach to manage user sessions.

And yes it is a design decision made after developers feedback that have been using the API. When you are running multi-tenant system or API that used by multiple teams, sometime best is to follow general industry practice to avoid additional confusion and extra time spent by developers, especially if alternative solution doesn't provide any advantage for end user.

Again to be clear, using JWT is great, and way easier to utilize especially for real time API and that's what we are using in 90% of cases + you don't need to run redis or something else to manage cookie sessions. But there some exceptional cases where it may not be the best chose, I brought example of that situation in my previous comment.

TheSinding commented 4 years ago

I wasn't saying you were wrong, I was just thinking "out loud" :)

IMO, I think the approach with JWT would be a better approach, since that is what is already supported and as @daffl it's also easier to work with

jackywxd commented 4 years ago

Thanks for all your feedback! JWT vs session is a different topic we can discuss separately.

I think one thing we all agree is that access token + refresh token is a much more secure solution than merely access token. It has been widely adopted by major Internet giants. It is fair to say the Feathers community would love to see Feathers main code base to provide built-in support for refresh token. Actually it surprised me when I first realized that Feathers doesn't support refresh token.

I have been using AWS cognito in couple of my projects, AWS Amplify will save three tokens in localStorage: ID token, access token and refresh token, Amplify handles all the dirty-works related to token management, and provides couple APIs that enables easy and straight forward interface working with Cognito backend. I would like to see similar development experience with Feathers.

jackywxd commented 4 years ago

@TheSinding Thanks for your previous great work!

Because existing authentication is implemented as normal service, we could easily enable refresh-token support by extending the class and adding couple hooks:

this.hooks({ after: { create: [issueRefreshToken(), connection('login'), event('login')], remove: [logoutUser(), connection('logout'), event('logout')], patch: [refreshAccessToken()], },

Just like we turn on Authentication by using the CLI, we could offer the similar option in CLI for refresh-token support. developer can simply answer YES, the CLI then automatically creating a customer "refresh-tokens" service and update refresh-token related configurations in default config file. So it is like a turn-key solution for developers.

jackywxd commented 4 years ago

@daffl David, thanks for creating Feathers! just wondering is there any "contributing guid", "coding guideline", "style guide" for Feathers?

daffl commented 4 years ago

As I mentioned before, a PR with the implementation for refresh tokens (or even just some ideas) would be very welcome. I didn't get a chance yet to check out the linked repos and this discussion is getting quite long. Having it all up to date and in one place would make things a lot easier. Some important bullet points:

matiaslopezd commented 3 years ago

If someone is using refreshToken, we create a library that handles in frontend, accessToken and refreshToken like "sessions", too easy to use.

Only need to pass the tokens and the library tries to obtain a new acessToken with refreshToken when will expire. Currently is used in Videsk.

Repository: Front Auth Handler

J3m5 commented 3 years ago

I saw this video about the risks related to JWT andrefresh tokens in SPA, it is really informative. https://pragmaticwebsecurity.com/talks/xssoauth.html