Java Code Examples for org.keycloak.services.managers.AuthenticationManager#isSessionValid()

The following examples show how to use org.keycloak.services.managers.AuthenticationManager#isSessionValid() . You can vote up the ones you like or vote down the ones you don't like, and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example 1
Source File: TokenManager.java    From keycloak with Apache License 2.0 5 votes vote down vote up
/**
 * Checks if the token is valid. Intended usage is for token introspection endpoints as the session last refresh
 * is updated if the token was valid. This is used to keep the session alive when long lived tokens are used.
 *
 * @param session
 * @param realm
 * @param token
 * @return
 * @throws OAuthErrorException
 */
public boolean checkTokenValidForIntrospection(KeycloakSession session, RealmModel realm, AccessToken token) throws OAuthErrorException {
    ClientModel client = realm.getClientByClientId(token.getIssuedFor());
    if (client == null || !client.isEnabled()) {
        return false;
    }

    try {
        TokenVerifier.createWithoutSignature(token)
                .withChecks(NotBeforeCheck.forModel(client), TokenVerifier.IS_ACTIVE)
                .verify();
    } catch (VerificationException e) {
        return false;
    }

    boolean valid = false;

    UserSessionModel userSession = new UserSessionCrossDCManager(session).getUserSessionWithClient(realm, token.getSessionState(), false, client.getId());

    if (AuthenticationManager.isSessionValid(realm, userSession)) {
        valid = isUserValid(session, realm, token, userSession);
    } else {
        userSession = new UserSessionCrossDCManager(session).getUserSessionWithClient(realm, token.getSessionState(), true, client.getId());
        if (AuthenticationManager.isOfflineSessionValid(realm, userSession)) {
            valid = isUserValid(session, realm, token, userSession);
        }
    }

    if (valid) {
        userSession.setLastSessionRefresh(Time.currentTime());
    }

    return valid;
}
 
Example 2
Source File: UserInfoEndpoint.java    From keycloak with Apache License 2.0 5 votes vote down vote up
private UserSessionModel findValidSession(AccessToken token, EventBuilder event, ClientModel client) {
    UserSessionModel userSession = new UserSessionCrossDCManager(session).getUserSessionWithClient(realm, token.getSessionState(), false, client.getId());
    UserSessionModel offlineUserSession = null;
    if (AuthenticationManager.isSessionValid(realm, userSession)) {
        checkTokenIssuedAt(token, userSession, event);
        event.session(userSession);
        return userSession;
    } else {
        offlineUserSession = new UserSessionCrossDCManager(session).getUserSessionWithClient(realm, token.getSessionState(), true, client.getId());
        if (AuthenticationManager.isOfflineSessionValid(realm, offlineUserSession)) {
            checkTokenIssuedAt(token, offlineUserSession, event);
            event.session(offlineUserSession);
            return offlineUserSession;
        }
    }

    if (userSession == null && offlineUserSession == null) {
        event.error(Errors.USER_SESSION_NOT_FOUND);
        throw newUnauthorizedErrorResponseException(OAuthErrorException.INVALID_REQUEST, "User session not found or doesn't have client attached on it");
    }

    if (userSession != null) {
        event.session(userSession);
    } else {
        event.session(offlineUserSession);
    }

    event.error(Errors.SESSION_EXPIRED);
    throw newUnauthorizedErrorResponseException(OAuthErrorException.INVALID_TOKEN, "Session expired");
}
 
