Search in sources :

Example 51 with AuthenticationSessionModel

use of org.keycloak.sessions.AuthenticationSessionModel in project keycloak by keycloak.

the class LoginActionsServiceChecks method checkIsClientValid.

/**
 * Verifies whether the client denoted by client ID in token's {@code iss} ({@code issuedFor})
 * field both exists and is enabled.
 */
public static <T extends JsonWebToken> void checkIsClientValid(T token, ActionTokenContext<T> context) throws VerificationException {
    String clientId = token.getIssuedFor();
    AuthenticationSessionModel authSession = context.getAuthenticationSession();
    ClientModel client = authSession == null ? null : authSession.getClient();
    try {
        checkIsClientValid(context.getSession(), client);
        if (clientId != null && !Objects.equals(client.getClientId(), clientId)) {
            throw new ExplainedTokenVerificationException(token, Errors.CLIENT_NOT_FOUND, Messages.UNKNOWN_LOGIN_REQUESTER);
        }
    } catch (ExplainedVerificationException ex) {
        throw new ExplainedTokenVerificationException(token, ex);
    }
}
Also used : ClientModel(org.keycloak.models.ClientModel) AuthenticationSessionModel(org.keycloak.sessions.AuthenticationSessionModel) ExplainedTokenVerificationException(org.keycloak.authentication.actiontoken.ExplainedTokenVerificationException) ExplainedVerificationException(org.keycloak.authentication.ExplainedVerificationException)

Example 52 with AuthenticationSessionModel

use of org.keycloak.sessions.AuthenticationSessionModel in project keycloak by keycloak.

the class LoginActionsServiceChecks method doesAuthenticationSessionFromCookieMatchOneFromToken.

/**
 *  This check verifies that current authentication session is consistent with the one specified in token.
 *  Examples:
 *  <ul>
 *      <li>1. Email from administrator with reset e-mail - token does not contain auth session ID</li>
 *      <li>2. Email from "verify e-mail" step within flow - token contains auth session ID.</li>
 *      <li>3. User clicked the link in an e-mail and gets to a new browser - authentication session cookie is not set</li>
 *      <li>4. User clicked the link in an e-mail while having authentication running - authentication session cookie
 *             is already set in the browser</li>
 *  </ul>
 *
 *  <ul>
 *      <li>For combinations 1 and 3, 1 and 4, and 2 and 3: Requests next step</li>
 *      <li>For combination 2 and 4:
 *          <ul>
 *          <li>If the auth session IDs from token and cookie match, pass</li>
 *          <li>Else if the auth session from cookie was forked and its parent auth session ID
 *              matches that of token, replaces current auth session with that of parent and passes</li>
 *          <li>Else requests restart by throwing RestartFlow exception</li>
 *          </ul>
 *      </li>
 *  </ul>
 *
 *  When the check passes, it also sets the authentication session in token context accordingly.
 *
 *  @param <T>
 */
public static <T extends JsonWebToken> boolean doesAuthenticationSessionFromCookieMatchOneFromToken(ActionTokenContext<T> context, AuthenticationSessionModel authSessionFromCookie, String authSessionCompoundIdFromToken) throws VerificationException {
    if (authSessionCompoundIdFromToken == null) {
        return false;
    }
    if (Objects.equals(AuthenticationSessionCompoundId.fromAuthSession(authSessionFromCookie).getEncodedId(), authSessionCompoundIdFromToken)) {
        context.setAuthenticationSession(authSessionFromCookie, false);
        return true;
    }
    // Check if it's forked session. It would have same parent (rootSession) as our browser authenticationSession
    String parentTabId = authSessionFromCookie.getAuthNote(AuthenticationProcessor.FORKED_FROM);
    if (parentTabId == null) {
        return false;
    }
    AuthenticationSessionModel authSessionFromParent = authSessionFromCookie.getParentSession().getAuthenticationSession(authSessionFromCookie.getClient(), parentTabId);
    if (authSessionFromParent == null) {
        return false;
    }
    // It's the correct browser. We won't continue login
    // from the login form (browser flow) but from the token's flow
    // Don't expire KC_RESTART cookie at this point
    LOG.debugf("Switched to forked tab: %s from: %s . Root session: %s", authSessionFromParent.getTabId(), authSessionFromCookie.getTabId(), authSessionFromCookie.getParentSession().getId());
    context.setAuthenticationSession(authSessionFromParent, false);
    context.setExecutionId(authSessionFromParent.getAuthNote(AuthenticationProcessor.LAST_PROCESSED_EXECUTION));
    return true;
}
Also used : AuthenticationSessionModel(org.keycloak.sessions.AuthenticationSessionModel)

