Search in sources :

Example 1 with ServiceAccountTokenRequestContext

use of org.keycloak.services.clientpolicy.context.ServiceAccountTokenRequestContext 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)

Aggregations

ClientSessionContext (org.keycloak.models.ClientSessionContext)1 UserModel (org.keycloak.models.UserModel)1 UserSessionModel (org.keycloak.models.UserSessionModel)1 TokenManager (org.keycloak.protocol.oidc.TokenManager)1 AccessTokenResponse (org.keycloak.representations.AccessTokenResponse)1 CorsErrorResponseException (org.keycloak.services.CorsErrorResponseException)1 ClientPolicyException (org.keycloak.services.clientpolicy.ClientPolicyException)1 ServiceAccountTokenRequestContext (org.keycloak.services.clientpolicy.context.ServiceAccountTokenRequestContext)1 AuthenticationSessionManager (org.keycloak.services.managers.AuthenticationSessionManager)1 ClientManager (org.keycloak.services.managers.ClientManager)1 RealmManager (org.keycloak.services.managers.RealmManager)1 DefaultClientSessionContext (org.keycloak.services.util.DefaultClientSessionContext)1 AuthenticationSessionModel (org.keycloak.sessions.AuthenticationSessionModel)1 RootAuthenticationSessionModel (org.keycloak.sessions.RootAuthenticationSessionModel)1