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
-
- When the client brings
header token
accessoauth2
The resource server, the resource server will automatically intercepttoken
- When the client brings
-
- send
token
Verification is performed on the authentication servertoken
legitimacy
- send
-
- If yes is returned by the authentication server to the resource server
token
If no, the resource server returns the corresponding information to the client
- If yes is returned by the authentication server to the resource server
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
-
- When we go to oAuth2 to get it
token
If the current user already has the corresponding token, the system returns the token without creating a new token.
- When we go to oAuth2 to get it
-
- This means that although the valid time for the corresponding client to obtain the token is set, it is obtained here
token
. If it is oldtoken
, the valid time will not andsession
Automatic renewal mechanism as well.
- This means that although the valid time for the corresponding client to obtain the token is set, it is obtained here
-
- To sum up, in the process of operation
token
Expiration is a constant problem.
- To sum up, in the process of operation
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, called
tokenStore
Generate 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
-
The client uses a token to access the resource server
-
Resource server intercepts token to authenticate server check_token
-
The authentication server returns a token expiration error, and the resource server returns a wrapper error message to the client
-
The client directly invokes the authentication server refresh_token based on the return error message (response code)
-
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
-
The client has the calculation logic to calculate the validity period of the token
-
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