protected void sendLogoutResponse(Status status, SAMLMessageContext context) throws MetadataProviderException, SAMLException, MessageEncodingException { SAMLObjectBuilder<LogoutResponse> responseBuilder = (SAMLObjectBuilder<LogoutResponse>) builderFactory.getBuilder(LogoutResponse.DEFAULT_ELEMENT_NAME); LogoutResponse logoutResponse = responseBuilder.buildObject(); IDPSSODescriptor idpDescriptor = SAMLUtil.getIDPDescriptor(metadata, context.getPeerEntityId()); SPSSODescriptor spDescriptor = (SPSSODescriptor) context.getLocalEntityRoleMetadata(); String binding = SAMLUtil.getLogoutBinding(idpDescriptor, spDescriptor); SingleLogoutService logoutService = SAMLUtil.getLogoutServiceForBinding(idpDescriptor, binding); logoutResponse.setID(generateID()); logoutResponse.setIssuer(getIssuer(context.getLocalEntityId())); logoutResponse.setVersion(SAMLVersion.VERSION_20); logoutResponse.setIssueInstant(new DateTime()); logoutResponse.setInResponseTo(context.getInboundSAMLMessageId()); logoutResponse.setDestination(logoutService.getLocation()); logoutResponse.setStatus(status); context.setCommunicationProfileId(getProfileIdentifier()); context.setOutboundMessage(logoutResponse); context.setOutboundSAMLMessage(logoutResponse); context.setPeerEntityEndpoint(logoutService); context.setPeerEntityId(idpDescriptor.getID()); context.setPeerEntityRoleMetadata(idpDescriptor); boolean signMessage = context.getPeerExtendedMetadata().isRequireLogoutResponseSigned(); sendMessage(context, signMessage); }
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); } }