use of org.keycloak.representations.UserInfo in project keycloak by keycloak.
the class UserInfoClientUtil method testSuccessfulUserInfoResponse.
public static UserInfo testSuccessfulUserInfoResponse(Response response, String userId, String expectedUsername, String expectedEmail) {
Assert.assertEquals(Response.Status.OK.getStatusCode(), response.getStatus());
Assert.assertEquals(response.getHeaderString(HttpHeaders.CONTENT_TYPE), MediaType.APPLICATION_JSON);
UserInfo userInfo = response.readEntity(UserInfo.class);
response.close();
Assert.assertNotNull(userInfo);
Assert.assertNotNull(userInfo.getSubject());
if (userId != null) {
Assert.assertEquals(userId, userInfo.getSubject());
}
Assert.assertEquals(expectedEmail, userInfo.getEmail());
Assert.assertEquals(expectedUsername, userInfo.getPreferredUsername());
return userInfo;
}
use of org.keycloak.representations.UserInfo in project keycloak by keycloak.
the class OIDCPairwiseClientRegistrationTest method loginUserToPairwiseClient.
@Test
public void loginUserToPairwiseClient() throws Exception {
// Create public client
OIDCClientRepresentation publicClient = create();
// Login to public client
oauth.clientId(publicClient.getClientId());
OAuthClient.AuthorizationEndpointResponse loginResponse = oauth.doLogin("test-user@localhost", "password");
OAuthClient.AccessTokenResponse accessTokenResponse = oauth.doAccessTokenRequest(loginResponse.getCode(), publicClient.getClientSecret());
AccessToken accessToken = oauth.verifyToken(accessTokenResponse.getAccessToken());
Assert.assertEquals("test-user", accessToken.getPreferredUsername());
Assert.assertEquals("test-user@localhost", accessToken.getEmail());
String tokenUserId = accessToken.getSubject();
// Assert public client has same subject like userId
UserRepresentation user = realmsResouce().realm("test").users().search("test-user", 0, 1).get(0);
Assert.assertEquals(user.getId(), tokenUserId);
// Create pairwise client
OIDCClientRepresentation clientRep = createRep();
clientRep.setSubjectType("pairwise");
OIDCClientRepresentation pairwiseClient = reg.oidc().create(clientRep);
Assert.assertEquals("pairwise", pairwiseClient.getSubjectType());
// Login to pairwise client
oauth.clientId(pairwiseClient.getClientId());
oauth.openLoginForm();
loginResponse = new OAuthClient.AuthorizationEndpointResponse(oauth);
accessTokenResponse = oauth.doAccessTokenRequest(loginResponse.getCode(), pairwiseClient.getClientSecret());
// Assert token payloads don't contain more than one "sub"
String accessTokenPayload = getPayload(accessTokenResponse.getAccessToken());
Assert.assertEquals(1, StringUtils.countMatches(accessTokenPayload, "\"sub\""));
String idTokenPayload = getPayload(accessTokenResponse.getIdToken());
Assert.assertEquals(1, StringUtils.countMatches(idTokenPayload, "\"sub\""));
String refreshTokenPayload = getPayload(accessTokenResponse.getRefreshToken());
Assert.assertEquals(1, StringUtils.countMatches(refreshTokenPayload, "\"sub\""));
accessToken = oauth.verifyToken(accessTokenResponse.getAccessToken());
Assert.assertEquals("test-user", accessToken.getPreferredUsername());
Assert.assertEquals("test-user@localhost", accessToken.getEmail());
// Assert pairwise client has different subject than userId
String pairwiseUserId = accessToken.getSubject();
Assert.assertNotEquals(pairwiseUserId, user.getId());
// Send request to userInfo endpoint
Client jaxrsClient = AdminClientUtil.createResteasyClient();
try {
// Check that userInfo contains pairwise subjectId as well
Response userInfoResponse = UserInfoClientUtil.executeUserInfoRequest_getMethod(jaxrsClient, accessTokenResponse.getAccessToken());
UserInfo userInfo = UserInfoClientUtil.testSuccessfulUserInfoResponse(userInfoResponse, "test-user", "test-user@localhost");
String userInfoSubId = userInfo.getSubject();
Assert.assertEquals(pairwiseUserId, userInfoSubId);
} finally {
jaxrsClient.close();
}
}
use of org.keycloak.representations.UserInfo 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.UserInfo in project keycloak by keycloak.
the class OIDCProtocolMappersTest method testTokenPropertiesMapping.
@Test
@AuthServerContainerExclude(AuthServer.REMOTE)
public void testTokenPropertiesMapping() throws Exception {
UserResource userResource = findUserByUsernameId(adminClient.realm("test"), "test-user@localhost");
UserRepresentation user = userResource.toRepresentation();
user.singleAttribute("userid", "123456789");
user.getAttributes().put("useraud", Arrays.asList("test-app", "other"));
userResource.update(user);
// create a user attr mapping for some claims that exist as properties in the tokens
ClientResource app = findClientResourceByClientId(adminClient.realm("test"), "test-app");
app.getProtocolMappers().createMapper(createClaimMapper("userid-as-sub", "userid", "sub", "String", true, true, false)).close();
app.getProtocolMappers().createMapper(createClaimMapper("useraud", "useraud", "aud", "String", true, true, true)).close();
app.getProtocolMappers().createMapper(createHardcodedClaim("website-hardcoded", "website", "http://localhost", "String", true, true)).close();
app.getProtocolMappers().createMapper(createHardcodedClaim("iat-hardcoded", "iat", "123", "long", true, false)).close();
// login
OAuthClient.AccessTokenResponse response = browserLogin("password", "test-user@localhost", "password");
// assert mappers work as expected
IDToken idToken = oauth.verifyIDToken(response.getIdToken());
assertEquals(user.firstAttribute("userid"), idToken.getSubject());
assertEquals("http://localhost", idToken.getWebsite());
assertNotNull(idToken.getAudience());
assertThat(Arrays.asList(idToken.getAudience()), hasItems("test-app", "other"));
AccessToken accessToken = oauth.verifyToken(response.getAccessToken());
assertEquals(user.firstAttribute("userid"), accessToken.getSubject());
assertEquals("http://localhost", accessToken.getWebsite());
assertNotNull(accessToken.getAudience());
assertThat(Arrays.asList(accessToken.getAudience()), hasItems("test-app", "other"));
// iat should not be modified
assertNotEquals(123L, accessToken.getIat().longValue());
// assert that tokens are also OK in the UserInfo response (hardcoded mappers in IDToken are in UserInfo)
Client client = AdminClientUtil.createResteasyClient();
try {
Response userInfoResponse = UserInfoClientUtil.executeUserInfoRequest_getMethod(client, response.getAccessToken());
UserInfo userInfo = userInfoResponse.readEntity(UserInfo.class);
assertEquals(user.firstAttribute("userid"), userInfo.getSubject());
assertEquals(user.getEmail(), userInfo.getEmail());
assertEquals(user.getUsername(), userInfo.getPreferredUsername());
assertEquals(user.getLastName(), userInfo.getFamilyName());
assertEquals(user.getFirstName(), userInfo.getGivenName());
assertEquals("http://localhost", userInfo.getWebsite());
assertNotNull(accessToken.getAudience());
assertThat(Arrays.asList(accessToken.getAudience()), hasItems("test-app", "other"));
} finally {
client.close();
}
// logout
oauth.openLogout();
// undo mappers
app = findClientByClientId(adminClient.realm("test"), "test-app");
ClientRepresentation clientRepresentation = app.toRepresentation();
for (ProtocolMapperRepresentation model : clientRepresentation.getProtocolMappers()) {
if (model.getName().equals("userid-as-sub") || model.getName().equals("website-hardcoded") || model.getName().equals("iat-hardcoded") || model.getName().equals("useraud")) {
app.getProtocolMappers().delete(model.getId());
}
}
events.clear();
}
use of org.keycloak.representations.UserInfo in project keycloak by keycloak.
the class UserInfoTest method testSuccessSignedResponse.
private void testSuccessSignedResponse(Algorithm sigAlg) throws Exception {
try {
// Require signed userInfo request
ClientResource clientResource = ApiUtil.findClientByClientId(adminClient.realm("test"), "test-app");
ClientRepresentation clientRep = clientResource.toRepresentation();
OIDCAdvancedConfigWrapper.fromClientRepresentation(clientRep).setUserInfoSignedResponseAlg(sigAlg);
clientResource.update(clientRep);
// test signed response
Client client = AdminClientUtil.createResteasyClient();
try {
AccessTokenResponse accessTokenResponse = executeGrantAccessTokenRequest(client);
Response response = UserInfoClientUtil.executeUserInfoRequest_getMethod(client, accessTokenResponse.getToken());
events.expect(EventType.USER_INFO_REQUEST).session(Matchers.notNullValue(String.class)).detail(Details.AUTH_METHOD, Details.VALIDATE_ACCESS_TOKEN).detail(Details.USERNAME, "test-user@localhost").detail(Details.SIGNATURE_REQUIRED, "true").detail(Details.SIGNATURE_ALGORITHM, sigAlg.toString()).assertEvent();
Assert.assertEquals(200, response.getStatus());
Assert.assertEquals(response.getHeaderString(HttpHeaders.CONTENT_TYPE), MediaType.APPLICATION_JWT);
String signedResponse = response.readEntity(String.class);
response.close();
JWSInput jwsInput = new JWSInput(signedResponse);
assertEquals(sigAlg.toString(), jwsInput.getHeader().getAlgorithm().name());
UserInfo userInfo = JsonSerialization.readValue(jwsInput.getContent(), UserInfo.class);
Assert.assertNotNull(userInfo);
Assert.assertNotNull(userInfo.getSubject());
Assert.assertEquals("test-user@localhost", userInfo.getEmail());
Assert.assertEquals("test-user@localhost", userInfo.getPreferredUsername());
Assert.assertTrue(userInfo.hasAudience("test-app"));
String expectedIssuer = Urls.realmIssuer(new URI(AUTH_SERVER_ROOT), "test");
Assert.assertEquals(expectedIssuer, userInfo.getIssuer());
} finally {
client.close();
}
// Revert signed userInfo request
OIDCAdvancedConfigWrapper.fromClientRepresentation(clientRep).setUserInfoSignedResponseAlg(null);
clientResource.update(clientRep);
} finally {
TokenSignatureUtil.changeRealmTokenSignatureProvider(adminClient, org.keycloak.crypto.Algorithm.RS256);
}
}
Aggregations