Search in sources :

Example 1 with SerializedBrokeredIdentityContext

use of org.keycloak.authentication.authenticators.broker.util.SerializedBrokeredIdentityContext in project keycloak by keycloak.

the class AbstractIdpAuthenticator method action.

@Override
public void action(AuthenticationFlowContext context) {
    AuthenticationSessionModel clientSession = context.getAuthenticationSession();
    SerializedBrokeredIdentityContext serializedCtx = SerializedBrokeredIdentityContext.readFromAuthenticationSession(clientSession, BROKERED_CONTEXT_NOTE);
    if (serializedCtx == null) {
        throw new AuthenticationFlowException("Not found serialized context in clientSession", AuthenticationFlowError.IDENTITY_PROVIDER_ERROR);
    }
    BrokeredIdentityContext brokerContext = serializedCtx.deserialize(context.getSession(), clientSession);
    if (!brokerContext.getIdpConfig().isEnabled()) {
        sendFailureChallenge(context, Response.Status.BAD_REQUEST, Errors.IDENTITY_PROVIDER_ERROR, Messages.IDENTITY_PROVIDER_UNEXPECTED_ERROR, AuthenticationFlowError.IDENTITY_PROVIDER_ERROR);
    }
    actionImpl(context, serializedCtx, brokerContext);
}
Also used : AuthenticationSessionModel(org.keycloak.sessions.AuthenticationSessionModel) AuthenticationFlowException(org.keycloak.authentication.AuthenticationFlowException) SerializedBrokeredIdentityContext(org.keycloak.authentication.authenticators.broker.util.SerializedBrokeredIdentityContext) BrokeredIdentityContext(org.keycloak.broker.provider.BrokeredIdentityContext) SerializedBrokeredIdentityContext(org.keycloak.authentication.authenticators.broker.util.SerializedBrokeredIdentityContext)

Example 2 with SerializedBrokeredIdentityContext

use of org.keycloak.authentication.authenticators.broker.util.SerializedBrokeredIdentityContext in project keycloak by keycloak.

the class LoginFormsUtil method filterIdentityProviders.

public static List<IdentityProviderModel> filterIdentityProviders(Stream<IdentityProviderModel> providers, KeycloakSession session, AuthenticationFlowContext context) {
    if (context != null) {
        AuthenticationSessionModel authSession = context.getAuthenticationSession();
        SerializedBrokeredIdentityContext serializedCtx = SerializedBrokeredIdentityContext.readFromAuthenticationSession(authSession, AbstractIdpAuthenticator.BROKERED_CONTEXT_NOTE);
        final IdentityProviderModel existingIdp = (serializedCtx == null) ? null : serializedCtx.deserialize(session, authSession).getIdpConfig();
        final Set<String> federatedIdentities;
        if (context.getUser() != null) {
            federatedIdentities = session.users().getFederatedIdentitiesStream(session.getContext().getRealm(), context.getUser()).map(federatedIdentityModel -> federatedIdentityModel.getIdentityProvider()).collect(Collectors.toSet());
        } else {
            federatedIdentities = null;
        }
        return providers.filter(p -> {
            // Filter current IDP during first-broker-login flow. Re-authentication with the "linked" broker should not be possible
            if (existingIdp == null)
                return true;
            return !Objects.equals(p.getAlias(), existingIdp.getAlias());
        }).filter(idp -> {
            // In case that we already have user established in authentication session, we show just providers already linked to this user
            if (federatedIdentities == null)
                return true;
            return federatedIdentities.contains(idp.getAlias());
        }).collect(Collectors.toList());
    }
    return providers.collect(Collectors.toList());
}
Also used : AuthenticationSessionModel(org.keycloak.sessions.AuthenticationSessionModel) RealmModel(org.keycloak.models.RealmModel) AbstractIdpAuthenticator(org.keycloak.authentication.authenticators.broker.AbstractIdpAuthenticator) KeycloakSession(org.keycloak.models.KeycloakSession) Set(java.util.Set) IdentityProviderModel(org.keycloak.models.IdentityProviderModel) Collectors(java.util.stream.Collectors) MultivaluedMap(javax.ws.rs.core.MultivaluedMap) Objects(java.util.Objects) List(java.util.List) UserModel(org.keycloak.models.UserModel) Stream(java.util.stream.Stream) SerializedBrokeredIdentityContext(org.keycloak.authentication.authenticators.broker.util.SerializedBrokeredIdentityContext) Map(java.util.Map) LoginFormsProvider(org.keycloak.forms.login.LoginFormsProvider) AuthenticationFlowContext(org.keycloak.authentication.AuthenticationFlowContext) LinkedList(java.util.LinkedList) AuthenticationSessionModel(org.keycloak.sessions.AuthenticationSessionModel) SerializedBrokeredIdentityContext(org.keycloak.authentication.authenticators.broker.util.SerializedBrokeredIdentityContext) IdentityProviderModel(org.keycloak.models.IdentityProviderModel)

