16

I am trying to find a way to revoke Oauth2 JWT Refresh Token with vanilla Spring implementation and JwtTokenStore.

First: can somebody confirm that there is no API similar to /oauth/token that allows me to revoke a refresh token?

I wanted to add a custom API that would delete the refresh token along the folowing lines:

OAuth2RefreshToken oauth2RefreshToken=tokenStore.readRefreshToken(refreshToken);
tokenStore.removeRefreshToken(oauth2RefreshToken);

Now, looking at the JwtTokenStore, I noticed that it uses an ApprovalStore. So I went ahead and provided an InMemoryApprovalStore to my JwtTokenStore. My JwtTokenStore instantiation this look as follows:

@Bean
protected JwtAccessTokenConverter jwtTokenEnhancer() {
    JwtAccessTokenConverter converter = new JwtAccessTokenConverter();
    converter.setSigningKey("123456");
    return converter;
}

@Bean
public JwtTokenStore getTokenStore(){
    tokenStore= new JwtTokenStore(jwtTokenEnhancer());
    tokenStore.setApprovalStore(new InMemoryApprovalStore());
    tokenStore.setTokenEnhancer(jwtTokenEnhancer());
    return tokenStore;
};

Results: with no InMemoryApprovalStore, I can authenticate users and refresh tokens without problems. However, as soon as I add InMemoryApprovalStore to the token store, I start getting the following error message:

{"error":"invalid_grant","error_description":"Invalid refresh token: eyJhbGciOiJIUzI1NiJ9.eyJleHAiOjE0NDUwMjQ2MTcsInVzZXJfbmFtZSI6IjYzZjIyYjZlLWU5MGUtNDFjYS1iYzJlLTBmZTgzNmY3MTQ2NyIsImF1dGhvcml0aWVzIjpbIlJPTEVfQURNSU4iLCJST0xFX1VTRVIiXSwianRpIjoiMjgwMDgwNWQtMjk1Zi00ZDQzLWI2NTYtMDNlZWYwMWFkMjg0IiwiY2xpZW50X2lkIjoid2ViLWNsaWVudCIsInNjb3BlIjpbInJlYWQiLCJ3cml0ZSIsInRydXN0Il19.BPC0HqLYjWGM0IFjvsUGGKQ9dyIXSXwMhraCVFIxD0U"}

My second question is thus what is the proper way to revoke a refresh token?

Edit: I found the following thread that suggests that ApprovalStore is indeed the way to revoke JWT tokens. I now just need to find out how to use them properly.

Klaus
  • 2,328
  • 5
  • 41
  • 62

1 Answers1

4

First: can somebody confirm that there is no API similar to /oauth/token that allows me to revoke a refresh token?

Confirmed.

You don't need to define JwtTokenStore bean, spring will create it for you using AuthorizationServerEndpointsConfigurer

private TokenStore tokenStore() {
    if (tokenStore == null) {
        if (accessTokenConverter() instanceof JwtAccessTokenConverter) {
            this.tokenStore = new JwtTokenStore((JwtAccessTokenConverter) accessTokenConverter());
        }
        else {
            this.tokenStore = new InMemoryTokenStore();
        }
    }
    return this.tokenStore;
}

private ApprovalStore approvalStore() {
    if (approvalStore == null && tokenStore() != null && !isApprovalStoreDisabled()) {
        TokenApprovalStore tokenApprovalStore = new TokenApprovalStore();
        tokenApprovalStore.setTokenStore(tokenStore());
        this.approvalStore = tokenApprovalStore;
    }
    return this.approvalStore;
}

My second question is thus what is the proper way to revoke a refresh token?

revoke the approval for the token, this was used by JwtTokenStore

private void remove(String token) {
    if (approvalStore != null) {
        OAuth2Authentication auth = readAuthentication(token);
        String clientId = auth.getOAuth2Request().getClientId();
        Authentication user = auth.getUserAuthentication();
        if (user != null) {
            Collection<Approval> approvals = new ArrayList<Approval>();
            for (String scope : auth.getOAuth2Request().getScope()) {
                approvals.add(new Approval(user.getName(), clientId, scope, new Date(), ApprovalStatus.APPROVED));
            }
            approvalStore.revokeApprovals(approvals);
        }
    }
}
KSTN
  • 2,002
  • 14
  • 18
  • TokenApprovalStore doesn't really let you revoke a refresh token. At least not with JWTTokenStore. JWTTokenStore.removeRefreshToken calls tokenStore.revokeApprovals. And this method in turn calls tokenStore.findTokensByClientIdAndUserName, which always returns an empty set in the case of JWTTokenStore. – Klaus Sep 17 '15 at 10:26
  • 1
    Yes, you're right, but concept is the same, use `ApprovalStore` and the implementation is up to you – KSTN Sep 17 '15 at 12:04
  • 2
    If I understand the approval process correctly, revoking the approval means that the client application is no longer authorized to 'use' the account, and therefore all access and refresh tokens for the user/client will rejected. But isn't that too rigorous if all you want is to revoke a single refresh token? Revoking the approval means that the user can't do anything anymore. Plus, as soon as the user approves the client again later on, all access and refresh tokens can be used again. Isn't there a way to revoke a refresh token in a way that doesn't block other access and refresh tokens? – Tom Mar 16 '16 at 16:47
  • @MangEngkus correct me if I'm wrong, but this won't work because `JwtTokenStore` does not provide an implementation for `storeRefreshToken(OAuth2RefreshToken refreshToken, OAuth2Authentication authentication)`, so even with an `InMemoryApprovalStore`, no approvals ever get added. – Will Faithfull Oct 06 '16 at 09:10
  • @WillFaithfull Yes and as I explained in my previous comment, you can provide your own implementation – KSTN Oct 06 '16 at 10:09
  • didn't get how can i revoke a token? – Nishant Varshney Feb 27 '19 at 11:29