Java Code Examples for org.keycloak.services.managers.AuthenticationManager#backchannelLogout()
The following examples show how to use
org.keycloak.services.managers.AuthenticationManager#backchannelLogout() .
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: SessionResource.java From keycloak with Apache License 2.0 | 6 votes |
/** * Remove sessions * * @param removeCurrent remove current session (default is false) * @return */ @DELETE @Produces(MediaType.APPLICATION_JSON) @NoCache public Response logout(@QueryParam("current") boolean removeCurrent) { auth.require(AccountRoles.MANAGE_ACCOUNT); List<UserSessionModel> userSessions = session.sessions().getUserSessions(realm, user); for (UserSessionModel s : userSessions) { if (removeCurrent || !isCurrentSession(s)) { AuthenticationManager.backchannelLogout(session, s, true); } } return Cors.add(request, Response.noContent()).auth().allowedOrigins(auth.getToken()).build(); }
Example 2
Source File: AuthorizationEndpointBase.java From keycloak with Apache License 2.0 | 5 votes |
protected AuthenticationSessionModel createAuthenticationSession(ClientModel client, String requestState) { AuthenticationSessionManager manager = new AuthenticationSessionManager(session); RootAuthenticationSessionModel rootAuthSession = manager.getCurrentRootAuthenticationSession(realm); AuthenticationSessionModel authSession; if (rootAuthSession != null) { authSession = rootAuthSession.createAuthenticationSession(client); logger.debugf("Sent request to authz endpoint. Root authentication session with ID '%s' exists. Client is '%s' . Created new authentication session with tab ID: %s", rootAuthSession.getId(), client.getClientId(), authSession.getTabId()); } else { UserSessionCrossDCManager userSessionCrossDCManager = new UserSessionCrossDCManager(session); UserSessionModel userSession = userSessionCrossDCManager.getUserSessionIfExistsRemotely(manager, realm); if (userSession != null) { UserModel user = userSession.getUser(); if (user != null && !user.isEnabled()) { authSession = createNewAuthenticationSession(manager, client); AuthenticationManager.backchannelLogout(session, userSession, true); } else { String userSessionId = userSession.getId(); rootAuthSession = session.authenticationSessions().createRootAuthenticationSession(userSessionId, realm); authSession = rootAuthSession.createAuthenticationSession(client); logger.debugf("Sent request to authz endpoint. We don't have root authentication session with ID '%s' but we have userSession." + "Re-created root authentication session with same ID. Client is: %s . New authentication session tab ID: %s", userSessionId, client.getClientId(), authSession.getTabId()); } } else { authSession = createNewAuthenticationSession(manager, client); } } session.getProvider(LoginFormsProvider.class).setAuthenticationSession(authSession); return authSession; }
Example 3
Source File: RealmAdminResource.java From keycloak with Apache License 2.0 | 5 votes |
/** * Remove a specific user session. Any client that has an admin url will also be told to invalidate this * particular session. * * @param sessionId */ @Path("sessions/{session}") @DELETE public void deleteSession(@PathParam("session") String sessionId) { auth.users().requireManage(); UserSessionModel userSession = session.sessions().getUserSession(realm, sessionId); if (userSession == null) throw new NotFoundException("Sesssion not found"); AuthenticationManager.backchannelLogout(session, realm, userSession, session.getContext().getUri(), connection, headers, true); adminEvent.operation(OperationType.DELETE).resource(ResourceType.USER_SESSION).resourcePath(session.getContext().getUri()).success(); }
Example 4
Source File: UserResource.java From keycloak with Apache License 2.0 | 5 votes |
/** * Remove all user sessions associated with the user * * Also send notification to all clients that have an admin URL to invalidate the sessions for the particular user. * */ @Path("logout") @POST public void logout() { auth.users().requireManage(user); session.users().setNotBeforeForUser(realm, user, Time.currentTime()); List<UserSessionModel> userSessions = session.sessions().getUserSessions(realm, user); for (UserSessionModel userSession : userSessions) { AuthenticationManager.backchannelLogout(session, realm, userSession, session.getContext().getUri(), clientConnection, headers, true); } adminEvent.operation(OperationType.ACTION).resourcePath(session.getContext().getUri()).success(); }
Example 5
Source File: SessionResource.java From keycloak with Apache License 2.0 | 5 votes |
/** * Remove a specific session * * @param id a specific session to remove * @return */ @Path("/{id}") @DELETE @Produces(MediaType.APPLICATION_JSON) @NoCache public Response logout(@PathParam("id") String id) { auth.require(AccountRoles.MANAGE_ACCOUNT); UserSessionModel userSession = session.sessions().getUserSession(realm, id); if (userSession != null && userSession.getUser().equals(user)) { AuthenticationManager.backchannelLogout(session, userSession, true); } return Cors.add(request, Response.noContent()).auth().allowedOrigins(auth.getToken()).build(); }
Example 6
Source File: AccountFormService.java From keycloak with Apache License 2.0 | 5 votes |
@Path("sessions") @POST public Response processSessionsLogout(final MultivaluedMap<String, String> formData) { if (auth == null) { return login("sessions"); } auth.require(AccountRoles.MANAGE_ACCOUNT); csrfCheck(formData); UserModel user = auth.getUser(); // Rather decrease time a bit. To avoid situation when user is immediatelly redirected to login screen, then automatically authenticated (eg. with Kerberos) and then seeing issues due the stale token // as time on the token will be same like notBefore session.users().setNotBeforeForUser(realm, user, Time.currentTime() - 1); List<UserSessionModel> userSessions = session.sessions().getUserSessions(realm, user); for (UserSessionModel userSession : userSessions) { AuthenticationManager.backchannelLogout(session, realm, userSession, session.getContext().getUri(), clientConnection, headers, true); } UriBuilder builder = Urls.accountBase(session.getContext().getUri().getBaseUri()).path(AccountFormService.class, "sessionsPage"); String referrer = session.getContext().getUri().getQueryParameters().getFirst("referrer"); if (referrer != null) { builder.queryParam("referrer", referrer); } URI location = builder.build(realm.getName()); return Response.seeOther(location).build(); }
Example 7
Source File: TokenManager.java From keycloak with Apache License 2.0 | 4 votes |
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 8
Source File: LogoutEndpoint.java From keycloak with Apache License 2.0 | 4 votes |
/** * Logout user session. User must be logged in via a session cookie. * * When the logout is initiated by a remote idp, the parameter "initiating_idp" can be supplied. This param will * prevent upstream logout (since the logout procedure has already been started in the remote idp). * * @param redirectUri * @param initiatingIdp The alias of the idp initiating the logout. * @return */ @GET @NoCache public Response logout(@QueryParam(OIDCLoginProtocol.REDIRECT_URI_PARAM) String redirectUri, // deprecated @QueryParam("id_token_hint") String encodedIdToken, @QueryParam("post_logout_redirect_uri") String postLogoutRedirectUri, @QueryParam("state") String state, @QueryParam("initiating_idp") String initiatingIdp) { String redirect = postLogoutRedirectUri != null ? postLogoutRedirectUri : redirectUri; if (redirect != null) { String validatedUri = RedirectUtils.verifyRealmRedirectUri(session, redirect); if (validatedUri == null) { event.event(EventType.LOGOUT); event.detail(Details.REDIRECT_URI, redirect); event.error(Errors.INVALID_REDIRECT_URI); return ErrorPage.error(session, null, Response.Status.BAD_REQUEST, Messages.INVALID_REDIRECT_URI); } redirect = validatedUri; } UserSessionModel userSession = null; IDToken idToken = null; if (encodedIdToken != null) { try { idToken = tokenManager.verifyIDTokenSignature(session, encodedIdToken); TokenVerifier.createWithoutSignature(idToken).tokenType(TokenUtil.TOKEN_TYPE_ID).verify(); userSession = session.sessions().getUserSession(realm, idToken.getSessionState()); if (userSession != null) { checkTokenIssuedAt(idToken, userSession); } } catch (OAuthErrorException | VerificationException e) { event.event(EventType.LOGOUT); event.error(Errors.INVALID_TOKEN); return ErrorPage.error(session, null, Response.Status.BAD_REQUEST, Messages.SESSION_NOT_ACTIVE); } } // authenticate identity cookie, but ignore an access token timeout as we're logging out anyways. AuthenticationManager.AuthResult authResult = AuthenticationManager.authenticateIdentityCookie(session, realm, false); if (authResult != null) { userSession = userSession != null ? userSession : authResult.getSession(); return initiateBrowserLogout(userSession, redirect, state, initiatingIdp); } else if (userSession != null) { // identity cookie is missing but there's valid id_token_hint which matches session cookie => continue with browser logout if (idToken != null && idToken.getSessionState().equals(AuthenticationManager.getSessionIdFromSessionCookie(session))) { return initiateBrowserLogout(userSession, redirect, state, initiatingIdp); } // non browser logout event.event(EventType.LOGOUT); AuthenticationManager.backchannelLogout(session, realm, userSession, session.getContext().getUri(), clientConnection, headers, true); event.user(userSession.getUser()).session(userSession).success(); } if (redirect != null) { UriBuilder uriBuilder = UriBuilder.fromUri(redirect); if (state != null) uriBuilder.queryParam(OIDCLoginProtocol.STATE_PARAM, state); return Response.status(302).location(uriBuilder.build()).build(); } else { // TODO Empty content with ok makes no sense. Should it display a page? Or use noContent? session.getProvider(SecurityHeadersProvider.class).options().allowEmptyContentType(); return Response.ok().build(); } }
Example 9
Source File: LogoutEndpoint.java From keycloak with Apache License 2.0 | 4 votes |
private void logout(UserSessionModel userSession, boolean offline) { AuthenticationManager.backchannelLogout(session, realm, userSession, session.getContext().getUri(), clientConnection, headers, true, offline); event.user(userSession.getUser()).session(userSession).success(); }
Example 10
Source File: AccountFormService.java From keycloak with Apache License 2.0 | 4 votes |
/** * Update account password * <p> * Form params: * <p> * password - old password * password-new * pasword-confirm * * @param formData * @return */ @Path("password") @POST @Consumes(MediaType.APPLICATION_FORM_URLENCODED) public Response processPasswordUpdate(final MultivaluedMap<String, String> formData) { if (auth == null) { return login("password"); } auth.require(AccountRoles.MANAGE_ACCOUNT); csrfCheck(formData); UserModel user = auth.getUser(); boolean requireCurrent = isPasswordSet(session, realm, user); account.setPasswordSet(requireCurrent); String password = formData.getFirst("password"); String passwordNew = formData.getFirst("password-new"); String passwordConfirm = formData.getFirst("password-confirm"); EventBuilder errorEvent = event.clone().event(EventType.UPDATE_PASSWORD_ERROR) .client(auth.getClient()) .user(auth.getSession().getUser()); if (requireCurrent) { if (Validation.isBlank(password)) { setReferrerOnPage(); errorEvent.error(Errors.PASSWORD_MISSING); return account.setError(Status.OK, Messages.MISSING_PASSWORD).createResponse(AccountPages.PASSWORD); } UserCredentialModel cred = UserCredentialModel.password(password); if (!session.userCredentialManager().isValid(realm, user, cred)) { setReferrerOnPage(); errorEvent.error(Errors.INVALID_USER_CREDENTIALS); return account.setError(Status.OK, Messages.INVALID_PASSWORD_EXISTING).createResponse(AccountPages.PASSWORD); } } if (Validation.isBlank(passwordNew)) { setReferrerOnPage(); errorEvent.error(Errors.PASSWORD_MISSING); return account.setError(Status.OK, Messages.MISSING_PASSWORD).createResponse(AccountPages.PASSWORD); } if (!passwordNew.equals(passwordConfirm)) { setReferrerOnPage(); errorEvent.error(Errors.PASSWORD_CONFIRM_ERROR); return account.setError(Status.OK, Messages.INVALID_PASSWORD_CONFIRM).createResponse(AccountPages.PASSWORD); } try { session.userCredentialManager().updateCredential(realm, user, UserCredentialModel.password(passwordNew, false)); } catch (ReadOnlyException mre) { setReferrerOnPage(); errorEvent.error(Errors.NOT_ALLOWED); return account.setError(Response.Status.BAD_REQUEST, Messages.READ_ONLY_PASSWORD).createResponse(AccountPages.PASSWORD); } catch (ModelException me) { ServicesLogger.LOGGER.failedToUpdatePassword(me); setReferrerOnPage(); errorEvent.detail(Details.REASON, me.getMessage()).error(Errors.PASSWORD_REJECTED); return account.setError(Response.Status.NOT_ACCEPTABLE, me.getMessage(), me.getParameters()).createResponse(AccountPages.PASSWORD); } catch (Exception ape) { ServicesLogger.LOGGER.failedToUpdatePassword(ape); setReferrerOnPage(); errorEvent.detail(Details.REASON, ape.getMessage()).error(Errors.PASSWORD_REJECTED); return account.setError(Response.Status.INTERNAL_SERVER_ERROR, ape.getMessage()).createResponse(AccountPages.PASSWORD); } List<UserSessionModel> sessions = session.sessions().getUserSessions(realm, user); for (UserSessionModel s : sessions) { if (!s.getId().equals(auth.getSession().getId())) { AuthenticationManager.backchannelLogout(session, realm, s, session.getContext().getUri(), clientConnection, headers, true); } } event.event(EventType.UPDATE_PASSWORD).client(auth.getClient()).user(auth.getUser()).success(); setReferrerOnPage(); return account.setPasswordSet(true).setSuccess(Messages.ACCOUNT_PASSWORD_UPDATED).createResponse(AccountPages.PASSWORD); }