diff --git a/Model/src/main/java/org/gluu/oxauth/model/configuration/AppConfiguration.java b/Model/src/main/java/org/gluu/oxauth/model/configuration/AppConfiguration.java index 80056a1481..ae0400cda6 100644 --- a/Model/src/main/java/org/gluu/oxauth/model/configuration/AppConfiguration.java +++ b/Model/src/main/java/org/gluu/oxauth/model/configuration/AppConfiguration.java @@ -207,6 +207,7 @@ public class AppConfiguration implements Configuration { private Boolean errorReasonEnabled = false; private Boolean removeRefreshTokensForClientOnLogout = true; private Boolean skipRefreshTokenDuringRefreshing = false; + private Boolean refreshTokenExtendLifetimeOnRotation = false; private Boolean consentGatheringScriptBackwardCompatibility = false; // means ignore client configuration (as defined in 4.2) and determine it globally (as in 4.1 and earlier) private Boolean introspectionScriptBackwardCompatibility = false; // means ignore client configuration (as defined in 4.2) and determine it globally (as in 4.1 and earlier) private Boolean clientAuthorizationBackwardCompatibility = false; // search client authorization by filter (instead of key) @@ -275,6 +276,14 @@ public Boolean getClientAuthorizationBackwardCompatibility() { public void setClientAuthorizationBackwardCompatibility(Boolean clientAuthorizationBackwardCompatibility) { this.clientAuthorizationBackwardCompatibility = clientAuthorizationBackwardCompatibility; } + public Boolean getRefreshTokenExtendLifetimeOnRotation() { + if (refreshTokenExtendLifetimeOnRotation == null) refreshTokenExtendLifetimeOnRotation = false; + return refreshTokenExtendLifetimeOnRotation; + } + + public void setRefreshTokenExtendLifetimeOnRotation(Boolean refreshTokenExtendLifetimeOnRotation) { + this.refreshTokenExtendLifetimeOnRotation = refreshTokenExtendLifetimeOnRotation; + } public Boolean getExpirationNotificatorEnabled() { if (expirationNotificatorEnabled == null) expirationNotificatorEnabled = false; diff --git a/Server/src/main/java/org/gluu/oxauth/model/common/AuthorizationGrant.java b/Server/src/main/java/org/gluu/oxauth/model/common/AuthorizationGrant.java index 90fd338f81..b644760530 100644 --- a/Server/src/main/java/org/gluu/oxauth/model/common/AuthorizationGrant.java +++ b/Server/src/main/java/org/gluu/oxauth/model/common/AuthorizationGrant.java @@ -19,15 +19,12 @@ import org.gluu.oxauth.model.jwt.JwtClaimName; import org.gluu.oxauth.model.ldap.TokenLdap; import org.gluu.oxauth.model.registration.Client; +import org.gluu.oxauth.model.token.HandleTokenFactory; import org.gluu.oxauth.model.token.IdTokenFactory; import org.gluu.oxauth.model.token.JsonWebResponse; import org.gluu.oxauth.model.token.JwtSigner; import org.gluu.oxauth.model.util.JwtUtil; -import org.gluu.oxauth.service.AttributeService; -import org.gluu.oxauth.service.ClientService; -import org.gluu.oxauth.service.GrantService; -import org.gluu.oxauth.service.MetricService; -import org.gluu.oxauth.service.SectorIdentifierService; +import org.gluu.oxauth.service.*; import org.gluu.oxauth.service.external.ExternalIntrospectionService; import org.gluu.oxauth.service.external.context.ExternalIntrospectionContext; import org.gluu.oxauth.util.TokenHashUtil; @@ -256,6 +253,27 @@ public RefreshToken createRefreshToken() { } } + public RefreshToken createRefreshToken(Date expirationDate) { + try { + RefreshToken refreshToken = new RefreshToken(HandleTokenFactory.generateHandleToken(), new Date(), expirationDate); + + refreshToken.setAuthMode(getAcrValues()); + refreshToken.setSessionDn(getSessionDn()); + + if (refreshToken.getExpiresIn() > 0) { + persist(asToken(refreshToken)); + metricService.incCounter(MetricType.OXAUTH_TOKEN_REFRESH_TOKEN_COUNT); + return refreshToken; + } + + log.debug("Token expiration date is in the past. Skip creation."); + return null; + } catch (Exception e) { + log.error(e.getMessage(), e); + return null; + } + } + @Override public IdToken createIdToken( String nonce, AuthorizationCode authorizationCode, AccessToken accessToken, RefreshToken refreshToken, diff --git a/Server/src/main/java/org/gluu/oxauth/token/ws/rs/TokenRestWebServiceImpl.java b/Server/src/main/java/org/gluu/oxauth/token/ws/rs/TokenRestWebServiceImpl.java index 24df0ba5d3..5fa60fcb3e 100644 --- a/Server/src/main/java/org/gluu/oxauth/token/ws/rs/TokenRestWebServiceImpl.java +++ b/Server/src/main/java/org/gluu/oxauth/token/ws/rs/TokenRestWebServiceImpl.java @@ -245,16 +245,27 @@ public Response requestAccessToken(String grantType, String code, AuthorizationGrant authorizationGrant = authorizationGrantList.getAuthorizationGrantByRefreshToken(client.getClientId(), refreshToken); if (authorizationGrant == null) { + log.trace("Grant object is not found by refresh token."); return response(error(400, TokenErrorResponseType.INVALID_GRANT, "Unable to find grant object by refresh token or otherwise token type or client does not match."), oAuth2AuditLog); } + final RefreshToken refreshTokenObject = authorizationGrant.getRefreshToken(refreshToken); + if (refreshTokenObject == null || !refreshTokenObject.isValid()) { + log.trace("Invalid refresh token."); + return response(error(400, TokenErrorResponseType.INVALID_GRANT, "Unable to find refresh token or otherwise token type or client does not match."), oAuth2AuditLog); + } + // The authorization server MAY issue a new refresh token, in which case // the client MUST discard the old refresh token and replace it with the new refresh token. RefreshToken reToken = null; if (!appConfiguration.getSkipRefreshTokenDuringRefreshing()) { - reToken = authorizationGrant.createRefreshToken(); + if (appConfiguration.getRefreshTokenExtendLifetimeOnRotation()) { + reToken = authorizationGrant.createRefreshToken(); // extend lifetime + } else { + reToken = authorizationGrant.createRefreshToken(refreshTokenObject.getExpirationDate()); // do not extend lifetime + } + grantService.removeByCode(refreshToken); } - grantService.removeByCode(refreshToken); if (scope != null && !scope.isEmpty()) { scope = authorizationGrant.checkScopesPolicy(scope);