Search in sources :

Example 56 with UserModel

use of org.keycloak.models.UserModel 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 57 with UserModel

use of org.keycloak.models.UserModel in project keycloak by keycloak.

the class TokenManager method validateToken.

public TokenValidation validateToken(KeycloakSession session, UriInfo uriInfo, ClientConnection connection, RealmModel realm, RefreshToken oldToken, HttpHeaders headers) throws OAuthErrorException {
    UserSessionModel userSession = null;
    boolean offline = TokenUtil.TOKEN_TYPE_OFFLINE.equals(oldToken.getType());
    if (offline) {
        UserSessionManager sessionManager = new UserSessionManager(session);
        userSession = sessionManager.findOfflineUserSession(realm, oldToken.getSessionState());
        if (userSession != null) {
            // Revoke timeouted offline userSession
            if (!AuthenticationManager.isOfflineSessionValid(realm, userSession)) {
                sessionManager.revokeOfflineUserSession(userSession);
                throw new OAuthErrorException(OAuthErrorException.INVALID_GRANT, "Offline session not active", "Offline session not active");
            }
        } else {
            throw new OAuthErrorException(OAuthErrorException.INVALID_GRANT, "Offline user session not found", "Offline user session not found");
        }
    } else {
        // Find userSession regularly for online tokens
        userSession = session.sessions().getUserSession(realm, oldToken.getSessionState());
        if (!AuthenticationManager.isSessionValid(realm, userSession)) {
            AuthenticationManager.backchannelLogout(session, realm, userSession, uriInfo, connection, headers, true);
            throw new OAuthErrorException(OAuthErrorException.INVALID_GRANT, "Session not active", "Session not active");
        }
    }
    UserModel user = userSession.getUser();
    if (user == null) {
        throw new OAuthErrorException(OAuthErrorException.INVALID_GRANT, "Invalid refresh token", "Unknown user");
    }
    if (!user.isEnabled()) {
        throw new OAuthErrorException(OAuthErrorException.INVALID_GRANT, "User disabled", "User disabled");
    }
    if (oldToken.isIssuedBeforeSessionStart(userSession.getStarted())) {
        logger.debug("Refresh toked issued before the user session started");
        throw new OAuthErrorException(OAuthErrorException.INVALID_GRANT, "Refresh toked issued before the user session started");
    }
    ClientModel client = session.getContext().getClient();
    AuthenticatedClientSessionModel clientSession = userSession.getAuthenticatedClientSessionByClient(client.getId());
    // Can theoretically happen in cross-dc environment. Try to see if userSession with our client is available in remoteCache
    if (clientSession == null) {
        userSession = new UserSessionCrossDCManager(session).getUserSessionWithClient(realm, userSession.getId(), offline, client.getId());
        if (userSession != null) {
            clientSession = userSession.getAuthenticatedClientSessionByClient(client.getId());
        } else {
            throw new OAuthErrorException(OAuthErrorException.INVALID_GRANT, "Session doesn't have required client", "Session doesn't have required client");
        }
    }
    if (oldToken.isIssuedBeforeSessionStart(clientSession.getStarted())) {
        logger.debug("Refresh toked issued before the client session started");
        throw new OAuthErrorException(OAuthErrorException.INVALID_GRANT, "Refresh toked issued before the client session started");
    }
    if (!client.getClientId().equals(oldToken.getIssuedFor())) {
        throw new OAuthErrorException(OAuthErrorException.INVALID_GRANT, "Unmatching clients", "Unmatching clients");
    }
    try {
        TokenVerifier.createWithoutSignature(oldToken).withChecks(NotBeforeCheck.forModel(client), NotBeforeCheck.forModel(session, realm, user)).verify();
    } catch (VerificationException e) {
        throw new OAuthErrorException(OAuthErrorException.INVALID_GRANT, "Stale token");
    }
    // Setup clientScopes from refresh token to the context
    String oldTokenScope = oldToken.getScope();
    // Case when offline token is migrated from previous version
    if (oldTokenScope == null && userSession.isOffline()) {
        logger.debugf("Migrating offline token of user '%s' for client '%s' of realm '%s'", user.getUsername(), client.getClientId(), realm.getName());
        MigrationUtils.migrateOldOfflineToken(session, realm, client, user);
        oldTokenScope = OAuth2Constants.OFFLINE_ACCESS;
    }
    ClientSessionContext clientSessionCtx = DefaultClientSessionContext.fromClientSessionAndScopeParameter(clientSession, oldTokenScope, session);
    // Check user didn't revoke granted consent
    if (!verifyConsentStillAvailable(session, user, client, clientSessionCtx.getClientScopesStream())) {
        throw new OAuthErrorException(OAuthErrorException.INVALID_SCOPE, "Client no longer has requested consent from user");
    }
    clientSessionCtx.setAttribute(OIDCLoginProtocol.NONCE_PARAM, oldToken.getNonce());
    // recreate token.
    AccessToken newToken = createClientAccessToken(session, realm, client, user, userSession, clientSessionCtx);
    return new TokenValidation(user, userSession, clientSessionCtx, newToken);
}
Also used : UserSessionModel(org.keycloak.models.UserSessionModel) OAuthErrorException(org.keycloak.OAuthErrorException) AuthenticatedClientSessionModel(org.keycloak.models.AuthenticatedClientSessionModel) UserSessionCrossDCManager(org.keycloak.services.managers.UserSessionCrossDCManager) UserSessionManager(org.keycloak.services.managers.UserSessionManager) UserModel(org.keycloak.models.UserModel) ClientModel(org.keycloak.models.ClientModel) DefaultClientSessionContext(org.keycloak.services.util.DefaultClientSessionContext) ClientSessionContext(org.keycloak.models.ClientSessionContext) AccessToken(org.keycloak.representations.AccessToken) VerificationException(org.keycloak.common.VerificationException)

