private Response buildMockResponse() throws Exception {
   Response samlMessage = new ResponseBuilder().buildObject();
   samlMessage.setID("foo");
   samlMessage.setVersion(SAMLVersion.VERSION_20);
   samlMessage.setIssueInstant(new DateTime(0));
   Issuer issuer = new IssuerBuilder().buildObject();
   issuer.setValue("MockedIssuer");
   samlMessage.setIssuer(issuer);
   Status status = new StatusBuilder().buildObject();
   StatusCode statusCode = new StatusCodeBuilder().buildObject();
   statusCode.setValue(StatusCode.SUCCESS_URI);
   status.setStatusCode(statusCode);
   samlMessage.setStatus(status);
   Assertion assertion = new AssertionBuilder().buildObject();
   Subject subject = new SubjectBuilder().buildObject();
   NameID nameID = new NameIDBuilder().buildObject();
   nameID.setValue("SOME-UNIQUE-ID");
   nameID.setFormat(NameIDType.PERSISTENT);
   subject.setNameID(nameID);
   assertion.setSubject(subject);
   AuthnStatement authnStatement = new AuthnStatementBuilder().buildObject();
   authnStatement.setSessionIndex("Some Session String");
   assertion.getAuthnStatements().add(authnStatement);
   AttributeStatement attributeStatement = new AttributeStatementBuilder().buildObject();
   assertion.getAttributeStatements().add(attributeStatement);
   samlMessage.getAssertions().add(assertion);
   return samlMessage;
 }
  /**
   * Validate the signature of a SAML2 Response and Assertion
   *
   * @param response SAML2 Response
   * @return true, if signature is valid.
   */
  private void validateSignature(Response response, Assertion assertion) throws SAMLSSOException {

    if (SSOUtils.isAuthnResponseSigned(properties)) {

      if (identityProvider.getCertificate() == null
          || identityProvider.getCertificate().isEmpty()) {
        throw new SAMLSSOException(
            "SAMLResponse signing is enabled, but IdP doesn't have a certificate");
      }

      if (response.getSignature() == null) {
        throw new SAMLSSOException(
            "SAMLResponse signing is enabled, but signature element "
                + "not found in SAML Response element.");
      } else {
        try {
          X509Credential credential =
              new X509CredentialImpl(tenantDomain, identityProvider.getCertificate());
          SignatureValidator validator = new SignatureValidator(credential);
          validator.validate(response.getSignature());
        } catch (ValidationException e) {
          throw new SAMLSSOException("Signature validation failed for SAML Response", e);
        }
      }
    }
    if (SSOUtils.isAssertionSigningEnabled(properties)) {

      if (identityProvider.getCertificate() == null
          || identityProvider.getCertificate().isEmpty()) {
        throw new SAMLSSOException(
            "SAMLAssertion signing is enabled, but IdP doesn't have a certificate");
      }

      if (assertion.getSignature() == null) {
        throw new SAMLSSOException(
            "SAMLAssertion signing is enabled, but signature element "
                + "not found in SAML Assertion element.");
      } else {
        try {
          X509Credential credential =
              new X509CredentialImpl(tenantDomain, identityProvider.getCertificate());
          SignatureValidator validator = new SignatureValidator(credential);
          validator.validate(assertion.getSignature());
        } catch (ValidationException e) {
          throw new SAMLSSOException("Signature validation failed for SAML Assertion", e);
        }
      }
    }
  }
  /**
   * Validate the signature of a SAML2 Response and Assertion
   *
   * @param response SAML2 Response
   * @return true, if signature is valid.
   */
  protected void validateSignature(Response response, Assertion assertion)
      throws SSOAgentException {

    if (SSOAgentDataHolder.getInstance().getSignatureValidator() != null) {
      // Custom implemetation of signature validation
      SAMLSignatureValidator signatureValidatorUtility =
          (SAMLSignatureValidator) SSOAgentDataHolder.getInstance().getSignatureValidator();
      signatureValidatorUtility.validateSignature(response, assertion, ssoAgentConfig);
    } else {
      // If custom implementation not found, Execute the default implementation
      if (ssoAgentConfig.getSAML2().isResponseSigned()) {
        if (response.getSignature() == null) {
          throw new SSOAgentException(
              "SAML2 Response signing is enabled, but signature element not found in SAML2 Response element");
        } else {
          try {
            SignatureValidator validator =
                new SignatureValidator(
                    new X509CredentialImpl(ssoAgentConfig.getSAML2().getSSOAgentX509Credential()));
            validator.validate(response.getSignature());
          } catch (ValidationException e) {
            if (log.isDebugEnabled()) {
              log.debug("Validation exception : ", e);
            }
            throw new SSOAgentException("Signature validation failed for SAML2 Response");
          }
        }
      }
      if (ssoAgentConfig.getSAML2().isAssertionSigned()) {
        if (assertion.getSignature() == null) {
          throw new SSOAgentException(
              "SAML2 Assertion signing is enabled, but signature element not found in SAML2 Assertion element");
        } else {
          try {
            SignatureValidator validator =
                new SignatureValidator(
                    new X509CredentialImpl(ssoAgentConfig.getSAML2().getSSOAgentX509Credential()));
            validator.validate(assertion.getSignature());
          } catch (ValidationException e) {
            if (log.isDebugEnabled()) {
              log.debug("Validation exception : ", e);
            }
            throw new SSOAgentException("Signature validation failed for SAML2 Assertion");
          }
        }
      }
    }
  }
  /**
   * Validate the AudienceRestriction of SAML2 Response
   *
   * @param assertion SAML2 Assertion
   * @return validity
   */
  private void validateAudienceRestriction(Assertion assertion) throws SAMLSSOException {

    if (assertion != null) {
      Conditions conditions = assertion.getConditions();
      if (conditions != null) {
        List<AudienceRestriction> audienceRestrictions = conditions.getAudienceRestrictions();
        if (audienceRestrictions != null && !audienceRestrictions.isEmpty()) {
          for (AudienceRestriction audienceRestriction : audienceRestrictions) {
            if (CollectionUtils.isNotEmpty(audienceRestriction.getAudiences())) {
              boolean audienceFound = false;
              for (Audience audience : audienceRestriction.getAudiences()) {
                if (properties
                    .get(IdentityApplicationConstants.Authenticator.SAML2SSO.SP_ENTITY_ID)
                    .equals(audience.getAudienceURI())) {
                  audienceFound = true;
                  break;
                }
              }
              if (!audienceFound) {
                throw new SAMLSSOException("SAML Assertion Audience Restriction validation failed");
              }
            } else {
              throw new SAMLSSOException(
                  "SAML Response's AudienceRestriction doesn't contain Audiences");
            }
          }
        } else {
          throw new SAMLSSOException("SAML Response doesn't contain AudienceRestrictions");
        }
      } else {
        throw new SAMLSSOException("SAML Response doesn't contain Conditions");
      }
    }
  }
  /**
   * Validate the AudienceRestriction of SAML2 Response
   *
   * @param assertion SAML2 Assertion
   * @return validity
   */
  protected void validateAudienceRestriction(Assertion assertion) throws SSOAgentException {

    if (assertion != null) {
      Conditions conditions = assertion.getConditions();
      if (conditions != null) {
        List<AudienceRestriction> audienceRestrictions = conditions.getAudienceRestrictions();
        if (audienceRestrictions != null && !audienceRestrictions.isEmpty()) {
          boolean audienceFound = false;
          for (AudienceRestriction audienceRestriction : audienceRestrictions) {
            if (audienceRestriction.getAudiences() != null
                && !audienceRestriction.getAudiences().isEmpty()) {
              for (Audience audience : audienceRestriction.getAudiences()) {
                if (ssoAgentConfig.getSAML2().getSPEntityId().equals(audience.getAudienceURI())) {
                  audienceFound = true;
                  break;
                }
              }
            }
            if (audienceFound) {
              break;
            }
          }
          if (!audienceFound) {
            throw new SSOAgentException("SAML2 Assertion Audience Restriction validation failed");
          }
        } else {
          throw new SSOAgentException("SAML2 Response doesn't contain AudienceRestrictions");
        }
      } else {
        throw new SSOAgentException("SAML2 Response doesn't contain Conditions");
      }
    }
  }
  /*
   * Process the response and returns the results
   */
  private Map<String, String> getAssertionStatements(Assertion assertion) {

    Map<String, String> results = new HashMap<String, String>();

    if (assertion != null && assertion.getAttributeStatements() != null) {

      List<AttributeStatement> attributeStatementList = assertion.getAttributeStatements();

      for (AttributeStatement statement : attributeStatementList) {
        List<Attribute> attributesList = statement.getAttributes();
        for (Attribute attribute : attributesList) {
          Element value = attribute.getAttributeValues().get(0).getDOM();
          String attributeValue = value.getTextContent();
          results.put(attribute.getName(), attributeValue);
        }
      }
    }
    return results;
  }
 /**
  * Returns SAML 2.0 Assertion Attribute Statement content.
  *
  * @param assertion the SAML 2.0 Assertion whose content is to be returned
  * @return Attribute Statement content of the SAML 2.0 Assertion specified
  */
 protected static Map<String, String> getAssertionStatements(Assertion assertion) {
   Map<String, String> results = new HashMap<>();
   if ((Optional.ofNullable(assertion).isPresent())
       && (Optional.ofNullable(assertion.getAttributeStatements()).isPresent())) {
     Stream<AttributeStatement> attributeStatements = assertion.getAttributeStatements().stream();
     attributeStatements.forEach(
         attributeStatement ->
             attributeStatement
                 .getAttributes()
                 .stream()
                 .forEach(
                     attribute -> {
                       Element value = attribute.getAttributeValues().get(0).getDOM();
                       String attributeValue = value.getTextContent();
                       results.put(attribute.getName(), attributeValue);
                     }));
   }
   return results;
 }
  private Map<String, Object> getUserAttributes(ResponseImpl samlResponse) {

    Map<String, Object> userAttributes = new HashMap<>();

    // Add 'Subject'
    Assertion assertion = samlResponse.getAssertions().get(0);
    userAttributes.put(
        SAMLConstants.SAML2_ASSERTION_SUBJECT, assertion.getSubject().getNameID().getValue());

    // Add other user attributes.
    List<AttributeStatement> attributeStatements = assertion.getAttributeStatements();
    if (attributeStatements != null) {
      for (AttributeStatement attributeStatement : attributeStatements) {
        List<Attribute> attributes = attributeStatement.getAttributes();
        for (Attribute attribute : attributes) {
          userAttributes.put(
              attribute.getName(), attribute.getAttributeValues().get(0).getDOM().getTextContent());
        }
      }
    }

    return userAttributes;
  }