Example 3
Source File: AbstractValidateEndpoint.java    From keycloak-protocol-cas with Apache License 2.0 4 votes vote down vote up
protected void checkTicket(String ticket, boolean requireReauth) {
    if (ticket == null) {
        event.error(Errors.INVALID_CODE);
        throw new CASValidationException(CASErrorCode.INVALID_REQUEST, "Missing parameter: " + CASLoginProtocol.TICKET_PARAM, Response.Status.BAD_REQUEST);
    }
    if (!ticket.startsWith(CASLoginProtocol.SERVICE_TICKET_PREFIX)) {
        event.error(Errors.INVALID_CODE);
        throw new CASValidationException(CASErrorCode.INVALID_TICKET_SPEC, "Malformed service ticket", Response.Status.BAD_REQUEST);
    }

    String code = ticket.substring(CASLoginProtocol.SERVICE_TICKET_PREFIX.length());

    OAuth2CodeParser.ParseResult parseResult = OAuth2CodeParser.parseCode(session, code, realm, event);
    if (parseResult.isIllegalCode()) {
        event.error(Errors.INVALID_CODE);

        // Attempt to use same code twice should invalidate existing clientSession
        AuthenticatedClientSessionModel clientSession = parseResult.getClientSession();
        if (clientSession != null) {
            clientSession.detachFromUserSession();
        }

        throw new CASValidationException(CASErrorCode.INVALID_TICKET, "Code not valid", Response.Status.BAD_REQUEST);
    }

    clientSession = parseResult.getClientSession();

    if (parseResult.isExpiredCode()) {
        event.error(Errors.EXPIRED_CODE);
        throw new CASValidationException(CASErrorCode.INVALID_TICKET, "Code is expired", Response.Status.BAD_REQUEST);
    }

    clientSession.setNote(CASLoginProtocol.SESSION_SERVICE_TICKET, ticket);

    if (requireReauth && AuthenticationManager.isSSOAuthentication(clientSession)) {
        event.error(Errors.SESSION_EXPIRED);
        throw new CASValidationException(CASErrorCode.INVALID_TICKET, "Interactive authentication was requested but not performed", Response.Status.BAD_REQUEST);
    }

    UserSessionModel userSession = clientSession.getUserSession();

    if (userSession == null) {
        event.error(Errors.USER_SESSION_NOT_FOUND);
        throw new CASValidationException(CASErrorCode.INVALID_TICKET, "User session not found", Response.Status.BAD_REQUEST);
    }

    UserModel user = userSession.getUser();
    if (user == null) {
        event.error(Errors.USER_NOT_FOUND);
        throw new CASValidationException(CASErrorCode.INVALID_TICKET, "User not found", Response.Status.BAD_REQUEST);
    }
    if (!user.isEnabled()) {
        event.error(Errors.USER_DISABLED);
        throw new CASValidationException(CASErrorCode.INVALID_TICKET, "User disabled", Response.Status.BAD_REQUEST);
    }

    event.user(userSession.getUser());
    event.session(userSession.getId());

    if (!client.getClientId().equals(clientSession.getClient().getClientId())) {
        event.error(Errors.INVALID_CODE);
        throw new CASValidationException(CASErrorCode.INVALID_SERVICE, "Auth error", Response.Status.BAD_REQUEST);
    }

    if (!AuthenticationManager.isSessionValid(realm, userSession)) {
        event.error(Errors.USER_SESSION_NOT_FOUND);
        throw new CASValidationException(CASErrorCode.INVALID_TICKET, "Session not active", Response.Status.BAD_REQUEST);
    }
}
 
Example 4
Source File: TokenManager.java    From keycloak with Apache License 2.0 4 votes vote down vote up
public TokenValidation validateToken(KeycloakSession session, UriInfo uriInfo, ClientConnection connection, RealmModel realm,
                                     RefreshToken oldToken, HttpHeaders headers) throws OAuthErrorException {
    UserSessionModel userSession = null;
    boolean offline = TokenUtil.TOKEN_TYPE_OFFLINE.equals(oldToken.getType());

    if (offline) {

        UserSessionManager sessionManager = new UserSessionManager(session);
        userSession = sessionManager.findOfflineUserSession(realm, oldToken.getSessionState());
        if (userSession != null) {

            // Revoke timeouted offline userSession
            if (!AuthenticationManager.isOfflineSessionValid(realm, userSession)) {
                sessionManager.revokeOfflineUserSession(userSession);
                throw new OAuthErrorException(OAuthErrorException.INVALID_GRANT, "Offline session not active", "Offline session not active");
            }

        } else {
            throw new OAuthErrorException(OAuthErrorException.INVALID_GRANT, "Offline user session not found", "Offline user session not found");
        }
    } else {
        // Find userSession regularly for online tokens
        userSession = session.sessions().getUserSession(realm, oldToken.getSessionState());
        if (!AuthenticationManager.isSessionValid(realm, userSession)) {
            AuthenticationManager.backchannelLogout(session, realm, userSession, uriInfo, connection, headers, true);
            throw new OAuthErrorException(OAuthErrorException.INVALID_GRANT, "Session not active", "Session not active");
        }
    }

    UserModel user = userSession.getUser();
    if (user == null) {
        throw new OAuthErrorException(OAuthErrorException.INVALID_GRANT, "Invalid refresh token", "Unknown user");
    }

    if (!user.isEnabled()) {
        throw new OAuthErrorException(OAuthErrorException.INVALID_GRANT, "User disabled", "User disabled");
    }

    if (oldToken.getIssuedAt() + 1 < userSession.getStarted()) {
        logger.debug("Refresh toked issued before the user session started");
        throw new OAuthErrorException(OAuthErrorException.INVALID_GRANT, "Refresh toked issued before the user session started");
    }


    ClientModel client = session.getContext().getClient();
    AuthenticatedClientSessionModel clientSession = userSession.getAuthenticatedClientSessionByClient(client.getId());

    // Can theoretically happen in cross-dc environment. Try to see if userSession with our client is available in remoteCache
    if (clientSession == null) {
        userSession = new UserSessionCrossDCManager(session).getUserSessionWithClient(realm, userSession.getId(), offline, client.getId());
        if (userSession != null) {
            clientSession = userSession.getAuthenticatedClientSessionByClient(client.getId());
        } else {
            throw new OAuthErrorException(OAuthErrorException.INVALID_GRANT, "Session doesn't have required client", "Session doesn't have required client");
        }
    }

    if (!client.getClientId().equals(oldToken.getIssuedFor())) {
        throw new OAuthErrorException(OAuthErrorException.INVALID_GRANT, "Unmatching clients", "Unmatching clients");
    }

    try {
        TokenVerifier.createWithoutSignature(oldToken)
                .withChecks(NotBeforeCheck.forModel(client), NotBeforeCheck.forModel(session, realm, user))
                .verify();
    } catch (VerificationException e) {
        throw new OAuthErrorException(OAuthErrorException.INVALID_GRANT, "Stale token");
    }

    // Setup clientScopes from refresh token to the context
    String oldTokenScope = oldToken.getScope();

    // Case when offline token is migrated from previous version
    if (oldTokenScope == null && userSession.isOffline()) {
        logger.debugf("Migrating offline token of user '%s' for client '%s' of realm '%s'", user.getUsername(), client.getClientId(), realm.getName());
        MigrationUtils.migrateOldOfflineToken(session, realm, client, user);
        oldTokenScope = OAuth2Constants.OFFLINE_ACCESS;
    }

    ClientSessionContext clientSessionCtx = DefaultClientSessionContext.fromClientSessionAndScopeParameter(clientSession, oldTokenScope, session);

    // Check user didn't revoke granted consent
    if (!verifyConsentStillAvailable(session, user, client, clientSessionCtx.getClientScopes())) {
        throw new OAuthErrorException(OAuthErrorException.INVALID_SCOPE, "Client no longer has requested consent from user");
    }

    clientSessionCtx.setAttribute(OIDCLoginProtocol.NONCE_PARAM, oldToken.getNonce());

    // recreate token.
    AccessToken newToken = createClientAccessToken(session, realm, client, user, userSession, clientSessionCtx);

    return new TokenValidation(user, userSession, clientSessionCtx, newToken);
}
 