Example 58 with UserModel

use of org.keycloak.models.UserModel in project keycloak by keycloak.

the class DefaultTokenExchangeProvider method tokenExchange.

protected Response tokenExchange() {
    UserModel tokenUser = null;
    UserSessionModel tokenSession = null;
    AccessToken token = null;
    String subjectToken = formParams.getFirst(OAuth2Constants.SUBJECT_TOKEN);
    if (subjectToken != null) {
        String subjectTokenType = formParams.getFirst(OAuth2Constants.SUBJECT_TOKEN_TYPE);
        String realmIssuerUrl = Urls.realmIssuer(session.getContext().getUri().getBaseUri(), realm.getName());
        String subjectIssuer = formParams.getFirst(OAuth2Constants.SUBJECT_ISSUER);
        if (subjectIssuer == null && OAuth2Constants.JWT_TOKEN_TYPE.equals(subjectTokenType)) {
            try {
                JWSInput jws = new JWSInput(subjectToken);
                JsonWebToken jwt = jws.readJsonContent(JsonWebToken.class);
                subjectIssuer = jwt.getIssuer();
            } catch (JWSInputException e) {
                event.detail(Details.REASON, "unable to parse jwt subject_token");
                event.error(Errors.INVALID_TOKEN);
                throw new CorsErrorResponseException(cors, OAuthErrorException.INVALID_TOKEN, "Invalid token type, must be access token", Response.Status.BAD_REQUEST);
            }
        }
        if (subjectIssuer != null && !realmIssuerUrl.equals(subjectIssuer)) {
            event.detail(OAuth2Constants.SUBJECT_ISSUER, subjectIssuer);
            return exchangeExternalToken(subjectIssuer, subjectToken);
        }
        if (subjectTokenType != null && !subjectTokenType.equals(OAuth2Constants.ACCESS_TOKEN_TYPE)) {
            event.detail(Details.REASON, "subject_token supports access tokens only");
            event.error(Errors.INVALID_TOKEN);
            throw new CorsErrorResponseException(cors, OAuthErrorException.INVALID_TOKEN, "Invalid token type, must be access token", Response.Status.BAD_REQUEST);
        }
        AuthenticationManager.AuthResult authResult = AuthenticationManager.verifyIdentityToken(session, realm, session.getContext().getUri(), clientConnection, true, true, null, false, subjectToken, headers);
        if (authResult == null) {
            event.detail(Details.REASON, "subject_token validation failure");
            event.error(Errors.INVALID_TOKEN);
            throw new CorsErrorResponseException(cors, OAuthErrorException.INVALID_TOKEN, "Invalid token", Response.Status.BAD_REQUEST);
        }
        tokenUser = authResult.getUser();
        tokenSession = authResult.getSession();
        token = authResult.getToken();
    }
    String requestedSubject = formParams.getFirst(OAuth2Constants.REQUESTED_SUBJECT);
    if (requestedSubject != null) {
        event.detail(Details.REQUESTED_SUBJECT, requestedSubject);
        UserModel requestedUser = session.users().getUserByUsername(realm, requestedSubject);
        if (requestedUser == null) {
            requestedUser = session.users().getUserById(realm, requestedSubject);
        }
        if (requestedUser == null) {
            // We always returned access denied to avoid username fishing
            event.detail(Details.REASON, "requested_subject not found");
            event.error(Errors.NOT_ALLOWED);
            throw new CorsErrorResponseException(cors, OAuthErrorException.ACCESS_DENIED, "Client not allowed to exchange", Response.Status.FORBIDDEN);
        }
        if (token != null) {
            event.detail(Details.IMPERSONATOR, tokenUser.getUsername());
            // for this case, the user represented by the token, must have permission to impersonate.
            AdminAuth auth = new AdminAuth(realm, token, tokenUser, client);
            if (!AdminPermissions.evaluator(session, realm, auth).users().canImpersonate(requestedUser)) {
                event.detail(Details.REASON, "subject not allowed to impersonate");
                event.error(Errors.NOT_ALLOWED);
                throw new CorsErrorResponseException(cors, OAuthErrorException.ACCESS_DENIED, "Client not allowed to exchange", Response.Status.FORBIDDEN);
            }
        } else {
            // to impersonate
            if (client.isPublicClient()) {
                event.detail(Details.REASON, "public clients not allowed");
                event.error(Errors.NOT_ALLOWED);
                throw new CorsErrorResponseException(cors, OAuthErrorException.ACCESS_DENIED, "Client not allowed to exchange", Response.Status.FORBIDDEN);
            }
            if (!AdminPermissions.management(session, realm).users().canClientImpersonate(client, requestedUser)) {
                event.detail(Details.REASON, "client not allowed to impersonate");
                event.error(Errors.NOT_ALLOWED);
                throw new CorsErrorResponseException(cors, OAuthErrorException.ACCESS_DENIED, "Client not allowed to exchange", Response.Status.FORBIDDEN);
            }
        }
        tokenSession = session.sessions().createUserSession(realm, requestedUser, requestedUser.getUsername(), clientConnection.getRemoteAddr(), "impersonate", false, null, null);
        if (tokenUser != null) {
            tokenSession.setNote(IMPERSONATOR_ID.toString(), tokenUser.getId());
            tokenSession.setNote(IMPERSONATOR_USERNAME.toString(), tokenUser.getUsername());
        }
        tokenUser = requestedUser;
    }
    String requestedIssuer = formParams.getFirst(OAuth2Constants.REQUESTED_ISSUER);
    if (requestedIssuer == null) {
        return exchangeClientToClient(tokenUser, tokenSession);
    } else {
        try {
            return exchangeToIdentityProvider(tokenUser, tokenSession, requestedIssuer);
        } finally {
            if (subjectToken == null) {
                // we are naked! So need to clean up user session
                try {
                    session.sessions().removeUserSession(realm, tokenSession);
                } catch (Exception ignore) {
                }
            }
        }
    }
}
Also used : UserModel(org.keycloak.models.UserModel) AuthenticationManager(org.keycloak.services.managers.AuthenticationManager) AdminAuth(org.keycloak.services.resources.admin.AdminAuth) UserSessionModel(org.keycloak.models.UserSessionModel) AccessToken(org.keycloak.representations.AccessToken) JWSInputException(org.keycloak.jose.jws.JWSInputException) JWSInput(org.keycloak.jose.jws.JWSInput) CorsErrorResponseException(org.keycloak.services.CorsErrorResponseException) JsonWebToken(org.keycloak.representations.JsonWebToken) OAuthErrorException(org.keycloak.OAuthErrorException) CorsErrorResponseException(org.keycloak.services.CorsErrorResponseException) JWSInputException(org.keycloak.jose.jws.JWSInputException)

