Search in sources :

Example 1 with SamlAuthenticationPreprocessor

use of org.keycloak.protocol.saml.preprocessor.SamlAuthenticationPreprocessor in project keycloak by keycloak.

the class SAMLIdentityProvider method buildLogoutRequest.

protected LogoutRequestType buildLogoutRequest(UserSessionModel userSession, UriInfo uriInfo, RealmModel realm, String singleLogoutServiceUrl, NodeGenerator... extensions) throws ConfigurationException {
    SAML2LogoutRequestBuilder logoutBuilder = new SAML2LogoutRequestBuilder().assertionExpiration(realm.getAccessCodeLifespan()).issuer(getEntityId(uriInfo, realm)).sessionIndex(userSession.getNote(SAMLEndpoint.SAML_FEDERATED_SESSION_INDEX)).nameId(NameIDType.deserializeFromString(userSession.getNote(SAMLEndpoint.SAML_FEDERATED_SUBJECT_NAMEID))).destination(singleLogoutServiceUrl);
    LogoutRequestType logoutRequest = logoutBuilder.createLogoutRequest();
    for (NodeGenerator extension : extensions) {
        logoutBuilder.addExtension(extension);
    }
    for (Iterator<SamlAuthenticationPreprocessor> it = SamlSessionUtils.getSamlAuthenticationPreprocessorIterator(session); it.hasNext(); ) {
        logoutRequest = it.next().beforeSendingLogoutRequest(logoutRequest, userSession, null);
    }
    return logoutRequest;
}
Also used : LogoutRequestType(org.keycloak.dom.saml.v2.protocol.LogoutRequestType) SamlAuthenticationPreprocessor(org.keycloak.protocol.saml.preprocessor.SamlAuthenticationPreprocessor) SAML2LogoutRequestBuilder(org.keycloak.saml.SAML2LogoutRequestBuilder) NodeGenerator(org.keycloak.saml.SamlProtocolExtensionsAwareBuilder.NodeGenerator)

Example 2 with SamlAuthenticationPreprocessor

use of org.keycloak.protocol.saml.preprocessor.SamlAuthenticationPreprocessor in project keycloak by keycloak.

the class SAMLIdentityProvider method performLogin.

