Search in sources :

Example 1 with SamlMetadataDescriptorUpdater

use of org.keycloak.protocol.saml.mappers.SamlMetadataDescriptorUpdater in project keycloak by keycloak.

the class SAMLIdentityProvider method export.

@Override
public Response export(UriInfo uriInfo, RealmModel realm, String format) {
    try {
        URI authnBinding = JBossSAMLURIConstants.SAML_HTTP_REDIRECT_BINDING.getUri();
        if (getConfig().isPostBindingAuthnRequest()) {
            authnBinding = JBossSAMLURIConstants.SAML_HTTP_POST_BINDING.getUri();
        }
        URI endpoint = uriInfo.getBaseUriBuilder().path("realms").path(realm.getName()).path("broker").path(getConfig().getAlias()).path("endpoint").build();
        boolean wantAuthnRequestsSigned = getConfig().isWantAuthnRequestsSigned();
        boolean wantAssertionsSigned = getConfig().isWantAssertionsSigned();
        boolean wantAssertionsEncrypted = getConfig().isWantAssertionsEncrypted();
        String entityId = getEntityId(uriInfo, realm);
        String nameIDPolicyFormat = getConfig().getNameIDPolicyFormat();
        List<Element> signingKeys = new LinkedList<>();
        List<Element> encryptionKeys = new LinkedList<>();
        session.keys().getKeysStream(realm, KeyUse.SIG, Algorithm.RS256).filter(Objects::nonNull).filter(key -> key.getCertificate() != null).sorted(SamlService::compareKeys).forEach(key -> {
            try {
                Element element = SPMetadataDescriptor.buildKeyInfoElement(key.getKid(), PemUtils.encodeCertificate(key.getCertificate()));
                signingKeys.add(element);
                if (key.getStatus() == KeyStatus.ACTIVE) {
                    encryptionKeys.add(element);
                }
            } catch (ParserConfigurationException e) {
                logger.warn("Failed to export SAML SP Metadata!", e);
                throw new RuntimeException(e);
            }
        });
        // Prepare the metadata descriptor model
        StringWriter sw = new StringWriter();
        XMLStreamWriter writer = StaxUtil.getXMLStreamWriter(sw);
        SAMLMetadataWriter metadataWriter = new SAMLMetadataWriter(writer);
        EntityDescriptorType entityDescriptor = SPMetadataDescriptor.buildSPdescriptor(authnBinding, authnBinding, endpoint, endpoint, wantAuthnRequestsSigned, wantAssertionsSigned, wantAssertionsEncrypted, entityId, nameIDPolicyFormat, signingKeys, encryptionKeys);
        // Create the AttributeConsumingService if at least one attribute importer mapper exists
        List<Entry<IdentityProviderMapperModel, SamlMetadataDescriptorUpdater>> metadataAttrProviders = new ArrayList<>();
        realm.getIdentityProviderMappersByAliasStream(getConfig().getAlias()).forEach(mapper -> {
            IdentityProviderMapper target = (IdentityProviderMapper) session.getKeycloakSessionFactory().getProviderFactory(IdentityProviderMapper.class, mapper.getIdentityProviderMapper());
            if (target instanceof SamlMetadataDescriptorUpdater)
                metadataAttrProviders.add(new java.util.AbstractMap.SimpleEntry<>(mapper, (SamlMetadataDescriptorUpdater) target));
        });
        if (!metadataAttrProviders.isEmpty()) {
            int attributeConsumingServiceIndex = getConfig().getAttributeConsumingServiceIndex() != null ? getConfig().getAttributeConsumingServiceIndex() : 1;
            String attributeConsumingServiceName = getConfig().getAttributeConsumingServiceName();
            // default value for attributeConsumingServiceName
            if (attributeConsumingServiceName == null)
                attributeConsumingServiceName = realm.getDisplayName() != null ? realm.getDisplayName() : realm.getName();
            AttributeConsumingServiceType attributeConsumingService = new AttributeConsumingServiceType(attributeConsumingServiceIndex);
            attributeConsumingService.setIsDefault(true);
            String currentLocale = realm.getDefaultLocale() == null ? "en" : realm.getDefaultLocale();
            LocalizedNameType attributeConsumingServiceNameElement = new LocalizedNameType(currentLocale);
            attributeConsumingServiceNameElement.setValue(attributeConsumingServiceName);
            attributeConsumingService.addServiceName(attributeConsumingServiceNameElement);
            // Look for the SP descriptor and add the attribute consuming service
            for (EntityDescriptorType.EDTChoiceType choiceType : entityDescriptor.getChoiceType()) {
                List<EntityDescriptorType.EDTDescriptorChoiceType> descriptors = choiceType.getDescriptors();
                for (EntityDescriptorType.EDTDescriptorChoiceType descriptor : descriptors) {
                    descriptor.getSpDescriptor().addAttributeConsumerService(attributeConsumingService);
                }
            }
            // Add the attribute mappers
            metadataAttrProviders.forEach(mapper -> {
                SamlMetadataDescriptorUpdater metadataAttrProvider = mapper.getValue();
                metadataAttrProvider.updateMetadata(mapper.getKey(), entityDescriptor);
            });
        }
        // Write the metadata and export it to a string
        metadataWriter.writeEntityDescriptor(entityDescriptor);
        String descriptor = sw.toString();
        // Metadata signing
        if (getConfig().isSignSpMetadata()) {
            KeyManager.ActiveRsaKey activeKey = session.keys().getActiveRsaKey(realm);
            String keyName = getConfig().getXmlSigKeyInfoKeyNameTransformer().getKeyName(activeKey.getKid(), activeKey.getCertificate());
            KeyPair keyPair = new KeyPair(activeKey.getPublicKey(), activeKey.getPrivateKey());
            Document metadataDocument = DocumentUtil.getDocument(descriptor);
            SAML2Signature signatureHelper = new SAML2Signature();
            signatureHelper.setSignatureMethod(getSignatureAlgorithm().getXmlSignatureMethod());
            signatureHelper.setDigestMethod(getSignatureAlgorithm().getXmlSignatureDigestMethod());
            Node nextSibling = metadataDocument.getDocumentElement().getFirstChild();
            signatureHelper.setNextSibling(nextSibling);
            signatureHelper.signSAMLDocument(metadataDocument, keyName, keyPair, CanonicalizationMethod.EXCLUSIVE);
            descriptor = DocumentUtil.getDocumentAsString(metadataDocument);
        }
        return Response.ok(descriptor, MediaType.APPLICATION_XML_TYPE).build();
    } catch (Exception e) {
        logger.warn("Failed to export SAML SP Metadata!", e);
        throw new RuntimeException(e);
    }
}
Also used : SAMLMetadataWriter(org.keycloak.saml.processing.core.saml.v2.writers.SAMLMetadataWriter) Element(org.w3c.dom.Element) Node(org.w3c.dom.Node) ArrayList(java.util.ArrayList) Document(org.w3c.dom.Document) URI(java.net.URI) Entry(java.util.Map.Entry) StringWriter(java.io.StringWriter) LocalizedNameType(org.keycloak.dom.saml.v2.metadata.LocalizedNameType) XMLStreamWriter(javax.xml.stream.XMLStreamWriter) IdentityProviderMapper(org.keycloak.broker.provider.IdentityProviderMapper) ParserConfigurationException(javax.xml.parsers.ParserConfigurationException) EntityDescriptorType(org.keycloak.dom.saml.v2.metadata.EntityDescriptorType) SAML2Signature(org.keycloak.saml.processing.api.saml.v2.sig.SAML2Signature) KeyManager(org.keycloak.models.KeyManager) KeyPair(java.security.KeyPair) LinkedList(java.util.LinkedList) ConfigurationException(org.keycloak.saml.common.exceptions.ConfigurationException) IdentityBrokerException(org.keycloak.broker.provider.IdentityBrokerException) ParserConfigurationException(javax.xml.parsers.ParserConfigurationException) SamlMetadataDescriptorUpdater(org.keycloak.protocol.saml.mappers.SamlMetadataDescriptorUpdater) AttributeConsumingServiceType(org.keycloak.dom.saml.v2.metadata.AttributeConsumingServiceType)

