public void sendLogoutRequest(SAMLMessageContext context, SAMLCredential credential) throws SAMLException, MetadataProviderException, MessageEncodingException { // If no user is logged in we do not initialize the protocol. if (credential == null) { return; } IDPSSODescriptor idpDescriptor = (IDPSSODescriptor) context.getPeerEntityRoleMetadata(); SPSSODescriptor spDescriptor = (SPSSODescriptor) context.getLocalEntityRoleMetadata(); String binding = SAMLUtil.getLogoutBinding(idpDescriptor, spDescriptor); SingleLogoutService logoutServiceIDP = SAMLUtil.getLogoutServiceForBinding(idpDescriptor, binding); LogoutRequest logoutRequest = getLogoutRequest(context, credential, logoutServiceIDP); context.setCommunicationProfileId(getProfileIdentifier()); context.setOutboundMessage(logoutRequest); context.setOutboundSAMLMessage(logoutRequest); context.setPeerEntityEndpoint(logoutServiceIDP); boolean signMessage = context.getPeerExtendedMetadata().isRequireLogoutRequestSigned(); sendMessage(context, signMessage); SAMLMessageStorage messageStorage = context.getMessageStorage(); if (messageStorage != null) { messageStorage.storeMessage(logoutRequest.getID(), logoutRequest); } }
/** * Initializes SSO by creating AuthnRequest assertion and sending it to the IDP using the default * binding. Default IDP is used to send the request. * * @param options values specified by caller to customize format of sent request * @throws SAMLException error initializing SSO * @throws SAMLRuntimeException in case context doesn't contain required entities or contains * invalid data * @throws MetadataProviderException error retrieving needed metadata * @throws MessageEncodingException error forming SAML message */ public void sendAuthenticationRequest(SAMLMessageContext context, WebSSOProfileOptions options) throws SAMLException, MetadataProviderException, MessageEncodingException { // Verify we deal with a local SP if (!SPSSODescriptor.DEFAULT_ELEMENT_NAME.equals(context.getLocalEntityRole())) { throw new SAMLException( "WebSSO can only be initialized for local SP, but localEntityRole is: " + context.getLocalEntityRole()); } // Load the entities from the context SPSSODescriptor spDescriptor = (SPSSODescriptor) context.getLocalEntityRoleMetadata(); IDPSSODescriptor idpssoDescriptor = (IDPSSODescriptor) context.getPeerEntityRoleMetadata(); ExtendedMetadata idpExtendedMetadata = context.getPeerExtendedMetadata(); if (spDescriptor == null || idpssoDescriptor == null || idpExtendedMetadata == null) { throw new SAMLException( "SPSSODescriptor, IDPSSODescriptor or IDPExtendedMetadata are not present in the SAMLContext"); } log.debug( "idpExtendedMetadata.getSigningAlgorithm=" + idpExtendedMetadata.getSigningAlgorithm()); idpExtendedMetadata.setSigningAlgorithm("http://www.w3.org/2001/04/xmldsig-more#rsa-sha512"); SingleSignOnService ssoService = getSingleSignOnService(options, idpssoDescriptor, spDescriptor); AssertionConsumerService consumerService = getAssertionConsumerService(options, idpssoDescriptor, spDescriptor); AuthnRequest authRequest = getAuthnRequest(context, options, consumerService, ssoService); if (authRequest == null) { throw new SAMLException("Erreur dans getAuthnRequest null"); } // authRequest.setForceAuthn(Boolean.TRUE); log.debug("getAuthnRequest.providerName=" + authRequest.getProviderName()); // TODO optionally implement support for conditions, subject context.setCommunicationProfileId(getProfileIdentifier()); context.setOutboundMessage(authRequest); context.setOutboundSAMLMessage(authRequest); context.setPeerEntityEndpoint(ssoService); context.setPeerEntityRoleMetadata(idpssoDescriptor); context.setPeerExtendedMetadata(idpExtendedMetadata); if (options.getRelayState() != null) { context.setRelayState(options.getRelayState()); } boolean sign = spDescriptor.isAuthnRequestsSigned() || idpssoDescriptor.getWantAuthnRequestsSigned(); log.debug("signature?" + sign + " avec http://www.w3.org/2001/04/xmldsig-more#rsa-sha512"); context .getLocalExtendedMetadata() .setSigningAlgorithm("http://www.w3.org/2001/04/xmldsig-more#rsa-sha512"); sendMessage(context, sign); SAMLMessageStorage messageStorage = context.getMessageStorage(); if (messageStorage != null) { messageStorage.storeMessage(authRequest.getID(), authRequest); } }
public void processLogoutResponse(SAMLMessageContext context) throws SAMLException, org.opensaml.xml.security.SecurityException, ValidationException { SAMLObject message = context.getInboundSAMLMessage(); // Verify type if (!(message instanceof LogoutResponse)) { log.debug("Received response is not of a Response object type"); throw new SAMLException("Error validating SAML response"); } LogoutResponse response = (LogoutResponse) message; // Make sure request was authenticated if required, authentication is done as part of the // binding processing if (!context.isInboundSAMLMessageAuthenticated() && context.getLocalExtendedMetadata().isRequireLogoutResponseSigned()) { log.debug( "Logout Response object is required to be signed by the entity policy: " + context.getInboundSAMLMessageId()); throw new SAMLException("Logout Response object is required to be signed"); } // Verify issue time DateTime time = response.getIssueInstant(); if (!isDateTimeSkewValid(getResponseSkew(), time)) { log.debug("Response issue time is either too old or with date in the future"); throw new SAMLException("Error validating SAML response"); } // Verify response to field if present, set request if correct // The inResponseTo field is optional, SAML 2.0 Core, 1542 SAMLMessageStorage messageStorage = context.getMessageStorage(); if (messageStorage != null && response.getInResponseTo() != null) { XMLObject xmlObject = messageStorage.retrieveMessage(response.getInResponseTo()); if (xmlObject == null) { log.debug( "InResponseToField doesn't correspond to sent message", response.getInResponseTo()); throw new SAMLException("Error validating SAML response"); } else if (xmlObject instanceof LogoutRequest) { // Expected } else { log.debug( "Sent request was of different type then received response", response.getInResponseTo()); throw new SAMLException("Error validating SAML response"); } } // Verify destination if (response.getDestination() != null) { SPSSODescriptor localDescriptor = (SPSSODescriptor) context.getLocalEntityRoleMetadata(); // Check if destination is correct on this SP List<SingleLogoutService> services = localDescriptor.getSingleLogoutServices(); boolean found = false; for (SingleLogoutService service : services) { if (response.getDestination().equals(service.getLocation()) && context.getInboundSAMLBinding().equals(service.getBinding())) { found = true; break; } } if (!found) { log.debug( "Destination of the response was not the expected value", response.getDestination()); throw new SAMLException("Error validating SAML response"); } } // Verify issuer if (response.getIssuer() != null) { Issuer issuer = response.getIssuer(); verifyIssuer(issuer, context); } // Verify status String statusCode = response.getStatus().getStatusCode().getValue(); if (StatusCode.SUCCESS_URI.equals(statusCode)) { log.trace("Single Logout was successful"); } else if (StatusCode.PARTIAL_LOGOUT_URI.equals(statusCode)) { log.trace("Single Logout was partially successful"); } else { String[] logMessage = new String[2]; logMessage[0] = response.getStatus().getStatusCode().getValue(); StatusMessage message1 = response.getStatus().getStatusMessage(); if (message1 != null) { logMessage[1] = message1.getMessage(); } log.warn("Received LogoutResponse has invalid status code", logMessage); } }