Search in sources :

Example 11 with IdentityProviderModel

use of org.keycloak.models.IdentityProviderModel 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 12 with IdentityProviderModel

use of org.keycloak.models.IdentityProviderModel 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)

Example 13 with IdentityProviderModel

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

the class MapRealmAdapter method removeIdentityProviderByAlias.

@Override
public void removeIdentityProviderByAlias(String alias) {
    IdentityProviderModel model = getIdentityProviderByAlias(alias);
    entity.removeIdentityProvider(model.getInternalId());
    // TODO: Sending an event should be extracted to store layer
    session.getKeycloakSessionFactory().publish(new RealmModel.IdentityProviderRemovedEvent() {

        @Override
        public RealmModel getRealm() {
            return MapRealmAdapter.this;
        }

        @Override
        public IdentityProviderModel getRemovedIdentityProvider() {
            return model;
        }

        @Override
        public KeycloakSession getKeycloakSession() {
            return session;
        }
    });
// TODO: ^^^^^^^ Up to here
}
Also used : RealmModel(org.keycloak.models.RealmModel) KeycloakSession(org.keycloak.models.KeycloakSession) IdentityProviderModel(org.keycloak.models.IdentityProviderModel)

Example 14 with IdentityProviderModel

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

the class IdentityBrokerService method performLogin.

@GET
@NoCache
@Path("/{provider_id}/login")
public Response performLogin(@PathParam("provider_id") String providerId, @QueryParam(LoginActionsService.SESSION_CODE) String code, @QueryParam("client_id") String clientId, @QueryParam(Constants.TAB_ID) String tabId, @QueryParam(OIDCLoginProtocol.LOGIN_HINT_PARAM) String loginHint) {
    this.event.detail(Details.IDENTITY_PROVIDER, providerId);
    if (isDebugEnabled()) {
        logger.debugf("Sending authentication request to identity provider [%s].", providerId);
    }
    try {
        AuthenticationSessionModel authSession = parseSessionCode(code, clientId, tabId);
        ClientSessionCode<AuthenticationSessionModel> clientSessionCode = new ClientSessionCode<>(session, realmModel, authSession);
        clientSessionCode.setAction(AuthenticationSessionModel.Action.AUTHENTICATE.name());
        IdentityProviderModel identityProviderModel = realmModel.getIdentityProviderByAlias(providerId);
        if (identityProviderModel == null) {
            throw new IdentityBrokerException("Identity Provider [" + providerId + "] not found.");
        }
        if (identityProviderModel.isLinkOnly()) {
            throw new IdentityBrokerException("Identity Provider [" + providerId + "] is not allowed to perform a login.");
        }
        if (clientSessionCode != null && clientSessionCode.getClientSession() != null && loginHint != null) {
            clientSessionCode.getClientSession().setClientNote(OIDCLoginProtocol.LOGIN_HINT_PARAM, loginHint);
        }
        IdentityProviderFactory providerFactory = getIdentityProviderFactory(session, identityProviderModel);
        IdentityProvider identityProvider = providerFactory.create(session, identityProviderModel);
        Response response = identityProvider.performLogin(createAuthenticationRequest(providerId, clientSessionCode));
        if (response != null) {
            if (isDebugEnabled()) {
                logger.debugf("Identity provider [%s] is going to send a request [%s].", identityProvider, response);
            }
            return response;
        }
    } catch (IdentityBrokerException e) {
        return redirectToErrorPage(Response.Status.BAD_GATEWAY, Messages.COULD_NOT_SEND_AUTHENTICATION_REQUEST, e, providerId);
    } catch (Exception e) {
        return redirectToErrorPage(Response.Status.INTERNAL_SERVER_ERROR, Messages.UNEXPECTED_ERROR_HANDLING_REQUEST, e, providerId);
    }
    return redirectToErrorPage(Response.Status.INTERNAL_SERVER_ERROR, Messages.COULD_NOT_PROCEED_WITH_AUTHENTICATION_REQUEST);
}
Also used : Response(javax.ws.rs.core.Response) ErrorResponse(org.keycloak.services.ErrorResponse) AuthenticationSessionModel(org.keycloak.sessions.AuthenticationSessionModel) RootAuthenticationSessionModel(org.keycloak.sessions.RootAuthenticationSessionModel) IdentityBrokerException(org.keycloak.broker.provider.IdentityBrokerException) SocialIdentityProvider(org.keycloak.broker.social.SocialIdentityProvider) IdentityProvider(org.keycloak.broker.provider.IdentityProvider) IdentityProviderModel(org.keycloak.models.IdentityProviderModel) ClientSessionCode(org.keycloak.services.managers.ClientSessionCode) IdentityProviderFactory(org.keycloak.broker.provider.IdentityProviderFactory) NoSuchAlgorithmException(java.security.NoSuchAlgorithmException) WebApplicationException(javax.ws.rs.WebApplicationException) IOException(java.io.IOException) IdentityBrokerException(org.keycloak.broker.provider.IdentityBrokerException) OAuthErrorException(org.keycloak.OAuthErrorException) NotFoundException(javax.ws.rs.NotFoundException) ErrorPageException(org.keycloak.services.ErrorPageException) Path(javax.ws.rs.Path) GET(javax.ws.rs.GET) NoCache(org.jboss.resteasy.annotations.cache.NoCache)

