Java Code Examples for org.keycloak.models.UserSessionModel#getAuthenticatedClientSessionByClient()

The following examples show how to use org.keycloak.models.UserSessionModel#getAuthenticatedClientSessionByClient() . 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: UserSessionProviderTest.java    From keycloak with Apache License 2.0 6 votes vote down vote up
@Test
@ModelTest
public void testUpdateClientSessionWithGetByClientId(KeycloakSession session) {
    RealmModel realm = session.realms().getRealmByName("test");
    UserSessionModel[] sessions = createSessions(session);

    String userSessionId = sessions[0].getId();
    String clientUUID = realm.getClientByClientId("test-app").getId();

    UserSessionModel userSession = session.sessions().getUserSession(realm, userSessionId);
    AuthenticatedClientSessionModel clientSession = userSession.getAuthenticatedClientSessionByClient(clientUUID);

    int time = clientSession.getTimestamp();
    assertNull(clientSession.getAction());

    clientSession.setAction(AuthenticatedClientSessionModel.Action.LOGGED_OUT.name());
    clientSession.setTimestamp(time + 10);

    AuthenticatedClientSessionModel updated = session.sessions().getUserSession(realm, userSessionId).getAuthenticatedClientSessionByClient(clientUUID);
    assertEquals(AuthenticatedClientSessionModel.Action.LOGGED_OUT.name(), updated.getAction());
    assertEquals(time + 10, updated.getTimestamp());
}
 
Example 2
Source File: UserSessionProviderTest.java    From keycloak with Apache License 2.0 6 votes vote down vote up
@Test
@ModelTest
public void testUpdateClientSessionInSameTransaction(KeycloakSession session) {
    RealmModel realm = session.realms().getRealmByName("test");
    UserSessionModel[] sessions = createSessions(session);

    String userSessionId = sessions[0].getId();
    String clientUUID = realm.getClientByClientId("test-app").getId();

    UserSessionModel userSession = session.sessions().getUserSession(realm, userSessionId);
    AuthenticatedClientSessionModel clientSession = userSession.getAuthenticatedClientSessionByClient(clientUUID);

    clientSession.setAction(AuthenticatedClientSessionModel.Action.LOGGED_OUT.name());
    clientSession.setNote("foo", "bar");

    AuthenticatedClientSessionModel updated = session.sessions().getUserSession(realm, userSessionId).getAuthenticatedClientSessionByClient(clientUUID);
    assertEquals(AuthenticatedClientSessionModel.Action.LOGGED_OUT.name(), updated.getAction());
    assertEquals("bar", updated.getNote("foo"));
}
 
Example 3
Source File: SamlSessionUtils.java    From keycloak with Apache License 2.0 6 votes vote down vote up
public static AuthenticatedClientSessionModel getClientSession(KeycloakSession session, RealmModel realm, String sessionIndex) {
    if (sessionIndex == null) {
        return null;
    }

    String[] parts = PATTERN.split(sessionIndex);
    if (parts.length != 2) {
        return null;
    }

    String userSessionId = parts[0];
    String clientUUID = parts[1];
    UserSessionModel userSession = new UserSessionCrossDCManager(session).getUserSessionWithClient(realm, userSessionId, false, clientUUID);
    if (userSession == null) {
        return null;
    }

    return userSession.getAuthenticatedClientSessionByClient(clientUUID);
}
 
Example 4
Source File: UserSessionManager.java    From keycloak with Apache License 2.0 6 votes vote down vote up
public void createOrUpdateOfflineSession(AuthenticatedClientSessionModel clientSession, UserSessionModel userSession) {
    UserModel user = userSession.getUser();

    // Create and persist offline userSession if we don't have one
    UserSessionModel offlineUserSession = kcSession.sessions().getOfflineUserSession(clientSession.getRealm(), userSession.getId());
    if (offlineUserSession == null) {
        offlineUserSession = createOfflineUserSession(user, userSession);
    } else {
        // update lastSessionRefresh but don't need to persist
        offlineUserSession.setLastSessionRefresh(Time.currentTime());
    }

    // Create and persist clientSession
    AuthenticatedClientSessionModel offlineClientSession = offlineUserSession.getAuthenticatedClientSessionByClient(clientSession.getClient().getId());
    if (offlineClientSession == null) {
        createOfflineClientSession(user, clientSession, offlineUserSession);
    }
}
 
