code:     private void writeFederationMetadata(
          XMLStreamWriter writer, Idp config, Crypto crypto
      ) throws XMLStreamException {
  
          writer.writeStartElement("md", "RoleDescriptor", WS_FEDERATION_NS);
          writer.writeAttribute(SCHEMA_INSTANCE_NS, "type", "fed:SecurityTokenServiceType");
          writer.writeAttribute("protocolSupportEnumeration", WS_FEDERATION_NS);
          if (config.getServiceDescription() != null && config.getServiceDescription().length() > 0 ) {
              writer.writeAttribute("ServiceDescription", config.getServiceDescription());
          }
          if (config.getServiceDisplayName() != null && config.getServiceDisplayName().length() > 0 ) {
              writer.writeAttribute("ServiceDisplayName", config.getServiceDisplayName());
          }
  
          //http://docs.oasis-open.org/security/saml/v2.0/saml-schema-metadata-2.0.xsd
          //missing organization, contactperson
  
          //KeyDescriptor
          writer.writeStartElement("", "KeyDescriptor", SAML2_METADATA_NS);
          writer.writeAttribute("use", "signing");
          writer.writeStartElement("", "KeyInfo", "http://www.w3.org/2000/09/xmldsig#");
          writer.writeStartElement("", "X509Data", "http://www.w3.org/2000/09/xmldsig#");
          writer.writeStartElement("", "X509Certificate", "http://www.w3.org/2000/09/xmldsig#");
  
          try {
              String keyAlias = crypto.getDefaultX509Identifier();
              X509Certificate cert = CertsUtils.getX509Certificate(crypto, keyAlias);
              writer.writeCharacters(Base64.encode(cert.getEncoded()));
          } catch (Exception ex) {
              LOG.error("Failed to add certificate information to metadata. Metadata incomplete", ex);
          }
  
          writer.writeEndElement(); // X509Certificate
          writer.writeEndElement(); // X509Data
          writer.writeEndElement(); // KeyInfo
          writer.writeEndElement(); // KeyDescriptor
  
  
          // SecurityTokenServiceEndpoint
          writer.writeStartElement("fed", "SecurityTokenServiceEndpoint", WS_FEDERATION_NS);
          writer.writeStartElement("wsa", "EndpointReference", WS_ADDRESSING_NS);
  
          writer.writeStartElement("wsa", "Address", WS_ADDRESSING_NS);
          writer.writeCharacters(config.getStsUrl().toString());
  
          writer.writeEndElement(); // Address
          writer.writeEndElement(); // EndpointReference
          writer.writeEndElement(); // SecurityTokenServiceEndpoint
  
  
          // PassiveRequestorEndpoint
          writer.writeStartElement("fed", "PassiveRequestorEndpoint", WS_FEDERATION_NS);
          writer.writeStartElement("wsa", "EndpointReference", WS_ADDRESSING_NS);
  
          writer.writeStartElement("wsa", "Address", WS_ADDRESSING_NS);
          writer.writeCharacters(config.getIdpUrl().toString());
  
          writer.writeEndElement(); // Address
          writer.writeEndElement(); // EndpointReference
          writer.writeEndElement(); // PassiveRequestorEndpoint
  
  
          // create ClaimsType section
          if (config.getClaimTypesOffered() != null && config.getClaimTypesOffered().size() > 0) {
              writer.writeStartElement("fed", "ClaimTypesOffered", WS_FEDERATION_NS);
              for (Claim claim : config.getClaimTypesOffered()) {
  
                  writer.writeStartElement("auth", "ClaimType", WS_FEDERATION_NS);
                  writer.writeAttribute("Uri", claim.getClaimType().toString());
                  writer.writeAttribute("Optional", "true");
                  writer.writeEndElement(); // ClaimType
  
              }
              writer.writeEndElement(); // ClaimTypesOffered
          }
  
          writer.writeEndElement(); // RoleDescriptor
      }
  
   
  