@Override public Response keycloakInitiatedBrowserLogout( UserSessionModel userSession, UriInfo uriInfo, RealmModel realm) { if (getConfig().getLogoutUrl() == null || getConfig().getLogoutUrl().trim().equals("")) return null; String idToken = userSession.getNote(FEDERATED_ID_TOKEN); if (idToken != null && getConfig().isBackchannelSupported()) { backchannelLogout(userSession, idToken); return null; } else { String sessionId = userSession.getId(); UriBuilder logoutUri = UriBuilder.fromUri(getConfig().getLogoutUrl()).queryParam("state", sessionId); if (idToken != null) logoutUri.queryParam("id_token_hint", idToken); String redirect = RealmsResource.brokerUrl(uriInfo) .path(IdentityBrokerService.class, "getEndpoint") .path(OIDCEndpoint.class, "logoutResponse") .build(realm.getName(), getConfig().getAlias()) .toString(); logoutUri.queryParam("post_logout_redirect_uri", redirect); Response response = Response.status(302).location(logoutUri.build()).build(); return response; } }
@Override public void backchannelLogout(UserSessionModel userSession, UriInfo uriInfo, RealmModel realm) { if (getConfig().getLogoutUrl() == null || getConfig().getLogoutUrl().trim().equals("") || !getConfig().isBackchannelSupported()) return; String idToken = userSession.getNote(FEDERATED_ID_TOKEN); if (idToken == null) return; backchannelLogout(userSession, idToken); }
@Override public Response finishLogout(UserSessionModel userSession) { String redirectUri = userSession.getNote(OIDCLoginProtocol.LOGOUT_REDIRECT_URI); String state = userSession.getNote(OIDCLoginProtocol.LOGOUT_STATE_PARAM); event.event(EventType.LOGOUT); if (redirectUri != null) { event.detail(Details.REDIRECT_URI, redirectUri); } event.user(userSession.getUser()).session(userSession).success(); if (redirectUri != null) { UriBuilder uriBuilder = UriBuilder.fromUri(redirectUri); if (state != null) uriBuilder.queryParam(STATE_PARAM, state); return Response.status(302).location(uriBuilder.build()).build(); } else { return Response.ok().build(); } }
@Override public Response finishLogout(UserSessionModel userSession) { logger.debug("finishLogout"); String logoutBindingUri = userSession.getNote(SAML_LOGOUT_BINDING_URI); if (logoutBindingUri == null) { logger.error( "Can't finish SAML logout as there is no logout binding set. Please configure the logout service url in the admin console for your client applications."); return ErrorPage.error(session, Messages.FAILED_LOGOUT); } String logoutRelayState = userSession.getNote(SAML_LOGOUT_RELAY_STATE); SAML2LogoutResponseBuilder builder = new SAML2LogoutResponseBuilder(); builder.logoutRequestID(userSession.getNote(SAML_LOGOUT_REQUEST_ID)); builder.destination(logoutBindingUri); builder.issuer(getResponseIssuer(realm)); JaxrsSAML2BindingBuilder binding = new JaxrsSAML2BindingBuilder(); binding.relayState(logoutRelayState); String signingAlgorithm = userSession.getNote(SAML_LOGOUT_SIGNATURE_ALGORITHM); if (signingAlgorithm != null) { SignatureAlgorithm algorithm = SignatureAlgorithm.valueOf(signingAlgorithm); String canonicalization = userSession.getNote(SAML_LOGOUT_CANONICALIZATION); if (canonicalization != null) { binding.canonicalizationMethod(canonicalization); } KeyManager.ActiveKey keys = session.keys().getActiveKey(realm); binding .signatureAlgorithm(algorithm) .signWith(keys.getPrivateKey(), keys.getPublicKey(), keys.getCertificate()) .signDocument(); } try { return buildLogoutResponse(userSession, logoutBindingUri, builder, binding); } catch (ConfigurationException e) { throw new RuntimeException(e); } catch (ProcessingException e) { throw new RuntimeException(e); } catch (IOException e) { throw new RuntimeException(e); } }
public static boolean isLogoutPostBindingForInitiator(UserSessionModel session) { String note = session.getNote(SamlProtocol.SAML_LOGOUT_BINDING); return SamlProtocol.SAML_POST_BINDING.equals(note); }