use of org.keycloak.protocol.oidc.LogoutTokenValidationCode in project keycloak by keycloak.
the class LogoutEndpoint method backchannelLogout.
/**
* Backchannel logout endpoint implementation for Keycloak, which tries to logout the user from all sessions via
* POST with a valid LogoutToken.
*
* Logout a session via a non-browser invocation. Will be implemented as a backchannel logout based on the
* specification
* https://openid.net/specs/openid-connect-backchannel-1_0.html
*
* @return
*/
@Path("/backchannel-logout")
@POST
@Consumes(MediaType.APPLICATION_FORM_URLENCODED)
public Response backchannelLogout() {
MultivaluedMap<String, String> form = request.getDecodedFormParameters();
event.event(EventType.LOGOUT);
String encodedLogoutToken = form.getFirst(OAuth2Constants.LOGOUT_TOKEN);
if (encodedLogoutToken == null) {
event.error(Errors.INVALID_TOKEN);
throw new ErrorResponseException(OAuthErrorException.INVALID_REQUEST, "No logout token", Response.Status.BAD_REQUEST);
}
LogoutTokenValidationCode validationCode = tokenManager.verifyLogoutToken(session, realm, encodedLogoutToken);
if (!validationCode.equals(LogoutTokenValidationCode.VALIDATION_SUCCESS)) {
event.error(Errors.INVALID_TOKEN);
throw new ErrorResponseException(OAuthErrorException.INVALID_REQUEST, validationCode.getErrorMessage(), Response.Status.BAD_REQUEST);
}
LogoutToken logoutToken = tokenManager.toLogoutToken(encodedLogoutToken).get();
Stream<String> identityProviderAliases = tokenManager.getValidOIDCIdentityProvidersForBackchannelLogout(realm, session, encodedLogoutToken, logoutToken).map(idp -> idp.getConfig().getAlias());
boolean logoutOfflineSessions = Boolean.parseBoolean(logoutToken.getEvents().getOrDefault(TokenUtil.TOKEN_BACKCHANNEL_LOGOUT_EVENT_REVOKE_OFFLINE_TOKENS, false).toString());
BackchannelLogoutResponse backchannelLogoutResponse;
if (logoutToken.getSid() != null) {
backchannelLogoutResponse = backchannelLogoutWithSessionId(logoutToken.getSid(), identityProviderAliases, logoutOfflineSessions, logoutToken.getSubject());
} else {
backchannelLogoutResponse = backchannelLogoutFederatedUserId(logoutToken.getSubject(), identityProviderAliases, logoutOfflineSessions);
}
if (!backchannelLogoutResponse.getLocalLogoutSucceeded()) {
event.error(Errors.LOGOUT_FAILED);
throw new ErrorResponseException(OAuthErrorException.SERVER_ERROR, "There was an error in the local logout", Response.Status.NOT_IMPLEMENTED);
}
session.getProvider(SecurityHeadersProvider.class).options().allowEmptyContentType();
if (oneOrMoreDownstreamLogoutsFailed(backchannelLogoutResponse)) {
return Cors.add(request).auth().builder(Response.status(Response.Status.GATEWAY_TIMEOUT).type(MediaType.APPLICATION_JSON_TYPE)).build();
}
return Cors.add(request).auth().builder(Response.ok().type(MediaType.APPLICATION_JSON_TYPE)).build();
}
Aggregations