Search in sources :

Example 6 with ClientSessionCode

use of org.keycloak.services.managers.ClientSessionCode in project keycloak by keycloak.

the class IdentityBrokerService method clientInitiatedAccountLinking.

@GET
@NoCache
@Path("/{provider_id}/link")
public Response clientInitiatedAccountLinking(@PathParam("provider_id") String providerId, @QueryParam("redirect_uri") String redirectUri, @QueryParam("client_id") String clientId, @QueryParam("nonce") String nonce, @QueryParam("hash") String hash) {
    this.event.event(EventType.CLIENT_INITIATED_ACCOUNT_LINKING);
    checkRealm();
    ClientModel client = checkClient(clientId);
    redirectUri = RedirectUtils.verifyRedirectUri(session, redirectUri, client);
    if (redirectUri == null) {
        event.error(Errors.INVALID_REDIRECT_URI);
        throw new ErrorPageException(session, Response.Status.BAD_REQUEST, Messages.INVALID_REQUEST);
    }
    event.detail(Details.REDIRECT_URI, redirectUri);
    if (nonce == null || hash == null) {
        event.error(Errors.INVALID_REDIRECT_URI);
        throw new ErrorPageException(session, Response.Status.BAD_REQUEST, Messages.INVALID_REQUEST);
    }
    AuthenticationManager.AuthResult cookieResult = AuthenticationManager.authenticateIdentityCookie(session, realmModel, true);
    String errorParam = "link_error";
    if (cookieResult == null) {
        event.error(Errors.NOT_LOGGED_IN);
        UriBuilder builder = UriBuilder.fromUri(redirectUri).queryParam(errorParam, Errors.NOT_LOGGED_IN).queryParam("nonce", nonce);
        return Response.status(302).location(builder.build()).build();
    }
    cookieResult.getSession();
    event.session(cookieResult.getSession());
    event.user(cookieResult.getUser());
    event.detail(Details.USERNAME, cookieResult.getUser().getUsername());
    AuthenticatedClientSessionModel clientSession = null;
    for (AuthenticatedClientSessionModel cs : cookieResult.getSession().getAuthenticatedClientSessions().values()) {
        if (cs.getClient().getClientId().equals(clientId)) {
            byte[] decoded = Base64Url.decode(hash);
            MessageDigest md = null;
            try {
                md = MessageDigest.getInstance("SHA-256");
            } catch (NoSuchAlgorithmException e) {
                throw new ErrorPageException(session, Response.Status.INTERNAL_SERVER_ERROR, Messages.UNEXPECTED_ERROR_HANDLING_REQUEST);
            }
            String input = nonce + cookieResult.getSession().getId() + clientId + providerId;
            byte[] check = md.digest(input.getBytes(StandardCharsets.UTF_8));
            if (MessageDigest.isEqual(decoded, check)) {
                clientSession = cs;
                break;
            }
        }
    }
    if (clientSession == null) {
        event.error(Errors.INVALID_TOKEN);
        throw new ErrorPageException(session, Response.Status.BAD_REQUEST, Messages.INVALID_REQUEST);
    }
    event.detail(Details.IDENTITY_PROVIDER, providerId);
    ClientModel accountService = this.realmModel.getClientByClientId(Constants.ACCOUNT_MANAGEMENT_CLIENT_ID);
    if (!accountService.getId().equals(client.getId())) {
        RoleModel manageAccountRole = accountService.getRole(AccountRoles.MANAGE_ACCOUNT);
        // Ensure user has role and client has "role scope" for this role
        ClientSessionContext ctx = DefaultClientSessionContext.fromClientSessionScopeParameter(clientSession, session);
        Set<RoleModel> userAccountRoles = ctx.getRolesStream().collect(Collectors.toSet());
        if (!userAccountRoles.contains(manageAccountRole)) {
            RoleModel linkRole = accountService.getRole(AccountRoles.MANAGE_ACCOUNT_LINKS);
            if (!userAccountRoles.contains(linkRole)) {
                event.error(Errors.NOT_ALLOWED);
                UriBuilder builder = UriBuilder.fromUri(redirectUri).queryParam(errorParam, Errors.NOT_ALLOWED).queryParam("nonce", nonce);
                return Response.status(302).location(builder.build()).build();
            }
        }
    }
    IdentityProviderModel identityProviderModel = realmModel.getIdentityProviderByAlias(providerId);
    if (identityProviderModel == null) {
        event.error(Errors.UNKNOWN_IDENTITY_PROVIDER);
        UriBuilder builder = UriBuilder.fromUri(redirectUri).queryParam(errorParam, Errors.UNKNOWN_IDENTITY_PROVIDER).queryParam("nonce", nonce);
        return Response.status(302).location(builder.build()).build();
    }
    // Create AuthenticationSessionModel with same ID like userSession and refresh cookie
    UserSessionModel userSession = cookieResult.getSession();
    // Auth session with ID corresponding to our userSession may already exists in some rare cases (EG. if some client tried to login in another browser tab with "prompt=login")
    RootAuthenticationSessionModel rootAuthSession = session.authenticationSessions().getRootAuthenticationSession(realmModel, userSession.getId());
    if (rootAuthSession == null) {
        rootAuthSession = session.authenticationSessions().createRootAuthenticationSession(realmModel, userSession.getId());
    }
    AuthenticationSessionModel authSession = rootAuthSession.createAuthenticationSession(client);
    // Refresh the cookie
    new AuthenticationSessionManager(session).setAuthSessionCookie(userSession.getId(), realmModel);
    ClientSessionCode<AuthenticationSessionModel> clientSessionCode = new ClientSessionCode<>(session, realmModel, authSession);
    clientSessionCode.setAction(AuthenticationSessionModel.Action.AUTHENTICATE.name());
    clientSessionCode.getOrGenerateCode();
    authSession.setProtocol(client.getProtocol());
    authSession.setRedirectUri(redirectUri);
    authSession.setClientNote(OIDCLoginProtocol.STATE_PARAM, UUID.randomUUID().toString());
    authSession.setAuthNote(LINKING_IDENTITY_PROVIDER, cookieResult.getSession().getId() + clientId + providerId);
    event.detail(Details.CODE_ID, userSession.getId());
    event.success();
    try {
        IdentityProvider identityProvider = getIdentityProvider(session, realmModel, providerId);
        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(authSession, Response.Status.INTERNAL_SERVER_ERROR, Messages.COULD_NOT_SEND_AUTHENTICATION_REQUEST, e, providerId);
    } catch (Exception e) {
        return redirectToErrorPage(authSession, Response.Status.INTERNAL_SERVER_ERROR, Messages.UNEXPECTED_ERROR_HANDLING_REQUEST, e, providerId);
    }
    return redirectToErrorPage(authSession, Response.Status.INTERNAL_SERVER_ERROR, Messages.COULD_NOT_PROCEED_WITH_AUTHENTICATION_REQUEST);
}
Also used : UserSessionModel(org.keycloak.models.UserSessionModel) AuthenticationSessionModel(org.keycloak.sessions.AuthenticationSessionModel) RootAuthenticationSessionModel(org.keycloak.sessions.RootAuthenticationSessionModel) AuthenticatedClientSessionModel(org.keycloak.models.AuthenticatedClientSessionModel) RoleModel(org.keycloak.models.RoleModel) SocialIdentityProvider(org.keycloak.broker.social.SocialIdentityProvider) IdentityProvider(org.keycloak.broker.provider.IdentityProvider) ErrorPageException(org.keycloak.services.ErrorPageException) NoSuchAlgorithmException(java.security.NoSuchAlgorithmException) IdentityProviderModel(org.keycloak.models.IdentityProviderModel) ClientSessionCode(org.keycloak.services.managers.ClientSessionCode) 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) AuthenticationManager(org.keycloak.services.managers.AuthenticationManager) AuthenticationSessionManager(org.keycloak.services.managers.AuthenticationSessionManager) Response(javax.ws.rs.core.Response) ErrorResponse(org.keycloak.services.ErrorResponse) ClientModel(org.keycloak.models.ClientModel) DefaultClientSessionContext(org.keycloak.services.util.DefaultClientSessionContext) ClientSessionContext(org.keycloak.models.ClientSessionContext) RootAuthenticationSessionModel(org.keycloak.sessions.RootAuthenticationSessionModel) IdentityBrokerException(org.keycloak.broker.provider.IdentityBrokerException) UriBuilder(javax.ws.rs.core.UriBuilder) MessageDigest(java.security.MessageDigest) Path(javax.ws.rs.Path) GET(javax.ws.rs.GET) NoCache(org.jboss.resteasy.annotations.cache.NoCache)