Example 5
Source File: AuthenticationProcessor.java    From keycloak with Apache License 2.0 4 votes vote down vote up
public static ClientSessionContext attachSession(AuthenticationSessionModel authSession, UserSessionModel userSession, KeycloakSession session, RealmModel realm, ClientConnection connection, EventBuilder event) {
    String username = authSession.getAuthenticatedUser().getUsername();
    String attemptedUsername = authSession.getAuthNote(AbstractUsernameFormAuthenticator.ATTEMPTED_USERNAME);
    if (attemptedUsername != null) username = attemptedUsername;
    String rememberMe = authSession.getAuthNote(Details.REMEMBER_ME);
    boolean remember = rememberMe != null && rememberMe.equalsIgnoreCase("true");
    String brokerSessionId = authSession.getAuthNote(BROKER_SESSION_ID);
    String brokerUserId = authSession.getAuthNote(BROKER_USER_ID);

    if (userSession == null) { // if no authenticator attached a usersession

        userSession = session.sessions().getUserSession(realm, authSession.getParentSession().getId());
        if (userSession == null) {
            userSession = session.sessions().createUserSession(authSession.getParentSession().getId(), realm, authSession.getAuthenticatedUser(), username, connection.getRemoteAddr(), authSession.getProtocol()
                    , remember, brokerSessionId, brokerUserId);
        } else if (userSession.getUser() == null || !AuthenticationManager.isSessionValid(realm, userSession)) {
            userSession.restartSession(realm, authSession.getAuthenticatedUser(), username, connection.getRemoteAddr(), authSession.getProtocol()
                    , remember, brokerSessionId, brokerUserId);
        } else {
            // We have existing userSession even if it wasn't attached to authenticator. Could happen if SSO authentication was ignored (eg. prompt=login) and in some other cases.
            // We need to handle case when different user was used
            logger.debugf("No SSO login, but found existing userSession with ID '%s' after finished authentication.", userSession.getId());
            if (!authSession.getAuthenticatedUser().equals(userSession.getUser())) {
                event.detail(Details.EXISTING_USER, userSession.getUser().getId());
                event.error(Errors.DIFFERENT_USER_AUTHENTICATED);
                throw new ErrorPageException(session, authSession, Response.Status.INTERNAL_SERVER_ERROR, Messages.DIFFERENT_USER_AUTHENTICATED, userSession.getUser().getUsername());
            }
        }
        userSession.setState(UserSessionModel.State.LOGGED_IN);
    }

    if (remember) {
        event.detail(Details.REMEMBER_ME, "true");
    }

    ClientSessionContext clientSessionCtx = TokenManager.attachAuthenticationSession(session, userSession, authSession);

    event.user(userSession.getUser())
            .detail(Details.USERNAME, username)
            .session(userSession);

    return clientSessionCtx;
}