Token Verification logic

// CheckTokenEndpoint.checkToken

@RequestMapping(value = "/oauth/check_token")

@ResponseBody

publicMap<String, ? > checkToken(@RequestParam("token") String value) {



// tokenStore tokenStore tokenStore tokenStore tokenStore

OAuth2AccessToken token = resourceServerTokenServices.readAccessToken(value);

if (token == null) {

throw new InvalidTokenException("Token was not recognised");

}



if (token.isExpired()) {

throw new InvalidTokenException("Token has expired");

}



// Authentication information saved by token query and permission roles (service information)

OAuth2Authentication authentication = resourceServerTokenServices.loadAuthentication(token.getValue());



return accessTokenConverter.convertAccessToken(token, authentication);

}

Copy the code
    1. When the client bringsheader tokenaccessoauth2The resource server, the resource server will automatically intercepttoken
    1. sendtokenVerification is performed on the authentication servertokenlegitimacy
    1. If yes is returned by the authentication server to the resource servertokenIf no, the resource server returns the corresponding information to the client

Token generation logic

    / / DefaultTokenServices createAccessToken code logic

public OAuth2AccessToken createAccessToken(OAuth2Authentication authentication) throws AuthenticationException {



// Query the delivered token based on user information (username)

OAuth2AccessToken existingAccessToken = tokenStore.getAccessToken(authentication);

OAuth2RefreshToken refreshToken = null;



// The issued token exists

if(existingAccessToken ! =null) {

// 1. If the token has expired, the token is deleted

if (existingAccessToken.isExpired()) {

if(existingAccessToken.getRefreshToken() ! =null) {

refreshToken = existingAccessToken.getRefreshToken();

tokenStore.removeRefreshToken(refreshToken);

}

tokenStore.removeAccessToken(existingAccessToken);

}

else {

// Return the existing token and save the relationship between the token and the user information (username)

tokenStore.storeAccessToken(existingAccessToken, authentication);

return existingAccessToken;

}

}



// Create a new token if it does not exist

OAuth2AccessToken accessToken = createAccessToken(authentication, refreshToken);

tokenStore.storeAccessToken(accessToken, authentication);

// In case it was modified

refreshToken = accessToken.getRefreshToken();

if(refreshToken ! =null) {

tokenStore.storeRefreshToken(refreshToken, authentication);

}

return accessToken;



}



Copy the code
    1. When we go to oAuth2 to get ittokenIf the current user already has the corresponding token, the system returns the token without creating a new token.
    1. This means that although the valid time for the corresponding client to obtain the token is set, it is obtained heretoken. If it is oldtoken, the valid time will not andsessionAutomatic renewal mechanism as well.
    1. To sum up, in the process of operationtokenExpiration is a constant problem.

Token refresh logic

curl --location --request POST 'http://auth-server/oauth/token? grant_type=refresh_token' \

--header 'Authorization: Basic dGVzdDp0ZXN0' \

--header 'VERSION: dev' \

--data-urlencode 'scope=server' \

--data-urlencode 'refresh_token=eccda61e-0c68-43af-8f67-6302cb389612'

Copy the code

If yes, when the front end calls the refresh endpoint of the authentication authority with the correct (unexpired and unused) refresh_Token refresh, RefreshTokenGranter is triggered and the new Token is returned

public class RefreshTokenGranter extends AbstractTokenGranter {



@Override

protected OAuth2AccessToken getAccessToken(ClientDetails client, TokenRequest tokenRequest) {

String refreshToken = tokenRequest.getRequestParameters().get("refresh_token");

return getTokenServices().refreshAccessToken(refreshToken, tokenRequest);

}



}



Copy the code
  • RefreshAccessToken code implementation, calledtokenStoreGenerate a newtoken
@Transactional(noRollbackFor={InvalidTokenException.class, InvalidGrantException.class})

public OAuth2AccessToken refreshAccessToken(String refreshTokenValue, TokenRequest tokenRequest)

throws AuthenticationException {





createRefreshedAuthentication(authentication, tokenRequest);



if (! reuseRefreshToken) {

tokenStore.removeRefreshToken(refreshToken);

refreshToken = createRefreshToken(authentication);

}



OAuth2AccessToken accessToken = createAccessToken(authentication, refreshToken);

tokenStore.storeAccessToken(accessToken, authentication);

if (! reuseRefreshToken) {

tokenStore.storeRefreshToken(accessToken.getRefreshToken(), authentication);

}

return accessToken;

}

Copy the code

When the client (front end) is refreshed

Passive refresh


  1. The client uses a token to access the resource server

  2. Resource server intercepts token to authenticate server check_token

  3. The authentication server returns a token expiration error, and the resource server returns a wrapper error message to the client

  4. The client directly invokes the authentication server refresh_token based on the return error message (response code)

  5. The authentication server returns the new token to the client and then invokes the resource again

The disadvantage of passive requests is that the user will fail the first time the request is made (return token fails) and is not very friendly to some business coherent operations

Take the initiative to refresh


  1. The client has the calculation logic to calculate the validity period of the token

  2. If the token is about to expire, initiate a refresh

The disadvantage of proactive request is that the client occupies some computing resources to handle token invalidation

// 10S Checks the validity period of the token

refreshToken() {

this.refreshTime = setInterval(() => {

const token = getStore({

name: 'access_token',

debug: true

})

if (this.validatenull(token)) {

return

}

if (this.expires_in <= 1000 && ! this.refreshLock) {

this.refreshLock = true

this.$store

.dispatch('RefreshToken')

.catch(() => {

clearInterval(this.refreshTime)

})

this.refreshLock = false

}

this.$store.commit('SET_EXPIRES_IN', this.expires_in - 10)

}, 10000).

},

Copy the code

“★★★★” based on Spring Boot 2.2, Spring Cloud Hoxton & Alibaba, OAuth2 RBAC authority management system