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

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?

Related

How to revoke a okta token from Golang SDK?

I want to know how to revoke the access token with Golang SDK because as I can see there is no API available in the SDK.
Consider using the endpoint for clearing user sessions, documented here.
For HTTP, the endpoint is DELETE /api/v1/sessions/${sessionId}. From the Okta documentation:
Removes all active identity provider sessions. This forces the user to authenticate on the next operation. Optionally revokes OpenID Connect and OAuth refresh and access tokens issued to the user.
So, for the Go SDK (v1.1.0), this method (documented here) is what you want: call Client.User.EndAllUserSessions(userId string, qp *query.Params) with oauthTokens=true as a query param to indicate that refresh and access tokens should be revoked in addition to ending the session.
Right now, as mentioned in the question, there isn't a method to call the token revocation endpoint directly, so ending the sessions and revoking the tokens together is the only option if you must only use the provided SDK.
You should be able to call the revoke endpoint (POST ${baseUrl}/v1/revoke, documented here) directly via regular HTTP. I would recommend clearing all user sessions via the SDK, however, since that is likely to provide more desirable behaviour (the circumstances in which you want to revoke a token but still keep your user signed in are limited).

Best way to store user related data from db, in a webapp with OIDC authentication

I have a Core3.1 web application protected with azureAD (OpenIdConnect) and I retrieve most of the user's related data I need, from the idtoken:
Username, email, employeeId, even the user's AD groups.
I also need to get some additional data from the database and I'm not sure how I should store this data in the application, to make it available everywhere and for the entire time the user is logged in.
I don't want to use cookie. For now, I used the session.
Problem is this session expires differently from the authentication session, so I had to call a static method to check if the variables are empty and eventually doing the query again.
It works... but is ugly.
I feel like I'm supposed to handle things differently but I don't know how.
A claims based solution can work best here, where you:
Define a Claims Object in your API
Populate it when your API first receives an access token
Cache the claims object for subsequent requests with the same access token
This cache will always be in sync with the user session
See my blog post for further details on the pattern. And here is some implementation code.

How to refresh personal access token programmatically in Laravel?

I have used createToken method on User model to create personal access token. Now I want to refresh that token in code without http request to oauth/token/refresh. How could I do that?
How often are you trying to refresh personal access tokens? You should just recreate one, if/when needed. They are by default long lived so the expiry is quite long, one year if I recall correctly.
Personal access tokens are always long-lived. Their lifetime is not modified when using the tokensExpireIn or refreshTokensExpireIn methods.

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.

Using JWT to implement Authentication on Asp.net web API

