{"record":{"id":"8c933db115c094de","repo":"spring-projects/spring-security","slug":"metadata-response-is-missing-the-necessary-idpssod","errorCode":null,"errorMessage":"Metadata response is missing the necessary IDPSSODescriptor element","messagePattern":"Metadata response is missing the necessary IDPSSODescriptor element","errorType":"exception","errorClass":"Saml2Exception","httpStatus":null,"severity":"error","filePath":"saml2/saml2-service-provider/src/main/java/org/springframework/security/saml2/provider/service/registration/OpenSamlAssertingPartyDetails.java","lineNumber":87,"sourceCode":"\t * {@link org.springframework.security.saml2.provider.service.registration.RelyingPartyRegistration.AssertingPartyDetails}.\n\t * @return the {@link EntityDescriptor}\n\t */\n\tpublic EntityDescriptor getEntityDescriptor() {\n\t\treturn this.descriptor;\n\t}\n\n\t/**\n\t * Use this {@link EntityDescriptor} to begin building an\n\t * {@link org.springframework.security.saml2.provider.service.registration.RelyingPartyRegistration.AssertingPartyDetails}.\n\t * @param entity the {@link EntityDescriptor} to use\n\t * @return the\n\t * {@link org.springframework.security.saml2.provider.service.registration.OpenSamlAssertingPartyDetails.Builder}\n\t * for further configurations\n\t */\n\tpublic static OpenSamlAssertingPartyDetails.Builder withEntityDescriptor(EntityDescriptor entity) {\n\t\tIDPSSODescriptor idpssoDescriptor = entity.getIDPSSODescriptor(SAMLConstants.SAML20P_NS);\n\t\tif (idpssoDescriptor == null) {\n\t\t\tthrow new Saml2Exception(\"Metadata response is missing the necessary IDPSSODescriptor element\");\n\t\t}\n\t\tList<Saml2X509Credential> verification = new ArrayList<>();\n\t\tList<Saml2X509Credential> encryption = new ArrayList<>();\n\t\tfor (KeyDescriptor keyDescriptor : idpssoDescriptor.getKeyDescriptors()) {\n\t\t\tif (UsageType.SIGNING.equals(keyDescriptor.getUse())) {\n\t\t\t\tList<X509Certificate> certificates = certificates(keyDescriptor);\n\t\t\t\tfor (X509Certificate certificate : certificates) {\n\t\t\t\t\tverification.add(Saml2X509Credential.verification(certificate));\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (UsageType.ENCRYPTION.equals(keyDescriptor.getUse())) {\n\t\t\t\tList<X509Certificate> certificates = certificates(keyDescriptor);\n\t\t\t\tfor (X509Certificate certificate : certificates) {\n\t\t\t\t\tencryption.add(Saml2X509Credential.encryption(certificate));\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (UsageType.UNSPECIFIED.equals(keyDescriptor.getUse())) {\n\t\t\t\tList<X509Certificate> certificates = certificates(keyDescriptor);","sourceCodeStart":69,"sourceCodeEnd":105,"githubUrl":"https://github.com/spring-projects/spring-security/blob/96852e8860138a482cb13d1479573f24ff6443c6/saml2/saml2-service-provider/src/main/java/org/springframework/security/saml2/provider/service/registration/OpenSamlAssertingPartyDetails.java#L69-L105","documentation":"OpenSamlAssertingPartyDetails.withEntityDescriptor converts an OpenSAML EntityDescriptor into an asserting-party builder. SAML 2.0 metadata must contain an IDPSSODescriptor for the SAML 2.0 protocol namespace; when the descriptor is absent the method cannot extract keys/endpoints and throws this Saml2Exception.","triggerScenarios":"Calling withEntityDescriptor with metadata whose EntityDescriptor lacks an IDPSSODescriptor element in the SAML20P_NS namespace — e.g. SP-only metadata, SAML 1.x-only metadata, or role descriptors under a different namespace.","commonSituations":"IdP publishes metadata containing only SPSSODescriptor or AttributeAuthorityDescriptor; fetching the wrong entity's metadata from an aggregate; SAML 1.1 IdP metadata supplied to a SAML 2.0 configuration; manually crafted/stale metadata files.","solutions":["Obtain correct IdP metadata that includes an IDPSSODescriptor for the SAML 2.0 protocol namespace","Verify you selected the correct entityID when metadata contains multiple entities","Check the IdP's metadata URL is the SAML 2.0 endpoint, not a SAML 1.x one","If parsing aggregates, filter to entities that contain the IdP SSO role before conversion","Regenerate the metadata from the IdP if it is stale or hand-edited"],"exampleFix":"// before\nvar builder = OpenSamlAssertingPartyDetails.withEntityDescriptor(wrongEntity);\n// after: guard on role presence\nif (entity.getIDPSSODescriptor(SAMLConstants.SAML20P_NS) == null) {\n    throw new Saml2Exception(\"entity \" + entity.getEntityID() + \" has no SAML 2.0 IDPSSODescriptor\");\n}\nvar builder = OpenSamlAssertingPartyDetails.withEntityDescriptor(entity);","handlingStrategy":"validation","validationCode":"boolean hasIdpSsoDescriptor(EntityDescriptor e) {\n    return e != null && e.getIDPSSODescriptor(SAMLConstants.SAML20P_NS) != null;\n}","typeGuard":null,"tryCatchPattern":"try {\n    var builder = OpenSamlAssertingPartyDetails.withEntityDescriptor(entity);\n} catch (Saml2Exception ex) {\n    logger.error(\"Entity {} lacks SAML 2.0 IDPSSODescriptor\", entity.getEntityID());\n    throw ex;\n}","preventionTips":["Verify IdP metadata contains IDPSSODescriptor with the SAML20P_NS namespace before conversion","When consuming aggregates, filter entities by IDPSSODescriptor role first","Ensure you fetch SAML 2.0 metadata, not SAML 1.1, from the IdP"],"tags":["saml","metadata","idp","validation"],"backgroundTag":"unexpected-response-shape","analyzedSha":"96852e8860138a482cb13d1479573f24ff6443c6","analyzedAt":"2026-09-10T23:25:23.477Z","contentChangedAt":"2026-09-10T23:25:23.477Z","schemaVersion":2},"datasetVersion":"2026-09-14T16:17:12.679Z"}