Example 53 with AuthenticationSessionModel

use of org.keycloak.sessions.AuthenticationSessionModel in project keycloak by keycloak.

the class SessionCodeChecks method initialVerifyAuthSession.

public AuthenticationSessionModel initialVerifyAuthSession() {
    // Basic realm checks
    if (!checkSsl()) {
        event.error(Errors.SSL_REQUIRED);
        response = ErrorPage.error(session, null, Response.Status.BAD_REQUEST, Messages.HTTPS_REQUIRED);
        return null;
    }
    if (!realm.isEnabled()) {
        event.error(Errors.REALM_DISABLED);
        response = ErrorPage.error(session, null, Response.Status.BAD_REQUEST, Messages.REALM_NOT_ENABLED);
        return null;
    }
    // Setup client to be shown on error/info page based on "client_id" parameter
    logger.debugf("Will use client '%s' in back-to-application link", clientId);
    ClientModel client = null;
    if (clientId != null) {
        client = realm.getClientByClientId(clientId);
    }
    if (client != null) {
        session.getContext().setClient(client);
    }
    // object retrieve
    AuthenticationSessionManager authSessionManager = new AuthenticationSessionManager(session);
    AuthenticationSessionModel authSession = null;
    if (authSessionId != null)
        authSession = authSessionManager.getAuthenticationSessionByIdAndClient(realm, authSessionId, client, tabId);
    AuthenticationSessionModel authSessionCookie = authSessionManager.getCurrentAuthenticationSession(realm, client, tabId);
    if (authSession != null && authSessionCookie != null && !authSession.getParentSession().getId().equals(authSessionCookie.getParentSession().getId())) {
        event.detail(Details.REASON, "cookie does not match auth_session query parameter");
        event.error(Errors.INVALID_CODE);
        response = ErrorPage.error(session, null, Response.Status.BAD_REQUEST, Messages.INVALID_CODE);
        return null;
    }
    if (authSession != null) {
        session.getProvider(LoginFormsProvider.class).setAuthenticationSession(authSession);
        return authSession;
    }
    if (authSessionCookie != null) {
        session.getProvider(LoginFormsProvider.class).setAuthenticationSession(authSessionCookie);
        return authSessionCookie;
    }
    // See if we are already authenticated and userSession with same ID exists.
    UserSessionModel userSession = authSessionManager.getUserSessionFromAuthCookie(realm);
    if (userSession != null) {
        LoginFormsProvider loginForm = session.getProvider(LoginFormsProvider.class).setAuthenticationSession(authSession).setSuccess(Messages.ALREADY_LOGGED_IN);
        if (client == null) {
            loginForm.setAttribute(Constants.SKIP_LINK, true);
        }
        response = loginForm.createInfoPage();
        return null;
    }
    // Otherwise just try to restart from the cookie
    RootAuthenticationSessionModel existingRootAuthSession = authSessionManager.getCurrentRootAuthenticationSession(realm);
    response = restartAuthenticationSessionFromCookie(existingRootAuthSession);
    return null;
}
Also used : AuthenticationSessionManager(org.keycloak.services.managers.AuthenticationSessionManager) ClientModel(org.keycloak.models.ClientModel) AuthenticationSessionModel(org.keycloak.sessions.AuthenticationSessionModel) RootAuthenticationSessionModel(org.keycloak.sessions.RootAuthenticationSessionModel) LoginFormsProvider(org.keycloak.forms.login.LoginFormsProvider) UserSessionModel(org.keycloak.models.UserSessionModel) RootAuthenticationSessionModel(org.keycloak.sessions.RootAuthenticationSessionModel)

Example 54 with AuthenticationSessionModel

use of org.keycloak.sessions.AuthenticationSessionModel in project keycloak by keycloak.

the class SessionCodeChecks method restartAuthenticationSessionFromCookie.

