Search in sources :

Example 1 with IdentityProviderMapper

use of org.keycloak.broker.provider.IdentityProviderMapper 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 2 with IdentityProviderMapper

use of org.keycloak.broker.provider.IdentityProviderMapper in project keycloak by keycloak.

the class SAMLIdentityProvider method export.

@Override
public Response export(UriInfo uriInfo, RealmModel realm, String format) {
    try {
        URI authnBinding = JBossSAMLURIConstants.SAML_HTTP_REDIRECT_BINDING.getUri();
        if (getConfig().isPostBindingAuthnRequest()) {
            authnBinding = JBossSAMLURIConstants.SAML_HTTP_POST_BINDING.getUri();
        }
        URI endpoint = uriInfo.getBaseUriBuilder().path("realms").path(realm.getName()).path("broker").path(getConfig().getAlias()).path("endpoint").build();
        boolean wantAuthnRequestsSigned = getConfig().isWantAuthnRequestsSigned();
        boolean wantAssertionsSigned = getConfig().isWantAssertionsSigned();
        boolean wantAssertionsEncrypted = getConfig().isWantAssertionsEncrypted();
        String entityId = getEntityId(uriInfo, realm);
        String nameIDPolicyFormat = getConfig().getNameIDPolicyFormat();
        List<Element> signingKeys = new LinkedList<>();
        List<Element> encryptionKeys = new LinkedList<>();
        session.keys().getKeysStream(realm, KeyUse.SIG, Algorithm.RS256).filter(Objects::nonNull).filter(key -> key.getCertificate() != null).sorted(SamlService::compareKeys).forEach(key -> {
            try {
                Element element = SPMetadataDescriptor.buildKeyInfoElement(key.getKid(), PemUtils.encodeCertificate(key.getCertificate()));
                signingKeys.add(element);
                if (key.getStatus() == KeyStatus.ACTIVE) {
                    encryptionKeys.add(element);
                }
            } catch (ParserConfigurationException e) {
                logger.warn("Failed to export SAML SP Metadata!", e);
                throw new RuntimeException(e);
            }
        });
        // Prepare the metadata descriptor model
        StringWriter sw = new StringWriter();
        XMLStreamWriter writer = StaxUtil.getXMLStreamWriter(sw);
        SAMLMetadataWriter metadataWriter = new SAMLMetadataWriter(writer);
        EntityDescriptorType entityDescriptor = SPMetadataDescriptor.buildSPdescriptor(authnBinding, authnBinding, endpoint, endpoint, wantAuthnRequestsSigned, wantAssertionsSigned, wantAssertionsEncrypted, entityId, nameIDPolicyFormat, signingKeys, encryptionKeys);
        // Create the AttributeConsumingService if at least one attribute importer mapper exists
        List<Entry<IdentityProviderMapperModel, SamlMetadataDescriptorUpdater>> metadataAttrProviders = new ArrayList<>();
        realm.getIdentityProviderMappersByAliasStream(getConfig().getAlias()).forEach(mapper -> {
            IdentityProviderMapper target = (IdentityProviderMapper) session.getKeycloakSessionFactory().getProviderFactory(IdentityProviderMapper.class, mapper.getIdentityProviderMapper());
            if (target instanceof SamlMetadataDescriptorUpdater)
                metadataAttrProviders.add(new java.util.AbstractMap.SimpleEntry<>(mapper, (SamlMetadataDescriptorUpdater) target));
        });
        if (!metadataAttrProviders.isEmpty()) {
            int attributeConsumingServiceIndex = getConfig().getAttributeConsumingServiceIndex() != null ? getConfig().getAttributeConsumingServiceIndex() : 1;
            String attributeConsumingServiceName = getConfig().getAttributeConsumingServiceName();
            // default value for attributeConsumingServiceName
            if (attributeConsumingServiceName == null)
                attributeConsumingServiceName = realm.getDisplayName() != null ? realm.getDisplayName() : realm.getName();
            AttributeConsumingServiceType attributeConsumingService = new AttributeConsumingServiceType(attributeConsumingServiceIndex);
            attributeConsumingService.setIsDefault(true);
            String currentLocale = realm.getDefaultLocale() == null ? "en" : realm.getDefaultLocale();
            LocalizedNameType attributeConsumingServiceNameElement = new LocalizedNameType(currentLocale);
            attributeConsumingServiceNameElement.setValue(attributeConsumingServiceName);
            attributeConsumingService.addServiceName(attributeConsumingServiceNameElement);
            // Look for the SP descriptor and add the attribute consuming service
            for (EntityDescriptorType.EDTChoiceType choiceType : entityDescriptor.getChoiceType()) {
                List<EntityDescriptorType.EDTDescriptorChoiceType> descriptors = choiceType.getDescriptors();
                for (EntityDescriptorType.EDTDescriptorChoiceType descriptor : descriptors) {
                    descriptor.getSpDescriptor().addAttributeConsumerService(attributeConsumingService);
                }
            }
            // Add the attribute mappers
            metadataAttrProviders.forEach(mapper -> {
                SamlMetadataDescriptorUpdater metadataAttrProvider = mapper.getValue();
                metadataAttrProvider.updateMetadata(mapper.getKey(), entityDescriptor);
            });
        }
        // Write the metadata and export it to a string
        metadataWriter.writeEntityDescriptor(entityDescriptor);
        String descriptor = sw.toString();
        // Metadata signing
        if (getConfig().isSignSpMetadata()) {
            KeyManager.ActiveRsaKey activeKey = session.keys().getActiveRsaKey(realm);
            String keyName = getConfig().getXmlSigKeyInfoKeyNameTransformer().getKeyName(activeKey.getKid(), activeKey.getCertificate());
            KeyPair keyPair = new KeyPair(activeKey.getPublicKey(), activeKey.getPrivateKey());
            Document metadataDocument = DocumentUtil.getDocument(descriptor);
            SAML2Signature signatureHelper = new SAML2Signature();
            signatureHelper.setSignatureMethod(getSignatureAlgorithm().getXmlSignatureMethod());
            signatureHelper.setDigestMethod(getSignatureAlgorithm().getXmlSignatureDigestMethod());
            Node nextSibling = metadataDocument.getDocumentElement().getFirstChild();
            signatureHelper.setNextSibling(nextSibling);
            signatureHelper.signSAMLDocument(metadataDocument, keyName, keyPair, CanonicalizationMethod.EXCLUSIVE);
            descriptor = DocumentUtil.getDocumentAsString(metadataDocument);
        }
        return Response.ok(descriptor, MediaType.APPLICATION_XML_TYPE).build();
    } catch (Exception e) {
        logger.warn("Failed to export SAML SP Metadata!", e);
        throw new RuntimeException(e);
    }
}
Also used : SAMLMetadataWriter(org.keycloak.saml.processing.core.saml.v2.writers.SAMLMetadataWriter) Element(org.w3c.dom.Element) Node(org.w3c.dom.Node) ArrayList(java.util.ArrayList) Document(org.w3c.dom.Document) URI(java.net.URI) Entry(java.util.Map.Entry) StringWriter(java.io.StringWriter) LocalizedNameType(org.keycloak.dom.saml.v2.metadata.LocalizedNameType) XMLStreamWriter(javax.xml.stream.XMLStreamWriter) IdentityProviderMapper(org.keycloak.broker.provider.IdentityProviderMapper) ParserConfigurationException(javax.xml.parsers.ParserConfigurationException) EntityDescriptorType(org.keycloak.dom.saml.v2.metadata.EntityDescriptorType) SAML2Signature(org.keycloak.saml.processing.api.saml.v2.sig.SAML2Signature) KeyManager(org.keycloak.models.KeyManager) KeyPair(java.security.KeyPair) LinkedList(java.util.LinkedList) ConfigurationException(org.keycloak.saml.common.exceptions.ConfigurationException) IdentityBrokerException(org.keycloak.broker.provider.IdentityBrokerException) ParserConfigurationException(javax.xml.parsers.ParserConfigurationException) SamlMetadataDescriptorUpdater(org.keycloak.protocol.saml.mappers.SamlMetadataDescriptorUpdater) AttributeConsumingServiceType(org.keycloak.dom.saml.v2.metadata.AttributeConsumingServiceType)

