Fix refresh token scope in refresh token flow with scope request parameter
Closes #28463 Signed-off-by: cgeorgilakis-grnet <cgeorgilakis@admin.grnet.gr>
This commit is contained in:
parent
4c2542b91f
commit
89263f5255
2 changed files with 14 additions and 8 deletions
|
@ -389,7 +389,7 @@ public class TokenManager {
|
|||
//if scope parameter is not null, remove every scope that is not part of scope parameter
|
||||
if (scopeParameter != null && ! scopeParameter.isEmpty()) {
|
||||
Set<String> scopeParamScopes = Arrays.stream(scopeParameter.split(" ")).collect(Collectors.toSet());
|
||||
oldTokenScope = Arrays.stream(oldTokenScope.split(" ")).filter(sc -> scopeParamScopes.contains(sc) || sc.equals(OAuth2Constants.OFFLINE_ACCESS))
|
||||
oldTokenScope = Arrays.stream(oldTokenScope.split(" ")).filter(sc -> scopeParamScopes.contains(sc))
|
||||
.collect(Collectors.joining(" "));
|
||||
}
|
||||
|
||||
|
@ -415,7 +415,7 @@ public class TokenManager {
|
|||
validation.userSession, validation.clientSessionCtx).accessToken(validation.newToken);
|
||||
if (clientConfig.isUseRefreshToken()) {
|
||||
//refresh token must have same scope as old refresh token (type, scope, expiration)
|
||||
responseBuilder.generateRefreshToken(refreshToken.getScope());
|
||||
responseBuilder.generateRefreshToken(refreshToken.getScope(), clientSession);
|
||||
}
|
||||
|
||||
if (validation.newToken.getAuthorization() != null
|
||||
|
@ -1099,12 +1099,14 @@ public class TokenManager {
|
|||
return this;
|
||||
}
|
||||
|
||||
public AccessTokenResponseBuilder generateRefreshToken(String scope) {
|
||||
public AccessTokenResponseBuilder generateRefreshToken(String scope, AuthenticatedClientSessionModel clientSession) {
|
||||
if (accessToken == null) {
|
||||
throw new IllegalStateException("accessToken not set");
|
||||
}
|
||||
|
||||
boolean offlineTokenRequested = Arrays.asList(scope.split(" ")).contains(OAuth2Constants.OFFLINE_ACCESS) ;
|
||||
if (offlineTokenRequested)
|
||||
clientSessionCtx = DefaultClientSessionContext.fromClientSessionAndScopeParameter(clientSession, scope, session);
|
||||
generateRefreshToken(offlineTokenRequested);
|
||||
refreshToken.setScope(scope);
|
||||
return this;
|
||||
|
|
|
@ -305,7 +305,7 @@ public class OfflineTokenTest extends AbstractKeycloakTest {
|
|||
Assert.assertNotNull(newRefreshToken);
|
||||
Assert.assertNotEquals(oldToken.getId(), refreshedToken.getId());
|
||||
|
||||
// scope parameter contains "offline_access" if not filter via scope parameter
|
||||
// scope parameter either does not exist either contains offline_access
|
||||
assertTrue(refreshedToken.getScope().contains(OAuth2Constants.OFFLINE_ACCESS));
|
||||
// Assert refresh token scope parameter contains "offline_access"
|
||||
assertTrue(newRefreshTokenFull.getScope().contains(OAuth2Constants.OFFLINE_ACCESS));
|
||||
|
@ -1050,10 +1050,6 @@ public class OfflineTokenTest extends AbstractKeycloakTest {
|
|||
|
||||
Assert.assertEquals(TokenUtil.TOKEN_TYPE_OFFLINE, offlineToken.getType());
|
||||
Assert.assertEquals(0, offlineToken.getExpiration());
|
||||
|
||||
//refresh token without sending offline_access scope
|
||||
oauth.scope("phone");
|
||||
testRefreshWithOfflineToken(token, offlineToken, offlineTokenString, token.getSessionState(), serviceAccountUserId);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -1306,6 +1302,14 @@ public class OfflineTokenTest extends AbstractKeycloakTest {
|
|||
oauth.scope("openid");
|
||||
response = oauth.doRefreshTokenRequest(response.getRefreshToken(), "secret1");
|
||||
assertEquals(200, response.getStatusCode());
|
||||
|
||||
AccessToken token = oauth.verifyToken(response.getAccessToken());
|
||||
// access token scope does not contain offline_access due to luck of it in scope request parameter
|
||||
assertFalse(token.getScope().contains(OAuth2Constants.OFFLINE_ACCESS));
|
||||
RefreshToken offlineToken = oauth.parseRefreshToken(response.getRefreshToken());
|
||||
// refresh token scope are always equal to original refresh token scope
|
||||
Assert.assertEquals(TokenUtil.TOKEN_TYPE_OFFLINE, offlineToken.getType());
|
||||
assertTrue(offlineToken.getScope().contains(OAuth2Constants.OFFLINE_ACCESS));
|
||||
}
|
||||
finally {
|
||||
ClientManager.realm(adminClient.realm("test")).clientId("offline-client").fullScopeAllowed(true);
|
||||
|
|
Loading…
Reference in a new issue