Example 59 with UserModel

use of org.keycloak.models.UserModel in project keycloak by keycloak.

the class DefaultTokenExchangeProvider method importUserFromExternalIdentity.

protected UserModel importUserFromExternalIdentity(BrokeredIdentityContext context) {
    IdentityProviderModel identityProviderConfig = context.getIdpConfig();
    String providerId = identityProviderConfig.getAlias();
    // do we need this?
    // AuthenticationSessionModel authenticationSession = clientCode.getClientSession();
    // context.setAuthenticationSession(authenticationSession);
    // session.getContext().setClient(authenticationSession.getClient());
    context.getIdp().preprocessFederatedIdentity(session, realm, context);
    Set<IdentityProviderMapperModel> mappers = realm.getIdentityProviderMappersByAliasStream(context.getIdpConfig().getAlias()).collect(Collectors.toSet());
    KeycloakSessionFactory sessionFactory = session.getKeycloakSessionFactory();
    for (IdentityProviderMapperModel mapper : mappers) {
        IdentityProviderMapper target = (IdentityProviderMapper) sessionFactory.getProviderFactory(IdentityProviderMapper.class, mapper.getIdentityProviderMapper());
        target.preprocessFederatedIdentity(session, realm, mapper, context);
    }
    FederatedIdentityModel federatedIdentityModel = new FederatedIdentityModel(providerId, context.getId(), context.getUsername(), context.getToken());
    UserModel user = this.session.users().getUserByFederatedIdentity(realm, federatedIdentityModel);
    if (user == null) {
        logger.debugf("Federated user not found for provider '%s' and broker username '%s'.", providerId, context.getUsername());
        String username = context.getModelUsername();
        if (username == null) {
            if (this.realm.isRegistrationEmailAsUsername() && !Validation.isBlank(context.getEmail())) {
                username = context.getEmail();
            } else if (context.getUsername() == null) {
                username = context.getIdpConfig().getAlias() + "." + context.getId();
            } else {
                username = context.getUsername();
            }
        }
        username = username.trim();
        context.setModelUsername(username);
        if (context.getEmail() != null && !realm.isDuplicateEmailsAllowed()) {
            UserModel existingUser = session.users().getUserByEmail(realm, context.getEmail());
            if (existingUser != null) {
                event.error(Errors.FEDERATED_IDENTITY_EXISTS);
                throw new CorsErrorResponseException(cors, Errors.INVALID_TOKEN, "User already exists", Response.Status.BAD_REQUEST);
            }
        }
        UserModel existingUser = session.users().getUserByUsername(realm, username);
        if (existingUser != null) {
            event.error(Errors.FEDERATED_IDENTITY_EXISTS);
            throw new CorsErrorResponseException(cors, Errors.INVALID_TOKEN, "User already exists", Response.Status.BAD_REQUEST);
        }
        user = session.users().addUser(realm, username);
        user.setEnabled(true);
        user.setEmail(context.getEmail());
        user.setFirstName(context.getFirstName());
        user.setLastName(context.getLastName());
        federatedIdentityModel = new FederatedIdentityModel(context.getIdpConfig().getAlias(), context.getId(), context.getUsername(), context.getToken());
        session.users().addFederatedIdentity(realm, user, federatedIdentityModel);
        context.getIdp().importNewUser(session, realm, user, context);
        for (IdentityProviderMapperModel mapper : mappers) {
            IdentityProviderMapper target = (IdentityProviderMapper) sessionFactory.getProviderFactory(IdentityProviderMapper.class, mapper.getIdentityProviderMapper());
            target.importNewUser(session, realm, user, mapper, context);
        }
        if (context.getIdpConfig().isTrustEmail() && !Validation.isBlank(user.getEmail())) {
            logger.debugf("Email verified automatically after registration of user '%s' through Identity provider '%s' ", user.getUsername(), context.getIdpConfig().getAlias());
            user.setEmailVerified(true);
        }
    } else {
        if (!user.isEnabled()) {
            event.error(Errors.USER_DISABLED);
            throw new CorsErrorResponseException(cors, Errors.INVALID_TOKEN, "Invalid Token", Response.Status.BAD_REQUEST);
        }
        String bruteForceError = getDisabledByBruteForceEventError(session.getProvider(BruteForceProtector.class), session, realm, user);
        if (bruteForceError != null) {
            event.error(bruteForceError);
            throw new CorsErrorResponseException(cors, Errors.INVALID_TOKEN, "Invalid Token", Response.Status.BAD_REQUEST);
        }
        context.getIdp().updateBrokeredUser(session, realm, user, context);
        for (IdentityProviderMapperModel mapper : mappers) {
            IdentityProviderMapper target = (IdentityProviderMapper) sessionFactory.getProviderFactory(IdentityProviderMapper.class, mapper.getIdentityProviderMapper());
            IdentityProviderMapperSyncModeDelegate.delegateUpdateBrokeredUser(session, realm, user, mapper, context, target);
        }
    }
    return user;
}
Also used : UserModel(org.keycloak.models.UserModel) IdentityProviderMapper(org.keycloak.broker.provider.IdentityProviderMapper) FederatedIdentityModel(org.keycloak.models.FederatedIdentityModel) BruteForceProtector(org.keycloak.services.managers.BruteForceProtector) IdentityProviderModel(org.keycloak.models.IdentityProviderModel) CorsErrorResponseException(org.keycloak.services.CorsErrorResponseException) KeycloakSessionFactory(org.keycloak.models.KeycloakSessionFactory) IdentityProviderMapperModel(org.keycloak.models.IdentityProviderMapperModel)

