{"record":{"id":"71d6e907510fb5e7","repo":"apereo/cas","slug":"could-not-validate-the-provided-assertion","errorCode":null,"errorMessage":"Could not validate the provided assertion","messagePattern":"Could not validate the provided assertion","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":103,"sourceCode":"            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\");\n            val authenticationResult = this.authenticationSystemSupport.finalizeAuthenticationTransaction(service, credential);\n            WebUtils.putAuthenticationResult(authenticationResult, context);\n            WebUtils.putAuthentication(authenticationResult.getAuthentication(), context);\n            WebUtils.putCredential(context, credential);\n            WebUtils.putServiceIntoFlowScope(context, service);\n\n            LOGGER.info(\"Token validated and new [{}] created: [{}]\", credential.getClass().getName(), credential);\n        } catch (final Exception e) {\n            LoggingUtils.error(LOGGER, e);\n            throw e;\n        }\n    }\n}\n","sourceCodeStart":85,"sourceCodeEnd":120,"githubUrl":"https://github.com/apereo/cas/blob/e7288fc434b4f4505b8452e1a57e8fb3111bb863/support/cas-server-support-wsfederation-webflow/src/main/java/org/apereo/cas/web/flow/WsFederationResponseValidator.java#L85-L120","documentation":"Thrown by WsFederationResponseValidator.buildCredentialsFromAssertion when the WsFederationCredential fails isValid(rpId, identityProviderIdentifier, tolerance). The SAML assertion is blank or no longer valid: its conditions (not-before/not-on-or-after) fail against the configured tolerance, or its audience/issuer does not match the RP and IdP identifiers.","triggerScenarios":"credential.isValid returns false because the assertion's NotBefore/NotOnOrAfter window does not cover 'now' (with configured tolerance), or the audience/RP identifier conditions in the assertion do not match the computed relying party identifier.","commonSituations":"Clock skew between the CAS server and the IdP (assertion appears not-yet-valid or expired), stale/replayed tokens, tolerance (setTolerance) too small for real clock drift, or an RP identifier mismatch making the audience condition fail.","solutions":["Synchronize clocks (NTP) between the CAS server and the IdP, or increase the tolerance in WsFederationConfiguration (e.g. setTolerance(300000) for a few minutes of skew).","Verify the relying party identifier matches the assertion's audience/realm; fix the configured realm if it drifted.","Ensure the user is not resubmitting an old wresult token; request a fresh sign-in from the IdP.","Enable debug logging to see which validity condition (time window vs RP/IdP match) rejected the credential."],"exampleFix":"// before: zero tolerance fails on any clock skew\nconfiguration.setTolerance(0);\n// after: allow 5 minutes of clock drift\nconfiguration.setTolerance(300000);","handlingStrategy":"try-catch","validationCode":"// pre-check time synchronization tolerance is non-trivial\nif (configuration.getTolerance() == 0) {\n    LOGGER.warn(\"Tolerance is 0; any clock skew between CAS and IdP will invalidate assertions\");\n}","typeGuard":"function hasValidTolerance(config) {\n  const t = config.getTolerance?.();\n  return typeof t === 'number' && t > 0 && t <= 15 * 60 * 1000;\n}","tryCatchPattern":"try {\n    validator.validateWsFederationAuthenticationRequest(context);\n} catch (IllegalArgumentException e) {\n    if (e.getMessage().contains(\"Could not validate the provided assertion\")) {\n        LOGGER.error(\"Assertion expired or outside validity window; check clocks and tolerance\");\n        return redirectToldPForFreshSignin();\n    }\n    throw e;\n}","preventionTips":["Run NTP on CAS servers and set a tolerance of a few minutes to absorb normal clock drift.","Reject stale tokens early: never cache or replay wresult values across requests.","Monitor time offsets between CAS and IdP hosts in operations dashboards."],"tags":["ws-federation","assertion-expired","clock-skew","saml-conditions"],"backgroundTag":"jwt-token-expired","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"}