Search in sources :

Example 6 with UserInfo

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;
}
Also used : UserInfo(org.keycloak.representations.UserInfo)

Example 7 with 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();
    }
}
Also used : Response(javax.ws.rs.core.Response) OIDCClientRepresentation(org.keycloak.representations.oidc.OIDCClientRepresentation) OAuthClient(org.keycloak.testsuite.util.OAuthClient) AccessToken(org.keycloak.representations.AccessToken) UserInfo(org.keycloak.representations.UserInfo) Client(javax.ws.rs.client.Client) OAuthClient(org.keycloak.testsuite.util.OAuthClient) UserRepresentation(org.keycloak.representations.idm.UserRepresentation) Test(org.junit.Test)

Example 8 with UserInfo

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);
    }
}
Also used : RefreshToken(org.keycloak.representations.RefreshToken) OAuthClient(org.keycloak.testsuite.util.OAuthClient) EventRepresentation(org.keycloak.representations.idm.EventRepresentation) JsonNode(com.fasterxml.jackson.databind.JsonNode) UserInfo(org.keycloak.representations.UserInfo) AbstractKeycloakTest(org.keycloak.testsuite.AbstractKeycloakTest) Test(org.junit.Test)

Example 9 with UserInfo

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();
}
Also used : Response(javax.ws.rs.core.Response) OAuthClient(org.keycloak.testsuite.util.OAuthClient) AccessToken(org.keycloak.representations.AccessToken) ProtocolMapperRepresentation(org.keycloak.representations.idm.ProtocolMapperRepresentation) UserResource(org.keycloak.admin.client.resource.UserResource) ClientResource(org.keycloak.admin.client.resource.ClientResource) IDToken(org.keycloak.representations.IDToken) UserInfo(org.keycloak.representations.UserInfo) OAuthClient(org.keycloak.testsuite.util.OAuthClient) Client(javax.ws.rs.client.Client) UserRepresentation(org.keycloak.representations.idm.UserRepresentation) ClientRepresentation(org.keycloak.representations.idm.ClientRepresentation) AuthServerContainerExclude(org.keycloak.testsuite.arquillian.annotation.AuthServerContainerExclude) AbstractKeycloakTest(org.keycloak.testsuite.AbstractKeycloakTest) Test(org.junit.Test)

Example 10 with UserInfo

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);
    }
}
Also used : AccessTokenResponse(org.keycloak.representations.AccessTokenResponse) Response(javax.ws.rs.core.Response) ClientResource(org.keycloak.admin.client.resource.ClientResource) UserInfo(org.keycloak.representations.UserInfo) JWSInput(org.keycloak.jose.jws.JWSInput) OAuthClient(org.keycloak.testsuite.util.OAuthClient) Client(javax.ws.rs.client.Client) AccessTokenResponse(org.keycloak.representations.AccessTokenResponse) URI(java.net.URI) ClientRepresentation(org.keycloak.representations.idm.ClientRepresentation)

Aggregations

UserInfo (org.keycloak.representations.UserInfo)12 OAuthClient (org.keycloak.testsuite.util.OAuthClient)11 Test (org.junit.Test)10 AbstractKeycloakTest (org.keycloak.testsuite.AbstractKeycloakTest)8 Client (javax.ws.rs.client.Client)7 Response (javax.ws.rs.core.Response)7 ClientResource (org.keycloak.admin.client.resource.ClientResource)4 AccessTokenResponse (org.keycloak.representations.AccessTokenResponse)4 AccessToken (org.keycloak.representations.AccessToken)3 ClientRepresentation (org.keycloak.representations.idm.ClientRepresentation)3 URI (java.net.URI)2 JWSInput (org.keycloak.jose.jws.JWSInput)2 IDToken (org.keycloak.representations.IDToken)2 EventRepresentation (org.keycloak.representations.idm.EventRepresentation)2 UserRepresentation (org.keycloak.representations.idm.UserRepresentation)2 JsonNode (com.fasterxml.jackson.databind.JsonNode)1 PublicKey (java.security.PublicKey)1 HashMap (java.util.HashMap)1 HttpResponse (org.apache.http.HttpResponse)1 CloseableHttpResponse (org.apache.http.client.methods.CloseableHttpResponse)1