Search in sources :

Example 16 with AccessTokenResponse

use of org.keycloak.representations.AccessTokenResponse in project keycloak by keycloak.

the class TokenEndpoint method clientCredentialsGrant.

public Response clientCredentialsGrant() {
    if (client.isBearerOnly()) {
        event.error(Errors.INVALID_CLIENT);
        throw new CorsErrorResponseException(cors, OAuthErrorException.UNAUTHORIZED_CLIENT, "Bearer-only client not allowed to retrieve service account", Response.Status.UNAUTHORIZED);
    }
    if (client.isPublicClient()) {
        event.error(Errors.INVALID_CLIENT);
        throw new CorsErrorResponseException(cors, OAuthErrorException.UNAUTHORIZED_CLIENT, "Public client not allowed to retrieve service account", Response.Status.UNAUTHORIZED);
    }
    if (!client.isServiceAccountsEnabled()) {
        event.error(Errors.INVALID_CLIENT);
        throw new CorsErrorResponseException(cors, OAuthErrorException.UNAUTHORIZED_CLIENT, "Client not enabled to retrieve service account", Response.Status.UNAUTHORIZED);
    }
    UserModel clientUser = session.users().getServiceAccount(client);
    if (clientUser == null || client.getProtocolMapperByName(OIDCLoginProtocol.LOGIN_PROTOCOL, ServiceAccountConstants.CLIENT_ID_PROTOCOL_MAPPER) == null) {
        // May need to handle bootstrap here as well
        logger.debugf("Service account user for client '%s' not found or default protocol mapper for service account not found. Creating now", client.getClientId());
        new ClientManager(new RealmManager(session)).enableServiceAccount(client);
        clientUser = session.users().getServiceAccount(client);
    }
    String clientUsername = clientUser.getUsername();
    event.detail(Details.USERNAME, clientUsername);
    event.user(clientUser);
    if (!clientUser.isEnabled()) {
        event.error(Errors.USER_DISABLED);
        throw new CorsErrorResponseException(cors, OAuthErrorException.INVALID_REQUEST, "User '" + clientUsername + "' disabled", Response.Status.UNAUTHORIZED);
    }
    String scope = getRequestedScopes();
    RootAuthenticationSessionModel rootAuthSession = new AuthenticationSessionManager(session).createAuthenticationSession(realm, false);
    AuthenticationSessionModel authSession = rootAuthSession.createAuthenticationSession(client);
    authSession.setAuthenticatedUser(clientUser);
    authSession.setProtocol(OIDCLoginProtocol.LOGIN_PROTOCOL);
    authSession.setClientNote(OIDCLoginProtocol.ISSUER, Urls.realmIssuer(session.getContext().getUri().getBaseUri(), realm.getName()));
    authSession.setClientNote(OIDCLoginProtocol.SCOPE_PARAM, scope);
    // persisting of userSession by default
    UserSessionModel.SessionPersistenceState sessionPersistenceState = UserSessionModel.SessionPersistenceState.PERSISTENT;
    boolean useRefreshToken = OIDCAdvancedConfigWrapper.fromClientModel(client).isUseRefreshTokenForClientCredentialsGrant();
    if (!useRefreshToken) {
        // we don't want to store a session hence we mark it as transient, see KEYCLOAK-9551
        sessionPersistenceState = UserSessionModel.SessionPersistenceState.TRANSIENT;
    }
    UserSessionModel userSession = session.sessions().createUserSession(authSession.getParentSession().getId(), realm, clientUser, clientUsername, clientConnection.getRemoteAddr(), ServiceAccountConstants.CLIENT_AUTH, false, null, null, sessionPersistenceState);
    event.session(userSession);
    AuthenticationManager.setClientScopesInSession(authSession);
    ClientSessionContext clientSessionCtx = TokenManager.attachAuthenticationSession(session, userSession, authSession);
    // Notes about client details
    userSession.setNote(ServiceAccountConstants.CLIENT_ID, client.getClientId());
    userSession.setNote(ServiceAccountConstants.CLIENT_HOST, clientConnection.getRemoteHost());
    userSession.setNote(ServiceAccountConstants.CLIENT_ADDRESS, clientConnection.getRemoteAddr());
    try {
        session.clientPolicy().triggerOnEvent(new ServiceAccountTokenRequestContext(formParams, clientSessionCtx.getClientSession()));
    } catch (ClientPolicyException cpe) {
        event.error(cpe.getError());
        throw new CorsErrorResponseException(cors, cpe.getError(), cpe.getErrorDetail(), Response.Status.BAD_REQUEST);
    }
    updateUserSessionFromClientAuth(userSession);
    TokenManager.AccessTokenResponseBuilder responseBuilder = tokenManager.responseBuilder(realm, client, event, session, userSession, clientSessionCtx).generateAccessToken();
    // Make refresh token generation optional, see KEYCLOAK-9551
    if (useRefreshToken) {
        responseBuilder = responseBuilder.generateRefreshToken();
    } else {
        responseBuilder.getAccessToken().setSessionState(null);
    }
    checkMtlsHoKToken(responseBuilder, useRefreshToken);
    String scopeParam = clientSessionCtx.getClientSession().getNote(OAuth2Constants.SCOPE);
    if (TokenUtil.isOIDCRequest(scopeParam)) {
        responseBuilder.generateIDToken().generateAccessTokenHash();
    }
    // TODO : do the same as codeToToken()
    AccessTokenResponse res = responseBuilder.build();
    event.success();
    return cors.builder(Response.ok(res, MediaType.APPLICATION_JSON_TYPE)).build();
}
Also used : AuthenticationSessionModel(org.keycloak.sessions.AuthenticationSessionModel) RootAuthenticationSessionModel(org.keycloak.sessions.RootAuthenticationSessionModel) UserSessionModel(org.keycloak.models.UserSessionModel) RealmManager(org.keycloak.services.managers.RealmManager) ServiceAccountTokenRequestContext(org.keycloak.services.clientpolicy.context.ServiceAccountTokenRequestContext) ClientPolicyException(org.keycloak.services.clientpolicy.ClientPolicyException) UserModel(org.keycloak.models.UserModel) AuthenticationSessionManager(org.keycloak.services.managers.AuthenticationSessionManager) DefaultClientSessionContext(org.keycloak.services.util.DefaultClientSessionContext) ClientSessionContext(org.keycloak.models.ClientSessionContext) ClientManager(org.keycloak.services.managers.ClientManager) RootAuthenticationSessionModel(org.keycloak.sessions.RootAuthenticationSessionModel) CorsErrorResponseException(org.keycloak.services.CorsErrorResponseException) TokenManager(org.keycloak.protocol.oidc.TokenManager) AccessTokenResponse(org.keycloak.representations.AccessTokenResponse)

