apereo/cas · error

Unable to resolve the encryption [public] key for entity id

Error message

Unable to resolve the encryption [public] key for entity id [{}]

What it means

The SAML IdP encrypter could not obtain an encryption (X.509 public key) credential for the peer SP from its metadata while building an OpenSAML Encrypter. When the registered service marks encryption as optional, the IdP logs a warning and proceeds without encryption; otherwise it throws SamlException and the response fails.

Solutions

  1. Verify the SP metadata contains a KeyDescriptor of type encryption with a valid X.509 certificate for the exact entity ID being resolved
  2. Mark the service as encryption-optional (service.isEncryptionOptional() = true) if unencrypted assertions are acceptable
  3. Re-fetch/reload current SP metadata (check entity ID, entityID attribute, and metadata validity interval)
  4. Confirm the mdCredentialResolver criteria set (entity ID, SPSSODescriptor role) matches how the metadata was indexed

Example fix

// before (JSON/YAML service config)
"encryptionOptional": false
// after
"encryptionOptional": true
Defensive patterns

Strategy: validation

Validate before calling

// Before building the encrypter, verify the SP metadata exposes an encryption key
val criteria = new CriteriaSet(
    new EntityIdCriterion(peerEntityId),
    new EntityRoleCriterion(SPSSODescriptor.DEFAULT_ELEMENT_NAME));
val cred = mdCredentialResolver.resolveSingle(criteria);
if (cred == null || cred.getPublicKey() == null) {
    // inspect service metadata or set encryptionOptional before proceeding
}

Try / catch

try {
    encrypter = buildEncrypterForSamlObject(...);
} catch (SamlException e) {
    // key unresolved for peer entity: fall back to unsigned/unencrypted or fail request
    LOGGER.error("No encryption key for entity [{}]", peerEntityId, e);
}

Prevention

When it happens

Trigger: buildEncrypterForSamlObject -> configureKeyEncryptionCredential runs mdCredentialResolver.resolveSingle(criteriaSet) for the peer entity ID and the metadata contains no KeyDescriptor with encryption use (or no valid public key) for that SP.

Common situations: SP metadata lacks USAGE_TYPE_ENCRYPTION KeyDescriptors; SP metadata loaded is the wrong entity or expired; mdCredentialResolver criteria (entity ID, roles, validUntil) do not match; service is configured with encryption required but the SP never published an encryption cert.

Related errors


AI-assisted analysis of apereo/cas@e7288fc434 (2026-09-08). Data as JSON: /api/errors/c4e80bd422b902e7. Report an issue: GitHub.

Appendix: source

Thrown at support/cas-server-support-saml-idp-web/src/main/java/org/apereo/cas/support/saml/web/idp/profile/builders/enc/SamlIdPObjectEncrypter.java:328

        val roleDescriptorResolver = SamlIdPUtils.getRoleDescriptorResolver(adaptor,
            samlIdPProperties.getMetadata().getCore().isRequireValidMetadata());

        mdCredentialResolver.setRoleDescriptorResolver(roleDescriptorResolver);
        mdCredentialResolver.initialize();

        val criteriaSet = new CriteriaSet();
        criteriaSet.add(new EncryptionConfigurationCriterion(encryptionConfiguration));
        criteriaSet.add(new EntityIdCriterion(peerEntityId));
        criteriaSet.add(new EntityRoleCriterion(SPSSODescriptor.DEFAULT_ELEMENT_NAME));
        criteriaSet.add(new UsageCriterion(UsageType.ENCRYPTION));
        criteriaSet.add(new SamlIdPSamlRegisteredServiceCriterion(service));

        LOGGER.debug("Attempting to resolve the encryption key for entity id [{}]", peerEntityId);
        val credential = mdCredentialResolver.resolveSingle(criteriaSet);

        if (credential == null || credential.getPublicKey() == null) {
            if (service.isEncryptionOptional()) {
                LOGGER.warn("Unable to resolve the encryption [public] key for entity id [{}]", peerEntityId);
                return null;
            }
            throw new SamlException("Unable to resolve the encryption [public] key for entity id " + peerEntityId);
        }

        val encodedKey = EncodingUtils.encodeBase64(credential.getPublicKey().getEncoded());
        LOGGER.debug("Found encryption public key: [{}]", encodedKey);
        encryptionConfiguration.setKeyTransportEncryptionCredentials(CollectionUtils.wrapList(credential));
        return credential;
    }

    /**
     * Resolve encryption parameters.
     *
     * @param service                 the service
     * @param encryptionConfiguration the encryption configuration
     * @return the encryption parameters
     * @throws ResolverException the exception

View on GitHub (pinned to e7288fc434)