protected Response handleSamlResponse(String samlResponse, String relayState) { event.event(EventType.LOGOUT); SAMLDocumentHolder holder = extractResponseDocument(samlResponse); StatusResponseType statusResponse = (StatusResponseType) holder.getSamlObject(); // validate destination if (statusResponse.getDestination() != null && !uriInfo.getAbsolutePath().toString().equals(statusResponse.getDestination())) { event.detail(Details.REASON, "invalid_destination"); event.error(Errors.INVALID_SAML_LOGOUT_RESPONSE); return ErrorPage.error(session, Messages.INVALID_REQUEST); } AuthenticationManager.AuthResult authResult = authManager.authenticateIdentityCookie(session, realm, false); if (authResult == null) { logger.warn("Unknown saml response."); event.event(EventType.LOGOUT); event.error(Errors.INVALID_TOKEN); return ErrorPage.error(session, Messages.INVALID_REQUEST); } // assume this is a logout response UserSessionModel userSession = authResult.getSession(); if (userSession.getState() != UserSessionModel.State.LOGGING_OUT) { logger.warn("Unknown saml response."); logger.warn("UserSession is not tagged as logging out."); event.event(EventType.LOGOUT); event.error(Errors.INVALID_SAML_LOGOUT_RESPONSE); return ErrorPage.error(session, Messages.INVALID_REQUEST); } logger.debug("logout response"); Response response = authManager.browserLogout( session, realm, userSession, uriInfo, clientConnection, headers); event.success(); return response; }
protected AuthOutcome handleSamlResponse( String samlResponse, String relayState, OnSessionCreated onCreateSession) { SAMLDocumentHolder holder = null; boolean postBinding = false; String requestUri = facade.getRequest().getURI(); if (facade.getRequest().getMethod().equalsIgnoreCase("GET")) { int index = requestUri.indexOf('?'); if (index > -1) { requestUri = requestUri.substring(0, index); } holder = extractRedirectBindingResponse(samlResponse); } else { postBinding = true; holder = extractPostBindingResponse(samlResponse); } final StatusResponseType statusResponse = (StatusResponseType) holder.getSamlObject(); // validate destination if (!requestUri.equals(statusResponse.getDestination())) { log.error("Request URI does not match SAML request destination"); return AuthOutcome.FAILED; } if (statusResponse instanceof ResponseType) { try { if (deployment.getIDP().getSingleSignOnService().validateResponseSignature()) { try { validateSamlSignature(holder, postBinding, GeneralConstants.SAML_RESPONSE_KEY); } catch (VerificationException e) { log.error("Failed to verify saml response signature", e); challenge = new AuthChallenge() { @Override public boolean challenge(HttpFacade exchange) { SamlAuthenticationError error = new SamlAuthenticationError( SamlAuthenticationError.Reason.INVALID_SIGNATURE); exchange.getRequest().setError(error); exchange.getResponse().sendError(403); return true; } @Override public int getResponseCode() { return 403; } }; return AuthOutcome.FAILED; } } return handleLoginResponse((ResponseType) statusResponse, onCreateSession); } finally { sessionStore.setCurrentAction(SamlSessionStore.CurrentAction.NONE); } } else { if (sessionStore.isLoggingOut()) { try { if (deployment.getIDP().getSingleLogoutService().validateResponseSignature()) { try { validateSamlSignature(holder, postBinding, GeneralConstants.SAML_RESPONSE_KEY); } catch (VerificationException e) { log.error("Failed to verify saml response signature", e); return AuthOutcome.FAILED; } } return handleLogoutResponse(holder, statusResponse, relayState); } finally { sessionStore.setCurrentAction(SamlSessionStore.CurrentAction.NONE); } } else if (sessionStore.isLoggingIn()) { try { // KEYCLOAK-2107 - handle user not authenticated due passive mode. Return special outcome // so different authentication mechanisms can behave accordingly. StatusType status = statusResponse.getStatus(); if (checkStatusCodeValue( status.getStatusCode(), JBossSAMLURIConstants.STATUS_RESPONDER.get()) && checkStatusCodeValue( status.getStatusCode().getStatusCode(), JBossSAMLURIConstants.STATUS_NO_PASSIVE.get())) { log.debug( "Not authenticated due passive mode Status found in SAML response: " + status.toString()); return AuthOutcome.NOT_AUTHENTICATED; } challenge = new AuthChallenge() { @Override public boolean challenge(HttpFacade exchange) { SamlAuthenticationError error = new SamlAuthenticationError( SamlAuthenticationError.Reason.ERROR_STATUS, statusResponse); exchange.getRequest().setError(error); exchange.getResponse().sendError(403); return true; } @Override public int getResponseCode() { return 403; } }; return AuthOutcome.FAILED; } finally { sessionStore.setCurrentAction(SamlSessionStore.CurrentAction.NONE); } } return AuthOutcome.NOT_ATTEMPTED; } }