Example 17 with AccessTokenResponse

use of org.keycloak.representations.AccessTokenResponse in project keycloak by keycloak.

the class AdminConsolePermissionsCalculatedTest method changeRealmTokenAlgorithm.

@Test
public void changeRealmTokenAlgorithm() throws Exception {
    try (Keycloak adminClient = AdminClientUtil.createAdminClient(suiteContext.isAdapterCompatTesting(), suiteContext.getAuthServerInfo().getContextRoot().toString());
        Creator c = Creator.create(adminClient, RealmBuilder.create().name(REALM_NAME).build())) {
        AccessTokenResponse accessToken = adminClient.tokenManager().getAccessToken();
        assertNotNull(adminClient.realms().findAll());
        String whoAmiUrl = suiteContext.getAuthServerInfo().getContextRoot().toString() + "/auth/admin/master/console/whoami";
        JsonNode jsonNode = SimpleHttp.doGet(whoAmiUrl, client).auth(accessToken.getToken()).asJson();
        assertTrue("Permissions for " + Config.getAdminRealm() + " realm.", jsonNode.at("/realm_access/" + Config.getAdminRealm()).isArray());
        assertTrue("Permissions for " + REALM_NAME + " realm.", jsonNode.at("/realm_access/" + REALM_NAME).isArray());
    }
}
Also used : JsonNode(com.fasterxml.jackson.databind.JsonNode) Creator(org.keycloak.testsuite.updaters.Creator) Keycloak(org.keycloak.admin.client.Keycloak) AccessTokenResponse(org.keycloak.representations.AccessTokenResponse) Test(org.junit.Test) AbstractKeycloakTest(org.keycloak.testsuite.AbstractKeycloakTest)

