@Override
  public SignableXMLObject setSignature(
      SignableXMLObject signableXMLObject,
      String signatureAlgorithm,
      String digestAlgorithm,
      X509Credential cred)
      throws IdentityException {

    Signature signature = (Signature) buildXMLObject(Signature.DEFAULT_ELEMENT_NAME);
    signature.setSigningCredential(cred);
    signature.setSignatureAlgorithm(signatureAlgorithm);
    signature.setCanonicalizationAlgorithm(Canonicalizer.ALGO_ID_C14N_EXCL_OMIT_COMMENTS);

    KeyInfo keyInfo = (KeyInfo) buildXMLObject(KeyInfo.DEFAULT_ELEMENT_NAME);
    X509Data data = (X509Data) buildXMLObject(X509Data.DEFAULT_ELEMENT_NAME);
    X509Certificate cert = (X509Certificate) buildXMLObject(X509Certificate.DEFAULT_ELEMENT_NAME);

    String value;
    try {
      value = org.apache.xml.security.utils.Base64.encode(cred.getEntityCertificate().getEncoded());
    } catch (CertificateEncodingException e) {
      throw IdentityException.error("Error occurred while retrieving encoded cert", e);
    }

    cert.setValue(value);
    data.getX509Certificates().add(cert);
    keyInfo.getX509Datas().add(data);
    signature.setKeyInfo(keyInfo);

    signableXMLObject.setSignature(signature);
    ((SAMLObjectContentReference) signature.getContentReferences().get(0))
        .setDigestAlgorithm(digestAlgorithm);

    List<Signature> signatureList = new ArrayList<Signature>();
    signatureList.add(signature);

    MarshallerFactory marshallerFactory = org.opensaml.xml.Configuration.getMarshallerFactory();
    Marshaller marshaller = marshallerFactory.getMarshaller(signableXMLObject);

    try {
      marshaller.marshall(signableXMLObject);
    } catch (MarshallingException e) {
      throw IdentityException.error("Unable to marshall the request", e);
    }

    org.apache.xml.security.Init.init();
    try {
      Signer.signObjects(signatureList);
    } catch (SignatureException e) {
      throw IdentityException.error("Error occurred while signing request", e);
    }

    return signableXMLObject;
  }
 /**
  * Based on the settings in the extended metadata either creates a PKIX trust engine with trusted
  * keys specified in the extended metadata as anchors or (by default) an explicit trust engine
  * using data from the metadata or from the values overridden in the ExtendedMetadata.
  *
  * @param samlContext context to populate
  */
 protected void populateTrustEngine(SAMLMessageContext samlContext) {
   SignatureTrustEngine engine;
   if ("pkix".equalsIgnoreCase(samlContext.getLocalExtendedMetadata().getSecurityProfile())) {
     engine =
         new PKIXSignatureTrustEngine(
             pkixResolver,
             Configuration.getGlobalSecurityConfiguration().getDefaultKeyInfoCredentialResolver());
   } else {
     engine =
         new ExplicitKeySignatureTrustEngine(
             metadataResolver,
             Configuration.getGlobalSecurityConfiguration().getDefaultKeyInfoCredentialResolver());
   }
   samlContext.setLocalTrustEngine(engine);
 }
  /**
   * Serialize the Auth. Request
   *
   * @param xmlObject
   * @return serialized auth. req
   */
  protected String marshall(XMLObject xmlObject) throws SSOAgentException {

    try {
      System.setProperty(
          "javax.xml.parsers.DocumentBuilderFactory",
          "org.apache.xerces.jaxp.DocumentBuilderFactoryImpl");
      MarshallerFactory marshallerFactory = org.opensaml.xml.Configuration.getMarshallerFactory();
      Marshaller marshaller = marshallerFactory.getMarshaller(xmlObject);
      Element element = marshaller.marshall(xmlObject);
      ByteArrayOutputStream byteArrayOutputStrm = new ByteArrayOutputStream();
      DOMImplementationRegistry registry = DOMImplementationRegistry.newInstance();
      DOMImplementationLS impl = (DOMImplementationLS) registry.getDOMImplementation("LS");
      LSSerializer writer = impl.createLSSerializer();
      LSOutput output = impl.createLSOutput();
      output.setByteStream(byteArrayOutputStrm);
      writer.write(element, output);
      return new String(byteArrayOutputStrm.toByteArray(), Charset.forName("UTF-8"));
    } catch (ClassNotFoundException e) {
      throw new SSOAgentException("Error in marshalling SAML2 Assertion", e);
    } catch (InstantiationException e) {
      throw new SSOAgentException("Error in marshalling SAML2 Assertion", e);
    } catch (MarshallingException e) {
      throw new SSOAgentException("Error in marshalling SAML2 Assertion", e);
    } catch (IllegalAccessException e) {
      throw new SSOAgentException("Error in marshalling SAML2 Assertion", e);
    }
  }
  /**
   * Applies the XML Digital Signature to the SAML 2.0 based Logout Request (LogoutRequest).
   *
   * @param logoutRequest the SAML 2.0 based Logout Request (LogoutRequest)
   * @param signatureAlgorithm the algorithm used to compute the signature
   * @param credential the signature signing credential
   * @return the SAML 2.0 based Logout Request (LogoutRequest) with XML Digital Signature set
   * @throws SSOException if an error occurs while signing the SAML 2.0 LogoutRequest message
   */
  protected static LogoutRequest setSignature(
      LogoutRequest logoutRequest, String signatureAlgorithm, X509Credential credential)
      throws SSOException {
    try {
      Signature signature = setSignatureRaw(signatureAlgorithm, credential);
      logoutRequest.setSignature(signature);

      List<Signature> signatureList = new ArrayList<>();
      signatureList.add(signature);

      // Marshall and Sign
      MarshallerFactory marshallerFactory = org.opensaml.xml.Configuration.getMarshallerFactory();
      Marshaller marshaller = marshallerFactory.getMarshaller(logoutRequest);
      marshaller.marshall(logoutRequest);

      //  Initializes and configures the library
      Init.init();
      //  Signer is responsible for creating the digital signatures for the given XML Objects.
      //  Signs the XML Objects based on the given order of the Signature list
      Signer.signObjects(signatureList);
      return logoutRequest;
    } catch (MarshallingException | SignatureException e) {
      throw new SSOException("Error while signing the SAML 2.0 based LogoutRequest message", e);
    }
  }
  private static String getMetadataAsString(final EntityDescriptor descriptor)
      throws MarshallingException {

    final MarshallerFactory marshallerFactory = Configuration.getMarshallerFactory();
    final Marshaller marshaller = marshallerFactory.getMarshaller(descriptor);
    final Element element = marshaller.marshall(descriptor);
    return XMLHelper.nodeToString(element);
  }
  private void initSAML2()
      throws ConfigurationException, ConfigXMLParsingException, MetadataProviderException {
    if (logger.isDebugEnabled()) {
      logger.debug("initSAML2() - start"); // $NON-NLS-1$
    }

    //
    //		 One-time init code here
    //

    DefaultBootstrap.bootstrap();

    StorageService<String, ReplayCacheEntry> storageEngine =
        new MapBasedStorageService<String, ReplayCacheEntry>();
    ReplayCache replayCache = new ReplayCache(storageEngine, 60 * 1000 * replayMinutes);
    replayRule = new MessageReplayRule(replayCache);

    //		 Get the private key that corresponds to a public key that may
    //		 have been used by other parties for encryption
    Credential decryptionCredential =
        getDecryptionCredential(decryptionKey.getKeystore(), localEntityId);

    List<Credential> localCredentials = new ArrayList<Credential>();
    localCredentials.add(decryptionCredential);

    CollectionCredentialResolver localCredResolver =
        new CollectionCredentialResolver(localCredentials);

    //		Support EncryptedKey/KeyInfo containing decryption key hints via
    //		KeyValue/RSAKeyValue and X509Data/X509Certificate
    List<KeyInfoProvider> kiProviders = new ArrayList<KeyInfoProvider>();
    kiProviders.add(new RSAKeyValueProvider());
    kiProviders.add(new InlineX509DataProvider());

    //		Resolves local credentials by using information in the EncryptedKey/KeyInfo to query the
    // supplied
    //		local credential resolver.
    kekResolver = new LocalKeyInfoCredentialResolver(kiProviders, localCredResolver);

    //		Supports resolution of EncryptedKeys by 3 common placement mechanisms
    encryptedKeyResolver = new ChainingEncryptedKeyResolver();
    encryptedKeyResolver.getResolverChain().add(new InlineEncryptedKeyResolver());
    encryptedKeyResolver.getResolverChain().add(new EncryptedElementTypeEncryptedKeyResolver());
    encryptedKeyResolver.getResolverChain().add(new SimpleRetrievalMethodEncryptedKeyResolver());

    // siginingCredential =
    // getVerificationCredential(signingKey.getKeystore(),signingKey.getEntityId());

    MetadataProvider mdProvider = getMetadataProvider();
    MetadataCredentialResolver mdCredResolver = new MetadataCredentialResolver(mdProvider);
    KeyInfoCredentialResolver keyInfoCredResolver =
        Configuration.getGlobalSecurityConfiguration().getDefaultKeyInfoCredentialResolver();
    trustEngine = new CustomKeySignatureTrustEngine(mdCredResolver, keyInfoCredResolver);

    if (logger.isDebugEnabled()) {
      logger.debug("initSAML2() - end"); // $NON-NLS-1$
    }
  }
 /**
  * Builds SAML Elements
  *
  * @param objectQName
  * @return
  * @throws IdentityException
  */
 private XMLObject buildXMLObject(QName objectQName) throws IdentityException {
   XMLObjectBuilder builder =
       org.opensaml.xml.Configuration.getBuilderFactory().getBuilder(objectQName);
   if (builder == null) {
     throw IdentityException.error("Unable to retrieve builder for object QName " + objectQName);
   }
   return builder.buildObject(
       objectQName.getNamespaceURI(), objectQName.getLocalPart(), objectQName.getPrefix());
 }
  /*
   * Create the AuthnRequest
   */
  public AuthnRequestImpl buildAuthnRequest() throws ValidationException {
    // Use the OpenSAML Configuration singleton to get a builder factory object
    final XMLObjectBuilderFactory xmlObjectBuilderFactory = Configuration.getBuilderFactory();
    // First get a builder for AuthnRequest
    final AuthnRequestBuilder authnRequestBuilder =
        (AuthnRequestBuilder) xmlObjectBuilderFactory.getBuilder(AuthnRequest.DEFAULT_ELEMENT_NAME);

    // And one for Issuer
    final IssuerBuilder issuerBuilder =
        (IssuerBuilder) xmlObjectBuilderFactory.getBuilder(Issuer.DEFAULT_ELEMENT_NAME);

    // get a builder for NameID
    final NameIDBuilder nameIDBuilder =
        (NameIDBuilder) xmlObjectBuilderFactory.getBuilder(NameID.DEFAULT_ELEMENT_NAME);

    // build a NameID object
    final NameID nameID = nameIDBuilder.buildObject();
    nameID.setFormat(NameIDType.PERSISTENT);
    nameID.setSPProvidedID("https://aa.bb.cc/sp/provider");
    nameID.setSPNameQualifier("https://aa.bb.cc/sp/provider");

    // get a builder for Subject
    final SubjectBuilder subjectBuilder =
        (SubjectBuilder) xmlObjectBuilderFactory.getBuilder(Subject.DEFAULT_ELEMENT_NAME);

    // build a Subject object
    final Subject subject = subjectBuilder.buildObject();
    subject.setNameID(nameID);

    // build an AuthnRequest object
    final AuthnRequestImpl authnRequest = (AuthnRequestImpl) authnRequestBuilder.buildObject();

    // Build the Issuer object
    final Issuer newIssuer = issuerBuilder.buildObject();
    newIssuer.setValue("https://aa.bb.cc/sp/provideraaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa");
    authnRequest.setIssuer(newIssuer);
    authnRequest.setProviderName("https://aa.bb.cc/sp/provider");
    authnRequest.setAssertionConsumerServiceURL("1");
    authnRequest.setDestination("https://aa.bb.cc/sp/provider");
    authnRequest.setProtocolBinding(SAMLConstants.SAML2_REDIRECT_BINDING_URI);
    authnRequest.setSubject(subject);
    // Only add the parameter if it is true.
    //        if (forceReAuthentication == true) {
    authnRequest.setForceAuthn(true);
    //        }

    authnRequest.setVersion(org.opensaml.common.SAMLVersion.VERSION_20);
    final DateTime dateTime = new DateTime();
    authnRequest.setIssueInstant(dateTime);
    authnRequest.setID(UUID.randomUUID().toString());

    authnRequest.validate(true);

    return authnRequest;
  }
 /**
  * Builds a SAML 2.0 based XML object using the fully qualified name.
  *
  * @param objectQualifiedName fully qualified name
  * @return a SAML 2.0 based XML object
  * @throws SSOException if an error occurs while retrieving the builder for the fully qualified
  *     name
  */
 private static XMLObject buildXMLObject(QName objectQualifiedName) throws SSOException {
   doBootstrap();
   XMLObjectBuilder builder =
       org.opensaml.xml.Configuration.getBuilderFactory().getBuilder(objectQualifiedName);
   if (!Optional.ofNullable(builder).isPresent()) {
     throw new SSOException("Unable to retrieve builder for object QName " + objectQualifiedName);
   }
   return builder.buildObject(
       objectQualifiedName.getNamespaceURI(),
       objectQualifiedName.getLocalPart(),
       objectQualifiedName.getPrefix());
 }
  private static void bootstrap() throws ConfigurationException {
    PaosBootstrap.bootstrap();

    NamedKeyInfoGeneratorManager manager =
        Configuration.getGlobalSecurityConfiguration().getKeyInfoGeneratorManager();
    X509KeyInfoGeneratorFactory generator = new X509KeyInfoGeneratorFactory();
    generator.setEmitEntityCertificate(true);
    generator.setEmitEntityCertificateChain(true);
    manager.registerFactory(
        org.springframework.security.saml.SAMLConstants.SAML_METADATA_KEY_INFO_GENERATOR,
        generator);
  }
  /*
   * Create a fully formed SAML Request.
   * @return The SAML Request as XML.
   */
  public String buildAuthnRequest2String()
      throws org.opensaml.xml.io.MarshallingException, BindingException, IOException,
          ValidationException {
    // build an AuthnRequest object
    final AuthnRequestImpl auth = buildAuthnRequest();

    // Now we must marshall the object for the transfer over the wire.
    final Marshaller marshaller = Configuration.getMarshallerFactory().getMarshaller(auth);
    final Element authDOM = marshaller.marshall(auth);
    // We use a StringWriter to produce our XML output. This gets us XML where
    // the encoding is UTF-8. We must have UTF-8 or bad things happen.
    return XMLHelper.prettyPrintXML(authDOM);
  }
  /**
   * Sign the SAML AuthnRequest message
   *
   * @param logoutRequest
   * @param signatureAlgorithm
   * @param cred
   * @return
   * @throws SAMLSSOException
   */
  public static LogoutRequest setSignature(
      LogoutRequest logoutRequest, String signatureAlgorithm, X509Credential cred)
      throws SAMLSSOException {
    try {
      Signature signature = (Signature) buildXMLObject(Signature.DEFAULT_ELEMENT_NAME);
      signature.setSigningCredential(cred);
      signature.setSignatureAlgorithm(signatureAlgorithm);
      signature.setCanonicalizationAlgorithm(Canonicalizer.ALGO_ID_C14N_EXCL_OMIT_COMMENTS);

      try {
        KeyInfo keyInfo = (KeyInfo) buildXMLObject(KeyInfo.DEFAULT_ELEMENT_NAME);
        X509Data data = (X509Data) buildXMLObject(X509Data.DEFAULT_ELEMENT_NAME);
        org.opensaml.xml.signature.X509Certificate cert =
            (org.opensaml.xml.signature.X509Certificate)
                buildXMLObject(org.opensaml.xml.signature.X509Certificate.DEFAULT_ELEMENT_NAME);
        String value =
            org.apache.xml.security.utils.Base64.encode(cred.getEntityCertificate().getEncoded());
        cert.setValue(value);
        data.getX509Certificates().add(cert);
        keyInfo.getX509Datas().add(data);
        signature.setKeyInfo(keyInfo);
      } catch (CertificateEncodingException e) {
        throw new SAMLSSOException("Error getting certificate", e);
      }

      logoutRequest.setSignature(signature);

      List<Signature> signatureList = new ArrayList<Signature>();
      signatureList.add(signature);

      // Marshall and Sign
      MarshallerFactory marshallerFactory = org.opensaml.xml.Configuration.getMarshallerFactory();
      Marshaller marshaller = marshallerFactory.getMarshaller(logoutRequest);

      marshaller.marshall(logoutRequest);

      org.apache.xml.security.Init.init();
      Signer.signObjects(signatureList);
      return logoutRequest;

    } catch (Exception e) {
      throw new SAMLSSOException("Error while signing the Logout Request message", e);
    }
  }
  /**
   * Gets the signature algorithm URI to use with the given signing credential.
   *
   * @param credential the credential that will be used to sign the message
   * @param config the SecurityConfiguration to use (may be null)
   * @return signature algorithm to use with the given signing credential
   * @throws MessageEncodingException thrown if the algorithm URI could not be derived from the
   *     supplied credential
   */
  protected String getSignatureAlgorithmURI(Credential credential, SecurityConfiguration config)
      throws MessageEncodingException {

    SecurityConfiguration secConfig;
    if (config != null) {
      secConfig = config;
    } else {
      secConfig = Configuration.getGlobalSecurityConfiguration();
    }

    String signAlgo = secConfig.getSignatureAlgorithmURI(credential);

    if (signAlgo == null) {
      throw new MessageEncodingException(
          "The signing credential's algorithm URI could not be derived");
    }

    return signAlgo;
  }
