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

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.

Related

Adding claims to already logged in user with Bearer token authentication

I have a .Net 6 application. I would like to persist some data to the user session and thought claims is probably an easy way to do it.
As far as I can understand this is the correct way to add claims to the user after the initial login.
var claims = new List<Claim>
{
new Claim("claimType", "blabla")
};
context.User.AddIdentity(new ClaimsIdentity(claims));
If I check the Identities before that request ends there is a new record added which contains the claim I created. But upon the next request to the server it is gone. Only the original Identity is there again.
The value I want to add is calculated during runtime and can't be created during login. I could add it to the database but I REALLY don't want to as I need to check it on every request.
What might I be doing wrong? Or any suggestions to alternate ways to store the information?
Update 1:
Because it might matter, we use an external identity provider and token based authentication to a .net 6 api.

Create new Parse.Session programmatically for a user, without their password

I'm working on a existing Parse server, and I am currently adding an OAuth system, so that external apps can connect in the name of Parse.User.
I created different classes for codes and tokens, and now my external apps can send requests with an accessToken, corresponding to their application and user (who granted access).
I'm looking for a way to inform the Parse server that the "logged in user" in requests is the end user that authorized the OAuth application. For this, I have created an express middleware handling request before the Parse server middleware, extracting the access token from the request, getting the correct User and Application, and then I wanted to create a Parse.Session programmatically, get the token, and set it in the request as x-parse-session-token. This way, the next handler, Parse, would treat the request as authenticated and performed by the end user.
My problem here is that I cannot find a way to create a session programmatically, I'm aware of the Parse.User.logIn, but that works only with a password.
I've tried the following:
const oAuthSession = await new Parse.Session().save({
user: user // user got from Parse.Query(Parse.User) with masterKey
}, { useMasterKey: true })
But get a Cannot modify readonly attribute user error.
Any hidden method to programmatically create a Parse.Session without a password ?
As pointed out by #DaviMacêdo in the community forum: https://community.parseplatform.org/t/create-new-parse-session-programmatically-for-a-user-without-their-password/1751
We can inject the user directly in the request field, and it will be picked up by Parse: https://github.com/parse-community/parse-server/blob/f6a41729a7a3adc6bd5310cefb3458835b4abb58/src/middlewares.js#L199
const user = await new Parse.Query(Parse.User).get(‘idOfUser’);
req.userFromJWT = user;

How do I revoke a persisted reference token in Identity Server 3

I have an Authentication service built on Identity Server 3. I recently switched it from JWTs to reference tokens and implemented SignOutAsync in my UserService to revoke the tokens when the user signs out. The code looks like this:
public override Task SignOutAsync(SignOutContext context)
{
string subjectId = GetSubjectId(context);
_tokenHandleStore.RevokeAsync(subjectId, context.ClientId);
return Task.FromResult(0);
}
And that code appears to work. (The ITokenHandleStore interface and RevokeAsync method were recommended in this post.)
If I copy the reference token, I can use it to access my services up until the user signs out. Then the reference token no longer works. Just as I'd expect.
Then I introduced persistent storage of the reference tokens using Identity Server's built-in Entity Framework implementation for operational data. The tokens are written to and purged from the data store as I expect, but they no longer appear to be revoked when the user signs out. I can copy the reference token and use it to access the services, even after the user has signed out.
I've stepped through the code so I know my SignOutAsync method is being called and _tokenHandleStore.RevokeAsync is being called.
Is ITokenHandleStore.RevokeAsync the right method to call? What should I see in the database Tokens table when a token is revoked? Will it be deleted or modified? I am seeing no change to the token data in the data store. The persistent storage and revocation are both built-in features of Identity Server, but do they know about each other? Does the built-in implementation of ITokenHandleStore detect the use of persistent storage and revoke those tokens? Or do I need to extend that method in some way or call a custom method?

Phoenix.Token for API logout?

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.

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