Example 3 with IdentityProviderMapper

use of org.keycloak.broker.provider.IdentityProviderMapper in project keycloak by keycloak.

the class IdentityBrokerService method authenticated.

public Response authenticated(BrokeredIdentityContext context) {
    IdentityProviderModel identityProviderConfig = context.getIdpConfig();
    AuthenticationSessionModel authenticationSession = context.getAuthenticationSession();
    String providerId = identityProviderConfig.getAlias();
    if (!identityProviderConfig.isStoreToken()) {
        if (isDebugEnabled()) {
            logger.debugf("Token will not be stored for identity provider [%s].", providerId);
        }
        context.setToken(null);
    }
    StatusResponseType loginResponse = (StatusResponseType) context.getContextData().get(SAMLEndpoint.SAML_LOGIN_RESPONSE);
    if (loginResponse != null) {
        for (Iterator<SamlAuthenticationPreprocessor> it = SamlSessionUtils.getSamlAuthenticationPreprocessorIterator(session); it.hasNext(); ) {
            loginResponse = it.next().beforeProcessingLoginResponse(loginResponse, authenticationSession);
        }
    }
    session.getContext().setClient(authenticationSession.getClient());
    context.getIdp().preprocessFederatedIdentity(session, realmModel, context);
    KeycloakSessionFactory sessionFactory = session.getKeycloakSessionFactory();
    realmModel.getIdentityProviderMappersByAliasStream(context.getIdpConfig().getAlias()).forEach(mapper -> {
        IdentityProviderMapper target = (IdentityProviderMapper) sessionFactory.getProviderFactory(IdentityProviderMapper.class, mapper.getIdentityProviderMapper());
        target.preprocessFederatedIdentity(session, realmModel, mapper, context);
    });
    FederatedIdentityModel federatedIdentityModel = new FederatedIdentityModel(providerId, context.getId(), context.getUsername(), context.getToken());
    this.event.event(EventType.IDENTITY_PROVIDER_LOGIN).detail(Details.REDIRECT_URI, authenticationSession.getRedirectUri()).detail(Details.IDENTITY_PROVIDER, providerId).detail(Details.IDENTITY_PROVIDER_USERNAME, context.getUsername());
    UserModel federatedUser = this.session.users().getUserByFederatedIdentity(this.realmModel, federatedIdentityModel);
    boolean shouldMigrateId = false;
    // try to find the user using legacy ID
    if (federatedUser == null && context.getLegacyId() != null) {
        federatedIdentityModel = new FederatedIdentityModel(federatedIdentityModel, context.getLegacyId());
        federatedUser = this.session.users().getUserByFederatedIdentity(this.realmModel, federatedIdentityModel);
        shouldMigrateId = true;
    }
    // Check if federatedUser is already authenticated (this means linking social into existing federatedUser account)
    UserSessionModel userSession = new AuthenticationSessionManager(session).getUserSession(authenticationSession);
    if (shouldPerformAccountLinking(authenticationSession, userSession, providerId)) {
        return performAccountLinking(authenticationSession, userSession, context, federatedIdentityModel, federatedUser);
    }
    if (federatedUser == 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.realmModel.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);
        SerializedBrokeredIdentityContext ctx0 = SerializedBrokeredIdentityContext.readFromAuthenticationSession(authenticationSession, AbstractIdpAuthenticator.BROKERED_CONTEXT_NOTE);
        if (ctx0 != null) {
            SerializedBrokeredIdentityContext ctx1 = SerializedBrokeredIdentityContext.serialize(context);
            ctx1.saveToAuthenticationSession(authenticationSession, AbstractIdpAuthenticator.NESTED_FIRST_BROKER_CONTEXT);
            logger.warnv("Nested first broker flow detected: {0} -> {1}", ctx0.getIdentityProviderId(), ctx1.getIdentityProviderId());
            logger.debug("Resuming last execution");
            URI redirect = new AuthenticationFlowURLHelper(session, realmModel, session.getContext().getUri()).getLastExecutionUrl(authenticationSession);
            return Response.status(Status.FOUND).location(redirect).build();
        }
        logger.debug("Redirecting to flow for firstBrokerLogin");
        boolean forwardedPassiveLogin = "true".equals(authenticationSession.getAuthNote(AuthenticationProcessor.FORWARDED_PASSIVE_LOGIN));
        // Redirect to firstBrokerLogin after successful login and ensure that previous authentication state removed
        AuthenticationProcessor.resetFlow(authenticationSession, LoginActionsService.FIRST_BROKER_LOGIN_PATH);
        // Set the FORWARDED_PASSIVE_LOGIN note (if needed) after resetting the session so it is not lost.
        if (forwardedPassiveLogin) {
            authenticationSession.setAuthNote(AuthenticationProcessor.FORWARDED_PASSIVE_LOGIN, "true");
        }
        SerializedBrokeredIdentityContext ctx = SerializedBrokeredIdentityContext.serialize(context);
        ctx.saveToAuthenticationSession(authenticationSession, AbstractIdpAuthenticator.BROKERED_CONTEXT_NOTE);
        URI redirect = LoginActionsService.firstBrokerLoginProcessor(session.getContext().getUri()).queryParam(Constants.CLIENT_ID, authenticationSession.getClient().getClientId()).queryParam(Constants.TAB_ID, authenticationSession.getTabId()).build(realmModel.getName());
        return Response.status(302).location(redirect).build();
    } else {
        Response response = validateUser(authenticationSession, federatedUser, realmModel);
        if (response != null) {
            return response;
        }
        updateFederatedIdentity(context, federatedUser);
        if (shouldMigrateId) {
            migrateFederatedIdentityId(context, federatedUser);
        }
        authenticationSession.setAuthenticatedUser(federatedUser);
        return finishOrRedirectToPostBrokerLogin(authenticationSession, context, false);
    }
}
Also used : AuthenticationSessionModel(org.keycloak.sessions.AuthenticationSessionModel) RootAuthenticationSessionModel(org.keycloak.sessions.RootAuthenticationSessionModel) UserSessionModel(org.keycloak.models.UserSessionModel) FederatedIdentityModel(org.keycloak.models.FederatedIdentityModel) AuthenticationFlowURLHelper(org.keycloak.services.util.AuthenticationFlowURLHelper) IdentityProviderModel(org.keycloak.models.IdentityProviderModel) SerializedBrokeredIdentityContext(org.keycloak.authentication.authenticators.broker.util.SerializedBrokeredIdentityContext) KeycloakSessionFactory(org.keycloak.models.KeycloakSessionFactory) URI(java.net.URI) StatusResponseType(org.keycloak.dom.saml.v2.protocol.StatusResponseType) UserModel(org.keycloak.models.UserModel) AuthenticationSessionManager(org.keycloak.services.managers.AuthenticationSessionManager) Response(javax.ws.rs.core.Response) ErrorResponse(org.keycloak.services.ErrorResponse) IdentityProviderMapper(org.keycloak.broker.provider.IdentityProviderMapper) SamlAuthenticationPreprocessor(org.keycloak.protocol.saml.preprocessor.SamlAuthenticationPreprocessor)

