protected AuthOutcome handleSamlRequest(String samlRequest, String relayState) { SAMLDocumentHolder holder = null; boolean postBinding = false; String requestUri = facade.getRequest().getURI(); if (facade.getRequest().getMethod().equalsIgnoreCase("GET")) { // strip out query params int index = requestUri.indexOf('?'); if (index > -1) { requestUri = requestUri.substring(0, index); } holder = SAMLRequestParser.parseRequestRedirectBinding(samlRequest); } else { postBinding = true; holder = SAMLRequestParser.parseRequestPostBinding(samlRequest); } RequestAbstractType requestAbstractType = (RequestAbstractType) holder.getSamlObject(); if (!requestUri.equals(requestAbstractType.getDestination().toString())) { log.error( "expected destination '" + requestUri + "' got '" + requestAbstractType.getDestination() + "'"); return AuthOutcome.FAILED; } if (requestAbstractType instanceof LogoutRequestType) { if (deployment.getIDP().getSingleLogoutService().validateRequestSignature()) { try { validateSamlSignature(holder, postBinding, GeneralConstants.SAML_REQUEST_KEY); } catch (VerificationException e) { log.error("Failed to verify saml request signature", e); return AuthOutcome.FAILED; } } LogoutRequestType logout = (LogoutRequestType) requestAbstractType; return logoutRequest(logout, relayState); } else { log.error("unknown SAML request type"); return AuthOutcome.FAILED; } }
private void validateSamlSignature( SAMLDocumentHolder holder, boolean postBinding, String paramKey) throws VerificationException { if (postBinding) { verifyPostBindingSignature( holder.getSamlDocument(), deployment.getIDP().getSignatureValidationKey()); } else { verifyRedirectBindingSignature(deployment.getIDP().getSignatureValidationKey(), paramKey); } }
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; }
@Override protected void verifySignature(SAMLDocumentHolder documentHolder, ClientModel client) throws VerificationException { SamlProtocolUtils.verifyDocumentSignature(client, documentHolder.getSamlDocument()); }
protected Response handleSamlRequest(String samlRequest, String relayState) { SAMLDocumentHolder documentHolder = extractRequestDocument(samlRequest); if (documentHolder == null) { event.event(EventType.LOGIN); event.error(Errors.INVALID_TOKEN); return ErrorPage.error(session, Messages.INVALID_REQUEST); } SAML2Object samlObject = documentHolder.getSamlObject(); RequestAbstractType requestAbstractType = (RequestAbstractType) samlObject; String issuer = requestAbstractType.getIssuer().getValue(); ClientModel client = realm.getClientByClientId(issuer); if (client == null) { event.event(EventType.LOGIN); event.client(issuer); event.error(Errors.CLIENT_NOT_FOUND); return ErrorPage.error(session, Messages.UNKNOWN_LOGIN_REQUESTER); } if (!client.isEnabled()) { event.event(EventType.LOGIN); event.error(Errors.CLIENT_DISABLED); return ErrorPage.error(session, Messages.LOGIN_REQUESTER_NOT_ENABLED); } if (client.isBearerOnly()) { event.event(EventType.LOGIN); event.error(Errors.NOT_ALLOWED); return ErrorPage.error(session, Messages.BEARER_ONLY); } if (!client.isStandardFlowEnabled()) { event.event(EventType.LOGIN); event.error(Errors.NOT_ALLOWED); return ErrorPage.error(session, Messages.STANDARD_FLOW_DISABLED); } session.getContext().setClient(client); try { verifySignature(documentHolder, client); } catch (VerificationException e) { SamlService.logger.error("request validation failed", e); event.event(EventType.LOGIN); event.error(Errors.INVALID_SIGNATURE); return ErrorPage.error(session, Messages.INVALID_REQUESTER); } logger.debug("verified request"); if (samlObject instanceof AuthnRequestType) { logger.debug("** login request"); event.event(EventType.LOGIN); // Get the SAML Request Message AuthnRequestType authn = (AuthnRequestType) samlObject; return loginRequest(relayState, authn, client); } else if (samlObject instanceof LogoutRequestType) { logger.debug("** logout request"); event.event(EventType.LOGOUT); LogoutRequestType logout = (LogoutRequestType) samlObject; return logoutRequest(logout, client, relayState); } else { event.event(EventType.LOGIN); event.error(Errors.INVALID_TOKEN); return ErrorPage.error(session, Messages.INVALID_REQUEST); } }
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; } }