adamniedzielski/tiddle

Time-based expiration mechanism for tokens

Closed this issue ยท 7 comments

Hello,

Really love the work you did with this gem!

Currently as much as I see, tokens can be used forever, there is no support for generating tokens that last for a certain amount of time (e.g. 2 weeks).

Do you plan on supporting something like this, and what's your take on this?

@DamirSvrtan thanks for the great discussion (and presentation) about that at Southeast Ruby.

As I said, the project from which I extracted Tiddle didn't have a need for tokens that expire after a certain amount of time. However, it sounds like a very reasonable use case so I'm willing to cover it.

The most "straightforward" option that I can see is manually adding a Rake task that does something like:

AuthenticationToken.where("created_at < ?", 2.weeks.ago).delete_all

This has the disadvantage of being imprecise. If the Rake runs every hour then we have a chance of allowing authentication with a token that should have already been expired.

Because of that, we may consider a better alternative. For me two most important requirements are:

  1. backwards compatible
  2. does not introduce a configuration option to Tiddle

What I came up with is:

  1. add expires_at field to the table that stores authentication tokens
  2. add expires_at keyword argument defaulting to nil to Tiddle.create_and_return_token
  3. in the strategy compare expires_at with the current time and refuse to authenticate user when the token is too old.

This allows to precisely specify the expiration time, and, for example, use different values depending on user role (admin, non-admin).

Does this sound reasonable?

riggy commented

I'd like to chip in, as I'm on a lookout for token based auth for app I'm working on and your gem has attracted my attention.

Time based expiration/revoke mechanism is a must in my opinion. I'm actually surprised that it wasn't included by default. I want to implement an api handling self expiring tokens, but it would require multiple tokens in order for the api to be accessed by multiple devices, without cutting them off all at once when token gets revoked.

What you propose above seems like the most feasible option. I actually wanted to fork this and try to add this part myself, when I noticed this issue. I'm eager to see this in action.

riggy commented

Also, I have another idea. Facebook, for example, expires/revokes the tokens after a period of inactivity. So maybe:

  1. instead of expires_at maybe use expires_in integer field
  2. keyword argument would also be names like expires_in where you could pass a duration argument like 3.months
  3. strategy would take last_used_at with expires_in added, which, when compared with current time would revoke the token or not

What do you think? It would be more flexible, without necessarily forcing users to relogin if they use the api/token on regular basis.

@riggy thanks for contributing to the discussion!

I'm actually surprised that it wasn't included by default.

As I said earlier, this wasn't the focus of the project I extracted this gem from.

I actually wanted to fork this and try to add this part myself

Please do and contribute back as a PR!

I'm fine with the approach that you presented (expiring the token after a period of inactivity).

riggy commented

@adamniedzielski I actually went other way with implementing devise_token_auth - it was more fitting into our policy as it's compliant with RFC 6750 Bearer Token. However I made the adjustments prior to that. I'm gonna open a PR in a bit. Commits are messy as I committed a bunch of rubocop based fixes reverting them later to make PR more strict to the topic.

Implemented by #37