apereo/cas · error · IllegalArgumentException
Could not extract and identify credentials
Error message
Could not extract and identify credentials
What it means
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.
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.
Example fix
// before cas.authn.wsfed[0].identity-provider-identifier=http://wrong-adfs/adfs/services/trust cas.authn.wsfed[0].relying-party-identifier=urn:cas:wrong // after: match the ADFS identifiers exactly cas.authn.wsfed[0].identity-provider-identifier=http://adfs.example.com/adfs/services/trust cas.authn.wsfed[0].relying-party-identifier=urn:cas:example
Defensive patterns
Strategy: validation
Validate before calling
// assert config identifiers are non-blank before processing a token
if (configuration.getIdentityProviderIdentifier() == null || configuration.getIdentityProviderIdentifier().isBlank()) {
throw new IllegalStateException("identityProviderIdentifier must be set to the IdP issuer");
} Type guard
function hasIdentityProviderIdentifier(config) {
return typeof config.getIdentityProviderIdentifier === 'function' && !!config.getIdentityProviderIdentifier();
} Try / catch
try {
validator.validateWsFederationAuthenticationRequest(context);
} catch (IllegalArgumentException e) {
if (e.getMessage().contains("Could not extract and identify credentials")) {
LOGGER.error("Check identityProviderIdentifier/relyingPartyIdentifier against the assertion issuer and realm");
}
throw e;
} Prevention
- 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.
When it happens
Trigger: 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.
Common situations: 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.
Understand the failure class
Background: "Invalid value" and "allowed values are" config errors: what your library rejected and how to fix it — this error's family across 41 libraries.
Related errors
- Could not validate assertion via the provided token
- WS Requested Security Token is blank or the signature is…
- No groovy script cache manager is available to execute…
- Unable to determine the [WA] parameter
- The authentication request is not recognized
AI-assisted analysis of apereo/cas@e7288fc434 (2026-09-08).
Data as JSON: /api/errors/fbd1e0a91aa58025.
Report an issue: GitHub.
Appendix: source
Thrown at support/cas-server-support-wsfederation-webflow/src/main/java/org/apereo/cas/web/flow/WsFederationResponseValidator.java:88
LOGGER.error(msg);
throw new IllegalArgumentException(msg);
}
buildCredentialsFromAssertion(context, assertion, service);
}
private void buildCredentialsFromAssertion(final RequestContext context,
final Pair<Assertion, WsFederationConfiguration> assertion,
final Service service) throws Throwable {
try {
LOGGER.debug("Creating credential based on the provided assertion");
val credential = wsFederationHelper.createCredentialFromToken(assertion.getKey());
val configuration = assertion.getValue();
val rpId = wsFederationHelper.getRelyingPartyIdentifier(service, configuration);
if (credential == null) {
LOGGER.error("No credential could be extracted from [{}] based on relying party identifier [{}] and identity provider identifier [{}]",
assertion.getKey(), rpId, configuration.getIdentityProviderIdentifier());
throw new IllegalArgumentException("Could not extract and identify credentials");
}
if (credential.isValid(rpId, configuration.getIdentityProviderIdentifier(), configuration.getTolerance())) {
val currentAttributes = credential.getAttributes();
LOGGER.debug("Validated assertion for the created credential successfully and located attributes [{}]", currentAttributes);
if (configuration.getAttributeMutator() != null) {
LOGGER.debug("Modifying credential attributes based on [{}]", configuration.getAttributeMutator().getClass().getSimpleName());
val attributes = configuration.getAttributeMutator().modifyAttributes(currentAttributes);
LOGGER.debug("Finalized credential attributes are [{}]", attributes);
credential.setAttributes(attributes);
}
} else {
LOGGER.error("SAML assertions are blank or no longer valid based on RP identifier [{}] and identity provider identifier [{}]",
rpId, configuration.getIdentityProviderIdentifier());
throw new IllegalArgumentException("Could not validate the provided assertion");
}
WebUtils.putServiceIntoFlowScope(context, service);
LOGGER.debug("Creating final authentication result based on the given credential");View on GitHub (pinned to e7288fc434)