Example 5
Source File: UserSessionManager.java    From keycloak with Apache License 2.0 6 votes vote down vote up
public boolean revokeOfflineToken(UserModel user, ClientModel client) {
    RealmModel realm = client.getRealm();

    List<UserSessionModel> userSessions = kcSession.sessions().getOfflineUserSessions(realm, user);
    boolean anyRemoved = false;
    for (UserSessionModel userSession : userSessions) {
        AuthenticatedClientSessionModel clientSession = userSession.getAuthenticatedClientSessionByClient(client.getId());
        if (clientSession != null) {
            if (logger.isTraceEnabled()) {
                logger.tracef("Removing existing offline token for user '%s' and client '%s' .",
                        user.getUsername(), client.getClientId());
            }

            clientSession.detachFromUserSession();
            persister.removeClientSession(userSession.getId(), client.getId(), true);
            checkOfflineUserSessionHasClientSessions(realm, user, userSession);
            anyRemoved = true;
        }
    }

    return anyRemoved;
}
 
Example 6
Source File: TokenRevocationEndpoint.java    From keycloak with Apache License 2.0 5 votes vote down vote up
private void revokeClient() {
    session.users().revokeConsentForClient(realm, user.getId(), client.getId());
    if (TokenUtil.TOKEN_TYPE_OFFLINE.equals(token.getType())) {
        new UserSessionManager(session).revokeOfflineToken(user, client);
    }

    List<UserSessionModel> userSessions = session.sessions().getUserSessions(realm, user);
    for (UserSessionModel userSession : userSessions) {
        AuthenticatedClientSessionModel clientSession = userSession.getAuthenticatedClientSessionByClient(client.getId());
        if (clientSession != null) {
            org.keycloak.protocol.oidc.TokenManager.dettachClientSession(session.sessions(), realm, clientSession);
        }
    }
}
 
Example 7
Source File: TokenEndpoint.java    From keycloak with Apache License 2.0 5 votes vote down vote up
public Response refreshTokenGrant() {
    String refreshToken = formParams.getFirst(OAuth2Constants.REFRESH_TOKEN);
    if (refreshToken == null) {
        throw new CorsErrorResponseException(cors, OAuthErrorException.INVALID_REQUEST, "No refresh token", Response.Status.BAD_REQUEST);
    }

    AccessTokenResponse res;
    try {
        // KEYCLOAK-6771 Certificate Bound Token
        TokenManager.RefreshResult result = tokenManager.refreshAccessToken(session, session.getContext().getUri(), clientConnection, realm, client, refreshToken, event, headers, request);
        res = result.getResponse();

        if (!result.isOfflineToken()) {
            UserSessionModel userSession = session.sessions().getUserSession(realm, res.getSessionState());
            AuthenticatedClientSessionModel clientSession = userSession.getAuthenticatedClientSessionByClient(client.getId());
            updateClientSession(clientSession);
            updateUserSessionFromClientAuth(userSession);
        }

    } catch (OAuthErrorException e) {
        logger.trace(e.getMessage(), e);
        // KEYCLOAK-6771 Certificate Bound Token
        if (MtlsHoKTokenUtil.CERT_VERIFY_ERROR_DESC.equals(e.getDescription())) {
            event.error(Errors.NOT_ALLOWED);
            throw new CorsErrorResponseException(cors, e.getError(), e.getDescription(), Response.Status.UNAUTHORIZED);
        } else {
            event.error(Errors.INVALID_TOKEN);
            throw new CorsErrorResponseException(cors, e.getError(), e.getDescription(), Response.Status.BAD_REQUEST);
        }
    }

    event.success();

    return cors.builder(Response.ok(res, MediaType.APPLICATION_JSON_TYPE)).build();
}
 
Example 8
Source File: AuthenticationManager.java    From keycloak with Apache License 2.0 5 votes vote down vote up
/**
 * Logout all clientSessions of this user and client
 * @param session
 * @param realm
 * @param user
 * @param client
 * @param uriInfo
 * @param headers
 */
