Search in sources :

Example 1 with ClientSessionCode

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

the class AuthenticationProcessor method generateCode.

public String generateCode() {
    ClientSessionCode accessCode = new ClientSessionCode(session, getRealm(), getAuthenticationSession());
    authenticationSession.getParentSession().setTimestamp(Time.currentTime());
    return accessCode.getOrGenerateCode();
}
Also used : ClientSessionCode(org.keycloak.services.managers.ClientSessionCode)

Example 2 with ClientSessionCode

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

the class LoginActionsService method redirectToAfterBrokerLoginEndpoint.

public static Response redirectToAfterBrokerLoginEndpoint(KeycloakSession session, RealmModel realm, UriInfo uriInfo, AuthenticationSessionModel authSession, boolean firstBrokerLogin) {
    ClientSessionCode<AuthenticationSessionModel> accessCode = new ClientSessionCode<>(session, realm, authSession);
    authSession.getParentSession().setTimestamp(Time.currentTime());
    String clientId = authSession.getClient().getClientId();
    String tabId = authSession.getTabId();
    URI redirect = firstBrokerLogin ? Urls.identityProviderAfterFirstBrokerLogin(uriInfo.getBaseUri(), realm.getName(), accessCode.getOrGenerateCode(), clientId, tabId) : Urls.identityProviderAfterPostBrokerLogin(uriInfo.getBaseUri(), realm.getName(), accessCode.getOrGenerateCode(), clientId, tabId);
    logger.debugf("Redirecting to '%s' ", redirect);
    return Response.status(302).location(redirect).build();
}
Also used : AuthenticationSessionModel(org.keycloak.sessions.AuthenticationSessionModel) RootAuthenticationSessionModel(org.keycloak.sessions.RootAuthenticationSessionModel) ClientSessionCode(org.keycloak.services.managers.ClientSessionCode) URI(java.net.URI)

Example 3 with ClientSessionCode

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

the class SessionCodeChecks method initialVerify.

public boolean initialVerify() {
    // Basic realm checks and authenticationSession retrieve
    authSession = initialVerifyAuthSession();
    if (authSession == null) {
        return false;
    }
    // Check cached response from previous action request
    response = BrowserHistoryHelper.getInstance().loadSavedResponse(session, authSession);
    if (response != null) {
        return false;
    }
    // Client checks
    event.detail(Details.CODE_ID, authSession.getParentSession().getId());
    ClientModel client = authSession.getClient();
    if (client == null) {
        event.error(Errors.CLIENT_NOT_FOUND);
        response = ErrorPage.error(session, authSession, Response.Status.BAD_REQUEST, Messages.UNKNOWN_LOGIN_REQUESTER);
        clientCode.removeExpiredClientSession();
        return false;
    }
    event.client(client);
    session.getContext().setClient(client);
    if (!client.isEnabled()) {
        event.error(Errors.CLIENT_DISABLED);
        response = ErrorPage.error(session, authSession, Response.Status.BAD_REQUEST, Messages.LOGIN_REQUESTER_NOT_ENABLED);
        clientCode.removeExpiredClientSession();
        return false;
    }
    // Check if it's action or not
    if (code == null) {
        String lastExecFromSession = authSession.getAuthNote(AuthenticationProcessor.CURRENT_AUTHENTICATION_EXECUTION);
        String lastFlow = authSession.getAuthNote(AuthenticationProcessor.CURRENT_FLOW_PATH);
        // Check if we transitted between flows (eg. clicking "register" on login screen)
        if (execution == null && !flowPath.equals(lastFlow)) {
            logger.debugf("Transition between flows! Current flow: %s, Previous flow: %s", flowPath, lastFlow);
            // Don't allow moving to different flow if I am on requiredActions already
            if (AuthenticationSessionModel.Action.AUTHENTICATE.name().equals(authSession.getAction())) {
                authSession.setAuthNote(AuthenticationProcessor.CURRENT_FLOW_PATH, flowPath);
                authSession.removeAuthNote(AuthenticationProcessor.CURRENT_AUTHENTICATION_EXECUTION);
                lastExecFromSession = null;
            }
        }
        if (execution == null || execution.equals(lastExecFromSession)) {
            // Allow refresh of previous page
            clientCode = new ClientSessionCode<>(session, realm, authSession);
            actionRequest = false;
            // Allow refresh, but rewrite browser history
            if (execution == null && lastExecFromSession != null) {
                logger.debugf("Parameter 'execution' is not in the request, but flow wasn't changed. Will update browser history");
                request.setAttribute(BrowserHistoryHelper.SHOULD_UPDATE_BROWSER_HISTORY, true);
            }
            return true;
        } else {
            response = showPageExpired(authSession);
            return false;
        }
    } else {
        ClientSessionCode.ParseResult<AuthenticationSessionModel> result = ClientSessionCode.parseResult(code, tabId, session, realm, client, event, authSession);
        clientCode = result.getCode();
        if (clientCode == null) {
            // In case that is replayed action, but sent to the same FORM like actual FORM, we just re-render the page
            if (ObjectUtil.isEqualOrBothNull(execution, authSession.getAuthNote(AuthenticationProcessor.CURRENT_AUTHENTICATION_EXECUTION))) {
                String latestFlowPath = authSession.getAuthNote(AuthenticationProcessor.CURRENT_FLOW_PATH);
                URI redirectUri = getLastExecutionUrl(latestFlowPath, execution, tabId);
                logger.debugf("Invalid action code, but execution matches. So just redirecting to %s", redirectUri);
                authSession.setAuthNote(LoginActionsService.FORWARDED_ERROR_MESSAGE_NOTE, Messages.EXPIRED_ACTION);
                response = Response.status(Response.Status.FOUND).location(redirectUri).build();
            } else {
                response = showPageExpired(authSession);
            }
            return false;
        }
        actionRequest = true;
        if (execution != null) {
            authSession.setAuthNote(AuthenticationProcessor.LAST_PROCESSED_EXECUTION, execution);
        }
        return true;
    }
}
Also used : ClientModel(org.keycloak.models.ClientModel) AuthenticationSessionModel(org.keycloak.sessions.AuthenticationSessionModel) RootAuthenticationSessionModel(org.keycloak.sessions.RootAuthenticationSessionModel) ClientSessionCode(org.keycloak.services.managers.ClientSessionCode) URI(java.net.URI)