Example 18 with AccessTokenResponse

use of org.keycloak.representations.AccessTokenResponse in project keycloak by keycloak.

the class AdminSignatureAlgorithmTest method changeRealmTokenAlgorithm.

@Test
public void changeRealmTokenAlgorithm() throws Exception {
    String defaultSignatureAlgorithm = adminClient.realm("master").toRepresentation().getDefaultSignatureAlgorithm();
    TokenSignatureUtil.changeRealmTokenSignatureProvider("master", adminClient, Algorithm.ES256);
    try (Keycloak adminClient = AdminClientUtil.createAdminClient(suiteContext.isAdapterCompatTesting(), suiteContext.getAuthServerInfo().getContextRoot().toString())) {
        AccessTokenResponse accessToken = adminClient.tokenManager().getAccessToken();
        TokenVerifier<AccessToken> verifier = TokenVerifier.create(accessToken.getToken(), AccessToken.class);
        assertEquals(Algorithm.ES256, verifier.getHeader().getAlgorithm().name());
        assertNotNull(adminClient.realms().findAll());
        String whoAmiUrl = suiteContext.getAuthServerInfo().getContextRoot().toString() + "/auth/admin/master/console/whoami";
        JsonNode jsonNode = SimpleHttp.doGet(whoAmiUrl, client).auth(accessToken.getToken()).asJson();
        assertNotNull(jsonNode.get("realm"));
        assertNotNull(jsonNode.get("userId"));
    } finally {
        TokenSignatureUtil.changeRealmTokenSignatureProvider("master", adminClient, defaultSignatureAlgorithm);
    }
}
Also used : AccessToken(org.keycloak.representations.AccessToken) JsonNode(com.fasterxml.jackson.databind.JsonNode) Keycloak(org.keycloak.admin.client.Keycloak) AccessTokenResponse(org.keycloak.representations.AccessTokenResponse) Test(org.junit.Test) AbstractKeycloakTest(org.keycloak.testsuite.AbstractKeycloakTest)

Example 19 with AccessTokenResponse

use of org.keycloak.representations.AccessTokenResponse in project keycloak by keycloak.

the class ClientTokenExchangeTest method testImpersonation.