Example 60 with UserModel

use of org.keycloak.models.UserModel in project keycloak by keycloak.

the class DefaultTokenExchangeProvider method exchangeExternalToken.

protected Response exchangeExternalToken(String issuer, String subjectToken) {
    AtomicReference<ExchangeExternalToken> externalIdp = new AtomicReference<>(null);
    AtomicReference<IdentityProviderModel> externalIdpModel = new AtomicReference<>(null);
    realm.getIdentityProvidersStream().filter(idpModel -> {
        IdentityProviderFactory factory = IdentityBrokerService.getIdentityProviderFactory(session, idpModel);
        IdentityProvider idp = factory.create(session, idpModel);
        if (idp instanceof ExchangeExternalToken) {
            ExchangeExternalToken external = (ExchangeExternalToken) idp;
            if (idpModel.getAlias().equals(issuer) || external.isIssuer(issuer, formParams)) {
                externalIdp.set(external);
                externalIdpModel.set(idpModel);
                return true;
            }
        }
        return false;
    }).findFirst();
    if (externalIdp.get() == null) {
        event.error(Errors.INVALID_ISSUER);
        throw new CorsErrorResponseException(cors, Errors.INVALID_ISSUER, "Invalid " + OAuth2Constants.SUBJECT_ISSUER + " parameter", Response.Status.BAD_REQUEST);
    }
    if (!AdminPermissions.management(session, realm).idps().canExchangeTo(client, externalIdpModel.get())) {
        event.detail(Details.REASON, "client not allowed to exchange subject_issuer");
        event.error(Errors.NOT_ALLOWED);
        throw new CorsErrorResponseException(cors, OAuthErrorException.ACCESS_DENIED, "Client not allowed to exchange", Response.Status.FORBIDDEN);
    }
    BrokeredIdentityContext context = externalIdp.get().exchangeExternal(event, formParams);
    if (context == null) {
        event.error(Errors.INVALID_ISSUER);
        throw new CorsErrorResponseException(cors, Errors.INVALID_ISSUER, "Invalid " + OAuth2Constants.SUBJECT_ISSUER + " parameter", Response.Status.BAD_REQUEST);
    }
    UserModel user = importUserFromExternalIdentity(context);
    UserSessionModel userSession = session.sessions().createUserSession(realm, user, user.getUsername(), clientConnection.getRemoteAddr(), "external-exchange", false, null, null);
    externalIdp.get().exchangeExternalComplete(userSession, context, formParams);
    // this must exist so that we can obtain access token from user session if idp's store tokens is off
    userSession.setNote(IdentityProvider.EXTERNAL_IDENTITY_PROVIDER, externalIdpModel.get().getAlias());
    userSession.setNote(IdentityProvider.FEDERATED_ACCESS_TOKEN, subjectToken);
    return exchangeClientToClient(user, userSession);
}
Also used : BrokeredIdentityContext(org.keycloak.broker.provider.BrokeredIdentityContext) AuthenticationSessionManager(org.keycloak.services.managers.AuthenticationSessionManager) AccessTokenResponse(org.keycloak.representations.AccessTokenResponse) OAuthErrorException(org.keycloak.OAuthErrorException) MediaType(javax.ws.rs.core.MediaType) AuthenticationManager(org.keycloak.services.managers.AuthenticationManager) AccessToken(org.keycloak.representations.AccessToken) ExchangeExternalToken(org.keycloak.broker.provider.ExchangeExternalToken) Validation(org.keycloak.services.validation.Validation) Map(java.util.Map) SamlService(org.keycloak.protocol.saml.SamlService) ClientConnection(org.keycloak.common.ClientConnection) AdminPermissions(org.keycloak.services.resources.admin.permissions.AdminPermissions) AuthenticationSessionModel(org.keycloak.sessions.AuthenticationSessionModel) RealmModel(org.keycloak.models.RealmModel) IdentityProviderMapperSyncModeDelegate(org.keycloak.broker.provider.IdentityProviderMapperSyncModeDelegate) Set(java.util.Set) SamlProtocol(org.keycloak.protocol.saml.SamlProtocol) IdentityProviderModel(org.keycloak.models.IdentityProviderModel) CorsErrorResponseException(org.keycloak.services.CorsErrorResponseException) Collectors(java.util.stream.Collectors) IMPERSONATOR_ID(org.keycloak.models.ImpersonationSessionNote.IMPERSONATOR_ID) TokenExchangeSamlProtocol(org.keycloak.protocol.oidc.endpoints.TokenEndpoint.TokenExchangeSamlProtocol) AdminAuth(org.keycloak.services.resources.admin.AdminAuth) HttpHeaders(javax.ws.rs.core.HttpHeaders) Response(javax.ws.rs.core.Response) Details(org.keycloak.events.Details) RootAuthenticationSessionModel(org.keycloak.sessions.RootAuthenticationSessionModel) KeycloakSessionFactory(org.keycloak.models.KeycloakSessionFactory) SamlClient(org.keycloak.protocol.saml.SamlClient) BruteForceProtector(org.keycloak.services.managers.BruteForceProtector) OAuth2Constants(org.keycloak.OAuth2Constants) LoginProtocol(org.keycloak.protocol.LoginProtocol) ClientModel(org.keycloak.models.ClientModel) IdentityProviderFactory(org.keycloak.broker.provider.IdentityProviderFactory) IdentityProviderMapperModel(org.keycloak.models.IdentityProviderMapperModel) ExchangeTokenToIdentityProviderToken(org.keycloak.broker.provider.ExchangeTokenToIdentityProviderToken) Logger(org.jboss.logging.Logger) GeneralConstants(org.keycloak.saml.common.constants.GeneralConstants) AtomicReference(java.util.concurrent.atomic.AtomicReference) LoginProtocolFactory(org.keycloak.protocol.LoginProtocolFactory) ResteasyProviderFactory(org.jboss.resteasy.spi.ResteasyProviderFactory) JWSInputException(org.keycloak.jose.jws.JWSInputException) TokenUtil(org.keycloak.util.TokenUtil) UserModel(org.keycloak.models.UserModel) ClientSessionContext(org.keycloak.models.ClientSessionContext) EventBuilder(org.keycloak.events.EventBuilder) Cors(org.keycloak.services.resources.Cors) Base64Url(org.keycloak.common.util.Base64Url) IdentityProvider(org.keycloak.broker.provider.IdentityProvider) IdentityProviderMapper(org.keycloak.broker.provider.IdentityProviderMapper) FederatedIdentityModel(org.keycloak.models.FederatedIdentityModel) JWSInput(org.keycloak.jose.jws.JWSInput) Errors(org.keycloak.events.Errors) IdentityBrokerService(org.keycloak.services.resources.IdentityBrokerService) KeycloakSession(org.keycloak.models.KeycloakSession) UserSessionModel(org.keycloak.models.UserSessionModel) JsonWebToken(org.keycloak.representations.JsonWebToken) MultivaluedMap(javax.ws.rs.core.MultivaluedMap) IMPERSONATOR_USERNAME(org.keycloak.models.ImpersonationSessionNote.IMPERSONATOR_USERNAME) AuthenticatorUtils.getDisabledByBruteForceEventError(org.keycloak.authentication.authenticators.util.AuthenticatorUtils.getDisabledByBruteForceEventError) Urls(org.keycloak.services.Urls) UserModel(org.keycloak.models.UserModel) UserSessionModel(org.keycloak.models.UserSessionModel) ExchangeExternalToken(org.keycloak.broker.provider.ExchangeExternalToken) AtomicReference(java.util.concurrent.atomic.AtomicReference) IdentityProvider(org.keycloak.broker.provider.IdentityProvider) IdentityProviderModel(org.keycloak.models.IdentityProviderModel) CorsErrorResponseException(org.keycloak.services.CorsErrorResponseException) IdentityProviderFactory(org.keycloak.broker.provider.IdentityProviderFactory) BrokeredIdentityContext(org.keycloak.broker.provider.BrokeredIdentityContext)

Aggregations

UserModel (org.keycloak.models.UserModel)383 RealmModel (org.keycloak.models.RealmModel)220 Test (org.junit.Test)126 ClientModel (org.keycloak.models.ClientModel)86 KeycloakSession (org.keycloak.models.KeycloakSession)81 CachedUserModel (org.keycloak.models.cache.CachedUserModel)52 ModelTest (org.keycloak.testsuite.arquillian.annotation.ModelTest)43 List (java.util.List)41 UserSessionModel (org.keycloak.models.UserSessionModel)40 AbstractTestRealmKeycloakTest (org.keycloak.testsuite.AbstractTestRealmKeycloakTest)40 RoleModel (org.keycloak.models.RoleModel)39 ComponentModel (org.keycloak.component.ComponentModel)31 HashMap (java.util.HashMap)30 Response (javax.ws.rs.core.Response)29 Path (javax.ws.rs.Path)28 UserManager (org.keycloak.models.UserManager)28 LDAPObject (org.keycloak.storage.ldap.idm.model.LDAPObject)27 Map (java.util.Map)25 GroupModel (org.keycloak.models.GroupModel)24 AbstractAuthTest (org.keycloak.testsuite.AbstractAuthTest)24