diff --git a/openid-connect-server-webapp/src/main/webapp/resources/js/locale/en/messages.json b/openid-connect-server-webapp/src/main/webapp/resources/js/locale/en/messages.json index e0b176d49..695ea44db 100644 --- a/openid-connect-server-webapp/src/main/webapp/resources/js/locale/en/messages.json +++ b/openid-connect-server-webapp/src/main/webapp/resources/js/locale/en/messages.json @@ -105,6 +105,7 @@ "refresh": "refresh", "refresh-tokens": "Refresh Tokens", "refresh-tokens-issued": "Refresh tokens are issued for this client", + "refresh-tokens-issued-help": "This will add the offline_access scope to the client's scopes.", "refresh-tokens-reused": "Refresh tokens for this client are re-used", "refresh-tokens-no-expire": "Refresh tokens do not time out", "registered": "Registered at", diff --git a/openid-connect-server-webapp/src/main/webapp/resources/template/client.html b/openid-connect-server-webapp/src/main/webapp/resources/template/client.html index 9bdf4cba6..bc4acc2be 100644 --- a/openid-connect-server-webapp/src/main/webapp/resources/template/client.html +++ b/openid-connect-server-webapp/src/main/webapp/resources/template/client.html @@ -543,6 +543,7 @@
> +

This will add the offline_access scope to the client's scopes.

diff --git a/openid-connect-server/src/main/java/org/mitre/oauth2/service/impl/DefaultOAuth2ProviderTokenService.java b/openid-connect-server/src/main/java/org/mitre/oauth2/service/impl/DefaultOAuth2ProviderTokenService.java index 876475c74..ab95cbcd5 100644 --- a/openid-connect-server/src/main/java/org/mitre/oauth2/service/impl/DefaultOAuth2ProviderTokenService.java +++ b/openid-connect-server/src/main/java/org/mitre/oauth2/service/impl/DefaultOAuth2ProviderTokenService.java @@ -170,33 +170,7 @@ public class DefaultOAuth2ProviderTokenService implements OAuth2TokenEntityServi // attach a refresh token, if this client is allowed to request them and the user gets the offline scope if (client.isAllowRefresh() && token.getScope().contains(SystemScopeService.OFFLINE_ACCESS)) { - OAuth2RefreshTokenEntity refreshToken = new OAuth2RefreshTokenEntity(); //refreshTokenFactory.createNewRefreshToken(); - JWTClaimsSet refreshClaims = new JWTClaimsSet(); - - - // make it expire if necessary - if (client.getRefreshTokenValiditySeconds() != null) { - Date expiration = new Date(System.currentTimeMillis() + (client.getRefreshTokenValiditySeconds() * 1000L)); - refreshToken.setExpiration(expiration); - refreshClaims.setExpirationTime(expiration); - } - - // set a random identifier - refreshClaims.setJWTID(UUID.randomUUID().toString()); - - // TODO: add issuer fields, signature to JWT - - PlainJWT refreshJwt = new PlainJWT(refreshClaims); - refreshToken.setJwt(refreshJwt); - - //Add the authentication - refreshToken.setAuthenticationHolder(authHolder); - refreshToken.setClient(client); - - - - // save the token first so that we can set it to a member of the access token (NOTE: is this step necessary?) - OAuth2RefreshTokenEntity savedRefreshToken = tokenRepository.saveRefreshToken(refreshToken); + OAuth2RefreshTokenEntity savedRefreshToken = createRefreshToken(client, authHolder); token.setRefreshToken(savedRefreshToken); } @@ -229,6 +203,38 @@ public class DefaultOAuth2ProviderTokenService implements OAuth2TokenEntityServi throw new AuthenticationCredentialsNotFoundException("No authentication credentials found"); } + + private OAuth2RefreshTokenEntity createRefreshToken(ClientDetailsEntity client, AuthenticationHolderEntity authHolder) { + OAuth2RefreshTokenEntity refreshToken = new OAuth2RefreshTokenEntity(); //refreshTokenFactory.createNewRefreshToken(); + JWTClaimsSet refreshClaims = new JWTClaimsSet(); + + + // make it expire if necessary + if (client.getRefreshTokenValiditySeconds() != null) { + Date expiration = new Date(System.currentTimeMillis() + (client.getRefreshTokenValiditySeconds() * 1000L)); + refreshToken.setExpiration(expiration); + refreshClaims.setExpirationTime(expiration); + } + + // set a random identifier + refreshClaims.setJWTID(UUID.randomUUID().toString()); + + // TODO: add issuer fields, signature to JWT + + PlainJWT refreshJwt = new PlainJWT(refreshClaims); + refreshToken.setJwt(refreshJwt); + + //Add the authentication + refreshToken.setAuthenticationHolder(authHolder); + refreshToken.setClient(client); + + + + // save the token first so that we can set it to a member of the access token (NOTE: is this step necessary?) + OAuth2RefreshTokenEntity savedRefreshToken = tokenRepository.saveRefreshToken(refreshToken); + return savedRefreshToken; + } + @Override public OAuth2AccessTokenEntity refreshAccessToken(String refreshTokenValue, TokenRequest authRequest) throws AuthenticationException { @@ -263,9 +269,6 @@ public class DefaultOAuth2ProviderTokenService implements OAuth2TokenEntityServi throw new InvalidTokenException("Expired refresh token: " + refreshTokenValue); } - // TODO: have the option to recycle the refresh token here, too - // for now, we just reuse it as long as it's valid, which is the original intent - OAuth2AccessTokenEntity token = new OAuth2AccessTokenEntity(); // get the stored scopes from the authentication holder's authorization request; these are the scopes associated with the refresh token @@ -302,7 +305,17 @@ public class DefaultOAuth2ProviderTokenService implements OAuth2TokenEntityServi token.setExpiration(expiration); } - token.setRefreshToken(refreshToken); + if (client.isReuseRefreshToken()) { + // if the client re-uses refresh tokens, do that + token.setRefreshToken(refreshToken); + } else { + // otherwise, make a new refresh token + OAuth2RefreshTokenEntity newRefresh = createRefreshToken(client, authHolder); + token.setRefreshToken(newRefresh); + + // clean up the old refresh token + tokenRepository.removeRefreshToken(refreshToken); + } token.setAuthenticationHolder(authHolder);