use of org.keycloak.representations.AccessToken in project keycloak by keycloak.
the class AccessTokenTest method accessTokenRequest.
@Test
public void accessTokenRequest() 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");
assertEquals(200, response.getStatusCode());
Assert.assertThat(response.getExpiresIn(), allOf(greaterThanOrEqualTo(250), lessThanOrEqualTo(300)));
Assert.assertThat(response.getRefreshExpiresIn(), allOf(greaterThanOrEqualTo(1750), lessThanOrEqualTo(1800)));
assertEquals("Bearer", response.getTokenType());
String expectedKid = oauth.doCertsRequest("test").getKeys()[0].getKeyId();
JWSHeader header = new JWSInput(response.getAccessToken()).getHeader();
assertEquals("RS256", header.getAlgorithm().name());
assertEquals("JWT", header.getType());
assertEquals(expectedKid, header.getKeyId());
assertNull(header.getContentType());
header = new JWSInput(response.getIdToken()).getHeader();
assertEquals("RS256", header.getAlgorithm().name());
assertEquals("JWT", header.getType());
assertEquals(expectedKid, header.getKeyId());
assertNull(header.getContentType());
header = new JWSInput(response.getRefreshToken()).getHeader();
assertEquals("HS256", header.getAlgorithm().name());
assertEquals("JWT", header.getType());
assertNull(header.getContentType());
AccessToken token = oauth.verifyToken(response.getAccessToken());
assertEquals(findUserByUsername(adminClient.realm("test"), "test-user@localhost").getId(), token.getSubject());
assertNotEquals("test-user@localhost", token.getSubject());
assertEquals(sessionId, token.getSessionState());
JWSInput idToken = new JWSInput(response.getIdToken());
ObjectMapper mapper = JsonSerialization.mapper;
JsonParser parser = mapper.getFactory().createParser(idToken.readContentAsString());
TreeNode treeNode = mapper.readTree(parser);
String sid = ((TextNode) treeNode.get("sid")).asText();
assertEquals(sessionId, sid);
assertNull(token.getNbf());
assertEquals(0, token.getNotBefore());
assertNotNull(token.getIat());
assertEquals(token.getIat().intValue(), token.getIssuedAt());
assertNotNull(token.getExp());
assertEquals(token.getExp().intValue(), token.getExpiration());
assertEquals(1, token.getRealmAccess().getRoles().size());
assertTrue(token.getRealmAccess().isUserInRole("user"));
assertEquals(1, token.getResourceAccess(oauth.getClientId()).getRoles().size());
assertTrue(token.getResourceAccess(oauth.getClientId()).isUserInRole("customer-user"));
EventRepresentation event = events.expectCodeToToken(codeId, sessionId).assertEvent();
assertEquals(token.getId(), event.getDetails().get(Details.TOKEN_ID));
assertEquals(oauth.parseRefreshToken(response.getRefreshToken()).getId(), event.getDetails().get(Details.REFRESH_TOKEN_ID));
assertEquals(sessionId, token.getSessionState());
}
use of org.keycloak.representations.AccessToken in project keycloak by keycloak.
the class OIDCProtocolMappersTest method testUserRolesMovedFromAccessTokenProperties.
// Test to update protocolMappers to not have roles on the default position (realm_access and resource_access properties)
@Test
@AuthServerContainerExclude(AuthServer.REMOTE)
public void testUserRolesMovedFromAccessTokenProperties() throws Exception {
RealmResource realm = adminClient.realm("test");
ClientScopeResource rolesScope = ApiUtil.findClientScopeByName(realm, OIDCLoginProtocolFactory.ROLES_SCOPE);
// Update builtin protocolMappers to put roles to different position (claim "custom.roles") for both realm and client roles
ProtocolMapperRepresentation realmRolesMapper = null;
ProtocolMapperRepresentation clientRolesMapper = null;
for (ProtocolMapperRepresentation rep : rolesScope.getProtocolMappers().getMappers()) {
if (OIDCLoginProtocolFactory.REALM_ROLES.equals(rep.getName())) {
realmRolesMapper = rep;
} else if (OIDCLoginProtocolFactory.CLIENT_ROLES.equals(rep.getName())) {
clientRolesMapper = rep;
}
}
String realmRolesTokenClaimOrig = realmRolesMapper.getConfig().get(OIDCAttributeMapperHelper.TOKEN_CLAIM_NAME);
String clientRolesTokenClaimOrig = clientRolesMapper.getConfig().get(OIDCAttributeMapperHelper.TOKEN_CLAIM_NAME);
realmRolesMapper.getConfig().put(OIDCAttributeMapperHelper.TOKEN_CLAIM_NAME, "custom.roles");
rolesScope.getProtocolMappers().update(realmRolesMapper.getId(), realmRolesMapper);
clientRolesMapper.getConfig().put(OIDCAttributeMapperHelper.TOKEN_CLAIM_NAME, "custom.roles");
rolesScope.getProtocolMappers().update(clientRolesMapper.getId(), clientRolesMapper);
// Create some hardcoded role mapper
Response resp = rolesScope.getProtocolMappers().createMapper(createHardcodedRole("hard-realm", "hardcoded"));
String hardcodedMapperId = ApiUtil.getCreatedId(resp);
resp.close();
try {
OAuthClient.AccessTokenResponse response = browserLogin("password", "test-user@localhost", "password");
AccessToken accessToken = oauth.verifyToken(response.getAccessToken());
// Assert roles are not on their original positions
Assert.assertNull(accessToken.getRealmAccess());
Assert.assertTrue(accessToken.getResourceAccess().isEmpty());
// KEYCLOAK-8481 Assert that accessToken JSON doesn't have "realm_access" or "resource_access" fields in it
String accessTokenJson = new String(new JWSInput(response.getAccessToken()).getContent(), StandardCharsets.UTF_8);
Assert.assertFalse(accessTokenJson.contains("realm_access"));
Assert.assertFalse(accessTokenJson.contains("resource_access"));
// Assert both realm and client roles on the new position. Hardcoded role should be here as well
Map<String, Object> cst1 = (Map<String, Object>) accessToken.getOtherClaims().get("custom");
List<String> roles = (List<String>) cst1.get("roles");
Assert.assertNames(roles, "offline_access", "user", "customer-user", "hardcoded", AccountRoles.VIEW_PROFILE, AccountRoles.MANAGE_ACCOUNT, AccountRoles.MANAGE_ACCOUNT_LINKS);
// Assert audience
Assert.assertNames(Arrays.asList(accessToken.getAudience()), "account");
} finally {
// Revert
rolesScope.getProtocolMappers().delete(hardcodedMapperId);
realmRolesMapper.getConfig().put(OIDCAttributeMapperHelper.TOKEN_CLAIM_NAME, realmRolesTokenClaimOrig);
rolesScope.getProtocolMappers().update(realmRolesMapper.getId(), realmRolesMapper);
clientRolesMapper.getConfig().put(OIDCAttributeMapperHelper.TOKEN_CLAIM_NAME, clientRolesTokenClaimOrig);
rolesScope.getProtocolMappers().update(clientRolesMapper.getId(), clientRolesMapper);
}
}
use of org.keycloak.representations.AccessToken in project keycloak by keycloak.
the class OIDCProtocolMappersTest method executeTokenMappersOnDynamicScopes.
@Test
@EnableFeature(value = Profile.Feature.DYNAMIC_SCOPES, skipRestart = true)
public void executeTokenMappersOnDynamicScopes() {
ClientResource clientResource = findClientResourceByClientId(adminClient.realm("test"), "test-app");
ClientScopeRepresentation scopeRep = new ClientScopeRepresentation();
scopeRep.setName("dyn-scope-with-mapper");
scopeRep.setProtocol("openid-connect");
scopeRep.setAttributes(new HashMap<String, String>() {
{
put(ClientScopeModel.IS_DYNAMIC_SCOPE, "true");
put(ClientScopeModel.DYNAMIC_SCOPE_REGEXP, "dyn-scope-with-mapper:*");
}
});
// create the attribute mapper
ProtocolMapperRepresentation protocolMapperRepresentation = createHardcodedClaim("dynamic-scope-hardcoded-mapper", "hardcoded-foo", "hardcoded-bar", "String", true, true);
scopeRep.setProtocolMappers(Collections.singletonList(protocolMapperRepresentation));
try (Response resp = adminClient.realm("test").clientScopes().create(scopeRep)) {
assertEquals(201, resp.getStatus());
String clientScopeId = ApiUtil.getCreatedId(resp);
getCleanup().addClientScopeId(clientScopeId);
clientResource.addOptionalClientScope(clientScopeId);
}
oauth.scope("openid dyn-scope-with-mapper:value");
OAuthClient.AccessTokenResponse response = browserLogin("password", "test-user@localhost", "password");
IDToken idToken = oauth.verifyIDToken(response.getIdToken());
AccessToken accessToken = oauth.verifyToken(response.getAccessToken());
assertNotNull(idToken.getOtherClaims());
assertNotNull(idToken.getOtherClaims().get("hardcoded-foo"));
assertTrue(idToken.getOtherClaims().get("hardcoded-foo") instanceof String);
assertEquals("hardcoded-bar", idToken.getOtherClaims().get("hardcoded-foo"));
assertNotNull(accessToken.getOtherClaims());
assertNotNull(accessToken.getOtherClaims().get("hardcoded-foo"));
assertTrue(accessToken.getOtherClaims().get("hardcoded-foo") instanceof String);
assertEquals("hardcoded-bar", accessToken.getOtherClaims().get("hardcoded-foo"));
}
use of org.keycloak.representations.AccessToken in project keycloak by keycloak.
the class RefreshTokenTest method refreshTokenRequest.
@Test
public void refreshTokenRequest() throws Exception {
oauth.nonce("123456");
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 tokenResponse = oauth.doAccessTokenRequest(code, "password");
AccessToken token = oauth.verifyToken(tokenResponse.getAccessToken());
assertEquals("123456", token.getNonce());
String refreshTokenString = tokenResponse.getRefreshToken();
RefreshToken refreshToken = oauth.parseRefreshToken(refreshTokenString);
EventRepresentation tokenEvent = events.expectCodeToToken(codeId, sessionId).assertEvent();
assertNotNull(refreshTokenString);
assertEquals("Bearer", tokenResponse.getTokenType());
Assert.assertThat(token.getExpiration() - getCurrentTime(), allOf(greaterThanOrEqualTo(200), lessThanOrEqualTo(350)));
int actual = refreshToken.getExpiration() - getCurrentTime();
Assert.assertThat(actual, allOf(greaterThanOrEqualTo(1799 - ALLOWED_CLOCK_SKEW), lessThanOrEqualTo(1800 + ALLOWED_CLOCK_SKEW)));
assertEquals(sessionId, refreshToken.getSessionState());
setTimeOffset(2);
OAuthClient.AccessTokenResponse response = oauth.doRefreshTokenRequest(refreshTokenString, "password");
AccessToken refreshedToken = oauth.verifyToken(response.getAccessToken());
RefreshToken refreshedRefreshToken = oauth.parseRefreshToken(response.getRefreshToken());
assertEquals(200, response.getStatusCode());
assertEquals(sessionId, refreshedToken.getSessionState());
assertEquals(sessionId, refreshedRefreshToken.getSessionState());
Assert.assertThat(response.getExpiresIn(), allOf(greaterThanOrEqualTo(250), lessThanOrEqualTo(300)));
Assert.assertThat(refreshedToken.getExpiration() - getCurrentTime(), allOf(greaterThanOrEqualTo(250 - ALLOWED_CLOCK_SKEW), lessThanOrEqualTo(300 + ALLOWED_CLOCK_SKEW)));
Assert.assertThat(refreshedToken.getExpiration() - token.getExpiration(), allOf(greaterThanOrEqualTo(1), lessThanOrEqualTo(10)));
Assert.assertThat(refreshedRefreshToken.getExpiration() - refreshToken.getExpiration(), allOf(greaterThanOrEqualTo(1), lessThanOrEqualTo(10)));
// "test-app" should not be an audience in the refresh token
assertEquals("test-app", refreshedRefreshToken.getIssuedFor());
Assert.assertFalse(refreshedRefreshToken.hasAudience("test-app"));
Assert.assertNotEquals(token.getId(), refreshedToken.getId());
Assert.assertNotEquals(refreshToken.getId(), refreshedRefreshToken.getId());
assertEquals("Bearer", response.getTokenType());
assertEquals(findUserByUsername(adminClient.realm("test"), "test-user@localhost").getId(), refreshedToken.getSubject());
Assert.assertNotEquals("test-user@localhost", refreshedToken.getSubject());
assertTrue(refreshedToken.getRealmAccess().isUserInRole("user"));
assertEquals(1, refreshedToken.getResourceAccess(oauth.getClientId()).getRoles().size());
assertTrue(refreshedToken.getResourceAccess(oauth.getClientId()).isUserInRole("customer-user"));
EventRepresentation refreshEvent = events.expectRefresh(tokenEvent.getDetails().get(Details.REFRESH_TOKEN_ID), sessionId).assertEvent();
Assert.assertNotEquals(tokenEvent.getDetails().get(Details.TOKEN_ID), refreshEvent.getDetails().get(Details.TOKEN_ID));
Assert.assertNotEquals(tokenEvent.getDetails().get(Details.REFRESH_TOKEN_ID), refreshEvent.getDetails().get(Details.UPDATED_REFRESH_TOKEN_ID));
assertEquals("123456", refreshedToken.getNonce());
setTimeOffset(0);
}
use of org.keycloak.representations.AccessToken in project keycloak by keycloak.
the class RefreshTokenTest method testUserSessionRefreshAndIdle.
@Test
public void testUserSessionRefreshAndIdle() throws Exception {
oauth.doLogin("test-user@localhost", "password");
EventRepresentation loginEvent = events.expectLogin().assertEvent();
String sessionId = loginEvent.getSessionId();
String code = oauth.getCurrentQuery().get(OAuth2Constants.CODE);
OAuthClient.AccessTokenResponse tokenResponse = oauth.doAccessTokenRequest(code, "password");
events.poll();
String refreshId = oauth.parseRefreshToken(tokenResponse.getRefreshToken()).getId();
int last = testingClient.testing().getLastSessionRefresh("test", sessionId, false);
setTimeOffset(2);
tokenResponse = oauth.doRefreshTokenRequest(tokenResponse.getRefreshToken(), "password");
AccessToken refreshedToken = oauth.verifyToken(tokenResponse.getAccessToken());
RefreshToken refreshedRefreshToken = oauth.parseRefreshToken(tokenResponse.getRefreshToken());
assertEquals(200, tokenResponse.getStatusCode());
int next = testingClient.testing().getLastSessionRefresh("test", sessionId, false);
Assert.assertNotEquals(last, next);
RealmResource realmResource = adminClient.realm("test");
int lastAccessTokenLifespan = realmResource.toRepresentation().getAccessTokenLifespan();
int originalIdle = realmResource.toRepresentation().getSsoSessionIdleTimeout();
try {
RealmManager.realm(realmResource).accessTokenLifespan(100000);
setTimeOffset(4);
tokenResponse = oauth.doRefreshTokenRequest(tokenResponse.getRefreshToken(), "password");
next = testingClient.testing().getLastSessionRefresh("test", sessionId, false);
// lastSEssionRefresh should be updated because access code lifespan is higher than sso idle timeout
Assert.assertThat(next, allOf(greaterThan(last), lessThan(last + 50)));
RealmManager.realm(realmResource).ssoSessionIdleTimeout(1);
events.clear();
// Needs to add some additional time due the tollerance allowed by IDLE_TIMEOUT_WINDOW_SECONDS
setTimeOffset(6 + SessionTimeoutHelper.IDLE_TIMEOUT_WINDOW_SECONDS);
tokenResponse = oauth.doRefreshTokenRequest(tokenResponse.getRefreshToken(), "password");
// test idle timeout
assertEquals(400, tokenResponse.getStatusCode());
assertNull(tokenResponse.getAccessToken());
assertNull(tokenResponse.getRefreshToken());
events.expectRefresh(refreshId, sessionId).error(Errors.INVALID_TOKEN);
} finally {
RealmManager.realm(realmResource).ssoSessionIdleTimeout(originalIdle).accessTokenLifespan(lastAccessTokenLifespan);
events.clear();
setTimeOffset(0);
}
}
Aggregations