Exemple #14
0
  /**
   * Serializing a SAML2 object into a String
   *
   * @param xmlObject object that needs to serialized.
   * @return serialized object
   * @throws Exception
   */
  public static String marshall(XMLObject xmlObject) throws Exception {
    try {
      doBootstrap();
      System.setProperty(
          "javax.xml.parsers.DocumentBuilderFactory",
          "org.apache.xerces.jaxp.DocumentBuilderFactoryImpl");

      MarshallerFactory marshallerFactory = org.opensaml.xml.Configuration.getMarshallerFactory();
      Marshaller marshaller = marshallerFactory.getMarshaller(xmlObject);
      Element element = marshaller.marshall(xmlObject);

      ByteArrayOutputStream byteArrayOutputStrm = new ByteArrayOutputStream();
      DOMImplementationRegistry registry = DOMImplementationRegistry.newInstance();
      DOMImplementationLS impl = (DOMImplementationLS) registry.getDOMImplementation("LS");
      LSSerializer writer = impl.createLSSerializer();
      LSOutput output = impl.createLSOutput();
      output.setByteStream(byteArrayOutputStrm);
      writer.write(element, output);
      return byteArrayOutputStrm.toString();
    } catch (Exception e) {
      throw new Exception("Error Serializing the SAML Response", e);
    }
  }