apereo/cas · warning

Could not determine authentication from the request context

Error message

Could not determine authentication from the request context

What it means

MultifactorAuthenticationVerifyTrustAction.doExecuteInternal begins by reading the current Authentication from the webflow request context. When none is present, the action logs this warning and returns the 'no' event, meaning the device cannot be verified as trusted and the flow proceeds as if the device is not trusted.

Solutions

  1. Ensure the standard CAS login flow (which establishes authentication in flow scope) precedes the MFA trust verification subflow.
  2. Check for custom webflow overrides that bypass the authentication setup step.
  3. Verify the session/flow is not expired or resumed without re-establishing authentication.
  4. Review MFA trigger/bypass configuration so this action only runs after authentication.

Example fix

// ensure authentication is available before invoking the action
val authentication = WebUtils.getAuthentication(requestContext);
if (authentication == null) {
    // route user through login flow instead of continuing trust check
    return no();
}
Defensive patterns

Strategy: type-guard

Validate before calling

// guard flow entry: only invoke trust verification when authentication exists
Authentication auth = WebUtils.getAuthentication(requestContext);
if (auth == null) {
    LOGGER.warn("Trust check requires authentication; redirecting to login");
    return error();
}

Type guard

boolean hasAuthentication(RequestContext ctx) {
    return WebUtils.getAuthentication(ctx) != null;
}

Prevention

When it happens

Trigger: The trusted-device verification webflow action executes in a request context where WebUtils.getAuthentication(requestContext) is null — i.e. the flow reached the MFA trust check without an established authentication (flow invoked out of order or authentication not yet stored in the flow scope).

Common situations: Direct/deep-link access to the MFA trust flow without a prior login step; custom flow modifications that skip authentication setup; session expiry combined with flow resumption; misordered MFA subflow configuration.

Understand the failure class

Related errors


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

Appendix: source

Thrown at support/cas-server-support-trusted-mfa-core/src/main/java/org/apereo/cas/trusted/web/flow/MultifactorAuthenticationVerifyTrustAction.java:48

@RequiredArgsConstructor
@Getter
public class MultifactorAuthenticationVerifyTrustAction extends BaseCasWebflowAction {

    private final MultifactorAuthenticationTrustStorage storage;

    private final DeviceFingerprintStrategy deviceFingerprintStrategy;

    private final TrustedDevicesMultifactorProperties trustedProperties;

    private final AuditableExecution registeredServiceAccessStrategyEnforcer;

    private final MultifactorAuthenticationTrustedDeviceBypassEvaluator bypassEvaluator;

    @Override
    protected @Nullable Event doExecuteInternal(final RequestContext requestContext) throws Throwable {
        val authentication = WebUtils.getAuthentication(requestContext);
        if (authentication == null) {
            LOGGER.warn("Could not determine authentication from the request context");
            return no();
        }
        val registeredService = WebUtils.getRegisteredService(requestContext);
        val service = WebUtils.getService(requestContext);

        val trustedDevicesDisabled = MultifactorAuthenticationTrustUtils.isMultifactorAuthenticationTrustedDevicesDisabled(requestContext);
        val publicWorkstation = WebUtils.isAuthenticatingAtPublicWorkstation(requestContext);
        if (publicWorkstation || trustedDevicesDisabled || bypassEvaluator.shouldBypassTrustedDevice(registeredService, service, authentication)) {
            LOGGER.debug("Trusted device registration is disabled for [{}]", registeredService);
            return result(CasWebflowConstants.TRANSITION_ID_SKIP);
        }
        val principal = authentication.getPrincipal().getId();
        LOGGER.trace("Retrieving trusted authentication records for [{}]", principal);
        val results = storage.isAvailable() ? storage.get(principal) : Set.<MultifactorAuthenticationTrustRecord>of();
        if (results.isEmpty()) {
            LOGGER.debug("No valid trusted authentication records could be found for [{}]", principal);
            return no();
        }

View on GitHub (pinned to e7288fc434)