{"record":{"id":"fbd1e0a91aa58025","repo":"apereo/cas","slug":"could-not-extract-and-identify-credentials","errorCode":null,"errorMessage":"Could not extract and identify credentials","messagePattern":"Could not extract and identify credentials","errorType":"exception","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"support/cas-server-support-wsfederation-webflow/src/main/java/org/apereo/cas/web/flow/WsFederationResponseValidator.java","lineNumber":88,"sourceCode":"            LOGGER.error(msg);\n            throw new IllegalArgumentException(msg);\n        }\n        buildCredentialsFromAssertion(context, assertion, service);\n    }\n\n    private void buildCredentialsFromAssertion(final RequestContext context,\n                                               final Pair<Assertion, WsFederationConfiguration> assertion,\n                                               final Service service) throws Throwable {\n        try {\n            LOGGER.debug(\"Creating credential based on the provided assertion\");\n            val credential = wsFederationHelper.createCredentialFromToken(assertion.getKey());\n            val configuration = assertion.getValue();\n            val rpId = wsFederationHelper.getRelyingPartyIdentifier(service, configuration);\n\n            if (credential == null) {\n                LOGGER.error(\"No credential could be extracted from [{}] based on relying party identifier [{}] and identity provider identifier [{}]\",\n                    assertion.getKey(), rpId, configuration.getIdentityProviderIdentifier());\n                throw new IllegalArgumentException(\"Could not extract and identify credentials\");\n            }\n\n            if (credential.isValid(rpId, configuration.getIdentityProviderIdentifier(), configuration.getTolerance())) {\n                val currentAttributes = credential.getAttributes();\n                LOGGER.debug(\"Validated assertion for the created credential successfully and located attributes [{}]\", currentAttributes);\n                if (configuration.getAttributeMutator() != null) {\n                    LOGGER.debug(\"Modifying credential attributes based on [{}]\", configuration.getAttributeMutator().getClass().getSimpleName());\n                    val attributes = configuration.getAttributeMutator().modifyAttributes(currentAttributes);\n                    LOGGER.debug(\"Finalized credential attributes are [{}]\", attributes);\n                    credential.setAttributes(attributes);\n                }\n            } else {\n                LOGGER.error(\"SAML assertions are blank or no longer valid based on RP identifier [{}] and identity provider identifier [{}]\",\n                    rpId, configuration.getIdentityProviderIdentifier());\n                throw new IllegalArgumentException(\"Could not validate the provided assertion\");\n            }\n            WebUtils.putServiceIntoFlowScope(context, service);\n            LOGGER.debug(\"Creating final authentication result based on the given credential\");","sourceCodeStart":70,"sourceCodeEnd":106,"githubUrl":"https://github.com/apereo/cas/blob/e7288fc434b4f4505b8452e1a57e8fb3111bb863/support/cas-server-support-wsfederation-webflow/src/main/java/org/apereo/cas/web/flow/WsFederationResponseValidator.java#L70-L106","documentation":"Thrown by WsFederationResponseValidator.buildCredentialsFromAssertion when the extracted SAML assertion is valid but no WsFederationCredential could be constructed from it. The credential extraction produced null, so CAS logs the relying-party identifier and identity-provider identifier it used and aborts the validation flow.","triggerScenarios":"wsFederationHelper.getRelyingPartyIdentifier(service, configuration) plus the configured identityProviderIdentifier do not match anything in the assertion, so credential extraction in WsFederationHelper returns null: the NameID/subject cannot be resolved against the RP ID or IdP identifier configured.","commonSituations":"Wrong cas.authn.wsfed[0].identityProviderIdentifier (does not match the IdP's entity/issuer ID), wrong relyingPartyIdentifier (realm/trust identifier in ADFS does not match the CAS service/realm), or the assertion has no usable subject/NameID.","solutions":["Check identityProviderIdentifier in WsFederationConfiguration exactly matches the IdP's issuer identifier as it appears in the assertion's Issuer element.","Verify the relying party identifier (getRelyingPartyIdentifier derives it from the service / configured realm) matches the WS-Federation realm configured at the IdP for CAS.","Inspect the assertion (debug log or decode wresult) to confirm it contains a subject/NameID.","Compare the relying party identifier and IdP identifier values logged in the error with your CAS properties and correct the mismatch."],"exampleFix":"// before\ncas.authn.wsfed[0].identity-provider-identifier=http://wrong-adfs/adfs/services/trust\ncas.authn.wsfed[0].relying-party-identifier=urn:cas:wrong\n// after: match the ADFS identifiers exactly\ncas.authn.wsfed[0].identity-provider-identifier=http://adfs.example.com/adfs/services/trust\ncas.authn.wsfed[0].relying-party-identifier=urn:cas:example","handlingStrategy":"validation","validationCode":"// assert config identifiers are non-blank before processing a token\nif (configuration.getIdentityProviderIdentifier() == null || configuration.getIdentityProviderIdentifier().isBlank()) {\n    throw new IllegalStateException(\"identityProviderIdentifier must be set to the IdP issuer\");\n}","typeGuard":"function hasIdentityProviderIdentifier(config) {\n  return typeof config.getIdentityProviderIdentifier === 'function' && !!config.getIdentityProviderIdentifier();\n}","tryCatchPattern":"try {\n    validator.validateWsFederationAuthenticationRequest(context);\n} catch (IllegalArgumentException e) {\n    if (e.getMessage().contains(\"Could not extract and identify credentials\")) {\n        LOGGER.error(\"Check identityProviderIdentifier/relyingPartyIdentifier against the assertion issuer and realm\");\n    }\n    throw e;\n}","preventionTips":["Copy identityProviderIdentifier verbatim from the IdP federation metadata (entityID).","Keep relyingPartyIdentifier identical to the realm configured in the ADFS relying-party trust.","Decode a sample wresult and confirm it has a subject/NameID before wiring production flows."],"tags":["ws-federation","credential-extraction","identifier-mismatch","saml-assertion"],"backgroundTag":"invalid-config-value","analyzedSha":"e7288fc434b4f4505b8452e1a57e8fb3111bb863","analyzedAt":"2026-09-08T15:39:16.015Z","contentChangedAt":"2026-09-08T15:39:16.015Z","schemaVersion":2},"datasetVersion":"2026-09-15T23:17:13.987Z"}