Example 4 with IdentityProviderMapper

use of org.keycloak.broker.provider.IdentityProviderMapper in project keycloak by keycloak.

the class IdentityBrokerService method updateFederatedIdentity.

private void updateFederatedIdentity(BrokeredIdentityContext context, UserModel federatedUser) {
    FederatedIdentityModel federatedIdentityModel = this.session.users().getFederatedIdentity(this.realmModel, federatedUser, context.getIdpConfig().getAlias());
    if (context.getIdpConfig().getSyncMode() == IdentityProviderSyncMode.FORCE) {
        setBasicUserAttributes(context, federatedUser);
    }
    // Skip DB write if tokens are null or equal
    updateToken(context, federatedUser, federatedIdentityModel);
    context.getIdp().updateBrokeredUser(session, realmModel, federatedUser, context);
    KeycloakSessionFactory sessionFactory = session.getKeycloakSessionFactory();
    realmModel.getIdentityProviderMappersByAliasStream(context.getIdpConfig().getAlias()).forEach(mapper -> {
        IdentityProviderMapper target = (IdentityProviderMapper) sessionFactory.getProviderFactory(IdentityProviderMapper.class, mapper.getIdentityProviderMapper());
        IdentityProviderMapperSyncModeDelegate.delegateUpdateBrokeredUser(session, realmModel, federatedUser, mapper, context, target);
    });
}
Also used : FederatedIdentityModel(org.keycloak.models.FederatedIdentityModel) IdentityProviderMapper(org.keycloak.broker.provider.IdentityProviderMapper) KeycloakSessionFactory(org.keycloak.models.KeycloakSessionFactory)