Aggregations

StringWriter (java.io.StringWriter)1 URI (java.net.URI)1 KeyPair (java.security.KeyPair)1 ArrayList (java.util.ArrayList)1 LinkedList (java.util.LinkedList)1 Entry (java.util.Map.Entry)1 ParserConfigurationException (javax.xml.parsers.ParserConfigurationException)1 XMLStreamWriter (javax.xml.stream.XMLStreamWriter)1 IdentityBrokerException (org.keycloak.broker.provider.IdentityBrokerException)1 IdentityProviderMapper (org.keycloak.broker.provider.IdentityProviderMapper)1 AttributeConsumingServiceType (org.keycloak.dom.saml.v2.metadata.AttributeConsumingServiceType)1 EntityDescriptorType (org.keycloak.dom.saml.v2.metadata.EntityDescriptorType)1 LocalizedNameType (org.keycloak.dom.saml.v2.metadata.LocalizedNameType)1 KeyManager (org.keycloak.models.KeyManager)1 SamlMetadataDescriptorUpdater (org.keycloak.protocol.saml.mappers.SamlMetadataDescriptorUpdater)1 ConfigurationException (org.keycloak.saml.common.exceptions.ConfigurationException)1 SAML2Signature (org.keycloak.saml.processing.api.saml.v2.sig.SAML2Signature)1 SAMLMetadataWriter (org.keycloak.saml.processing.core.saml.v2.writers.SAMLMetadataWriter)1 Document (org.w3c.dom.Document)1 Element (org.w3c.dom.Element)1