How to implement ITokenHandle interface in UserService to revoke a reference token - access-token

I have an Identity Server 3 based Authentication service. It's currently using JWTs, but I'm planning to switch over to reference tokens so that we can revoke them when the user logs out of the client application. I've been researching this (Dominick Baier - Reference Tokens and Introspection) and understand that one option - the one I'd like to implement - is to have my user service - part of my authentication service implementation - use the Identity Server ITokenHandle interface to revoke the token. I have not been able to find any more information on this interface or how to implement it in my user service.
Has anyone done Identity Server 3 token revocation in their user service or can anyone point me to more information about this approach?

The two GitHub postings in the comments on the original post contained the information I needed. I was able to switch from JWTs to reference tokens and then implement automatic revocation of the reference tokens on user sign out. The switch of the token type was a simple matter of setting
AccessTokenType = AccessTokenType.Reference
in my client setup code. To revoke the tokens on sign out I first added
idSrvFactory.Register(new Registration<DefaultClientPermissionsService>());
in Startup.cs. Then in my UserService, I added it to the UserService constructor
public UserService(DefaultClientPermissionsService clientPermissionsSvc)
{
_clientPermissionsSvc = clientPermissionsSvc;
}
Then finally, still in my UserService, I implemented
public override Task SignOutAsync(SignOutContext context)
{
string subjectId = GetSubjectId(context);
_clientPermissionsSvc.RevokeClientPermissionsAsync(subjectId, context.ClientId);
return Task.FromResult(0);
}

Related

Add claims to security.oauth2.jwt.Jwt

I have a SpringBoot OAuth2 Client and ResourceServer. My AuthorizationServer is Okta.
Now suppose that in a certain moment I want to add a claim to my token, for Example:
#GetMapping("/addIdUser")
public ResponseEntity<String> addUser(#AuthenticationPrincipal Jwt jwt) {
// here I want to add a claim to my Jwt, the token
// should return to the frontend and when I resend back to my resourceserver
// it should be validated again
return new ResponseEntity<String>(token, HttpStatus.OK);
}
I have read tons of docs of TokenEnhencer and TokenConverter but it not seems to be the solution I looking for.
Can I do something like this?
Seems like you want to authorize based on domain specific claims, and there are two main options here:
Get extra claims at the time of token issuance - Okta needs to either call an API or do a database lookup - this is the preferred option but not always possible
Look up claims in the resource server when an access token is first received, then cache them for subsequent requests with the same access token
Leave the Okta issued token alone in the client, then adopt one of the above two approaches in the API. Out of interest, here is a Spring Boot API of mine that uses a library based approach to OAuth handling and implements both approaches:
Standard Authorizer
Claims Caching Authorizer

jwt validation in backend springboot

Im looking to create an angular application which login against a new authentication server created in springboot and return a jwt.
The idea is to create the application to be able to generate and sign the jwt token with a private key based on the user/password provided in the screen, the authentication server will validate the login information in database and generate the jwt token.
After that, a request will be sent to another microservice and in here I need to be able to validate the token, but this microservice wont be connected to the authentication service or database in any way, it will just validate the integrity of the token using a public key.
Im looking everywhere and I dont find the clue to be able to validate the token, I found this piece of code but for some reason when I execute the rest API exposed this code is not executed:
#Bean
public JwtAccessTokenConverter accessTokenConverter() {
JwtAccessTokenConverter converter = new JwtAccessTokenConverter();
Resource resource = new ClassPathResource("public.txt");
String publicKey = null;
try {
publicKey = IOUtils.toString(resource.getInputStream(), Charset.defaultCharset());
} catch (final IOException e) {
throw new RuntimeException(e);
}
converter.setVerifierKey(publicKey);
return converter;
}
Does what im trying to do makes any sense?
Thanks
Regards
Your auth server will will need to be the single issuer of JWTs to your microservices. So, when a user logs in and successfully authenticates, your auth server will issue a JWT signed with a private key (signing MUST be asymmetric - RS256 is one example) you keep on the auth server only; do not give this private key to other microservices that you wish to validate JWTs inside of. What you can do is derive a public key based on the private key you sign your tokens with and publish that to an endpoint on your auth server that requires no authentication - the public key will be represented in the form of a JWK (see link to spec). Google does something similar here. Then, in each of your microservices, you will need to devise a way to make a GET request to the public key endpoint on your auth server every X minutes and cache the public key in each microservice.
Then whenever a request comes into one of your microservices, you grab the JWT, check its validity, and grant access/authorization if the token is valid. The beauty of using a private/public key pair and asymmetric key signing is that you can validate a token based on the public key alone, but not sign it. So as long as each service has the public key from your /cert endpoint, they can validate a token without ever needing to talk to the auth server or knowing the private key.
This will require a little more work up front, but will yield you massive amount of ease, flexibility, and peace of mind in the future knowing only one source knows your private key.
I suggest using this library to do JWT validation.
The overall architecture will end up looking something like this:

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?

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.

MissingAuthorizationException: Getting last tweets

Why is it needed to be authorized when I just want the last 2 tweets?
I would like to create a minimal config as I don't need the connection stuff.
And as I understand the twitter api it is not necessary to have a consumerKey/consumerSecret for just getting some tweets?!
Bean:
<bean id="twitter" class="org.springframework.social.twitter.api.impl.TwitterTemplate" />
Spring Controller:
#Controller
public class FragmentController {
#Autowired
private Twitter twitter;
#ModelAttribute
public void global(ModelMap map) {
map.addAttribute("tweets", twitter.timelineOperations().getUserTimeline("myTwitterUsername", 2));
}
#RequestMapping("index.html")
public String index() {
return "index";
}
}
As of the release of version 1.1 of Twitter's API, all operations against the API require authorization, including those that you would think do not need it.
That said, you do not necessarily need user authorization to request resources that would otherwise be public and not private to any specific user. A specified user's tweets, for instance, can be had without user authorization. But you still need application authorization.
This is where Twitter's API gets a bit weird. For user authorization, Twitter is secured with OAuth 1.0a and this applies to all (or most all) resources at Twitter. For app-only authorization, Twitter uses OAuth 2 client credentials grant. This kind of authorization applies to a subset of the whole API.
Fortunately, Spring Social supports this in the very latest snapshot build (1.1.0.BUILD-SNAPSHOT). Via OAuth2Template, you can call authenticateClient() to obtain an AccessGrant (and from that obtain an access token). Then you can create an instance of TwitterTemplate, passing in only the client's access token and use it to access Twitter's API for those operations that access app-only authorization.
Know that when I say "very latest snapshot build", that's quite literal. I pushed the changes to TwitterTemplate last last night and it could still stand some more testing. I have tested it a bit with regard to search, but all other resources are relatively untested. If you run into any issues, please let me know by creating a bug issue at https://jira.springsource.org/browse/SOCIALTW.

Resources