2

The Authentication and Authorization flows are difficult to get right without concrete examples. NestJs doc has a good example for JWT tokens, however I find it difficult to establish the correct flow.

Here is the closest I have been able to get to solve the authorization flow:

  1. after authentication, store refresh token in DB (which I don't like much but couldn't find an easier way to handle it), send access token to Angular and keep it in local storage or a cookie
  2. On every request send the access token and check if it's still valid and not close to expiry; if it's expired or about to expire, then go to the DB, get the refresh token and use it to acquire a new access token. I would very much liked to have refresh token stored in a cookie too, but the problem with that is that I don't know how to get more than Authorization header when implementing the JwtStrategy, and what's the best (if any) way to attach the refresh token
  3. If access token is updated, somehow send it back to the Angular side to be replaced. send the expired time as well so Angular side doesn't replace a newer access token with an older one if there are concurrent requests. But concurrent requests still have a chance of running into a race condition and each, separately, requesting an access token.

There are a bunch of details that are missing in the summary above, but that should give the overall flow that I am trying to implement. The two challenges I have right now is:

  1. The possibility of multiple concurrent requests, all finding out that access token is about to expire and trying to refresh it at once.
  2. How to add the new access token and expiry timestamp to response header (or body if it should be there), in JwtStrategy itself so the whole auth cycle can be handled with one single annotation/guard.

I appreciate if somebody can help with the above two questions.

Also, I am not sure if it complies with SO policies, but since there is no solid material for the NestJs/Angular/Cognito combination, and since auth is the most important part of a secure webpage. I will be happy to grant some bounties for someone who can put a full working example in github that demonstrates fully how both authentication and authorization (both access and refresh tokens) flows are implemented using best practices.

Finally, here are the best (only?) resources I have found and used so far for NestJs/Cognito combo; none really get to answer the above questions.

Nylon Smile
  • 8,990
  • 1
  • 25
  • 34
  • Do you have any progress on this? – Jacobdo May 01 '20 at 13:23
  • @Nylon Smile, if you are still having issues with this, checkout [this article](https://hasura.io/blog/best-practices-of-using-jwt-with-graphql/) it has best practices and it follows a nice pattern and it also has techniques for dealing with multiple tabs open (I think this is the one case where your concurrency issues may be coming from) – omaraguirre Aug 11 '20 at 20:54
  • @Jacobdo did you write [this](https://medium.com/@jacob.do/token-validation-with-aws-cognito-and-nestjs-6f9e4088393c)? – omaraguirre Aug 11 '20 at 20:55
  • yes @omaraguirre after some research I did. – Jacobdo Aug 13 '20 at 12:25

2 Answers2

0

The flow should be

  1. After signing up/in, update the refresh token stored on that user record in database. Then backend returns data with an access-token and refresh-token to the frontend.
  1. When requesting an endpoint that requires authentication, verify the jwt token stored in the authentication header. If verified successfully, return data; otherwise, return unauthorized request error.
  1. The frontend receives the data that requires authentication from the backend side. If it is with valid data, don't request the refresh access token endpoints, otherwise request backend and ask for a new access token by providing refresh token stored locally.
  1. When the backend receives a refreshing access token request, it checks three aspects:

1, Is there a refresh token stored on that user record in DB? 2, Is this refresh token is valid? 3, Is the refresh token expired?

If the refresh token is valid and unexpired, return a new access token to the frontend.

Otherwise, report the error to the frontend.

The frontend reacts to the refreshing access token in this way

  1. Get a renewed access token; it refreshes the access token locally
  2. Get an error, clear local data, and require the user to sign in again.
  1. when the user signs out, delete the refresh token and expire time stored on that user record in the database.

I also have a sample https://github.com/katesroad/Roles_Based_Sample/tree/main/backend.

Please check the auth.controller.ts and strategies folder.

Kate
  • 71
  • 1
  • 5
0

I ended up solving this by issuing my own JWT tokens and handling the User's session in the app, instead of storing the tokens received from the auth provider.

Check these articles:

and this repo: https://github.com/thisismydesign/nestjs-starter

and this question: OAuth2 flow in full-stack NestJS application

thisismydesign
  • 21,553
  • 9
  • 123
  • 126