Example 3 with SerializedBrokeredIdentityContext

use of org.keycloak.authentication.authenticators.broker.util.SerializedBrokeredIdentityContext in project keycloak by keycloak.

the class LoginActionsService method brokerLoginFlow.

protected Response brokerLoginFlow(String authSessionId, String code, String execution, String clientId, String tabId, String flowPath) {
    boolean firstBrokerLogin = flowPath.equals(FIRST_BROKER_LOGIN_PATH);
    EventType eventType = firstBrokerLogin ? EventType.IDENTITY_PROVIDER_FIRST_LOGIN : EventType.IDENTITY_PROVIDER_POST_LOGIN;
    event.event(eventType);
    SessionCodeChecks checks = checksForCode(authSessionId, code, execution, clientId, tabId, flowPath);
    if (!checks.verifyActiveAndValidAction(AuthenticationSessionModel.Action.AUTHENTICATE.name(), ClientSessionCode.ActionType.LOGIN)) {
        return checks.getResponse();
    }
    event.detail(Details.CODE_ID, code);
    final AuthenticationSessionModel authSession = checks.getAuthenticationSession();
    processLocaleParam(authSession);
    String noteKey = firstBrokerLogin ? AbstractIdpAuthenticator.BROKERED_CONTEXT_NOTE : PostBrokerLoginConstants.PBL_BROKERED_IDENTITY_CONTEXT;
    SerializedBrokeredIdentityContext serializedCtx = SerializedBrokeredIdentityContext.readFromAuthenticationSession(authSession, noteKey);
    if (serializedCtx == null) {
        ServicesLogger.LOGGER.notFoundSerializedCtxInClientSession(noteKey);
        throw new WebApplicationException(ErrorPage.error(session, authSession, Response.Status.BAD_REQUEST, "Not found serialized context in authenticationSession."));
    }
    BrokeredIdentityContext brokerContext = serializedCtx.deserialize(session, authSession);
    final String identityProviderAlias = brokerContext.getIdpConfig().getAlias();
    String flowId = firstBrokerLogin ? brokerContext.getIdpConfig().getFirstBrokerLoginFlowId() : brokerContext.getIdpConfig().getPostBrokerLoginFlowId();
    if (flowId == null) {
        ServicesLogger.LOGGER.flowNotConfigForIDP(identityProviderAlias);
        throw new WebApplicationException(ErrorPage.error(session, authSession, Response.Status.BAD_REQUEST, "Flow not configured for identity provider"));
    }
    AuthenticationFlowModel brokerLoginFlow = realm.getAuthenticationFlowById(flowId);
    if (brokerLoginFlow == null) {
        ServicesLogger.LOGGER.flowNotFoundForIDP(flowId, identityProviderAlias);
        throw new WebApplicationException(ErrorPage.error(session, authSession, Response.Status.BAD_REQUEST, "Flow not found for identity provider"));
    }
    event.detail(Details.IDENTITY_PROVIDER, identityProviderAlias).detail(Details.IDENTITY_PROVIDER_USERNAME, brokerContext.getUsername());
    AuthenticationProcessor processor = new AuthenticationProcessor() {

        @Override
        public Response authenticateOnly() throws AuthenticationFlowException {
            Response challenge = super.authenticateOnly();
            if (challenge != null) {
                if ("true".equals(authenticationSession.getAuthNote(FORWARDED_PASSIVE_LOGIN))) {
                    // forwarded passive login is incompatible with challenges created by the broker flows.
                    logger.errorf("Challenge encountered when executing %s flow. Auth requests with prompt=none are incompatible with challenges", flowPath);
                    LoginProtocol protocol = session.getProvider(LoginProtocol.class, authSession.getProtocol());
                    protocol.setRealm(realm).setHttpHeaders(headers).setUriInfo(session.getContext().getUri()).setEventBuilder(event);
                    return protocol.sendError(authSession, Error.PASSIVE_INTERACTION_REQUIRED);
                }
            }
            return challenge;
        }

        @Override
        protected Response authenticationComplete() {
            if (firstBrokerLogin) {
                authSession.setAuthNote(AbstractIdpAuthenticator.FIRST_BROKER_LOGIN_SUCCESS, identityProviderAlias);
            } else {
                String authStateNoteKey = PostBrokerLoginConstants.PBL_AUTH_STATE_PREFIX + identityProviderAlias;
                authSession.setAuthNote(authStateNoteKey, "true");
            }
            return redirectToAfterBrokerLoginEndpoint(authSession, firstBrokerLogin);
        }
    };
    return processFlow(checks.isActionRequest(), execution, authSession, flowPath, brokerLoginFlow, null, processor);
}
Also used : Response(javax.ws.rs.core.Response) AuthenticationSessionModel(org.keycloak.sessions.AuthenticationSessionModel) RootAuthenticationSessionModel(org.keycloak.sessions.RootAuthenticationSessionModel) WebApplicationException(javax.ws.rs.WebApplicationException) EventType(org.keycloak.events.EventType) AuthenticationFlowModel(org.keycloak.models.AuthenticationFlowModel) SerializedBrokeredIdentityContext(org.keycloak.authentication.authenticators.broker.util.SerializedBrokeredIdentityContext) AuthenticationProcessor(org.keycloak.authentication.AuthenticationProcessor) OIDCLoginProtocol(org.keycloak.protocol.oidc.OIDCLoginProtocol) LoginProtocol(org.keycloak.protocol.LoginProtocol) BrokeredIdentityContext(org.keycloak.broker.provider.BrokeredIdentityContext) SerializedBrokeredIdentityContext(org.keycloak.authentication.authenticators.broker.util.SerializedBrokeredIdentityContext)