Example 7 with ClientSessionCode

use of org.keycloak.services.managers.ClientSessionCode in project keycloak by keycloak.

the class AuthenticationProcessor method checkClientSession.

private void checkClientSession(boolean checkAction) {
    ClientSessionCode code = new ClientSessionCode(session, realm, authenticationSession);
    if (checkAction) {
        String action = AuthenticationSessionModel.Action.AUTHENTICATE.name();
        if (!code.isValidAction(action)) {
            throw new AuthenticationFlowException(AuthenticationFlowError.INVALID_CLIENT_SESSION);
        }
    }
    if (!code.isActionActive(ClientSessionCode.ActionType.LOGIN)) {
        throw new AuthenticationFlowException(AuthenticationFlowError.EXPIRED_CODE);
    }
    authenticationSession.getParentSession().setTimestamp(Time.currentTime());
}
Also used : ClientSessionCode(org.keycloak.services.managers.ClientSessionCode)

Example 8 with ClientSessionCode

use of org.keycloak.services.managers.ClientSessionCode in project keycloak by keycloak.

the class IdentityProviderAuthenticator method redirect.

private void redirect(AuthenticationFlowContext context, String providerId) {
    Optional<IdentityProviderModel> idp = context.getRealm().getIdentityProvidersStream().filter(IdentityProviderModel::isEnabled).filter(identityProvider -> Objects.equals(providerId, identityProvider.getAlias())).findFirst();
    if (idp.isPresent()) {
        String accessCode = new ClientSessionCode<>(context.getSession(), context.getRealm(), context.getAuthenticationSession()).getOrGenerateCode();
        String clientId = context.getAuthenticationSession().getClient().getClientId();
        String tabId = context.getAuthenticationSession().getTabId();
        URI location = Urls.identityProviderAuthnRequest(context.getUriInfo().getBaseUri(), providerId, context.getRealm().getName(), accessCode, clientId, tabId);
        if (context.getAuthenticationSession().getClientNote(OAuth2Constants.DISPLAY) != null) {
            location = UriBuilder.fromUri(location).queryParam(OAuth2Constants.DISPLAY, context.getAuthenticationSession().getClientNote(OAuth2Constants.DISPLAY)).build();
        }
        Response response = Response.seeOther(location).build();
        // will forward the request to the IDP with prompt=none if the IDP accepts forwards with prompt=none.
        if ("none".equals(context.getAuthenticationSession().getClientNote(OIDCLoginProtocol.PROMPT_PARAM)) && Boolean.valueOf(idp.get().getConfig().get(ACCEPTS_PROMPT_NONE))) {
            context.getAuthenticationSession().setAuthNote(AuthenticationProcessor.FORWARDED_PASSIVE_LOGIN, "true");
        }
        LOG.debugf("Redirecting to %s", providerId);
        context.forceChallenge(response);
        return;
    }
    LOG.warnf("Provider not found or not enabled for realm %s", providerId);
    context.attempted();
}
Also used : ClientSessionCode(org.keycloak.services.managers.ClientSessionCode) RealmModel(org.keycloak.models.RealmModel) Authenticator(org.keycloak.authentication.Authenticator) AuthenticationProcessor(org.keycloak.authentication.AuthenticationProcessor) Logger(org.jboss.logging.Logger) KeycloakSession(org.keycloak.models.KeycloakSession) AdapterConstants(org.keycloak.constants.AdapterConstants) IdentityProviderModel(org.keycloak.models.IdentityProviderModel) Objects(java.util.Objects) UserModel(org.keycloak.models.UserModel) Response(javax.ws.rs.core.Response) OIDCLoginProtocol(org.keycloak.protocol.oidc.OIDCLoginProtocol) Optional(java.util.Optional) Urls(org.keycloak.services.Urls) UriBuilder(javax.ws.rs.core.UriBuilder) URI(java.net.URI) AuthenticationFlowContext(org.keycloak.authentication.AuthenticationFlowContext) OAuth2Constants(org.keycloak.OAuth2Constants) Response(javax.ws.rs.core.Response) IdentityProviderModel(org.keycloak.models.IdentityProviderModel) URI(java.net.URI)