I have been reading about JWT.
But from what I read it is not an authentication mechanism but more like a crucial component in a Authentication mechanism.
I have currently implemented a solution which works, but it was just to try out JWT and see how it works. But what I am after now is how one should make use of it. From my experience of it its basically just an encryption mechanism that gives you a unique encrypted key. You are also able to put information inside of this token.
I am wanting to implement it in terms on a ASP.NET web api 2 to be consumed by a mobile application.
So step 1:
app => Server : Login (user, pasword)
Server => app : Login OK, heres your JWT
app => server : Get my profile (sends JWT with request)
Server then decrypts JWT and determines the requests Identity.
Now this is just my understanding of it, Look I could be on the totally wrong path.
Is the Ideal of JWT so that you dont have to authenticate on every request? I just authenticate the users credentials once (on the initial login) and there on after the server can simply use JWT and no have to lookup the users pw and user in the DB?
I just want to use the JWT to Identity who the user is. I will then authorize then after i have authenticated them. As I know there is a big confused with the new MVC and Authentication and Authorization.
So what my question comes down to.
How can I safely and effectively Implement a Authentication Mechanism Using JWT?
I don't want to just cough something up that seems to work and not have any Idea of the security implications. I am sure that there exists a source some where that has possibly designed a secure mechanism that would suit my requirements.
My requirements are:
Must only have to check db for users credentials once off per session? Due to the use of bcrypt using a lot of resources to compare passwords.
Must be able to identify the user from their request. (I.e who they are, userId will be sufficient) and preferably without accessing the DB as well
Should be as low overhead as possible, with regards to resources on the server side processing the request.
If an intruder had to copy a devices previous request, then he should not be able to access the real users data. (obviously)
Thanks
Your understanding of JWTs is good. But here are a couple corrections and some recommendations.
Authentication and Authorization
JWTs have nothing to do with authentication. Hitting your DB and hashing passwords only happens when you authenticate on creation of the JWT. This is orthogonal to JWTs and you can do that in any way you like. I personally like Membership Reboot, which also has a good example of using JWTs.
Theoretically, you could have the user enter a password once a year and have the JWT be valid that entire year. This most likely not the best solution, if the JWT gets stolen at any point the users resources would be compromised.
Encryption
Tokens can, but don't have to be encrypted. Encrypting your tokens will increase the complexity of your system and amount of computation your server needs to read the JWTs. This might be important if you require that no one is able to read the token when it is at rest.
Tokens are always cryptographically signed by the issuer to ensure their integrity. Meaning they cannot be tampered with by the user or a third party.
Claims
Your JWTs can contain any information you want. The users name, birthdate, email, etc. You do this with claims based authorization. You then just tell your provider to make a JWT with these claims from the Claims Principle. The following code is from that Membership Reboot example and it shows you how this is done.
public override Task GrantResourceOwnerCredentials(OAuthGrantResourceOwnerCredentialsContext context)
{
var svc = context.OwinContext.Environment.GetUserAccountService<UserAccount>();
UserAccount user;
if (svc.Authenticate("users", context.UserName, context.Password, out user))
{
var claims = user.GetAllClaims();
var id = new System.Security.Claims.ClaimsIdentity(claims, "MembershipReboot");
context.Validated(id);
}
return base.GrantResourceOwnerCredentials(context);
}
This allows you to control with precision whom is accessing your resources, all without hitting your processor intensive authentication service.
Implementation
A very easy way to implement a Token provider is to use Microsoft's OAuth Authorization Server in your WebAPI project. It give you the bare bones of what you need to make a OAuth server for your API.
You could also look into Thinktecture's Identity Server which would give you much easier control over users. For instance, you can easily implement refresh tokens with identity server where the user is authenticated once and then for a certain amount of time (maybe a month) they can continue getting short lived JWTs from the Identity Server. The refresh tokens are good because they can be revoked, whereas JWTs cannot. The downside of this solution is that you need to set up another server or two to host the Identity service.
To deal with your last point, that an intruder should not be able to copy the last request to get access to a resource, you must use SSL at a bare minimum. This will protect the token in transport.
If you are protecting something extremely sensitive, you should keep the token lifetime to a very short window of time. If you are protecting something less sensitive, you could make the lifetime longer. The longer the token if valid, the larger the window of time a attacker will have to impersonate the authenticated user if the user's machine is compromised.
I've written detailed blog post about configuring the OWIN Authorization server to issue signed JSON Web Tokens instead of default token. So the resource servers (Audience) can register with the Authorization server, and then they can use the JWT tokens issued by Token issuer party without the need to unify machineKey values between all parties. You can read the post JSON Web Token in ASP.NET Web API 2 using Owin
For the formal concept . The Authentication is the process of verifying who a user is, while authorization is the process of verifying what they have access to.
Let’s see the real life example
Imagine that your neighbor has asked you to feed his pets while he is away. In this example, you have the authorization to access the kitchen and open the cupboard storing the pet food. However, you can’t go into your neighbor’s bedroom as he did not explicitly permit you to do so. Even though you had the right to enter the house (authentication), your neighbor only allowed you access to certain areas (authorization).
For more detailed and for users who like more STEP BY STEP implementation on practical use of JSON Web Token in WEB API. This is must read post Secure WebAPI Using JSON WEB TOKEN
Updated to use: System.IdentityModel.Tokens.Jwt -Version 5.1.4

Resources