Example 4 with SerializedBrokeredIdentityContext

use of org.keycloak.authentication.authenticators.broker.util.SerializedBrokeredIdentityContext in project keycloak by keycloak.

the class IdentityBrokerService method finishOrRedirectToPostBrokerLogin.

private Response finishOrRedirectToPostBrokerLogin(AuthenticationSessionModel authSession, BrokeredIdentityContext context, boolean wasFirstBrokerLogin) {
    String postBrokerLoginFlowId = context.getIdpConfig().getPostBrokerLoginFlowId();
    if (postBrokerLoginFlowId == null) {
        logger.debugf("Skip redirect to postBrokerLogin flow. PostBrokerLogin flow not set for identityProvider '%s'.", context.getIdpConfig().getAlias());
        return afterPostBrokerLoginFlowSuccess(authSession, context, wasFirstBrokerLogin);
    } else {
        logger.debugf("Redirect to postBrokerLogin flow after authentication with identityProvider '%s'.", context.getIdpConfig().getAlias());
        authSession.getParentSession().setTimestamp(Time.currentTime());
        SerializedBrokeredIdentityContext ctx = SerializedBrokeredIdentityContext.serialize(context);
        ctx.saveToAuthenticationSession(authSession, PostBrokerLoginConstants.PBL_BROKERED_IDENTITY_CONTEXT);
        authSession.setAuthNote(PostBrokerLoginConstants.PBL_AFTER_FIRST_BROKER_LOGIN, String.valueOf(wasFirstBrokerLogin));
        URI redirect = LoginActionsService.postBrokerLoginProcessor(session.getContext().getUri()).queryParam(Constants.CLIENT_ID, authSession.getClient().getClientId()).queryParam(Constants.TAB_ID, authSession.getTabId()).build(realmModel.getName());
        return Response.status(302).location(redirect).build();
    }
}
Also used : SerializedBrokeredIdentityContext(org.keycloak.authentication.authenticators.broker.util.SerializedBrokeredIdentityContext) URI(java.net.URI)