private Response restartAuthenticationSessionFromCookie(RootAuthenticationSessionModel existingRootSession) {
    logger.debug("Authentication session not found. Trying to restart from cookie.");
    AuthenticationSessionModel authSession = null;
    Cookie cook = RestartLoginCookie.getRestartCookie(session);
    if (cook == null) {
        event.error(Errors.COOKIE_NOT_FOUND);
        return ErrorPage.error(session, authSession, Response.Status.BAD_REQUEST, Messages.COOKIE_NOT_FOUND);
    }
    try {
        authSession = RestartLoginCookie.restartSession(session, realm, existingRootSession, clientId, cook);
    } catch (Exception e) {
        ServicesLogger.LOGGER.failedToParseRestartLoginCookie(e);
    }
    if (authSession != null) {
        event.clone();
        event.detail(Details.RESTART_AFTER_TIMEOUT, "true");
        event.error(Errors.EXPIRED_CODE);
        String warningMessage = Messages.LOGIN_TIMEOUT;
        authSession.setAuthNote(LoginActionsService.FORWARDED_ERROR_MESSAGE_NOTE, warningMessage);
        String flowPath = authSession.getClientNote(AuthorizationEndpointBase.APP_INITIATED_FLOW);
        if (flowPath == null) {
            flowPath = LoginActionsService.AUTHENTICATE_PATH;
        }
        URI redirectUri = getLastExecutionUrl(flowPath, null, authSession.getTabId());
        logger.debugf("Authentication session restart from cookie succeeded. Redirecting to %s", redirectUri);
        return Response.status(Response.Status.FOUND).location(redirectUri).build();
    } else {
        // Finally need to show error as all the fallbacks failed
        event.error(Errors.INVALID_CODE);
        return ErrorPage.error(session, authSession, Response.Status.BAD_REQUEST, Messages.INVALID_CODE);
    }
}
Also used : Cookie(javax.ws.rs.core.Cookie) RestartLoginCookie(org.keycloak.protocol.RestartLoginCookie) AuthenticationSessionModel(org.keycloak.sessions.AuthenticationSessionModel) RootAuthenticationSessionModel(org.keycloak.sessions.RootAuthenticationSessionModel) URI(java.net.URI)

Example 55 with AuthenticationSessionModel

use of org.keycloak.sessions.AuthenticationSessionModel in project keycloak by keycloak.

the class SessionCodeChecks method verifyActiveAndValidAction.

public boolean verifyActiveAndValidAction(String expectedAction, ClientSessionCode.ActionType actionType) {
    if (failed()) {
        return false;
    }
    if (!isActionActive(actionType)) {
        return false;
    }
    if (!clientCode.isValidAction(expectedAction)) {
        AuthenticationSessionModel authSession = getAuthenticationSession();
        if (AuthenticationSessionModel.Action.REQUIRED_ACTIONS.name().equals(authSession.getAction())) {
            logger.debugf("Incorrect action '%s' . User authenticated already.", authSession.getAction());
            response = showPageExpired(authSession);
            return false;
        } else {
            logger.errorf("Bad action. Expected action '%s', current action '%s'", expectedAction, authSession.getAction());
            response = ErrorPage.error(session, authSession, Response.Status.BAD_REQUEST, Messages.EXPIRED_CODE);
            return false;
        }
    }
    return true;
}
Also used : AuthenticationSessionModel(org.keycloak.sessions.AuthenticationSessionModel) RootAuthenticationSessionModel(org.keycloak.sessions.RootAuthenticationSessionModel)

Aggregations

AuthenticationSessionModel (org.keycloak.sessions.AuthenticationSessionModel)89 RootAuthenticationSessionModel (org.keycloak.sessions.RootAuthenticationSessionModel)48 ClientModel (org.keycloak.models.ClientModel)27 UserModel (org.keycloak.models.UserModel)24 Response (javax.ws.rs.core.Response)23 RealmModel (org.keycloak.models.RealmModel)20 UserSessionModel (org.keycloak.models.UserSessionModel)20 AuthenticationSessionManager (org.keycloak.services.managers.AuthenticationSessionManager)18 KeycloakSession (org.keycloak.models.KeycloakSession)16 ClientSessionContext (org.keycloak.models.ClientSessionContext)13 LoginFormsProvider (org.keycloak.forms.login.LoginFormsProvider)10 URI (java.net.URI)9 UriBuilder (javax.ws.rs.core.UriBuilder)9 EventBuilder (org.keycloak.events.EventBuilder)9 LoginProtocol (org.keycloak.protocol.LoginProtocol)9 GET (javax.ws.rs.GET)8 Path (javax.ws.rs.Path)8 AuthenticationFlowException (org.keycloak.authentication.AuthenticationFlowException)8 OIDCLoginProtocol (org.keycloak.protocol.oidc.OIDCLoginProtocol)8 Map (java.util.Map)7