Aggregations

ClientSessionCode (org.keycloak.services.managers.ClientSessionCode)8 AuthenticationSessionModel (org.keycloak.sessions.AuthenticationSessionModel)4 URI (java.net.URI)3 Response (javax.ws.rs.core.Response)3 ClientModel (org.keycloak.models.ClientModel)3 IdentityProviderModel (org.keycloak.models.IdentityProviderModel)3 RootAuthenticationSessionModel (org.keycloak.sessions.RootAuthenticationSessionModel)3 IOException (java.io.IOException)2 NoSuchAlgorithmException (java.security.NoSuchAlgorithmException)2 GET (javax.ws.rs.GET)2 NotFoundException (javax.ws.rs.NotFoundException)2 Path (javax.ws.rs.Path)2 WebApplicationException (javax.ws.rs.WebApplicationException)2 UriBuilder (javax.ws.rs.core.UriBuilder)2 NoCache (org.jboss.resteasy.annotations.cache.NoCache)2 OAuthErrorException (org.keycloak.OAuthErrorException)2 IdentityBrokerException (org.keycloak.broker.provider.IdentityBrokerException)2 IdentityProvider (org.keycloak.broker.provider.IdentityProvider)2 SocialIdentityProvider (org.keycloak.broker.social.SocialIdentityProvider)2 RealmModel (org.keycloak.models.RealmModel)2