Example 5 with SerializedBrokeredIdentityContext

use of org.keycloak.authentication.authenticators.broker.util.SerializedBrokeredIdentityContext in project keycloak by keycloak.

the class IdentityBrokerService method afterPostBrokerLoginFlowSuccess.

private Response afterPostBrokerLoginFlowSuccess(AuthenticationSessionModel authSession, BrokeredIdentityContext context, boolean wasFirstBrokerLogin) {
    String providerId = context.getIdpConfig().getAlias();
    UserModel federatedUser = authSession.getAuthenticatedUser();
    if (wasFirstBrokerLogin) {
        return finishBrokerAuthentication(context, federatedUser, authSession, providerId);
    } else {
        boolean firstBrokerLoginInProgress = (authSession.getAuthNote(AbstractIdpAuthenticator.BROKERED_CONTEXT_NOTE) != null);
        if (firstBrokerLoginInProgress) {
            logger.debugf("Reauthenticated with broker '%s' when linking user '%s' with other broker", context.getIdpConfig().getAlias(), federatedUser.getUsername());
            SerializedBrokeredIdentityContext serializedCtx = SerializedBrokeredIdentityContext.readFromAuthenticationSession(authSession, AbstractIdpAuthenticator.BROKERED_CONTEXT_NOTE);
            authSession.setAuthNote(AbstractIdpAuthenticator.FIRST_BROKER_LOGIN_SUCCESS, serializedCtx.getIdentityProviderId());
            return afterFirstBrokerLogin(authSession);
        } else {
            return finishBrokerAuthentication(context, federatedUser, authSession, providerId);
        }
    }
}
Also used : UserModel(org.keycloak.models.UserModel) SerializedBrokeredIdentityContext(org.keycloak.authentication.authenticators.broker.util.SerializedBrokeredIdentityContext)

Aggregations

SerializedBrokeredIdentityContext (org.keycloak.authentication.authenticators.broker.util.SerializedBrokeredIdentityContext)10 BrokeredIdentityContext (org.keycloak.broker.provider.BrokeredIdentityContext)6 AuthenticationSessionModel (org.keycloak.sessions.AuthenticationSessionModel)6 UserModel (org.keycloak.models.UserModel)4 AuthenticationFlowException (org.keycloak.authentication.AuthenticationFlowException)3 RootAuthenticationSessionModel (org.keycloak.sessions.RootAuthenticationSessionModel)3 URI (java.net.URI)2 WebApplicationException (javax.ws.rs.WebApplicationException)2 Response (javax.ws.rs.core.Response)2 IdentityBrokerException (org.keycloak.broker.provider.IdentityBrokerException)2 IdentityProviderMapper (org.keycloak.broker.provider.IdentityProviderMapper)2 LoginFormsProvider (org.keycloak.forms.login.LoginFormsProvider)2 FederatedIdentityModel (org.keycloak.models.FederatedIdentityModel)2 IdentityProviderModel (org.keycloak.models.IdentityProviderModel)2 KeycloakSessionFactory (org.keycloak.models.KeycloakSessionFactory)2 IOException (java.io.IOException)1 NoSuchAlgorithmException (java.security.NoSuchAlgorithmException)1 LinkedList (java.util.LinkedList)1 List (java.util.List)1 Map (java.util.Map)1