Example 15 with IdentityProviderModel

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

the class IdentityBrokerService method getToken.

private Response getToken(String providerId, boolean forceRetrieval) {
    this.event.event(EventType.IDENTITY_PROVIDER_RETRIEVE_TOKEN);
    try {
        AuthenticationManager.AuthResult authResult = new AppAuthManager.BearerTokenAuthenticator(session).setRealm(realmModel).setConnection(clientConnection).setHeaders(request.getHttpHeaders()).authenticate();
        if (authResult != null) {
            AccessToken token = authResult.getToken();
            ClientModel clientModel = authResult.getClient();
            session.getContext().setClient(clientModel);
            ClientModel brokerClient = realmModel.getClientByClientId(Constants.BROKER_SERVICE_CLIENT_ID);
            if (brokerClient == null) {
                return corsResponse(forbidden("Realm has not migrated to support the broker token exchange service"), clientModel);
            }
            if (!canReadBrokerToken(token)) {
                return corsResponse(forbidden("Client [" + clientModel.getClientId() + "] not authorized to retrieve tokens from identity provider [" + providerId + "]."), clientModel);
            }
            IdentityProvider identityProvider = getIdentityProvider(session, realmModel, providerId);
            IdentityProviderModel identityProviderConfig = getIdentityProviderConfig(providerId);
            if (identityProviderConfig.isStoreToken()) {
                FederatedIdentityModel identity = this.session.users().getFederatedIdentity(this.realmModel, authResult.getUser(), providerId);
                if (identity == null) {
                    return corsResponse(badRequest("User [" + authResult.getUser().getId() + "] is not associated with identity provider [" + providerId + "]."), clientModel);
                }
                this.event.success();
                return corsResponse(identityProvider.retrieveToken(session, identity), clientModel);
            }
            return corsResponse(badRequest("Identity Provider [" + providerId + "] does not support this operation."), clientModel);
        }
        return badRequest("Invalid token.");
    } catch (IdentityBrokerException e) {
        return redirectToErrorPage(Response.Status.BAD_GATEWAY, Messages.COULD_NOT_OBTAIN_TOKEN, e, providerId);
    } catch (Exception e) {
        return redirectToErrorPage(Response.Status.BAD_GATEWAY, Messages.UNEXPECTED_ERROR_RETRIEVING_TOKEN, e, providerId);
    }
}
Also used : AuthenticationManager(org.keycloak.services.managers.AuthenticationManager) ClientModel(org.keycloak.models.ClientModel) AccessToken(org.keycloak.representations.AccessToken) FederatedIdentityModel(org.keycloak.models.FederatedIdentityModel) IdentityBrokerException(org.keycloak.broker.provider.IdentityBrokerException) SocialIdentityProvider(org.keycloak.broker.social.SocialIdentityProvider) IdentityProvider(org.keycloak.broker.provider.IdentityProvider) IdentityProviderModel(org.keycloak.models.IdentityProviderModel) NoSuchAlgorithmException(java.security.NoSuchAlgorithmException) WebApplicationException(javax.ws.rs.WebApplicationException) IOException(java.io.IOException) IdentityBrokerException(org.keycloak.broker.provider.IdentityBrokerException) OAuthErrorException(org.keycloak.OAuthErrorException) NotFoundException(javax.ws.rs.NotFoundException) ErrorPageException(org.keycloak.services.ErrorPageException)

Aggregations

IdentityProviderModel (org.keycloak.models.IdentityProviderModel)32 RealmModel (org.keycloak.models.RealmModel)10 Response (javax.ws.rs.core.Response)8 IdentityProvider (org.keycloak.broker.provider.IdentityProvider)8 KeycloakSession (org.keycloak.models.KeycloakSession)6 UserModel (org.keycloak.models.UserModel)6 NotFoundException (javax.ws.rs.NotFoundException)5 Path (javax.ws.rs.Path)5 Test (org.junit.Test)5 AuthenticationSessionModel (org.keycloak.sessions.AuthenticationSessionModel)5 IOException (java.io.IOException)4 Map (java.util.Map)4 OAuthErrorException (org.keycloak.OAuthErrorException)4 IdentityBrokerException (org.keycloak.broker.provider.IdentityBrokerException)4 IdentityProviderFactory (org.keycloak.broker.provider.IdentityProviderFactory)4 SocialIdentityProvider (org.keycloak.broker.social.SocialIdentityProvider)4 ClientModel (org.keycloak.models.ClientModel)4 FederatedIdentityModel (org.keycloak.models.FederatedIdentityModel)4 ErrorResponse (org.keycloak.services.ErrorResponse)4 URI (java.net.URI)3