public static void backchannelLogoutUserFromClient(KeycloakSession session, RealmModel realm, UserModel user, ClientModel client, UriInfo uriInfo, HttpHeaders headers) {
    List<UserSessionModel> userSessions = session.sessions().getUserSessions(realm, user);
    for (UserSessionModel userSession : userSessions) {
        AuthenticatedClientSessionModel clientSession = userSession.getAuthenticatedClientSessionByClient(client.getId());
        if (clientSession != null) {
            backchannelLogoutClientSession(session, realm, clientSession, null, uriInfo, headers);
            clientSession.setAction(AuthenticationSessionModel.Action.LOGGED_OUT.name());
            org.keycloak.protocol.oidc.TokenManager.dettachClientSession(session.sessions(), realm, clientSession);
        }
    }
}
 
Example 9
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 10
Source File: OAuth2CodeParser.java    From keycloak with Apache License 2.0 4 votes vote down vote up
/**
 * Will parse the code and retrieve the corresponding OAuth2Code and AuthenticatedClientSessionModel. Will also check if code wasn't already
 * used and if it wasn't expired. If it was already used (or other error happened during parsing), then returned parser will have "isIllegalHash"
 * set to true. If it was expired, the parser will have "isExpired" set to true
 *
 * @param session
 * @param code
 * @param realm
 * @param event
 * @return
 */
public static ParseResult parseCode(KeycloakSession session, String code, RealmModel realm, EventBuilder event) {
    ParseResult result = new ParseResult(code);

    String[] parsed = DOT.split(code, 3);
    if (parsed.length < 3) {
        logger.warn("Invalid format of the code");
        return result.illegalCode();
    }

    String userSessionId = parsed[1];
    String clientUUID = parsed[2];

    event.detail(Details.CODE_ID, userSessionId);
    event.session(userSessionId);

    // Parse UUID
    UUID codeUUID;
    try {
        codeUUID = UUID.fromString(parsed[0]);
    } catch (IllegalArgumentException re) {
        logger.warn("Invalid format of the UUID in the code");
        return result.illegalCode();
    }

    // Retrieve UserSession
    UserSessionModel userSession = new UserSessionCrossDCManager(session).getUserSessionWithClient(realm, userSessionId, clientUUID);
    if (userSession == null) {
        // Needed to track if code is invalid or was already used.
        userSession = session.sessions().getUserSession(realm, userSessionId);
        if (userSession == null) {
            return result.illegalCode();
        }
    }

    result.clientSession = userSession.getAuthenticatedClientSessionByClient(clientUUID);

    CodeToTokenStoreProvider codeStore = session.getProvider(CodeToTokenStoreProvider.class);
    Map<String, String> codeData = codeStore.remove(codeUUID);

    // Either code not available or was already used
    if (codeData == null) {
        logger.warnf("Code '%s' already used for userSession '%s' and client '%s'.", codeUUID, userSessionId, clientUUID);
        return result.illegalCode();
    }

    logger.tracef("Successfully verified code '%s'. User session: '%s', client: '%s'", codeUUID, userSessionId, clientUUID);

    result.codeData = OAuth2Code.deserializeCode(codeData);

    // Finally doublecheck if code is not expired
    int currentTime = Time.currentTime();
    if (currentTime > result.codeData.getExpiration()) {
        return result.expiredCode();
    }

    return result;
}
 
Example 11
Source File: AccountFormService.java    From keycloak with Apache License 2.0 4 votes vote down vote up
public void init() {
    eventStore = session.getProvider(EventStoreProvider.class);

    account = session.getProvider(AccountProvider.class).setRealm(realm).setUriInfo(session.getContext().getUri()).setHttpHeaders(headers);

    AuthenticationManager.AuthResult authResult = authManager.authenticateIdentityCookie(session, realm);
    if (authResult != null) {
        stateChecker = (String) session.getAttribute("state_checker");
        auth = new Auth(realm, authResult.getToken(), authResult.getUser(), client, authResult.getSession(), true);
        account.setStateChecker(stateChecker);
    }

    String requestOrigin = UriUtils.getOrigin(session.getContext().getUri().getBaseUri());

    String origin = headers.getRequestHeaders().getFirst("Origin");
    if (origin != null && !requestOrigin.equals(origin)) {
        throw new ForbiddenException();
    }

    if (!request.getHttpMethod().equals("GET")) {
        String referrer = headers.getRequestHeaders().getFirst("Referer");
        if (referrer != null && !requestOrigin.equals(UriUtils.getOrigin(referrer))) {
            throw new ForbiddenException();
        }
    }

    if (authResult != null) {
        UserSessionModel userSession = authResult.getSession();
        if (userSession != null) {
            AuthenticatedClientSessionModel clientSession = userSession.getAuthenticatedClientSessionByClient(client.getId());
            if (clientSession == null) {
                clientSession = session.sessions().createClientSession(userSession.getRealm(), client, userSession);
            }
            auth.setClientSession(clientSession);
        }

        account.setUser(auth.getUser());
    }

    account.setFeatures(realm.isIdentityFederationEnabled(), eventStore != null && realm.isEventsEnabled(), true, true);
}
 
