if (!endpointUri.equals(data.getRecipient())) { throw new SamlException("recipient is not matched: " + data.getRecipient()); if (now.isAfter(data.getNotOnOrAfter())) { throw new SamlException("response has been expired: " + data.getNotOnOrAfter()); if (!requestIdManager.validateId(data.getInResponseTo())) { throw new SamlException("request ID is not valid: " + data.getInResponseTo());
final SubjectConfirmationData data = build(SubjectConfirmationData.DEFAULT_ELEMENT_NAME); data.setInResponseTo(requestIdManager.newId()); data.setNotOnOrAfter(DateTime.now().plusMinutes(1)); data.setRecipient(recipient);
/** * Create an efficient field-wise copy of a {@link SubjectConfirmation}. * * @param confirmation the object to clone * * @return the copy */ @Nonnull private SubjectConfirmation cloneConfirmation(@Nonnull final SubjectConfirmation confirmation) { final SubjectConfirmation clone = confirmationBuilder.buildObject(); clone.setMethod(confirmation.getMethod()); final SubjectConfirmationData data = confirmation.getSubjectConfirmationData(); if (data != null) { final SubjectConfirmationData cloneData = confirmationDataBuilder.buildObject(); cloneData.setAddress(data.getAddress()); cloneData.setInResponseTo(data.getInResponseTo()); cloneData.setRecipient(data.getRecipient()); cloneData.setNotBefore(data.getNotBefore()); cloneData.setNotOnOrAfter(data.getNotOnOrAfter()); clone.setSubjectConfirmationData(cloneData); } return clone; }
/** {@inheritDoc} */ protected void processAttribute(XMLObject samlObject, Attr attribute) throws UnmarshallingException { SubjectConfirmationData subjectCD = (SubjectConfirmationData) samlObject; if (attribute.getLocalName().equals(SubjectConfirmationData.NOT_BEFORE_ATTRIB_NAME) && !Strings.isNullOrEmpty(attribute.getValue())) { subjectCD.setNotBefore(new DateTime(attribute.getValue(), ISOChronology.getInstanceUTC())); } else if (attribute.getLocalName().equals(SubjectConfirmationData.NOT_ON_OR_AFTER_ATTRIB_NAME) && !Strings.isNullOrEmpty(attribute.getValue())) { subjectCD.setNotOnOrAfter(new DateTime(attribute.getValue(), ISOChronology.getInstanceUTC())); } else if (attribute.getLocalName().equals(SubjectConfirmationData.RECIPIENT_ATTRIB_NAME)) { subjectCD.setRecipient(attribute.getValue()); } else if (attribute.getLocalName().equals(SubjectConfirmationData.IN_RESPONSE_TO_ATTRIB_NAME)) { subjectCD.setInResponseTo(attribute.getValue()); } else if (attribute.getLocalName().equals(SubjectConfirmationData.ADDRESS_ATTRIB_NAME)) { subjectCD.setAddress(attribute.getValue()); } else { processUnknownAttribute(subjectCD, attribute); } } }
/** {@inheritDoc} */ protected void marshallAttributes(XMLObject samlObject, Element domElement) throws MarshallingException { SubjectConfirmationData subjectCD = (SubjectConfirmationData) samlObject; if (subjectCD.getNotBefore() != null) { String notBeforeStr = SAMLConfigurationSupport.getSAMLDateFormatter().print(subjectCD.getNotBefore()); domElement.setAttributeNS(null, SubjectConfirmationData.NOT_BEFORE_ATTRIB_NAME, notBeforeStr); } if (subjectCD.getNotOnOrAfter() != null) { String notOnOrAfterStr = SAMLConfigurationSupport.getSAMLDateFormatter().print(subjectCD.getNotOnOrAfter()); domElement.setAttributeNS(null, SubjectConfirmationData.NOT_ON_OR_AFTER_ATTRIB_NAME, notOnOrAfterStr); } if (subjectCD.getRecipient() != null) { domElement.setAttributeNS(null, SubjectConfirmationData.RECIPIENT_ATTRIB_NAME, subjectCD.getRecipient()); } if (subjectCD.getInResponseTo() != null) { domElement.setAttributeNS(null, SubjectConfirmationData.IN_RESPONSE_TO_ATTRIB_NAME, subjectCD .getInResponseTo()); } if (subjectCD.getAddress() != null) { domElement.setAttributeNS(null, SubjectConfirmationData.ADDRESS_ATTRIB_NAME, subjectCD.getAddress()); } marshallUnknownAttributes(subjectCD, domElement); } }
/** * Validate a (Bearer) Subject Confirmation */ private void validateSubjectConfirmation(Message m, Conditions cs, SubjectConfirmationData subjectConfData) { if (subjectConfData == null) { if (!subjectConfirmationDataRequired && cs.getNotOnOrAfter() != null && !cs.getNotOnOrAfter().isBeforeNow()) { return; } throw ExceptionUtils.toNotAuthorizedException(null, null); } // Recipient must match assertion consumer URL String recipient = subjectConfData.getRecipient(); if (recipient == null || !recipient.equals(getAbsoluteTargetAddress(m))) { throw ExceptionUtils.toNotAuthorizedException(null, null); } // We must have a NotOnOrAfter timestamp if (subjectConfData.getNotOnOrAfter() == null || subjectConfData.getNotOnOrAfter().isBeforeNow()) { throw ExceptionUtils.toNotAuthorizedException(null, null); } //TODO: replay cache, same as with SAML SSO case // Check address if (subjectConfData.getAddress() != null && (clientAddress == null || !subjectConfData.getAddress().equals(clientAddress))) { throw ExceptionUtils.toNotAuthorizedException(null, null); } }
if (data.getNotBefore() != null) { logger.debug("SubjectConfirmationData notBefore must be null for Bearer confirmation"); return false; if (data.getNotOnOrAfter() == null) { logger.debug("SubjectConfirmationData notOnOrAfter cannot be null for Bearer confirmation"); return false; if (data.getNotOnOrAfter().plusSeconds(acceptedSkew).isBeforeNow()) { logger.debug("SubjectConfirmationData notOnOrAfter is too old"); return false; if (data.getRecipient() == null) { logger.debug("SubjectConfirmationData recipient cannot be null for Bearer confirmation"); return false; final URI recipientUri = new URI(data.getRecipient()); final URI appEndpointUri = new URI(endpoint.getLocation()); if (!SAML2Utils.urisEqualAfterPortNormalization(recipientUri, appEndpointUri)) {
subjectConfirmationData.setRecipient(ssoIdPConfigs.getAssertionConsumerUrl()); subjectConfirmationData.setNotOnOrAfter(notOnOrAfter);
/** * Validates the <code>NotOnOrAfter</code> condition of the {@link SubjectConfirmationData}, if any is present. * * @param confirmation confirmation method, with {@link SubjectConfirmationData}, being validated * @param assertion assertion bearing the confirmation method * @param context current validation context * * @return the result of the validation evaluation * * @throws AssertionValidationException thrown if there is a problem determining the validity of the NotOnOrAFter */ @Nonnull protected ValidationResult validateNotOnOrAfter(@Nonnull final SubjectConfirmation confirmation, @Nonnull final Assertion assertion, @Nonnull final ValidationContext context) throws AssertionValidationException { DateTime skewedNow = new DateTime(ISOChronology.getInstanceUTC()).minus(SAML20AssertionValidator .getClockSkew(context)); DateTime notOnOrAfter = confirmation.getSubjectConfirmationData().getNotOnOrAfter(); log.debug("Evaluating SubjectConfirmationData NotOnOrAfter '{}' against 'skewed now' time '{}'", notOnOrAfter, skewedNow); if (notOnOrAfter != null && notOnOrAfter.isBefore(skewedNow)) { context.setValidationFailureMessage(String.format( "Subject confirmation, in assertion '%s', with NotOnOrAfter condition of '%s' is no longer valid", assertion.getID(), notOnOrAfter)); return ValidationResult.INVALID; } return ValidationResult.VALID; }
@Nonnull final Assertion assertion, @Nonnull final ValidationContext context) throws AssertionValidationException { String recipient = StringSupport.trimOrNull(confirmation.getSubjectConfirmationData().getRecipient()); if (recipient == null) { return ValidationResult.VALID;
/** * Validates the <code>NotBefore</code> condition of the {@link SubjectConfirmationData}, if any is present. * * @param confirmation confirmation method, with {@link SubjectConfirmationData}, being validated * @param assertion assertion bearing the confirmation method * @param context current validation context * * @return the result of the validation evaluation * * @throws AssertionValidationException thrown if there is a problem determining the validity of the NotBefore */ @Nonnull protected ValidationResult validateNotBefore(@Nonnull final SubjectConfirmation confirmation, @Nonnull final Assertion assertion, @Nonnull final ValidationContext context) throws AssertionValidationException { DateTime skewedNow = new DateTime(ISOChronology.getInstanceUTC()).plus(SAML20AssertionValidator .getClockSkew(context)); DateTime notBefore = confirmation.getSubjectConfirmationData().getNotBefore(); log.debug("Evaluating SubjectConfirmationData NotBefore '{}' against 'skewed now' time '{}'", notBefore, skewedNow); if (notBefore != null && notBefore.isAfter(skewedNow)) { context.setValidationFailureMessage(String.format( "Subject confirmation, in assertion '%s', with NotBefore condition of '%s' is not yet valid", assertion.getID(), notBefore)); return ValidationResult.INVALID; } return ValidationResult.VALID; }
@Nonnull final Assertion assertion, @Nonnull final ValidationContext context) throws AssertionValidationException { String address = StringSupport.trimOrNull(confirmation.getSubjectConfirmationData().getAddress()); if (address == null) { return ValidationResult.VALID;
if (address != null) { confirmationData = confirmationData != null ? confirmationData : confirmationDataBuilder.buildObject(); confirmationData.setAddress(address); if (inResponseTo != null) { confirmationData = confirmationData != null ? confirmationData : confirmationDataBuilder.buildObject(); confirmationData.setInResponseTo(inResponseTo); if (recipient != null) { confirmationData = confirmationData != null ? confirmationData : confirmationDataBuilder.buildObject(); confirmationData.setRecipient(recipient); if (lifetime != null) { confirmationData = confirmationData != null ? confirmationData : confirmationDataBuilder.buildObject(); confirmationData.setNotOnOrAfter(new DateTime().plus(lifetime));
String recipient = subjectConfData.getRecipient(); if (recipient == null || !recipient.equals(assertionConsumerURL)) { LOG.fine("Recipient " + recipient + " does not match assertion consumer URL " if (subjectConfData.getNotOnOrAfter() == null || subjectConfData.getNotOnOrAfter().isBeforeNow()) { LOG.fine("Subject Conf Data does not contain NotOnOrAfter or it has expired"); throw new WSSecurityException(WSSecurityException.ErrorCode.FAILURE, "invalidSAMLsecurity"); Instant expires = Instant.ofEpochMilli(subjectConfData.getNotOnOrAfter().toDate().getTime()); Instant currentTime = Instant.now(); long ttl = Duration.between(currentTime, expires).getSeconds(); if (subjectConfData.getAddress() != null && clientAddress != null && !subjectConfData.getAddress().equals(clientAddress)) { LOG.fine("Subject Conf Data address " + subjectConfData.getAddress() + " does not match" + " client address " + clientAddress); throw new WSSecurityException(WSSecurityException.ErrorCode.FAILURE, "invalidSAMLsecurity"); if (subjectConfData.getNotBefore() != null) { LOG.fine("The Subject Conf Data must not contain a NotBefore timestamp"); throw new WSSecurityException(WSSecurityException.ErrorCode.FAILURE, "invalidSAMLsecurity"); if (requestId != null && !requestId.equals(subjectConfData.getInResponseTo())) { LOG.fine("The InResponseTo String does match the original request id " + requestId); throw new WSSecurityException(WSSecurityException.ErrorCode.FAILURE, "invalidSAMLsecurity"); } else if (requestId == null && subjectConfData.getInResponseTo() != null) { LOG.fine("No InResponseTo String is allowed for the unsolicted case"); throw new WSSecurityException(WSSecurityException.ErrorCode.FAILURE, "invalidSAMLsecurity");
/** * Validate a (Bearer) Subject Confirmation */ private void validateSubjectConfirmation(Message m, Conditions cs, SubjectConfirmationData subjectConfData) { if (subjectConfData == null) { if (!subjectConfirmationDataRequired && cs.getNotOnOrAfter() != null && !cs.getNotOnOrAfter().isBeforeNow()) { return; } throw ExceptionUtils.toNotAuthorizedException(null, null); } // Recipient must match assertion consumer URL String recipient = subjectConfData.getRecipient(); if (recipient == null || !recipient.equals(getAbsoluteTargetAddress(m))) { throw ExceptionUtils.toNotAuthorizedException(null, null); } // We must have a NotOnOrAfter timestamp if (subjectConfData.getNotOnOrAfter() == null || subjectConfData.getNotOnOrAfter().isBeforeNow()) { throw ExceptionUtils.toNotAuthorizedException(null, null); } //TODO: replay cache, same as with SAML SSO case // Check address if (subjectConfData.getAddress() != null && (clientAddress == null || !subjectConfData.getAddress().equals(clientAddress))) { throw ExceptionUtils.toNotAuthorizedException(null, null); } }
subjectConfirmationData.setRecipient(ssoIdPConfigs.getAssertionConsumerUrl()); subjectConfirmationData.setNotOnOrAfter(notOnOrAfter);
sessionNotOnOrAfter = Instant.ofEpochMilli(subjectConf.getSubjectConfirmationData() .getNotOnOrAfter().toDate().getTime());
subjectConfirmationData.setInResponseTo(subjectConfirmationDataBean.getInResponseTo()); subjectConfirmationData.setRecipient(subjectConfirmationDataBean.getRecipient()); subjectConfirmationData.setAddress(subjectConfirmationDataBean.getAddress()); subjectConfirmationData.setNotOnOrAfter(subjectConfirmationDataBean.getNotAfter()); subjectConfirmationData.setNotBefore(subjectConfirmationDataBean.getNotBefore()); List<XMLObject> unknownObjects = subjectConfirmationData.getUnknownXMLObjects(); for (Object obj : subjectConfirmationDataBean.getAny()) { if (obj == null) {
protected List<SubjectConfirmation> getConfirmations( List<org.opensaml.saml.saml2.core .SubjectConfirmation> subjectConfirmations, List<SimpleKey> localKeys ) { List<SubjectConfirmation> result = new LinkedList<>(); for (org.opensaml.saml.saml2.core.SubjectConfirmation s : subjectConfirmations) { NameID nameID = getNameID(s.getNameID(), s.getEncryptedID(), localKeys); result.add( new SubjectConfirmation() .setNameId(nameID != null ? nameID.getValue() : null) .setFormat(nameID != null ? NameId.fromUrn(nameID.getFormat()) : null) .setMethod(SubjectConfirmationMethod.fromUrn(s.getMethod())) .setConfirmationData( new SubjectConfirmationData() .setRecipient(s.getSubjectConfirmationData().getRecipient()) .setNotOnOrAfter(s.getSubjectConfirmationData().getNotOnOrAfter()) .setNotBefore(s.getSubjectConfirmationData().getNotBefore()) .setInResponseTo(s.getSubjectConfirmationData().getInResponseTo()) ) ); } return result; }
if (!endpointUri.equals(data.getRecipient())) { throw new SamlException("recipient is not matched: " + data.getRecipient()); if (now.isAfter(data.getNotOnOrAfter())) { throw new SamlException("response has been expired: " + data.getNotOnOrAfter()); if (!requestIdManager.validateId(data.getInResponseTo())) { throw new SamlException("request ID is not valid: " + data.getInResponseTo());