Example 5 with IdentityProviderMapper

use of org.keycloak.broker.provider.IdentityProviderMapper in project keycloak by keycloak.

the class IdentityBrokerService method afterFirstBrokerLogin.

private Response afterFirstBrokerLogin(AuthenticationSessionModel authSession) {
    try {
        this.event.detail(Details.CODE_ID, authSession.getParentSession().getId()).removeDetail("auth_method");
        SerializedBrokeredIdentityContext serializedCtx = SerializedBrokeredIdentityContext.readFromAuthenticationSession(authSession, AbstractIdpAuthenticator.BROKERED_CONTEXT_NOTE);
        if (serializedCtx == null) {
            throw new IdentityBrokerException("Not found serialized context in clientSession");
        }
        BrokeredIdentityContext context = serializedCtx.deserialize(session, authSession);
        String providerId = context.getIdpConfig().getAlias();
        event.detail(Details.IDENTITY_PROVIDER, providerId);
        event.detail(Details.IDENTITY_PROVIDER_USERNAME, context.getUsername());
        // Ensure the first-broker-login flow was successfully finished
        String authProvider = authSession.getAuthNote(AbstractIdpAuthenticator.FIRST_BROKER_LOGIN_SUCCESS);
        if (authProvider == null || !authProvider.equals(providerId)) {
            throw new IdentityBrokerException("Invalid request. Not found the flag that first-broker-login flow was finished");
        }
        // firstBrokerLogin workflow finished. Removing note now
        authSession.removeAuthNote(AbstractIdpAuthenticator.BROKERED_CONTEXT_NOTE);
        UserModel federatedUser = authSession.getAuthenticatedUser();
        if (federatedUser == null) {
            throw new IdentityBrokerException("Couldn't found authenticated federatedUser in authentication session");
        }
        event.user(federatedUser);
        event.detail(Details.USERNAME, federatedUser.getUsername());
        if (context.getIdpConfig().isAddReadTokenRoleOnCreate()) {
            ClientModel brokerClient = realmModel.getClientByClientId(Constants.BROKER_SERVICE_CLIENT_ID);
            if (brokerClient == null) {
                throw new IdentityBrokerException("Client 'broker' not available. Maybe realm has not migrated to support the broker token exchange service");
            }
            RoleModel readTokenRole = brokerClient.getRole(Constants.READ_TOKEN_ROLE);
            federatedUser.grantRole(readTokenRole);
        }
        // Add federated identity link here
        FederatedIdentityModel federatedIdentityModel = new FederatedIdentityModel(context.getIdpConfig().getAlias(), context.getId(), context.getUsername(), context.getToken());
        session.users().addFederatedIdentity(realmModel, federatedUser, federatedIdentityModel);
        String isRegisteredNewUser = authSession.getAuthNote(AbstractIdpAuthenticator.BROKER_REGISTERED_NEW_USER);
        if (Boolean.parseBoolean(isRegisteredNewUser)) {
            logger.debugf("Registered new user '%s' after first login with identity provider '%s'. Identity provider username is '%s' . ", federatedUser.getUsername(), providerId, context.getUsername());
            context.getIdp().importNewUser(session, realmModel, federatedUser, context);
            KeycloakSessionFactory sessionFactory = session.getKeycloakSessionFactory();
            realmModel.getIdentityProviderMappersByAliasStream(providerId).forEach(mapper -> {
                IdentityProviderMapper target = (IdentityProviderMapper) sessionFactory.getProviderFactory(IdentityProviderMapper.class, mapper.getIdentityProviderMapper());
                target.importNewUser(session, realmModel, federatedUser, mapper, context);
            });
            if (context.getIdpConfig().isTrustEmail() && !Validation.isBlank(federatedUser.getEmail()) && !Boolean.parseBoolean(authSession.getAuthNote(AbstractIdpAuthenticator.UPDATE_PROFILE_EMAIL_CHANGED))) {
                logger.debugf("Email verified automatically after registration of user '%s' through Identity provider '%s' ", federatedUser.getUsername(), context.getIdpConfig().getAlias());
                federatedUser.setEmailVerified(true);
            }
            event.event(EventType.REGISTER).detail(Details.REGISTER_METHOD, "broker").detail(Details.EMAIL, federatedUser.getEmail()).success();
        } else {
            logger.debugf("Linked existing keycloak user '%s' with identity provider '%s' . Identity provider username is '%s' .", federatedUser.getUsername(), providerId, context.getUsername());
            event.event(EventType.FEDERATED_IDENTITY_LINK).success();
            updateFederatedIdentity(context, federatedUser);
        }
        return finishOrRedirectToPostBrokerLogin(authSession, context, true);
    } catch (Exception e) {
        return redirectToErrorPage(authSession, Response.Status.INTERNAL_SERVER_ERROR, Messages.IDENTITY_PROVIDER_UNEXPECTED_ERROR, e);
    }
}
Also used : UserModel(org.keycloak.models.UserModel) ClientModel(org.keycloak.models.ClientModel) IdentityBrokerException(org.keycloak.broker.provider.IdentityBrokerException) FederatedIdentityModel(org.keycloak.models.FederatedIdentityModel) IdentityProviderMapper(org.keycloak.broker.provider.IdentityProviderMapper) RoleModel(org.keycloak.models.RoleModel) SerializedBrokeredIdentityContext(org.keycloak.authentication.authenticators.broker.util.SerializedBrokeredIdentityContext) KeycloakSessionFactory(org.keycloak.models.KeycloakSessionFactory) BrokeredIdentityContext(org.keycloak.broker.provider.BrokeredIdentityContext) SerializedBrokeredIdentityContext(org.keycloak.authentication.authenticators.broker.util.SerializedBrokeredIdentityContext) 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

