apereo/cas · warning

Unable to detect authenticated user profile for prompt-less…

Error message

Unable to detect authenticated user profile for prompt-less login attempts. Redirecting to URL [{}]

What it means

When an OIDC authorization request arrives without an explicit prompt value and CAS cannot detect an already-authenticated user profile in the request context, it cannot silently authorize the request. CAS logs this warning and redirects the user to the login flow, appending an error/status (e.g. login_required for non-form-post response modes) to the original redirect URL.

Solutions

  1. Have the client send an explicit prompt parameter (e.g. prompt=login) so CAS takes a deterministic path.
  2. Ensure CAS SSO sessions are valid: verify ticket registry replication across nodes and session timeout settings.
  3. Check browser cookie settings/third-party cookie blocking if the flow runs in an iframe.
  4. Confirm the user logged in to CAS before the OIDC request; the redirect is usually correct behavior, not a defect.
  5. If redirect loops occur, inspect the built redirect URL and response mode to confirm the client handles the login_required error.

Example fix

// before
GET /cas/oidc/authorize?client_id=app&response_type=code&redirect_uri=...
// after
GET /cas/oidc/authorize?client_id=app&response_type=code&prompt=login&redirect_uri=...
Defensive patterns

Strategy: fallback

Validate before calling

// Client-side: check for an existing CAS session cookie before a prompt-less authorize call;
boolean hasCasSsoSession(jakarta.servlet.http.HttpServletRequest req) {
    return req.getCookies() != null && java.util.Arrays.stream(req.getCookies())
        .anyMatch(c -> c.getName().startsWith("TGC"));
}

Prevention

When it happens

Trigger: OidcCallbackAuthorizeViewResolver.resolve processes an authorize/callback URL where prompt is absent or lacks login/none, and the authenticated profile lookup finds nothing (expired SSO session, missing ticket cookie), so CAS falls back to authorizationModelAndViewBuilder.build with a login redirect.

Common situations: User's CAS SSO session expired before the prompt-less authorization request; cookies blocked in an iframe so no session profile is detected; CAS nodes behind a load balancer without shared ticket registry; client relies on silent SSO while no session exists.

Understand the failure class

Related errors


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

Appendix: source

Thrown at support/cas-server-support-oidc-core-api/src/main/java/org/apereo/cas/oidc/web/OidcCallbackAuthorizeViewResolver.java:67

                val model = new HashMap<String, String>();
                model.put(OAuth20Constants.ERROR, OidcConstants.LOGIN_REQUIRED);
                return new ModelAndView(new JacksonJsonView(), model);
            }
            val parameters = new LinkedHashMap<String, String>();
            parameters.put(OAuth20Constants.ERROR, OidcConstants.LOGIN_REQUIRED);
            oauthRequestParameterResolver.resolveRequestParameter(context, OAuth20Constants.STATE)
                .ifPresent(state -> parameters.put(OAuth20Constants.STATE, state));
            val clientId = oauthRequestParameterResolver.resolveRequestParameter(context, OAuth20Constants.CLIENT_ID).orElse(StringUtils.EMPTY);
            val registeredService = OAuth20Utils.getRegisteredOAuthServiceByClientId(servicesManager, clientId);

            OAuth20Utils.validateRedirectUri(originalRedirectUrl.get(), true);
            val responseType = oauthRequestParameterResolver.resolveResponseModeType(context);
            val redirect = FunctionUtils.doIf(OAuth20ResponseModeFactory.isResponseModeTypeFormPost(registeredService, responseType),
                    originalRedirectUrl::get,
                    () -> OidcRequestSupport.getRedirectUrlWithError(originalRedirectUrl.get(), OidcConstants.LOGIN_REQUIRED, context))
                .get();
            return FunctionUtils.doUnchecked(() -> {
                LOGGER.warn("Unable to detect authenticated user profile for prompt-less login attempts. Redirecting to URL [{}]", redirect);
                return authorizationModelAndViewBuilder.build(registeredService, responseType, redirect, parameters);
            });
        }
        if (prompt.contains(OidcConstants.PROMPT_LOGIN)) {
            LOGGER.trace("Removing login prompt from URL [{}]", url);
            val newUrl = OidcRequestSupport.removeOidcPromptFromAuthorizationRequest(url, OidcConstants.PROMPT_LOGIN);
            LOGGER.trace("Redirecting to URL [{}]", newUrl);
            return OAuth20CallbackAuthorizeViewResolver.asDefault().resolve(context, manager, newUrl);
        }
        LOGGER.trace("Redirecting to URL [{}]", url);
        return OAuth20CallbackAuthorizeViewResolver.asDefault().resolve(context, manager, url);
    }

}

View on GitHub (pinned to e7288fc434)