@Test
@UncaughtServerErrorExpected
public void testImpersonation() throws Exception {
    testingClient.server().run(ClientTokenExchangeTest::setupRealm);
    oauth.realm(TEST);
    oauth.clientId("client-exchanger");
    Client httpClient = AdminClientUtil.createResteasyClient();
    WebTarget exchangeUrl = httpClient.target(OAuthClient.AUTH_SERVER_ROOT).path("/realms").path(TEST).path("protocol/openid-connect/token");
    System.out.println("Exchange url: " + exchangeUrl.getUri().toString());
    OAuthClient.AccessTokenResponse tokenResponse = oauth.doGrantAccessTokenRequest("secret", "user", "password");
    String accessToken = tokenResponse.getAccessToken();
    TokenVerifier<AccessToken> accessTokenVerifier = TokenVerifier.create(accessToken, AccessToken.class);
    AccessToken token = accessTokenVerifier.parse().getToken();
    Assert.assertEquals(token.getPreferredUsername(), "user");
    Assert.assertTrue(token.getRealmAccess() == null || !token.getRealmAccess().isUserInRole("example"));
    // client-exchanger can impersonate from token "user" to user "impersonated-user"
    {
        Response response = exchangeUrl.request().header(HttpHeaders.AUTHORIZATION, BasicAuthHelper.createHeader("client-exchanger", "secret")).post(Entity.form(new Form().param(OAuth2Constants.GRANT_TYPE, OAuth2Constants.TOKEN_EXCHANGE_GRANT_TYPE).param(OAuth2Constants.SUBJECT_TOKEN, accessToken).param(OAuth2Constants.SUBJECT_TOKEN_TYPE, OAuth2Constants.ACCESS_TOKEN_TYPE).param(OAuth2Constants.REQUESTED_SUBJECT, "impersonated-user")));
        org.junit.Assert.assertEquals(200, response.getStatus());
        AccessTokenResponse accessTokenResponse = response.readEntity(AccessTokenResponse.class);
        response.close();
        String exchangedTokenString = accessTokenResponse.getToken();
        TokenVerifier<AccessToken> verifier = TokenVerifier.create(exchangedTokenString, AccessToken.class);
        AccessToken exchangedToken = verifier.parse().getToken();
        Assert.assertEquals("client-exchanger", exchangedToken.getIssuedFor());
        Assert.assertNull(exchangedToken.getAudience());
        Assert.assertEquals("impersonated-user", exchangedToken.getPreferredUsername());
        Assert.assertNull(exchangedToken.getRealmAccess());
        Object impersonatorRaw = exchangedToken.getOtherClaims().get("impersonator");
        Assert.assertThat(impersonatorRaw, instanceOf(Map.class));
        Map impersonatorClaim = (Map) impersonatorRaw;
        Assert.assertEquals(token.getSubject(), impersonatorClaim.get("id"));
        Assert.assertEquals("user", impersonatorClaim.get("username"));
    }
    // client-exchanger can impersonate from token "user" to user "impersonated-user" and to "target" client
    {
        Response response = exchangeUrl.request().header(HttpHeaders.AUTHORIZATION, BasicAuthHelper.createHeader("client-exchanger", "secret")).post(Entity.form(new Form().param(OAuth2Constants.GRANT_TYPE, OAuth2Constants.TOKEN_EXCHANGE_GRANT_TYPE).param(OAuth2Constants.SUBJECT_TOKEN, accessToken).param(OAuth2Constants.SUBJECT_TOKEN_TYPE, OAuth2Constants.ACCESS_TOKEN_TYPE).param(OAuth2Constants.REQUESTED_SUBJECT, "impersonated-user").param(OAuth2Constants.AUDIENCE, "target")));
        org.junit.Assert.assertEquals(200, response.getStatus());
        AccessTokenResponse accessTokenResponse = response.readEntity(AccessTokenResponse.class);
        response.close();
        String exchangedTokenString = accessTokenResponse.getToken();
        TokenVerifier<AccessToken> verifier = TokenVerifier.create(exchangedTokenString, AccessToken.class);
        AccessToken exchangedToken = verifier.parse().getToken();
        Assert.assertEquals("client-exchanger", exchangedToken.getIssuedFor());
        Assert.assertEquals("target", exchangedToken.getAudience()[0]);
        Assert.assertEquals(exchangedToken.getPreferredUsername(), "impersonated-user");
        Assert.assertTrue(exchangedToken.getRealmAccess().isUserInRole("example"));
    }
}
Also used : OAuthClient(org.keycloak.testsuite.util.OAuthClient) Form(javax.ws.rs.core.Form) AccessTokenResponse(org.keycloak.representations.AccessTokenResponse) Response(javax.ws.rs.core.Response) AccessToken(org.keycloak.representations.AccessToken) TokenVerifier(org.keycloak.TokenVerifier) WebTarget(javax.ws.rs.client.WebTarget) OAuthClient(org.keycloak.testsuite.util.OAuthClient) Client(javax.ws.rs.client.Client) AccessTokenResponse(org.keycloak.representations.AccessTokenResponse) Map(java.util.Map) AbstractKeycloakTest(org.keycloak.testsuite.AbstractKeycloakTest) Test(org.junit.Test) UncaughtServerErrorExpected(org.keycloak.testsuite.arquillian.annotation.UncaughtServerErrorExpected)

