riverrun / phauxth

Not actively maintained - Authentication library for Phoenix, and other Plug-based, web applications
409 stars 21 forks source link

Expire token validity only after X idle time #38

Closed acrolink closed 7 years ago

acrolink commented 7 years ago

I assume that the default setting of 4 hours max-age for token validity does not take into consideration if the token is actively being used or if it is idle, i.e. it always expires 4 hours after generation (login). How to make it expire only after 4 hours of being idle (not used)?

riverrun commented 7 years ago

I'll look into this and get back to you as soon as I can.

riverrun commented 7 years ago

I think this is probably best handled by using refresh tokens.

I hope to be able to add support for this within the next week or two.

riverrun commented 7 years ago

Sorry about the delay.

After looking into this issue a bit more, I think that refresh tokens are probably not the best option, as they are designed for a different type of workflow.

Instead, I think either of the following two options can be used.

Refresh token before it expires

  1. Setup a route (controller and view) to handle the refresh process.
  2. Before the token expires, send a request to this route with the existing token in the headers.
  3. Verify the token, and if it is valid, send the user a new token.

This process will be similar to the login process.

When checking if the token is valid, you can perform other checks as well (same IP address, etc.).

You will need to store information about how long the user has stayed logged in because this will no longer be present in the token.

Revoke token after idle time (and set max_age to a longer time - one day, for example)

  1. Set the max_age to a longer time - for example, one day (86_400 seconds).
  2. Monitor the usage / idle time on the frontend - if the user is idle for more than a certain amount of time, revoke the token.
  3. Check if the token has been revoked - either on the frontend or by customizing the Phauxth.Authenticate module.

If you have any further questions, please let me know.

acrolink commented 6 years ago

I am using 100% VueJS on the front-end with Phoenix JSON API on the back-end. I think tokens can be extended this way:

  1. Setting a high max-age (one day).
  2. At login, to send with the token back to the front-end a date-time / Unix time-stamp value specifying when the token will expire (login time + 24 hours)
  3. The front-end application checks periodically or at every path change (during navigation) if the expire time is getting closer (compared to machine time). At certain time frame (e.g. less than 4 hours to expiry), calls a specific route on the back-end, which validates the token and issues a new token back to the front-end.

Does this sound reasonable? Which validations are reasonable to do on the back-end before issuing a new token, besides IP?

Thank you.

riverrun commented 6 years ago

Yes, the outline you provide sounds fine. A couple of comments:

  1. If you are validating IP address, you might get false negatives, especially with the increasing use of mobile. Maybe the user-agent string, or any other device-specific information, can help you track devices better.
  2. If you keep on refreshing tokens, are you going to keep track of the total time since login? There might also be certain actions where you want the user to log in first, so you might need some way of checking if the current token was the result of logging in or a refresh.
acrolink commented 6 years ago

Does the session based mechanism provide any refresh cookie feature?

dsignr commented 5 years ago

Don't want to kindle an old issue, but refreshing tokens only using existing access tokens is a security vulnerability as an attacker can compromise an access token and keep renewing it infinitely. The standard flow of how this is accomplished using refresh tokens is, in your end point to get a new access token, you'd pass in the refresh token, existing access token, username and password. Even if one of them fail/aren't available, then you would force the user to re-login. Now, at this time you can do your other checks as well such as IP, User agent, etc. etc. An added layer of security would also be to keep track of existing logins and probably keep the user informed of it through a separate sessions table or similar (Phauxth already provides create_session function in SessionController which could be re-used for this).

riverrun commented 5 years ago

@dsignr thanks for the input. I will look into how others handle this, and I will probably add something to the wiki about it

dsignr commented 5 years ago

@riverrun Hi David, thanks for your reply. I found this super useful resource which explains the spec in full. https://tools.ietf.org/html/rfc6749

It's a bit of a long read, but actually goes into every nitty gritty. I'm trying to implement Phauxth based on that link, I'll see if I can get something working so I can share it or send you a PR.