Example #9
0
  private Saml2Credentials buildSaml2Credentials(final ExtendedSAMLMessageContext context) {

    NameID nameId = (NameID) context.getSubjectNameIdentifier();
    Assertion subjectAssertion = context.getSubjectAssertion();

    List<Attribute> attributes = new ArrayList<Attribute>();
    for (AttributeStatement attributeStatement : subjectAssertion.getAttributeStatements()) {
      for (Attribute attribute : attributeStatement.getAttributes()) {
        attributes.add(attribute);
      }
      if (attributeStatement.getEncryptedAttributes().size() > 0) {
        logger.warn("Encrypted attributes returned, but no keystore was provided.");
      }
      for (EncryptedAttribute encryptedAttribute : attributeStatement.getEncryptedAttributes()) {
        try {
          attributes.add(decrypter.decrypt(encryptedAttribute));
        } catch (DecryptionException e) {
          logger.warn("Decryption of attribute failed, continue with the next one", e);
        }
      }
    }

    return new Saml2Credentials(nameId, attributes, subjectAssertion.getConditions(), getName());
  }
  private void processSSOResponse(HttpServletRequest request) throws SAMLSSOException {

    Response samlResponse =
        (Response)
            unmarshall(
                new String(
                    Base64.decode(request.getParameter(SSOConstants.HTTP_POST_PARAM_SAML2_RESP))));

    Assertion assertion = null;

    if (SSOUtils.isAssertionEncryptionEnabled(properties)) {
      List<EncryptedAssertion> encryptedAssertions = samlResponse.getEncryptedAssertions();
      EncryptedAssertion encryptedAssertion = null;
      if (CollectionUtils.isNotEmpty(encryptedAssertions)) {
        encryptedAssertion = encryptedAssertions.get(0);
        try {
          assertion = getDecryptedAssertion(encryptedAssertion);
        } catch (Exception e) {
          throw new SAMLSSOException("Unable to decrypt the SAML Assertion", e);
        }
      }
    } else {
      List<Assertion> assertions = samlResponse.getAssertions();
      if (CollectionUtils.isNotEmpty(assertions)) {
        assertion = assertions.get(0);
      }
    }

    if (assertion == null) {
      if (samlResponse.getStatus() != null
          && samlResponse.getStatus().getStatusCode() != null
          && samlResponse
              .getStatus()
              .getStatusCode()
              .getValue()
              .equals(SSOConstants.StatusCodes.IDENTITY_PROVIDER_ERROR)
          && samlResponse.getStatus().getStatusCode().getStatusCode() != null
          && samlResponse
              .getStatus()
              .getStatusCode()
              .getStatusCode()
              .getValue()
              .equals(SSOConstants.StatusCodes.NO_PASSIVE)) {
        return;
      }
      throw new SAMLSSOException("SAML Assertion not found in the Response");
    }

    // Get the subject name from the Response Object and forward it to login_action.jsp
    String subject = null;
    String nameQualifier = null;
    String spNameQualifier = null;
    if (assertion.getSubject() != null && assertion.getSubject().getNameID() != null) {
      subject = assertion.getSubject().getNameID().getValue();
    }

    if (subject == null) {
      throw new SAMLSSOException("SAML Response does not contain the name of the subject");
    }

    request.getSession().setAttribute("username", subject); // get the subject
    nameQualifier = assertion.getSubject().getNameID().getNameQualifier();
    spNameQualifier = assertion.getSubject().getNameID().getSPNameQualifier();

    // validate audience restriction
    validateAudienceRestriction(assertion);

    // validate signature this SP only looking for assertion signature
    validateSignature(samlResponse, assertion);

    request.getSession(false).setAttribute("samlssoAttributes", getAssertionStatements(assertion));

    // For removing the session when the single sign out request made by the SP itself
    if (SSOUtils.isLogoutEnabled(properties)) {
      String sessionId = assertion.getAuthnStatements().get(0).getSessionIndex();
      if (sessionId == null) {
        throw new SAMLSSOException(
            "Single Logout is enabled but IdP Session ID not found in SAML Assertion");
      }
      request.getSession().setAttribute(SSOConstants.IDP_SESSION, sessionId);
      request.getSession().setAttribute(SSOConstants.LOGOUT_USERNAME, nameQualifier);
      request.getSession().setAttribute(SSOConstants.SP_NAME_QUALIFIER, spNameQualifier);
    }
  }
  protected void processSSOResponse(HttpServletRequest request) throws SSOAgentException {

    LoggedInSessionBean sessionBean = new LoggedInSessionBean();
    sessionBean.setSAML2SSO(sessionBean.new SAML2SSO());

    String saml2ResponseString =
        new String(
            Base64.decode(
                request.getParameter(SSOAgentConstants.SAML2SSO.HTTP_POST_PARAM_SAML2_RESP)),
            Charset.forName("UTF-8"));
    Response saml2Response = (Response) SSOAgentUtils.unmarshall(saml2ResponseString);
    sessionBean.getSAML2SSO().setResponseString(saml2ResponseString);
    sessionBean.getSAML2SSO().setSAMLResponse(saml2Response);

    Assertion assertion = null;
    if (ssoAgentConfig.getSAML2().isAssertionEncrypted()) {
      List<EncryptedAssertion> encryptedAssertions = saml2Response.getEncryptedAssertions();
      EncryptedAssertion encryptedAssertion = null;
      if (!org.apache.commons.collections.CollectionUtils.isEmpty(encryptedAssertions)) {
        encryptedAssertion = encryptedAssertions.get(0);
        try {
          assertion = getDecryptedAssertion(encryptedAssertion);
        } catch (Exception e) {
          if (log.isDebugEnabled()) {
            log.debug("Assertion decryption failure : ", e);
          }
          throw new SSOAgentException("Unable to decrypt the SAML2 Assertion");
        }
      }
    } else {
      List<Assertion> assertions = saml2Response.getAssertions();
      if (assertions != null && !assertions.isEmpty()) {
        assertion = assertions.get(0);
      }
    }
    if (assertion == null) {
      if (isNoPassive(saml2Response)) {
        LOGGER.log(Level.FINE, "Cannot authenticate in passive mode");
        return;
      }
      throw new SSOAgentException("SAML2 Assertion not found in the Response");
    }

    String idPEntityIdValue = assertion.getIssuer().getValue();
    if (idPEntityIdValue == null || idPEntityIdValue.isEmpty()) {
      throw new SSOAgentException("SAML2 Response does not contain an Issuer value");
    } else if (!idPEntityIdValue.equals(ssoAgentConfig.getSAML2().getIdPEntityId())) {
      throw new SSOAgentException("SAML2 Response Issuer verification failed");
    }
    sessionBean.getSAML2SSO().setAssertion(assertion);
    // Cannot marshall SAML assertion here, before signature validation due to a weird issue in
    // OpenSAML

    // Get the subject name from the Response Object and forward it to login_action.jsp
    String subject = null;
    if (assertion.getSubject() != null && assertion.getSubject().getNameID() != null) {
      subject = assertion.getSubject().getNameID().getValue();
    }

    if (subject == null) {
      throw new SSOAgentException("SAML2 Response does not contain the name of the subject");
    }

    sessionBean.getSAML2SSO().setSubjectId(subject); // set the subject
    request.getSession().setAttribute(SSOAgentConstants.SESSION_BEAN_NAME, sessionBean);

    // validate audience restriction
    validateAudienceRestriction(assertion);

    // validate signature
    validateSignature(saml2Response, assertion);

    // Marshalling SAML2 assertion after signature validation due to a weird issue in OpenSAML
    sessionBean.getSAML2SSO().setAssertionString(marshall(assertion));

    ((LoggedInSessionBean) request.getSession().getAttribute(SSOAgentConstants.SESSION_BEAN_NAME))
        .getSAML2SSO()
        .setSubjectAttributes(getAssertionStatements(assertion));

    // For removing the session when the single sign out request made by the SP itself
    if (ssoAgentConfig.getSAML2().isSLOEnabled()) {
      String sessionId = assertion.getAuthnStatements().get(0).getSessionIndex();
      if (sessionId == null) {
        throw new SSOAgentException(
            "Single Logout is enabled but IdP Session ID not found in SAML2 Assertion");
      }
      ((LoggedInSessionBean) request.getSession().getAttribute(SSOAgentConstants.SESSION_BEAN_NAME))
          .getSAML2SSO()
          .setSessionIndex(sessionId);
      SSOAgentSessionManager.addAuthenticatedSession(request.getSession(false));
    }

    request.getSession().setAttribute(SSOAgentConstants.SESSION_BEAN_NAME, sessionBean);
  }
  private Assertion buildSAMLAssertion(
      SAMLSSOAuthnReqDTO authReqDTO, DateTime notOnOrAfter, String sessionId)
      throws IdentityException {
    try {
      DateTime currentTime = new DateTime();
      Assertion samlAssertion = new AssertionBuilder().buildObject();
      samlAssertion.setID(SAMLSSOUtil.createID());
      samlAssertion.setVersion(SAMLVersion.VERSION_20);
      samlAssertion.setIssuer(SAMLSSOUtil.getIssuer());
      samlAssertion.setIssueInstant(currentTime);
      Subject subject = new SubjectBuilder().buildObject();

      NameID nameId = new NameIDBuilder().buildObject();
      if (authReqDTO.getUseFullyQualifiedUsernameAsSubject()) {
        nameId.setValue(authReqDTO.getUsername());
        nameId.setFormat(NameIdentifier.EMAIL);
      } else {
        nameId.setValue(MultitenantUtils.getTenantAwareUsername(authReqDTO.getUsername()));
        nameId.setFormat(authReqDTO.getNameIDFormat());
      }

      subject.setNameID(nameId);

      SubjectConfirmation subjectConfirmation = new SubjectConfirmationBuilder().buildObject();
      subjectConfirmation.setMethod(SAMLSSOConstants.SUBJECT_CONFIRM_BEARER);

      SubjectConfirmationData scData = new SubjectConfirmationDataBuilder().buildObject();
      scData.setRecipient(authReqDTO.getAssertionConsumerURL());
      scData.setNotOnOrAfter(notOnOrAfter);
      scData.setInResponseTo(authReqDTO.getId());
      subjectConfirmation.setSubjectConfirmationData(scData);

      subject.getSubjectConfirmations().add(subjectConfirmation);

      samlAssertion.setSubject(subject);

      AuthnStatement authStmt = new AuthnStatementBuilder().buildObject();
      authStmt.setAuthnInstant(new DateTime());

      AuthnContext authContext = new AuthnContextBuilder().buildObject();
      AuthnContextClassRef authCtxClassRef = new AuthnContextClassRefBuilder().buildObject();
      authCtxClassRef.setAuthnContextClassRef(AuthnContext.PASSWORD_AUTHN_CTX);
      authContext.setAuthnContextClassRef(authCtxClassRef);
      authStmt.setAuthnContext(authContext);
      if (authReqDTO.isDoSingleLogout()) {
        authStmt.setSessionIndex(sessionId);
      }
      samlAssertion.getAuthnStatements().add(authStmt);

      /*
       * If <AttributeConsumingServiceIndex> element is in the
       * <AuthnRequest> and
       * according to the spec 2.0 the subject MUST be in the assertion
       */
      Map<String, String> claims = SAMLSSOUtil.getAttributes(authReqDTO);
      if (claims != null) {
        samlAssertion.getAttributeStatements().add(buildAttributeStatement(claims));
      }

      AudienceRestriction audienceRestriction = new AudienceRestrictionBuilder().buildObject();
      Audience issuerAudience = new AudienceBuilder().buildObject();
      issuerAudience.setAudienceURI(authReqDTO.getIssuer());
      audienceRestriction.getAudiences().add(issuerAudience);
      if (authReqDTO.getRequestedAudiences() != null) {
        for (String requestedAudience : authReqDTO.getRequestedAudiences()) {
          Audience audience = new AudienceBuilder().buildObject();
          audience.setAudienceURI(requestedAudience);
          audienceRestriction.getAudiences().add(audience);
        }
      }
      Conditions conditions = new ConditionsBuilder().buildObject();
      conditions.setNotBefore(currentTime);
      conditions.setNotOnOrAfter(notOnOrAfter);
      conditions.getAudienceRestrictions().add(audienceRestriction);
      samlAssertion.setConditions(conditions);

      if (authReqDTO.getDoSignAssertions()) {
        SAMLSSOUtil.setSignature(
            samlAssertion,
            XMLSignature.ALGO_ID_SIGNATURE_RSA,
            new SignKeyDataHolder(authReqDTO.getUsername()));
      }

      return samlAssertion;
    } catch (Exception e) {
      log.error("Error when reading claim values for generating SAML Response", e);
      throw new IdentityException(
          "Error when reading claim values for generating SAML Response", e);
    }
  }
  /*
   * Unit test for serialization/deserialization check on
   * AuthenticationResponse and validation of Assertion's signature
   * afterwards.
   */
  @Test
  public void testAssertion() throws Exception {

    // Setup
    KeyPair keyPair = generateKeyPair();
    DateTime notBefore = new DateTime();
    DateTime notAfter = notBefore.plusMonths(1);
    X509Certificate certificate =
        generateSelfSignedCertificate(keyPair, "CN=Test", notBefore, notAfter);

    KeyStore.PrivateKeyEntry privateKeyEntry =
        new KeyStore.PrivateKeyEntry(keyPair.getPrivate(), new Certificate[] {certificate});

    String userId = UUID.randomUUID().toString();
    String attributeName = "urn:test:attribute";
    Attribute attribute =
        new Attribute(attributeName, AttributeType.STRING, UUID.randomUUID().toString());
    Map<String, Attribute> attributes = new HashMap<String, Attribute>();
    attributes.put(attributeName, attribute);

    String issuerName = "test-issuer";

    String requestIssuer = "request-issuer";
    String requestId = UUID.randomUUID().toString();
    String recipient = "http://www.testsp.com/saml";

    Assertion assertion =
        Saml2Util.getAssertion(
            issuerName,
            requestId,
            requestIssuer,
            recipient,
            5,
            new DateTime(),
            SamlAuthenticationPolicy.IDENTIFICATION,
            userId,
            attributes,
            null,
            null);

    // Operate: sign assertion
    Saml2Util.sign(assertion, privateKeyEntry);

    // Verify
    List<X509Certificate> certChain = Saml2Util.validateSignature(assertion.getSignature());
    assertNotNull(certChain);
    assertEquals(1, certChain.size());

    // Operate: validate assertion
    AuthenticationResponse authenticationResponse =
        Saml2Util.validateAssertion(
            assertion, new DateTime(), 5, requestIssuer, recipient, requestId, null, null);

    // Verify
    assertNotNull(authenticationResponse);
    assertNotNull(authenticationResponse.getAssertion());

    // Operate: serialize AuthenticationResponse
    ByteArrayOutputStream out = new ByteArrayOutputStream();
    ObjectOutputStream oos = new ObjectOutputStream(out);
    oos.writeObject(authenticationResponse);
    oos.close();

    // Operate: deserialize AuthenticationResponse
    byte[] input = out.toByteArray();
    InputStream in = new ByteArrayInputStream(input);
    ObjectInputStream ois = new ObjectInputStream(in);
    Object o = ois.readObject();
    AuthenticationResponse copy = (AuthenticationResponse) o;

    // Verify
    assertNotNull(copy);
    Assertion assertionCopy = copy.getAssertion();
    assertNotNull(assertionCopy);
    Saml2Util.validateSignature(assertionCopy.getSignature());
    AuthenticationResponse authenticationResponseCopy =
        Saml2Util.validateAssertion(
            assertionCopy, new DateTime(), 5, requestIssuer, recipient, requestId, null, null);
    assertEquals(
        authenticationResponse.getEncodedAssertion(),
        authenticationResponseCopy.getEncodedAssertion());
  }
  private static List<AttributeStatement> validateAssertion(
      Assertion samlAssertion,
      SignatureTrustEngine sigTrustEngine,
      String myURI,
      MessageReplayRule replayRule,
      VerifySignatureType verifySignature,
      boolean responseSignatureVerified)
      throws SAMLValidationException {
    if (logger.isDebugEnabled()) {
      logger.debug(
          "validateAndExtractContext(Assertion, String, SignatureTrustEngine, String, MessageReplayRule, VerifySignatureType) - start"); //$NON-NLS-1$
    }

    // Check the replay attack
    if (replayRule != null) {
      BasicSAMLMessageContext messageContext = new BasicSAMLMessageContext();
      // messageContext.setInboundMessage(samlResponse);
      if (samlAssertion.getIssuer() != null)
        messageContext.setInboundMessageIssuer(samlAssertion.getIssuer().getValue());
      messageContext.setInboundSAMLMessageId(samlAssertion.getID());

      try {
        replayRule.evaluate(messageContext);
      } catch (SecurityPolicyException e) {
        logger.error(
            "validateAndExtractContext(Assertion, String, SignatureTrustEngine, String, MessageReplayRule, VerifySignatureType)",
            e); //$NON-NLS-1$

        throw createSAMLValidationException("Possible Replay Attack for Assertion", false, e);
      }
    }

    if (verifySignature != VerifySignatureType.never) {
      Signature signature = samlAssertion.getSignature();
      if (signature == null) {
        if (verifySignature == VerifySignatureType.force && !responseSignatureVerified) {
          throw createSAMLValidationException("Signature does exist in Assertion", true);
        }
      } else {
        verifySignature(signature, samlAssertion.getIssuer().getValue(), sigTrustEngine);
      }
    }
    DateTime dt = new DateTime();

    // get subject (code below only processes first Subject confirmation)
    Subject subject = samlAssertion.getSubject();
    SubjectSchemaValidator subjectSchemaValidator = new SubjectSchemaValidator();
    try {
      subjectSchemaValidator.validate(subject);
    } catch (ValidationException e) {
      logger.error(
          "validateAndExtractContext(Assertion, String, SignatureTrustEngine, String, MessageReplayRule, VerifySignatureType)",
          e); //$NON-NLS-1$

      throw createSAMLValidationException("Subject validation failed: " + e.getMessage(), true, e);
    }
    List<SubjectConfirmation> subjectConfirmations = subject.getSubjectConfirmations();
    for (SubjectConfirmation subjectConfirmation : subjectConfirmations) {
      SubjectConfirmationSchemaValidator subjectConfirmationSchemaValidator =
          new SubjectConfirmationSchemaValidator();
      try {
        subjectConfirmationSchemaValidator.validate(subjectConfirmation);
      } catch (ValidationException e) {
        logger.error(
            "validateAndExtractContext(Assertion, String, SignatureTrustEngine, String, MessageReplayRule, VerifySignatureType)",
            e); //$NON-NLS-1$

        throw createSAMLValidationException(
            "Subject Confirmation validation failed: " + e.getMessage(), true, e);
      }
      SubjectConfirmationData subjectConfirmationData =
          subjectConfirmation.getSubjectConfirmationData();
      try {
        subjectConfirmationSchemaValidator.validate(subjectConfirmation);
      } catch (ValidationException e) {
        logger.error(
            "validateAndExtractContext(Assertion, String, SignatureTrustEngine, String, MessageReplayRule, VerifySignatureType)",
            e); //$NON-NLS-1$

        throw createSAMLValidationException(
            "Subject Confirmation validation failed: " + e.getMessage(), true, e);
      }

      // verify the validity of time using clock skew, subjectConfirmationData.getNotBefore() and
      // subjectConfirmationData.getNotOnOrAfter()@
      DateTime notBefore = subjectConfirmationData.getNotBefore();
      DateTime notAfter = subjectConfirmationData.getNotOnOrAfter();

      if (notBefore != null && dt.isBefore(notBefore)) {
        throw createSAMLValidationException("Subject confirmation expired.", true);
      }

      if (notAfter != null && (dt.equals(notAfter) || dt.isAfter(notAfter))) {
        throw createSAMLValidationException("Subject confirmation expired.", true);
      }
    }

    //		 validate conditions
    Conditions conditions = samlAssertion.getConditions();

    // Validate the spec

    ConditionsSpecValidator conditionValidator = new ConditionsSpecValidator();
    try {
      conditionValidator.validate(conditions);
    } catch (ValidationException e) {
      logger.error(
          "validateAndExtractContext(Assertion, String, SignatureTrustEngine, String, MessageReplayRule, VerifySignatureType)",
          e); //$NON-NLS-1$

      throw createSAMLValidationException("Condition Validity Failed.", true, e);
    }

    // verify the validity of time using clock skew, conditions.getNotBefore() and
    // conditions.getNotOnOrAfter()@
    DateTime notBefore = conditions.getNotBefore();
    DateTime notAfter = conditions.getNotOnOrAfter();
    if (notBefore != null && dt.isBefore(notBefore)) {
      throw createSAMLValidationException("Assertion expired.", true);
    }

    if (notAfter != null && (dt.equals(notAfter) || dt.isAfter(notAfter))) {
      throw createSAMLValidationException("Assertion expired.", true);
    }

    for (Condition condition : conditions.getConditions()) {
      if (condition instanceof AudienceRestriction) {
        if (myURI != null && myURI.length() > 0) {
          boolean audiencePresent = false;
          boolean iAmOneOfTheAudience = false;
          AudienceRestriction audienceRestriction = (AudienceRestriction) condition;
          for (Audience audience : audienceRestriction.getAudiences()) {
            audiencePresent = true;
            String audienceURI = audience.getAudienceURI();
            if (myURI.equals(audienceURI)) {
              iAmOneOfTheAudience = true;
              break;
            }
          }
          if (!(audiencePresent && iAmOneOfTheAudience)) {
            throw createSAMLValidationException(
                "None of the audience is intended for me: " + myURI, false);
          }
        }
      }
    }

    List<AttributeStatement> asList = samlAssertion.getAttributeStatements();

    if (logger.isDebugEnabled()) {
      logger.debug(
          "validateAndExtractContext(Assertion, String, SignatureTrustEngine, String, MessageReplayRule, VerifySignatureType) - end"); //$NON-NLS-1$
    }
    return asList;
  }