IdentityProviderMapper (org.keycloak.broker.provider.IdentityProviderMapper)5 FederatedIdentityModel (org.keycloak.models.FederatedIdentityModel)4 KeycloakSessionFactory (org.keycloak.models.KeycloakSessionFactory)4 UserModel (org.keycloak.models.UserModel)3 URI (java.net.URI)2 SerializedBrokeredIdentityContext (org.keycloak.authentication.authenticators.broker.util.SerializedBrokeredIdentityContext)2 IdentityBrokerException (org.keycloak.broker.provider.IdentityBrokerException)2 IdentityProviderModel (org.keycloak.models.IdentityProviderModel)2 IOException (java.io.IOException)1 StringWriter (java.io.StringWriter)1 KeyPair (java.security.KeyPair)1 NoSuchAlgorithmException (java.security.NoSuchAlgorithmException)1 ArrayList (java.util.ArrayList)1 LinkedList (java.util.LinkedList)1 Entry (java.util.Map.Entry)1 NotFoundException (javax.ws.rs.NotFoundException)1 WebApplicationException (javax.ws.rs.WebApplicationException)1 Response (javax.ws.rs.core.Response)1 ParserConfigurationException (javax.xml.parsers.ParserConfigurationException)1 XMLStreamWriter (javax.xml.stream.XMLStreamWriter)1