use of org.keycloak.representations.RefreshToken in project keycloak by keycloak.
the class RefreshTokenTest method refreshTokenUserDeleted.
@Test
public void refreshTokenUserDeleted() throws Exception {
String userId = createUser("test", "temp-user@localhost", "password");
oauth.doLogin("temp-user@localhost", "password");
EventRepresentation loginEvent = events.expectLogin().user(userId).assertEvent();
String sessionId = loginEvent.getSessionId();
String codeId = loginEvent.getDetails().get(Details.CODE_ID);
String code = oauth.getCurrentQuery().get(OAuth2Constants.CODE);
OAuthClient.AccessTokenResponse response = oauth.doAccessTokenRequest(code, "password");
String refreshTokenString = response.getRefreshToken();
RefreshToken refreshToken = oauth.parseRefreshToken(refreshTokenString);
events.expectCodeToToken(codeId, sessionId).user(userId).assertEvent();
adminClient.realm("test").users().delete(userId);
setTimeOffset(2);
response = oauth.doRefreshTokenRequest(refreshTokenString, "password");
assertEquals(400, response.getStatusCode());
assertEquals("invalid_grant", response.getError());
events.expectRefresh(refreshToken.getId(), sessionId).user(userId).clearDetails().error(Errors.INVALID_TOKEN).assertEvent();
}
use of org.keycloak.representations.RefreshToken in project keycloak by keycloak.
the class RefreshTokenTest method refreshTokenReuseTokenWithRefreshTokensRevokedAndSSOReauthentication.
// Doublecheck that with "revokeRefreshToken" and revoked tokens, the SSO re-authentication won't cause old tokens to be valid again
@Test
public void refreshTokenReuseTokenWithRefreshTokensRevokedAndSSOReauthentication() throws Exception {
try {
// Initial login
RealmManager.realm(adminClient.realm("test")).revokeRefreshToken(true);
oauth.doLogin("test-user@localhost", "password");
EventRepresentation loginEvent = events.expectLogin().assertEvent();
String sessionId = loginEvent.getSessionId();
String codeId = loginEvent.getDetails().get(Details.CODE_ID);
String code = oauth.getCurrentQuery().get(OAuth2Constants.CODE);
OAuthClient.AccessTokenResponse response1 = oauth.doAccessTokenRequest(code, "password");
RefreshToken refreshToken1 = oauth.parseRefreshToken(response1.getRefreshToken());
events.expectCodeToToken(codeId, sessionId).assertEvent();
// Refresh token for the first time - should pass
setTimeOffset(2);
OAuthClient.AccessTokenResponse response2 = oauth.doRefreshTokenRequest(response1.getRefreshToken(), "password");
RefreshToken refreshToken2 = oauth.parseRefreshToken(response2.getRefreshToken());
assertEquals(200, response2.getStatusCode());
events.expectRefresh(refreshToken1.getId(), sessionId).assertEvent();
// Client sessions is available now
Assert.assertTrue(hasClientSessionForTestApp());
// Refresh token for the second time - should fail and invalidate client session
setTimeOffset(4);
OAuthClient.AccessTokenResponse response3 = oauth.doRefreshTokenRequest(response1.getRefreshToken(), "password");
assertEquals(400, response3.getStatusCode());
events.expectRefresh(refreshToken1.getId(), sessionId).removeDetail(Details.TOKEN_ID).removeDetail(Details.UPDATED_REFRESH_TOKEN_ID).error("invalid_token").assertEvent();
// No client sessions available after revoke
Assert.assertFalse(hasClientSessionForTestApp());
// Introspection with the accessToken from the first authentication. This should fail
String introspectionResponse = oauth.introspectAccessTokenWithClientCredential("test-app", "password", response1.getAccessToken());
JsonNode jsonNode = JsonSerialization.mapper.readTree(introspectionResponse);
Assert.assertFalse(jsonNode.get("active").asBoolean());
events.clear();
// SSO re-authentication
setTimeOffset(6);
oauth.openLoginForm();
loginEvent = events.expectLogin().assertEvent();
sessionId = loginEvent.getSessionId();
codeId = loginEvent.getDetails().get(Details.CODE_ID);
code = oauth.getCurrentQuery().get(OAuth2Constants.CODE);
OAuthClient.AccessTokenResponse response4 = oauth.doAccessTokenRequest(code, "password");
RefreshToken refreshToken4 = oauth.parseRefreshToken(response4.getRefreshToken());
events.expectCodeToToken(codeId, sessionId).assertEvent();
// Client sessions should be available again now after re-authentication
Assert.assertTrue(hasClientSessionForTestApp());
// Introspection again with the accessToken from the very first authentication. This should fail as the access token was obtained for the old client session before SSO re-authentication
introspectionResponse = oauth.introspectAccessTokenWithClientCredential("test-app", "password", response1.getAccessToken());
jsonNode = JsonSerialization.mapper.readTree(introspectionResponse);
Assert.assertFalse(jsonNode.get("active").asBoolean());
// Try userInfo with the same old access token. Should fail as well
UserInfo userInfo = oauth.doUserInfoRequest(response1.getAccessToken());
Assert.assertNull(userInfo.getSubject());
Assert.assertEquals(userInfo.getOtherClaims().get(OAuth2Constants.ERROR), OAuthErrorException.INVALID_TOKEN);
events.clear();
// Try to refresh with one of the old refresh tokens before SSO re-authentication - should fail
setTimeOffset(8);
OAuthClient.AccessTokenResponse response5 = oauth.doRefreshTokenRequest(response2.getRefreshToken(), "password");
assertEquals(400, response5.getStatusCode());
events.expectRefresh(refreshToken2.getId(), sessionId).removeDetail(Details.TOKEN_ID).removeDetail(Details.UPDATED_REFRESH_TOKEN_ID).error("invalid_token").assertEvent();
} finally {
setTimeOffset(0);
RealmManager.realm(adminClient.realm("test")).revokeRefreshToken(false);
}
}
use of org.keycloak.representations.RefreshToken in project keycloak by keycloak.
the class RefreshTokenTest method refreshTokenUserDisabled.
@Test
public void refreshTokenUserDisabled() throws Exception {
oauth.doLogin("test-user@localhost", "password");
EventRepresentation loginEvent = events.expectLogin().assertEvent();
String sessionId = loginEvent.getSessionId();
String codeId = loginEvent.getDetails().get(Details.CODE_ID);
String code = oauth.getCurrentQuery().get(OAuth2Constants.CODE);
OAuthClient.AccessTokenResponse response = oauth.doAccessTokenRequest(code, "password");
String refreshTokenString = response.getRefreshToken();
RefreshToken refreshToken = oauth.parseRefreshToken(refreshTokenString);
events.expectCodeToToken(codeId, sessionId).assertEvent();
try {
UserManager.realm(adminClient.realm("test")).username("test-user@localhost").enabled(false);
setTimeOffset(2);
response = oauth.doRefreshTokenRequest(refreshTokenString, "password");
assertEquals(400, response.getStatusCode());
assertEquals("invalid_grant", response.getError());
events.expectRefresh(refreshToken.getId(), sessionId).clearDetails().error(Errors.INVALID_TOKEN).assertEvent();
} finally {
UserManager.realm(adminClient.realm("test")).username("test-user@localhost").enabled(true);
}
}
use of org.keycloak.representations.RefreshToken in project keycloak by keycloak.
the class ServiceAccountTest method clientCredentialsAuthSuccess.
@Test
public void clientCredentialsAuthSuccess() throws Exception {
oauth.clientId("service-account-cl-refresh-on");
OAuthClient.AccessTokenResponse response = oauth.doClientCredentialsGrantAccessTokenRequest("secret1");
assertEquals(200, response.getStatusCode());
// older clients which use client-credentials grant may create a refresh-token and session, see KEYCLOAK-9551.
List<Map<String, String>> clientSessionStats = getAdminClient().realm(oauth.getRealm()).getClientSessionStats();
assertThat(clientSessionStats, hasSize(1));
Map<String, String> sessionStats = clientSessionStats.get(0);
assertEquals(sessionStats.get("clientId"), oauth.getClientId());
// Refresh token is for backwards compatibility only. It won't be in client credentials by default
AccessToken accessToken = oauth.verifyToken(response.getAccessToken());
RefreshToken refreshToken = oauth.parseRefreshToken(response.getRefreshToken());
events.expectClientLogin().client("service-account-cl-refresh-on").user(userId).session(accessToken.getSessionState()).detail(Details.TOKEN_ID, accessToken.getId()).detail(Details.REFRESH_TOKEN_ID, refreshToken.getId()).detail(Details.USERNAME, userName).assertEvent();
assertEquals(accessToken.getSessionState(), refreshToken.getSessionState());
System.out.println("Access token other claims: " + accessToken.getOtherClaims());
Assert.assertEquals("service-account-cl-refresh-on", accessToken.getOtherClaims().get(ServiceAccountConstants.CLIENT_ID));
Assert.assertTrue(accessToken.getOtherClaims().containsKey(ServiceAccountConstants.CLIENT_ADDRESS));
Assert.assertTrue(accessToken.getOtherClaims().containsKey(ServiceAccountConstants.CLIENT_HOST));
OAuthClient.AccessTokenResponse refreshedResponse = oauth.doRefreshTokenRequest(response.getRefreshToken(), "secret1");
AccessToken refreshedAccessToken = oauth.verifyToken(refreshedResponse.getAccessToken());
RefreshToken refreshedRefreshToken = oauth.parseRefreshToken(refreshedResponse.getRefreshToken());
assertEquals(accessToken.getSessionState(), refreshedAccessToken.getSessionState());
assertEquals(accessToken.getSessionState(), refreshedRefreshToken.getSessionState());
events.expectRefresh(refreshToken.getId(), refreshToken.getSessionState()).user(userId).client("service-account-cl-refresh-on").assertEvent();
}
use of org.keycloak.representations.RefreshToken in project keycloak by keycloak.
the class AuthorizationTokenService method createAuthorizationResponse.
private AuthorizationResponse createAuthorizationResponse(KeycloakIdentity identity, Collection<Permission> entitlements, KeycloakAuthorizationRequest request, ClientModel targetClient) {
KeycloakSession keycloakSession = request.getKeycloakSession();
AccessToken accessToken = identity.getAccessToken();
RealmModel realm = request.getRealm();
UserSessionProvider sessions = keycloakSession.sessions();
UserSessionModel userSessionModel;
if (accessToken.getSessionState() == null) {
// Create temporary (request-scoped) transient session
UserModel user = TokenManager.lookupUserFromStatelessToken(keycloakSession, realm, accessToken);
userSessionModel = sessions.createUserSession(KeycloakModelUtils.generateId(), realm, user, user.getUsername(), request.getClientConnection().getRemoteAddr(), ServiceAccountConstants.CLIENT_AUTH, false, null, null, UserSessionModel.SessionPersistenceState.TRANSIENT);
} else {
userSessionModel = sessions.getUserSession(realm, accessToken.getSessionState());
if (userSessionModel == null) {
userSessionModel = sessions.getOfflineUserSession(realm, accessToken.getSessionState());
}
}
ClientModel client = realm.getClientByClientId(accessToken.getIssuedFor());
AuthenticatedClientSessionModel clientSession = userSessionModel.getAuthenticatedClientSessionByClient(targetClient.getId());
ClientSessionContext clientSessionCtx;
if (clientSession == null) {
RootAuthenticationSessionModel rootAuthSession = keycloakSession.authenticationSessions().getRootAuthenticationSession(realm, userSessionModel.getId());
if (rootAuthSession == null) {
if (userSessionModel.getUser().getServiceAccountClientLink() == null) {
rootAuthSession = keycloakSession.authenticationSessions().createRootAuthenticationSession(realm, userSessionModel.getId());
} else {
// if the user session is associated with a service account
rootAuthSession = new AuthenticationSessionManager(keycloakSession).createAuthenticationSession(realm, false);
}
}
AuthenticationSessionModel authSession = rootAuthSession.createAuthenticationSession(targetClient);
authSession.setAuthenticatedUser(userSessionModel.getUser());
authSession.setProtocol(OIDCLoginProtocol.LOGIN_PROTOCOL);
authSession.setClientNote(OIDCLoginProtocol.ISSUER, Urls.realmIssuer(keycloakSession.getContext().getUri().getBaseUri(), realm.getName()));
AuthenticationManager.setClientScopesInSession(authSession);
clientSessionCtx = TokenManager.attachAuthenticationSession(keycloakSession, userSessionModel, authSession);
} else {
clientSessionCtx = DefaultClientSessionContext.fromClientSessionScopeParameter(clientSession, keycloakSession);
}
TokenManager tokenManager = request.getTokenManager();
EventBuilder event = request.getEvent();
AccessTokenResponseBuilder responseBuilder = tokenManager.responseBuilder(realm, client, event, keycloakSession, userSessionModel, clientSessionCtx).generateAccessToken();
AccessToken rpt = responseBuilder.getAccessToken();
Authorization authorization = new Authorization();
authorization.setPermissions(entitlements);
rpt.setAuthorization(authorization);
if (accessToken.getSessionState() == null) {
// Skip generating refresh token for accessToken without sessionState claim. This is "stateless" accessToken not pointing to any real persistent userSession
rpt.setSessionState(null);
} else {
if (OIDCAdvancedConfigWrapper.fromClientModel(client).isUseRefreshToken()) {
responseBuilder.generateRefreshToken();
RefreshToken refreshToken = responseBuilder.getRefreshToken();
refreshToken.issuedFor(client.getClientId());
refreshToken.setAuthorization(authorization);
}
}
if (!rpt.hasAudience(targetClient.getClientId())) {
rpt.audience(targetClient.getClientId());
}
return new AuthorizationResponse(responseBuilder.build(), isUpgraded(request, authorization));
}
Aggregations