@Override
public Response performLogin(AuthenticationRequest request) {
    try {
        UriInfo uriInfo = request.getUriInfo();
        RealmModel realm = request.getRealm();
        String issuerURL = getEntityId(uriInfo, realm);
        String destinationUrl = getConfig().getSingleSignOnServiceUrl();
        String nameIDPolicyFormat = getConfig().getNameIDPolicyFormat();
        if (nameIDPolicyFormat == null) {
            nameIDPolicyFormat = JBossSAMLURIConstants.NAMEID_FORMAT_PERSISTENT.get();
        }
        String protocolBinding = JBossSAMLURIConstants.SAML_HTTP_REDIRECT_BINDING.get();
        String assertionConsumerServiceUrl = request.getRedirectUri();
        if (getConfig().isPostBindingResponse()) {
            protocolBinding = JBossSAMLURIConstants.SAML_HTTP_POST_BINDING.get();
        }
        SAML2RequestedAuthnContextBuilder requestedAuthnContext = new SAML2RequestedAuthnContextBuilder().setComparison(getConfig().getAuthnContextComparisonType());
        for (String authnContextClassRef : getAuthnContextClassRefUris()) requestedAuthnContext.addAuthnContextClassRef(authnContextClassRef);
        for (String authnContextDeclRef : getAuthnContextDeclRefUris()) requestedAuthnContext.addAuthnContextDeclRef(authnContextDeclRef);
        Integer attributeConsumingServiceIndex = getConfig().getAttributeConsumingServiceIndex();
        String loginHint = getConfig().isLoginHint() ? request.getAuthenticationSession().getClientNote(OIDCLoginProtocol.LOGIN_HINT_PARAM) : null;
        Boolean allowCreate = null;
        if (getConfig().getConfig().get(SAMLIdentityProviderConfig.ALLOW_CREATE) == null || getConfig().isAllowCreate())
            allowCreate = Boolean.TRUE;
        SAML2AuthnRequestBuilder authnRequestBuilder = new SAML2AuthnRequestBuilder().assertionConsumerUrl(assertionConsumerServiceUrl).destination(destinationUrl).issuer(issuerURL).forceAuthn(getConfig().isForceAuthn()).protocolBinding(protocolBinding).nameIdPolicy(SAML2NameIDPolicyBuilder.format(nameIDPolicyFormat).setAllowCreate(allowCreate)).attributeConsumingServiceIndex(attributeConsumingServiceIndex).requestedAuthnContext(requestedAuthnContext).subject(loginHint);
        JaxrsSAML2BindingBuilder binding = new JaxrsSAML2BindingBuilder(session).relayState(request.getState().getEncoded());
        boolean postBinding = getConfig().isPostBindingAuthnRequest();
        if (getConfig().isWantAuthnRequestsSigned()) {
            KeyManager.ActiveRsaKey keys = session.keys().getActiveRsaKey(realm);
            String keyName = getConfig().getXmlSigKeyInfoKeyNameTransformer().getKeyName(keys.getKid(), keys.getCertificate());
            binding.signWith(keyName, keys.getPrivateKey(), keys.getPublicKey(), keys.getCertificate()).signatureAlgorithm(getSignatureAlgorithm()).signDocument();
            if (!postBinding && getConfig().isAddExtensionsElementWithKeyInfo()) {
                // Only include extension if REDIRECT binding and signing whole SAML protocol message
                authnRequestBuilder.addExtension(new KeycloakKeySamlExtensionGenerator(keyName));
            }
        }
        AuthnRequestType authnRequest = authnRequestBuilder.createAuthnRequest();
        for (Iterator<SamlAuthenticationPreprocessor> it = SamlSessionUtils.getSamlAuthenticationPreprocessorIterator(session); it.hasNext(); ) {
            authnRequest = it.next().beforeSendingLoginRequest(authnRequest, request.getAuthenticationSession());
        }
        if (authnRequest.getDestination() != null) {
            destinationUrl = authnRequest.getDestination().toString();
        }
        // Save the current RequestID in the Auth Session as we need to verify it against the ID returned from the IdP
        request.getAuthenticationSession().setClientNote(SamlProtocol.SAML_REQUEST_ID_BROKER, authnRequest.getID());
        if (postBinding) {
            return binding.postBinding(authnRequestBuilder.toDocument()).request(destinationUrl);
        } else {
            return binding.redirectBinding(authnRequestBuilder.toDocument()).request(destinationUrl);
        }
    } catch (Exception e) {
        throw new IdentityBrokerException("Could not create authentication request.", e);
    }
}
Also used : SAML2RequestedAuthnContextBuilder(org.keycloak.saml.SAML2RequestedAuthnContextBuilder) JaxrsSAML2BindingBuilder(org.keycloak.protocol.saml.JaxrsSAML2BindingBuilder) KeycloakKeySamlExtensionGenerator(org.keycloak.saml.processing.core.util.KeycloakKeySamlExtensionGenerator) ConfigurationException(org.keycloak.saml.common.exceptions.ConfigurationException) IdentityBrokerException(org.keycloak.broker.provider.IdentityBrokerException) ParserConfigurationException(javax.xml.parsers.ParserConfigurationException) RealmModel(org.keycloak.models.RealmModel) AuthnRequestType(org.keycloak.dom.saml.v2.protocol.AuthnRequestType) IdentityBrokerException(org.keycloak.broker.provider.IdentityBrokerException) SamlAuthenticationPreprocessor(org.keycloak.protocol.saml.preprocessor.SamlAuthenticationPreprocessor) SAML2AuthnRequestBuilder(org.keycloak.saml.SAML2AuthnRequestBuilder) KeyManager(org.keycloak.models.KeyManager) UriInfo(javax.ws.rs.core.UriInfo)