Example 20 with AccessTokenResponse

use of org.keycloak.representations.AccessTokenResponse in project keycloak by keycloak.

the class AbstractOAuth2IdentityProvider method exchangeStoredToken.

protected Response exchangeStoredToken(UriInfo uriInfo, EventBuilder event, ClientModel authorizedClient, UserSessionModel tokenUserSession, UserModel tokenSubject) {
    FederatedIdentityModel model = session.users().getFederatedIdentity(authorizedClient.getRealm(), tokenSubject, getConfig().getAlias());
    if (model == null || model.getToken() == null) {
        event.detail(Details.REASON, "requested_issuer is not linked");
        event.error(Errors.INVALID_TOKEN);
        return exchangeNotLinked(uriInfo, authorizedClient, tokenUserSession, tokenSubject);
    }
    String accessToken = extractTokenFromResponse(model.getToken(), getAccessTokenResponseParameter());
    if (accessToken == null) {
        model.setToken(null);
        session.users().updateFederatedIdentity(authorizedClient.getRealm(), tokenSubject, model);
        event.detail(Details.REASON, "requested_issuer token expired");
        event.error(Errors.INVALID_TOKEN);
        return exchangeTokenExpired(uriInfo, authorizedClient, tokenUserSession, tokenSubject);
    }
    AccessTokenResponse tokenResponse = new AccessTokenResponse();
    tokenResponse.setToken(accessToken);
    tokenResponse.setIdToken(null);
    tokenResponse.setRefreshToken(null);
    tokenResponse.setRefreshExpiresIn(0);
    tokenResponse.getOtherClaims().clear();
    tokenResponse.getOtherClaims().put(OAuth2Constants.ISSUED_TOKEN_TYPE, OAuth2Constants.ACCESS_TOKEN_TYPE);
    tokenResponse.getOtherClaims().put(ACCOUNT_LINK_URL, getLinkingUrl(uriInfo, authorizedClient, tokenUserSession));
    event.success();
    return Response.ok(tokenResponse).type(MediaType.APPLICATION_JSON_TYPE).build();
}
Also used : FederatedIdentityModel(org.keycloak.models.FederatedIdentityModel) AccessTokenResponse(org.keycloak.representations.AccessTokenResponse)

Aggregations

AccessTokenResponse (org.keycloak.representations.AccessTokenResponse)74 Response (javax.ws.rs.core.Response)30 Test (org.junit.Test)30 OAuthClient (org.keycloak.testsuite.util.OAuthClient)25 Client (javax.ws.rs.client.Client)24 AbstractKeycloakTest (org.keycloak.testsuite.AbstractKeycloakTest)17 Form (javax.ws.rs.core.Form)15 WebTarget (javax.ws.rs.client.WebTarget)14 AccessToken (org.keycloak.representations.AccessToken)14 IOException (java.io.IOException)12 ClientResource (org.keycloak.admin.client.resource.ClientResource)7 AuthorizationResponse (org.keycloak.representations.idm.authorization.AuthorizationResponse)7 AuthzClient (org.keycloak.authorization.client.AuthzClient)5 PermissionRequest (org.keycloak.representations.idm.authorization.PermissionRequest)5 CorsErrorResponseException (org.keycloak.services.CorsErrorResponseException)5 UncaughtServerErrorExpected (org.keycloak.testsuite.arquillian.annotation.UncaughtServerErrorExpected)5 InputStream (java.io.InputStream)4 URI (java.net.URI)4 NameValuePair (org.apache.http.NameValuePair)4 UrlEncodedFormEntity (org.apache.http.client.entity.UrlEncodedFormEntity)4