use of org.opensaml.saml.saml2.core.Response in project cas by apereo.
the class SamlProfileSaml2ResponseBuilder method buildResponse.
@Override
public Response buildResponse(final Assertion assertion, final Object casAssertion, final RequestAbstractType authnRequest, final SamlRegisteredService service, final SamlRegisteredServiceServiceProviderMetadataFacade adaptor, final HttpServletRequest request, final HttpServletResponse response, final String binding) throws SamlException {
final String id = '_' + String.valueOf(Math.abs(RandomUtils.getNativeInstance().nextLong()));
Response samlResponse = newResponse(id, ZonedDateTime.now(ZoneOffset.UTC), authnRequest.getID(), null);
samlResponse.setVersion(SAMLVersion.VERSION_20);
samlResponse.setIssuer(buildEntityIssuer());
if (casProperties.getAuthn().getSamlIdp().isAttributeQueryProfileEnabled()) {
storeAttributeQueryTicketInRegistry(assertion, request, adaptor);
}
final SAMLObject finalAssertion = encryptAssertion(assertion, request, response, service, adaptor);
if (finalAssertion instanceof EncryptedAssertion) {
LOGGER.debug("Built assertion is encrypted, so the response will add it to the encrypted assertions collection");
samlResponse.getEncryptedAssertions().add(EncryptedAssertion.class.cast(finalAssertion));
} else {
LOGGER.debug("Built assertion is not encrypted, so the response will add it to the assertions collection");
samlResponse.getAssertions().add(Assertion.class.cast(finalAssertion));
}
final Status status = newStatus(StatusCode.SUCCESS, null);
samlResponse.setStatus(status);
SamlUtils.logSamlObject(this.configBean, samlResponse);
if (service.isSignResponses()) {
LOGGER.debug("SAML entity id [{}] indicates that SAML responses should be signed", adaptor.getEntityId());
samlResponse = this.samlObjectSigner.encode(samlResponse, service, adaptor, response, request, binding);
SamlUtils.logSamlObject(configBean, samlResponse);
}
return samlResponse;
}
use of org.opensaml.saml.saml2.core.Response in project cas by apereo.
the class ECPProfileHandlerController method handleEcpRequest.
/**
* Handle ecp request.
*
* @param response the response
* @param request the request
* @param soapContext the soap context
* @param credential the credential
* @param binding the binding
*/
protected void handleEcpRequest(final HttpServletResponse response, final HttpServletRequest request, final MessageContext soapContext, final Credential credential, final String binding) {
LOGGER.debug("Handling ECP request for SOAP context [{}]", soapContext);
final Envelope envelope = soapContext.getSubcontext(SOAP11Context.class).getEnvelope();
SamlUtils.logSamlObject(configBean, envelope);
final AuthnRequest authnRequest = (AuthnRequest) soapContext.getMessage();
final Pair<AuthnRequest, MessageContext> authenticationContext = Pair.of(authnRequest, soapContext);
try {
LOGGER.debug("Verifying ECP authentication request [{}]", authnRequest);
final Pair<SamlRegisteredService, SamlRegisteredServiceServiceProviderMetadataFacade> serviceRequest = verifySamlAuthenticationRequest(authenticationContext, request);
LOGGER.debug("Attempting to authenticate ECP request for credential id [{}]", credential.getId());
final Authentication authentication = authenticateEcpRequest(credential, authenticationContext);
LOGGER.debug("Authenticated [{}] successfully with authenticated principal [{}]", credential.getId(), authentication.getPrincipal());
LOGGER.debug("Building ECP SAML response for [{}]", credential.getId());
final String issuer = SamlIdPUtils.getIssuerFromSamlRequest(authnRequest);
final Service service = webApplicationServiceFactory.createService(issuer);
final Assertion casAssertion = buildCasAssertion(authentication, service, serviceRequest.getKey(), new LinkedHashMap<>());
LOGGER.debug("CAS assertion to use for building ECP SAML response is [{}]", casAssertion);
buildSamlResponse(response, request, authenticationContext, casAssertion, binding);
} catch (final AuthenticationException e) {
LOGGER.error(e.getMessage(), e);
final String error = e.getHandlerErrors().values().stream().map(Throwable::getMessage).filter(Objects::nonNull).collect(Collectors.joining(","));
buildEcpFaultResponse(response, request, Pair.of(authnRequest, error));
} catch (final Exception e) {
LOGGER.error(e.getMessage(), e);
buildEcpFaultResponse(response, request, Pair.of(authnRequest, e.getMessage()));
}
}
use of org.opensaml.saml.saml2.core.Response in project cxf by apache.
the class SAMLSSOResponseValidator method validateSamlResponse.
/**
* Validate a SAML 2 Protocol Response
* @param samlResponse
* @param postBinding
* @return a SSOValidatorResponse object
* @throws WSSecurityException
*/
public SSOValidatorResponse validateSamlResponse(org.opensaml.saml.saml2.core.Response samlResponse, boolean postBinding) throws WSSecurityException {
// Check the Issuer
validateIssuer(samlResponse.getIssuer());
// The Response must contain at least one Assertion.
if (samlResponse.getAssertions() == null || samlResponse.getAssertions().isEmpty()) {
LOG.fine("The Response must contain at least one Assertion");
throw new WSSecurityException(WSSecurityException.ErrorCode.FAILURE, "invalidSAMLsecurity");
}
// The Response must contain a Destination that matches the assertionConsumerURL if it is
// signed
String destination = samlResponse.getDestination();
if (samlResponse.isSigned() && (destination == null || !destination.equals(assertionConsumerURL))) {
LOG.fine("The Response must contain a destination that matches the assertion consumer URL");
throw new WSSecurityException(WSSecurityException.ErrorCode.FAILURE, "invalidSAMLsecurity");
}
if (enforceResponseSigned && !samlResponse.isSigned()) {
LOG.fine("The Response must be signed!");
throw new WSSecurityException(WSSecurityException.ErrorCode.FAILURE, "invalidSAMLsecurity");
}
// Validate Assertions
org.opensaml.saml.saml2.core.Assertion validAssertion = null;
Instant sessionNotOnOrAfter = null;
for (org.opensaml.saml.saml2.core.Assertion assertion : samlResponse.getAssertions()) {
// Check the Issuer
if (assertion.getIssuer() == null) {
LOG.fine("Assertion Issuer must not be null");
throw new WSSecurityException(WSSecurityException.ErrorCode.FAILURE, "invalidSAMLsecurity");
}
validateIssuer(assertion.getIssuer());
if (!samlResponse.isSigned() && enforceAssertionsSigned && assertion.getSignature() == null) {
LOG.fine("The enclosed assertions in the SAML Response must be signed");
throw new WSSecurityException(WSSecurityException.ErrorCode.FAILURE, "invalidSAMLsecurity");
}
// Check for AuthnStatements and validate the Subject accordingly
if (assertion.getAuthnStatements() != null && !assertion.getAuthnStatements().isEmpty()) {
org.opensaml.saml.saml2.core.Subject subject = assertion.getSubject();
org.opensaml.saml.saml2.core.SubjectConfirmation subjectConf = validateAuthenticationSubject(subject, assertion.getID(), postBinding);
if (subjectConf != null) {
validateAudienceRestrictionCondition(assertion.getConditions());
validAssertion = assertion;
// Store Session NotOnOrAfter
for (AuthnStatement authnStatment : assertion.getAuthnStatements()) {
if (authnStatment.getSessionNotOnOrAfter() != null) {
sessionNotOnOrAfter = Instant.ofEpochMilli(authnStatment.getSessionNotOnOrAfter().toDate().getTime());
}
}
// Fall back to the SubjectConfirmationData NotOnOrAfter if we have no session NotOnOrAfter
if (sessionNotOnOrAfter == null) {
sessionNotOnOrAfter = Instant.ofEpochMilli(subjectConf.getSubjectConfirmationData().getNotOnOrAfter().toDate().getTime());
}
}
}
}
if (validAssertion == null) {
LOG.fine("The Response did not contain any Authentication Statement that matched " + "the Subject Confirmation criteria");
throw new WSSecurityException(WSSecurityException.ErrorCode.FAILURE, "invalidSAMLsecurity");
}
SSOValidatorResponse validatorResponse = new SSOValidatorResponse();
validatorResponse.setResponseId(samlResponse.getID());
validatorResponse.setSessionNotOnOrAfter(sessionNotOnOrAfter);
if (samlResponse.getIssueInstant() != null) {
validatorResponse.setCreated(Instant.ofEpochMilli(samlResponse.getIssueInstant().toDate().getTime()));
}
Element assertionElement = validAssertion.getDOM();
Element clonedAssertionElement = (Element) assertionElement.cloneNode(true);
validatorResponse.setAssertionElement(clonedAssertionElement);
validatorResponse.setAssertion(DOM2Writer.nodeToString(clonedAssertionElement));
validatorResponse.setOpensamlAssertion(validAssertion);
return validatorResponse;
}
use of org.opensaml.saml.saml2.core.Response in project cxf by apache.
the class CombinedValidatorTest method createResponse.
private Response createResponse(Document doc) throws Exception {
Status status = SAML2PResponseComponentBuilder.createStatus(SAMLProtocolResponseValidator.SAML2_STATUSCODE_SUCCESS, null);
Response response = SAML2PResponseComponentBuilder.createSAMLResponse("http://cxf.apache.org/saml", "http://cxf.apache.org/issuer", status);
response.setDestination("http://recipient.apache.org");
// Create an AuthenticationAssertion
SAML2CallbackHandler callbackHandler = new SAML2CallbackHandler();
callbackHandler.setStatement(SAML2CallbackHandler.Statement.AUTHN);
callbackHandler.setIssuer("http://cxf.apache.org/issuer");
callbackHandler.setConfirmationMethod(SAML2Constants.CONF_BEARER);
callbackHandler.setSubjectName("alice");
SubjectConfirmationDataBean subjectConfirmationData = new SubjectConfirmationDataBean();
subjectConfirmationData.setAddress("http://apache.org");
subjectConfirmationData.setInResponseTo("12345");
subjectConfirmationData.setNotAfter(new DateTime().plusMinutes(5));
subjectConfirmationData.setRecipient("http://recipient.apache.org");
callbackHandler.setSubjectConfirmationData(subjectConfirmationData);
ConditionsBean conditions = new ConditionsBean();
conditions.setNotBefore(new DateTime());
conditions.setNotAfter(new DateTime().plusMinutes(5));
AudienceRestrictionBean audienceRestriction = new AudienceRestrictionBean();
audienceRestriction.setAudienceURIs(Collections.singletonList("http://service.apache.org"));
conditions.setAudienceRestrictions(Collections.singletonList(audienceRestriction));
callbackHandler.setConditions(conditions);
SAMLCallback samlCallback = new SAMLCallback();
SAMLUtil.doSAMLCallback(callbackHandler, samlCallback);
SamlAssertionWrapper assertion = new SamlAssertionWrapper(samlCallback);
Crypto issuerCrypto = new Merlin();
KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
ClassLoader loader = Loader.getClassLoader(CombinedValidatorTest.class);
InputStream input = Merlin.loadInputStream(loader, "alice.jks");
keyStore.load(input, "password".toCharArray());
((Merlin) issuerCrypto).setKeyStore(keyStore);
assertion.signAssertion("alice", "password", issuerCrypto, false);
response.getAssertions().add(assertion.getSaml2());
return response;
}
use of org.opensaml.saml.saml2.core.Response in project cxf by apache.
the class CombinedValidatorTest method testWrappingAttack3.
@org.junit.Test
public void testWrappingAttack3() throws Exception {
Document doc = DOMUtils.createDocument();
Response response = createResponse(doc);
Element responseElement = OpenSAMLUtil.toDom(response, doc);
doc.appendChild(responseElement);
assertNotNull(responseElement);
// Get Assertion Element
Element assertionElement = (Element) responseElement.getElementsByTagNameNS(SAMLConstants.SAML20_NS, "Assertion").item(0);
assertNotNull(assertionElement);
// Clone it, strip the Signature, modify the Subject, change Subj Conf
Element clonedAssertion = (Element) assertionElement.cloneNode(true);
clonedAssertion.setAttributeNS(null, "ID", "_12345623562");
Element sigElement = (Element) clonedAssertion.getElementsByTagNameNS(WSS4JConstants.SIG_NS, "Signature").item(0);
clonedAssertion.removeChild(sigElement);
Element subjElement = (Element) clonedAssertion.getElementsByTagNameNS(SAMLConstants.SAML20_NS, "Subject").item(0);
Element subjNameIdElement = (Element) subjElement.getElementsByTagNameNS(SAMLConstants.SAML20_NS, "NameID").item(0);
subjNameIdElement.setTextContent("bob");
Element subjConfElement = (Element) subjElement.getElementsByTagNameNS(SAMLConstants.SAML20_NS, "SubjectConfirmation").item(0);
subjConfElement.setAttributeNS(null, "Method", SAML2Constants.CONF_SENDER_VOUCHES);
// Now insert the modified cloned Assertion into the Response before actual assertion
responseElement.insertBefore(clonedAssertion, assertionElement);
// System.out.println(DOM2Writer.nodeToString(responseElement));
Response marshalledResponse = (Response) OpenSAMLUtil.fromDom(responseElement);
Crypto issuerCrypto = new Merlin();
KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
ClassLoader loader = Loader.getClassLoader(CombinedValidatorTest.class);
InputStream input = Merlin.loadInputStream(loader, "alice.jks");
keyStore.load(input, "password".toCharArray());
((Merlin) issuerCrypto).setKeyStore(keyStore);
// Validate the Response
SAMLProtocolResponseValidator validator = new SAMLProtocolResponseValidator();
validator.validateSamlResponse(marshalledResponse, issuerCrypto, new KeystorePasswordCallback());
// Test SSO validation
SAMLSSOResponseValidator ssoValidator = new SAMLSSOResponseValidator();
ssoValidator.setEnforceAssertionsSigned(false);
ssoValidator.setIssuerIDP("http://cxf.apache.org/issuer");
ssoValidator.setAssertionConsumerURL("http://recipient.apache.org");
ssoValidator.setClientAddress("http://apache.org");
ssoValidator.setRequestId("12345");
ssoValidator.setSpIdentifier("http://service.apache.org");
// Parse the response
SSOValidatorResponse ssoResponse = ssoValidator.validateSamlResponse(marshalledResponse, false);
SamlAssertionWrapper parsedAssertion = new SamlAssertionWrapper(ssoResponse.getAssertionElement());
assertEquals("alice", parsedAssertion.getSubjectName());
}
Aggregations