Example 3 with SamlAuthenticationPreprocessor

use of org.keycloak.protocol.saml.preprocessor.SamlAuthenticationPreprocessor 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 SamlAuthenticationPreprocessor

use of org.keycloak.protocol.saml.preprocessor.SamlAuthenticationPreprocessor in project keycloak by keycloak.

the class SamlProtocol method createLogoutRequest.

protected LogoutRequestType createLogoutRequest(String logoutUrl, AuthenticatedClientSessionModel clientSession, ClientModel client, NodeGenerator... extensions) throws ConfigurationException {
    // build userPrincipal with subject used at login
    SAML2LogoutRequestBuilder logoutBuilder = new SAML2LogoutRequestBuilder().assertionExpiration(realm.getAccessCodeLifespan()).issuer(getResponseIssuer(realm)).userPrincipal(clientSession.getNote(SAML_NAME_ID), clientSession.getNote(SAML_NAME_ID_FORMAT)).destination(logoutUrl);
    String sessionIndex = SamlSessionUtils.getSessionIndex(clientSession);
    logoutBuilder.sessionIndex(sessionIndex);
    for (NodeGenerator extension : extensions) {
        logoutBuilder.addExtension(extension);
    }
    LogoutRequestType logoutRequest = logoutBuilder.createLogoutRequest();
    for (Iterator<SamlAuthenticationPreprocessor> it = SamlSessionUtils.getSamlAuthenticationPreprocessorIterator(session); it.hasNext(); ) {
        logoutRequest = it.next().beforeSendingLogoutRequest(logoutRequest, clientSession.getUserSession(), clientSession);
    }
    return logoutRequest;
}
Also used : LogoutRequestType(org.keycloak.dom.saml.v2.protocol.LogoutRequestType) SamlAuthenticationPreprocessor(org.keycloak.protocol.saml.preprocessor.SamlAuthenticationPreprocessor) SAML2LogoutRequestBuilder(org.keycloak.saml.SAML2LogoutRequestBuilder) NodeGenerator(org.keycloak.saml.SamlProtocolExtensionsAwareBuilder.NodeGenerator)

Aggregations

SamlAuthenticationPreprocessor (org.keycloak.protocol.saml.preprocessor.SamlAuthenticationPreprocessor)4 LogoutRequestType (org.keycloak.dom.saml.v2.protocol.LogoutRequestType)2 SAML2LogoutRequestBuilder (org.keycloak.saml.SAML2LogoutRequestBuilder)2 NodeGenerator (org.keycloak.saml.SamlProtocolExtensionsAwareBuilder.NodeGenerator)2 URI (java.net.URI)1 Response (javax.ws.rs.core.Response)1 UriInfo (javax.ws.rs.core.UriInfo)1 ParserConfigurationException (javax.xml.parsers.ParserConfigurationException)1 SerializedBrokeredIdentityContext (org.keycloak.authentication.authenticators.broker.util.SerializedBrokeredIdentityContext)1 IdentityBrokerException (org.keycloak.broker.provider.IdentityBrokerException)1 IdentityProviderMapper (org.keycloak.broker.provider.IdentityProviderMapper)1 AuthnRequestType (org.keycloak.dom.saml.v2.protocol.AuthnRequestType)1 StatusResponseType (org.keycloak.dom.saml.v2.protocol.StatusResponseType)1 FederatedIdentityModel (org.keycloak.models.FederatedIdentityModel)1 IdentityProviderModel (org.keycloak.models.IdentityProviderModel)1 KeyManager (org.keycloak.models.KeyManager)1 KeycloakSessionFactory (org.keycloak.models.KeycloakSessionFactory)1 RealmModel (org.keycloak.models.RealmModel)1 UserModel (org.keycloak.models.UserModel)1 UserSessionModel (org.keycloak.models.UserSessionModel)1