Phoenix.Token for API logout? - phoenix-framework

I know that you can use Phoenix.Token for generating and verifying tokens for the API.
I generate it this way:
session = %{token: Phoenix.Token.sign(conn, "user", user.id)}
And verifying:
Phoenix.Token.verify(conn, "user", token)
I do not understand how I can organize the process of "deleting" a session when the user logout. Is it possible?

The Token is a signed string, Phoenix.Token.verify will just check if the Token was generated with the real secret. There is no way to make the token invalid.
Depending on what you need, you could store the token inside a user related table, like auth_tokens and when the user logs out, you can delete the the token from there. And create a new one, when the user logs in again.
The main purpose of the Token is to make sure, that it was generated on a trusted instance, once created, the verify function will always accept such a token.

Related

Does an API require a Logout endpoint?

I've read on various blog posts that a REST API does not require a logout endpoint.
Instead, the front end should just invalidate the token.
I'm using Laravel Sanctum, is this applicable to that?
Could someone explain why the session does not need invalidating on the server? If the token on the server is not invalidated, is there not a chance that a new user could be given the same token and access another user's details?
"is there not a chance that a new user could be given the same token and access another user's details?"
no mate, not a chance. because you must generating token with user information, in other words you are "attaching" a token to specified user. you can check this if you want.

Understanding the authorization part of JWT and session

So i read about how authentication is done using JWT, where we basically verify if the token is valid using a private key (assuming RSA is the algortihm). And if the token is valid, then the user is considered authenticated. And I also read about session authentication where we check if the user supplied session id (through cookie), exist in the session store (assuming mysql / redis is used to store session). If it exist, then the user is considered authenticated.
But how do we use JWT and session for authorization ? Lets consider an action such as GET invoice , whereby a user can only view the invoice that he owns.
If we consider the user is already authenticated,
how do we check if the user is authorized if we are using JWT?
And how do we do it for session ?
You are probably confusing the things. One of the benefits using JWT is to avoid maintaining sessions which is big bottle neck in scaling.
JWT (Json Web Token) carry all the information that would require it to get authenticated, you don't need to maintain the session. Every single HTTP request to server will carry JWT that would contain necessary user claims including the signature. On server you will validate the signature to verify if the token is valid or not. You can verify the token without maintaining any session and there are number of ways to do it.
Since JWT is essentially a Json object (Header, Body , Signature) , you can put in claims (emails, roles, profile etc) in JWT body. Once you verify the token , you can extract the claims including any roles and check if user is authorized to access the resource.
You must look into Open ID Connect and Tokens here

Are refresh token still valid even if they are not stored in a database anymore?

Lets put on this situation.
User logs in, he gets a refresh token and an access token
Access token expires, user gets a new one by refreshing it, and the refresh token in the database assigned to the user is overwritten by a new one.
The old refresh token, is now not stored in the database, but is it still valid? Since the expire date is in 7 days.
If an attacker managed to get access to that refreshtoken, will he still be able to generate new access tokens by verifying it with the refresh? I guess he needs to obtain the secret for this anyway.
Is a solution to avoid this simply checking if the refreshtoken is assigned to an user in the database during the refreshing proccess?

Is there a way to revoke another user's access tokens and end their session in Identity Server 4?

Is there a recommended way to revoke another user's access in Identity Server 4? The use case I'm looking at is an Administrator revoking system access for a currently logged in user.
I've read the documentation for the Revocation Endpoint and can see how that can be used by a user to revoke their own access. But how can this be done when the Administrator wouldn't know what a particular user's access token is?
Same goes for the End Session Endpoint I suppose, how would the Admin know their ID Token?
What I've tried so far is implementing an IProfileService and checking the user's account is valid in the IsActiveAsync method. In our customer db I can deactivate their account and this has the desired effect of redirecting them to to the Login page. But the tokens and session are still 'alive'. Would this be a good place to end session and revoke access token?
Or is persisting user tokens to the database an option?
Update
Based on the answer from #Mashton below I found an example of how to implement persistence in the Identity Server docs here.
Creating the data migrations described there will persist tokens to [dbo].[PersistedGrants] in the Key column. I was confused at first since they didn't look anything like my reference access tokens but after a little digging I found that they are stored as a SHA-256 hash. Looking at the DefaultGrantStore implementation in Identity Server's GitHub the Hashed Key is calculated as follows ...
const string KeySeparator = ":";
protected string GetHashedKey(string value)
{
return (value + KeySeparator + _grantType).Sha256();
}
... where the value is the token and the _grantType is one of the following ...
public static class PersistedGrantTypes
{
public const string AuthorizationCode = "authorization_code";
public const string ReferenceToken = "reference_token";
public const string RefreshToken = "refresh_token";
public const string UserConsent = "user_consent";
}
Using persisted grants doesn't give me the original access token but it does allow me the ability to revoke access tokens since the [dbo].[PersistedGrants] table has the SubjectId.
Update 2 - Identity Server keeps creating tokens
I created an implicit mvc client and after successful login I'm dumpimg the claims on the screen. I delete the access token from the persisted grant db then use Postman to end the session in the End Session Endpoint (using the id token in the claims). When I refresh the browser I'd expect the user to get redirected to the login screen but instead they get a new access token and a new id token. The Client.IdentityTokenLifetime is only 30 seconds.
Any ideas of what I'm missing here?
You can only revoke Reference tokens not JWTs, and yes those need to be stored in a db. Have a look at the IPersistedGrantStore (of the top of my head, so may have got the name wrong), and you'll see the structure is pretty simple.
Once you've got them stored, you can obviously do anything you like admin-wise, such as change the expiry or just outright delete them.

What should happen to when user changes username in Oauth2

Am pretty new to Oauth2 and I wondering what should happen in a scenario where a user changes the username used to authorize a client.
Should all access tokens expire after change is successful requesting the client to a new access code?
or
The access tokens are to be updated with the new username by the authentication server?
In normal cases, username of a user and the unique ID of the user are different. If an access token is associated with the unique ID (not with username), you don't have to invalidate or update access tokens even if username is changed.
Otherwise, if you associate access tokens with username (not with the unique ID), when username is changed, you should invalidate access tokens or update access tokens with the new username.
The OAuth spec doesn't specify what should happen -- one the user passes authentication and gets a token, they have an active authorization "session" as long as that token is valid.
You can invalidate tokens, and authorization sessions, as you like, though. So as a matter of policy, if you want to invalidate their tokens when there's a change to the account, then you are free to do that.
Just remember to invalidate both access tokens and refresh tokens for the user, or else they might just use their refresh token to start over with a access token.

Resources