Example 4 with ClientSessionCode

use of org.keycloak.services.managers.ClientSessionCode 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 ClientSessionCode

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

the class LoginTimeoutValidationTest method testIsLoginTimeoutValid.

@Test
@ModelTest
public void testIsLoginTimeoutValid(KeycloakSession keycloakSession) {
    RealmModel realm = keycloakSession.realms().getRealmByName("test");
    UserSessionModel userSession = keycloakSession.sessions().createUserSession(realm, keycloakSession.users().getUserByUsername(realm, "user1"), "user1", "127.0.0.1", "form", true, null, null);
    ClientModel client = realm.getClientByClientId("account");
    AuthenticationSessionModel authSession = keycloakSession.authenticationSessions().createRootAuthenticationSession(realm).createAuthenticationSession(client);
    ClientSessionCode clientSessionCode = new ClientSessionCode(keycloakSession, realm, authSession);
    /*
         * KEYCLOAK-10636 Large Login timeout causes login failure
         * realm > Realm setting > Tokens > Login timeout
         */
    // Login timeout
    int accessCodeLifespanLoginOrig = realm.getAccessCodeLifespanLogin();
    realm.setAccessCodeLifespanLogin(Integer.MAX_VALUE);
    Assert.assertTrue("Login validataion with large Login Timeout failed", clientSessionCode.isActionActive(ClientSessionCode.ActionType.LOGIN));
    realm.setAccessCodeLifespanLogin(accessCodeLifespanLoginOrig);
    /*
         * KEYCLOAK-10637 Large Login Action timeout causes login failure
         * realm > Realm setting > Tokens > Login Action timeout
         */
    // Login Action timeout
    int accessCodeLifespanUserActionOrig = realm.getAccessCodeLifespanUserAction();
    realm.setAccessCodeLifespanUserAction(Integer.MAX_VALUE);
    Assert.assertTrue("Login validataion with large Login Action Timeout failed", clientSessionCode.isActionActive(ClientSessionCode.ActionType.USER));
    realm.setAccessCodeLifespanUserAction(accessCodeLifespanUserActionOrig);
}
Also used : RealmModel(org.keycloak.models.RealmModel) ClientModel(org.keycloak.models.ClientModel) UserSessionModel(org.keycloak.models.UserSessionModel) AuthenticationSessionModel(org.keycloak.sessions.AuthenticationSessionModel) ClientSessionCode(org.keycloak.services.managers.ClientSessionCode) ModelTest(org.keycloak.testsuite.arquillian.annotation.ModelTest) ModelTest(org.keycloak.testsuite.arquillian.annotation.ModelTest) Test(org.junit.Test) AbstractTestRealmKeycloakTest(org.keycloak.testsuite.AbstractTestRealmKeycloakTest)

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