Search in sources :

Example 1 with IdentityProvider

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

the class DefaultTokenExchangeProvider method exchangeToIdentityProvider.

protected Response exchangeToIdentityProvider(UserModel targetUser, UserSessionModel targetUserSession, String requestedIssuer) {
    event.detail(Details.REQUESTED_ISSUER, requestedIssuer);
    IdentityProviderModel providerModel = realm.getIdentityProviderByAlias(requestedIssuer);
    if (providerModel == null) {
        event.detail(Details.REASON, "unknown requested_issuer");
        event.error(Errors.UNKNOWN_IDENTITY_PROVIDER);
        throw new CorsErrorResponseException(cors, OAuthErrorException.INVALID_REQUEST, "Invalid issuer", Response.Status.BAD_REQUEST);
    }
    IdentityProvider provider = IdentityBrokerService.getIdentityProvider(session, realm, requestedIssuer);
    if (!(provider instanceof ExchangeTokenToIdentityProviderToken)) {
        event.detail(Details.REASON, "exchange unsupported by requested_issuer");
        event.error(Errors.UNKNOWN_IDENTITY_PROVIDER);
        throw new CorsErrorResponseException(cors, OAuthErrorException.INVALID_REQUEST, "Issuer does not support token exchange", Response.Status.BAD_REQUEST);
    }
    if (!AdminPermissions.management(session, realm).idps().canExchangeTo(client, providerModel)) {
        event.detail(Details.REASON, "client not allowed to exchange for requested_issuer");
        event.error(Errors.NOT_ALLOWED);
        throw new CorsErrorResponseException(cors, OAuthErrorException.ACCESS_DENIED, "Client not allowed to exchange", Response.Status.FORBIDDEN);
    }
    Response response = ((ExchangeTokenToIdentityProviderToken) provider).exchangeFromToken(session.getContext().getUri(), event, client, targetUserSession, targetUser, formParams);
    return cors.builder(Response.fromResponse(response)).build();
}
Also used : AccessTokenResponse(org.keycloak.representations.AccessTokenResponse) Response(javax.ws.rs.core.Response) ExchangeTokenToIdentityProviderToken(org.keycloak.broker.provider.ExchangeTokenToIdentityProviderToken) IdentityProvider(org.keycloak.broker.provider.IdentityProvider) IdentityProviderModel(org.keycloak.models.IdentityProviderModel) CorsErrorResponseException(org.keycloak.services.CorsErrorResponseException)

Example 2 with IdentityProvider

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

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

the class AuthenticationManager method browserLogout.

public static Response browserLogout(KeycloakSession session, RealmModel realm, UserSessionModel userSession, UriInfo uriInfo, ClientConnection connection, HttpHeaders headers, String initiatingIdp) {
    if (userSession == null)
        return null;
    if (logger.isDebugEnabled()) {
        UserModel user = userSession.getUser();
        logger.debugv("Logging out: {0} ({1})", user.getUsername(), userSession.getId());
    }
    if (userSession.getState() != UserSessionModel.State.LOGGING_OUT) {
        userSession.setState(UserSessionModel.State.LOGGING_OUT);
    }
    final AuthenticationSessionManager asm = new AuthenticationSessionManager(session);
    AuthenticationSessionModel logoutAuthSession = createOrJoinLogoutSession(session, realm, asm, userSession, true);
    Response response = browserLogoutAllClients(userSession, session, realm, headers, uriInfo, logoutAuthSession);
    if (response != null) {
        return response;
    }
    String brokerId = userSession.getNote(Details.IDENTITY_PROVIDER);
    if (brokerId != null && !brokerId.equals(initiatingIdp)) {
        IdentityProvider identityProvider = IdentityBrokerService.getIdentityProvider(session, realm, brokerId);
        response = identityProvider.keycloakInitiatedBrowserLogout(session, userSession, uriInfo, realm);
        if (response != null) {
            return response;
        }
    }
    return finishBrowserLogout(session, realm, userSession, uriInfo, connection, headers);
}
Also used : UserModel(org.keycloak.models.UserModel) BackchannelLogoutResponse(org.keycloak.protocol.oidc.BackchannelLogoutResponse) Response(javax.ws.rs.core.Response) AuthenticationSessionModel(org.keycloak.sessions.AuthenticationSessionModel) RootAuthenticationSessionModel(org.keycloak.sessions.RootAuthenticationSessionModel) IdentityProvider(org.keycloak.broker.provider.IdentityProvider)

Example 4 with IdentityProvider

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

use of org.keycloak.broker.provider.IdentityProvider 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

IdentityProvider (org.keycloak.broker.provider.IdentityProvider)9 Response (javax.ws.rs.core.Response)6 IdentityProviderModel (org.keycloak.models.IdentityProviderModel)6 IOException (java.io.IOException)4 NotFoundException (javax.ws.rs.NotFoundException)4 OAuthErrorException (org.keycloak.OAuthErrorException)4 IdentityBrokerException (org.keycloak.broker.provider.IdentityBrokerException)4 SocialIdentityProvider (org.keycloak.broker.social.SocialIdentityProvider)4 AuthenticationSessionModel (org.keycloak.sessions.AuthenticationSessionModel)4 RootAuthenticationSessionModel (org.keycloak.sessions.RootAuthenticationSessionModel)4 NoSuchAlgorithmException (java.security.NoSuchAlgorithmException)3 Path (javax.ws.rs.Path)3 WebApplicationException (javax.ws.rs.WebApplicationException)3 ClientModel (org.keycloak.models.ClientModel)3 ErrorPageException (org.keycloak.services.ErrorPageException)3 AuthenticationManager (org.keycloak.services.managers.AuthenticationManager)3 Map (java.util.Map)2 GET (javax.ws.rs.GET)2 NoCache (org.jboss.resteasy.annotations.cache.NoCache)2 BrokeredIdentityContext (org.keycloak.broker.provider.BrokeredIdentityContext)2