Example 12
Source File: AuthorizationTokenService.java    From keycloak with Apache License 2.0 4 votes vote down vote up
private AuthorizationResponse createAuthorizationResponse(KeycloakIdentity identity, Collection<Permission> entitlements, KeycloakAuthorizationRequest request, ClientModel targetClient) {
    KeycloakSession keycloakSession = request.getKeycloakSession();
    AccessToken accessToken = identity.getAccessToken();
    RealmModel realm = request.getRealm();
    UserSessionProvider sessions = keycloakSession.sessions();
    UserSessionModel userSessionModel = sessions.getUserSession(realm, accessToken.getSessionState());

    if (userSessionModel == null) {
        userSessionModel = sessions.getOfflineUserSession(realm, accessToken.getSessionState());
    }

    ClientModel client = realm.getClientByClientId(accessToken.getIssuedFor());
    AuthenticatedClientSessionModel clientSession = userSessionModel.getAuthenticatedClientSessionByClient(targetClient.getId());
    ClientSessionContext clientSessionCtx;

    if (clientSession == null) {
        RootAuthenticationSessionModel rootAuthSession = keycloakSession.authenticationSessions().getRootAuthenticationSession(realm, userSessionModel.getId());

        if (rootAuthSession == null) {
            if (userSessionModel.getUser().getServiceAccountClientLink() == null) {
                rootAuthSession = keycloakSession.authenticationSessions().createRootAuthenticationSession(userSessionModel.getId(), realm);
            } else {
                // if the user session is associated with a service account
                rootAuthSession = new AuthenticationSessionManager(keycloakSession).createAuthenticationSession(realm, false);
            }
        }

        AuthenticationSessionModel authSession = rootAuthSession.createAuthenticationSession(targetClient);

        authSession.setAuthenticatedUser(userSessionModel.getUser());
        authSession.setProtocol(OIDCLoginProtocol.LOGIN_PROTOCOL);
        authSession.setClientNote(OIDCLoginProtocol.ISSUER, Urls.realmIssuer(keycloakSession.getContext().getUri().getBaseUri(), realm.getName()));

        AuthenticationManager.setClientScopesInSession(authSession);
        clientSessionCtx = TokenManager.attachAuthenticationSession(keycloakSession, userSessionModel, authSession);
    } else {
        clientSessionCtx = DefaultClientSessionContext.fromClientSessionScopeParameter(clientSession, keycloakSession);
    }

    TokenManager tokenManager = request.getTokenManager();
    EventBuilder event = request.getEvent();
    AccessTokenResponseBuilder responseBuilder = tokenManager.responseBuilder(realm, client, event, keycloakSession, userSessionModel, clientSessionCtx)
            .generateAccessToken()
            .generateRefreshToken();
    AccessToken rpt = responseBuilder.getAccessToken();
    Authorization authorization = new Authorization();

    authorization.setPermissions(entitlements);

    rpt.setAuthorization(authorization);

    RefreshToken refreshToken = responseBuilder.getRefreshToken();

    refreshToken.issuedFor(client.getClientId());
    refreshToken.setAuthorization(authorization);

    if (!rpt.hasAudience(targetClient.getClientId())) {
        rpt.audience(targetClient.getClientId());
    }

    return new AuthorizationResponse(responseBuilder.build(), isUpgraded(request, authorization));
}