Implementing token inactivity timeout with automatic expiry extend

Hi folks, I am using the ash_authentication password strategy with my resource configured to store all tokens, and require token presence. The project has a VueJS frontend that communicates with the backend via GQL. When a user logs in, the frontend receives the token and includes it in the header as a bearer token. This is all working well. I have set a short-lived token_lifetime, and would now like to add a way to log the user out after a period of inactivity, and also extend their session expiry whenever they make a request to keep them logged in beyond the initial expiry time. I have realised that this may be at odds with using JWTs as the token, as they are effectively tamper proof. Any thoughts on how to implement this? I think what I actually want is closer to a session based login strategy, that doesn't use JWTs at all, and simply generates a random token to give to the frontend.
11 Replies
ZachDaniel
ZachDaniel•2y ago
So ultimately IIRC the JWT is stored in the session and you don't actually have to use anything that is in it So it can behave just like a session token Ah, actually yeah I think I see what you mean now 🙂 because the expiration is stored in the JWT @jart is there some way to use expiration from the tokens table or something instead of expiration from the token? That would solve for this, and re-extending the token would be as simple as adding some logic in a plug to bump the expiration.
Alan Heywood
Alan HeywoodOP•2y ago
That's a good point, as a work-around I could potentially set a very long token_lifetime and manage expiry myself outside ash_auth.
ZachDaniel
ZachDaniel•2y ago
That is also true. You can add custom attributes to the token resource too.
jart
jart•2y ago
I think at some point we should look at making the token system more pluggable so that we can cover more of these use cases.
ZachDaniel
ZachDaniel•2y ago
Yeah, that is a good point too I've been thinking about the autogenerated actions by extensions, and I'm thinking that we might want to rework how we do this, both here and in other extensions that generate actions. Specifically, we should just always choose to validate, and never add actions we can add a tool in Ash, like validate_has_action(:create, :name, arguments: [...]) That is I think the best of both worlds. We don't hide the surface area of the extension from users, but we can use introspection to ensure that it is correct. Then, if we add customizations, they can allow for users to deviate from the path incrementally as needed. just a thought. Not a short term solution though. @Alan Heywood if its reasonable to add like an attribute like session_expires_at to your resource, and manage that yourself, and then you can do something like this:
prepare fn query, _ ->
if query.action.name in [:actions_looking_for_tokens?] do
Ash.Query.filter(query, session_expires_at > now())
else
query
end
end
prepare fn query, _ ->
if query.action.name in [:actions_looking_for_tokens?] do
Ash.Query.filter(query, session_expires_at > now())
else
query
end
end
and then when a user authenticates, you could find the corresponding token and bump that session_expires_at
Alan Heywood
Alan HeywoodOP•2y ago
Yes that seems reasonable to me, thanks 🙂 Interesting thought, so extensions would never add actions, and users would need to add them in. However the extension could provide preparations / helpers to make this easy.
ZachDaniel
ZachDaniel•2y ago
Yeah, exactly So you'd be instructed like "add this action"
create :register_with_password do
change Change
change Change
change Change
end
create :register_with_password do
change Change
change Change
change Change
end
Alan Heywood
Alan HeywoodOP•2y ago
I like the sound of that! Using extensions I have had to dig into the source, and this would help a lot.
jart
jart•2y ago
what if instead of just validating that the action has the right stuff in it we provide a way to extend a predefined action like?
defmodule User do
use Ash.Resource, extensions: [AshAuthentication]

actions do
read :get_by_subject do
extends AshAuthentcation, :get_by_subject
# .. customisations that override the defaults
end
end
end
defmodule User do
use Ash.Resource, extensions: [AshAuthentication]

actions do
read :get_by_subject do
extends AshAuthentcation, :get_by_subject
# .. customisations that override the defaults
end
end
end
ZachDaniel
ZachDaniel•2y ago
it might also be kind of an overcorrection and yeah that would be pretty interesting
Alan Heywood
Alan HeywoodOP•2y ago
For posterity, the token record is now provided by the plug helper (https://github.com/team-alembic/ash_authentication/pull/426/commits/2d6e563c1bc4b02a160bc2b374e61d500739b5d6), and I was able to implement session inactivity timeout in my application outside of ash_auth. Now that's done, I could possibly extract it (time allowing) and implement it in ash_auth as a new feature. Perhaps as an option on the tokens do block

Did you find this page helpful?