Open henrikwirth opened 4 years ago
@henrikwirth these questions are great and much needed to bring clarity to this project.
When a user changes his password, all old Tokens should be invalid. Is this happening already?
This was a planned feature, but it has yet to be coded.
There should be a way to invalidate all refreshTokens, so all clients would have to login with user credentials again.
The "auth" token is free to use until it expires, which is why it's recommended to keep the expiration pretty short. I believe the default is 5 minutes.
The Refresh Token can be invalidated
or revoked
.
When a token is invalidated, it means the shape of existing tokens will no longer properly validate and users must login to get a new one.
The refresh tokens have a user_secret
that is added to their hashed token. This secret is stored in user_meta under the key graphql_jwt_auth_secret
.
If that meta value ever changes, all previously issued refresh tokens will fail to validate and users must login again to get new tokens.
This is essentially the same as "logout of all clients" as once the Auth tokens already granted to any client expire, refreshTokens will no longer work for getting new auth tokens.
Users can still login to get new tokens.
When a Refresh Token is revoked, this means new tokens won't be granted to the user at all, even during a login mutation or refreshJwtAuthToken
The following static methods currently exist for revoking / unrevoking tokens:
Auth::revoke_user_secret( $user_id )
Auth::unrevoke_user_secret( $user_id )
At the moment, a Boolean input field named revokeJwtUserSecret
exists on some mutations such as createUser
, registerUser
and updateUser
where you can pass true
to revoke tokens from the user (prevent new tokens from being issued), or false
to unrevoke them (allow new tokens to be issued).
Currently, the requesting user must have the edit_users
capability to revoke / unrevoke tokens.
Is it possible to only invalidate tokens, that are linked to one client?
No. Tokens aren't tied to any particular client.
Thanks for clarifying.
For invalidating the Refresh Tokens/ changing user_secret: Is there a mutation for it? So the user can do something like Logout of all clients?
@jasonbahl Okay so i just tried the refreshUserSecret
and it works to create a new User Secret, but the old Auth Tokens still works. I can use the old Auth Token and also I can still use the Refresh Token.
@jasonbahl Great plugin, thanks! I've followed the advice above, and found the same issue as @henrikwirth, changing the meta value graphql_jwt_auth_secret
doesn't seem to invalidate previous refresh tokens. I can see that Auth tokens would still work as they don't have the user's secret encoded.
I dug around a little, and have tweaked the validate_token
function in Auth.js in my plugin installation here to the following:
<?php
if ( isset( $token->data->user->user_secret ) ) {
$token_user_secret = $token->data->user->user_secret;
$current_user_secret = get_user_meta( $token->data->user->id, 'graphql_jwt_auth_secret', true );
if ( Auth::is_jwt_secret_revoked( $token->data->user->id ) || strcmp($token_user_secret, $current_user_secret) != 0 ) {
return new \WP_Error( 'invalid-jwt', __( 'The User Secret does not match or has been revoked for this user', 'wp-graphql-jwt-authentication' ) );
}
I can see this is an open issue. Is there any reason the above isn't OK? I'd rather not revoke tokens, as I'm just trying to provide a "logout" style feature for an app.
Appreciate the feedback!
Why you just don't delete the token from your client app?
@spiralni Your suggestion is not really the best way to go about it.
What if user log in on a public computer and after awhile, they noticed suspicious activities on their account and decided to change password? That shows changing password doesn't matter as they'll still be logged in on other browser.
I think we do need a way to destroy all session.
One thing I'm wondering is how to force logout users.