apereo/cas · warning

CAS is configured to only accept pushed authorization…

Error message

CAS is configured to only accept pushed authorization requests and this is not a POST

What it means

CAS's OIDC request interceptor rejects non-POST authorization requests when 'requirePushedAuthorizationRequests' is enabled, unless the request uses a request_uri (i.e. an already-pushed request). Per JAR/PAR, when this mode is on, clients must first POST parameters to the pushed authorization request endpoint and then hit /authorize with only request_uri. This is a deliberate rejection (HTTP 403) enforced in OidcHandlerInterceptorAdapter.preHandle.

Solutions

  1. Update all relying parties to POST authorization parameters to the PAR endpoint (/oidc/pushAuthRequest or similar) and then redirect to /authorize with the returned request_uri
  2. Set cas.authn.oidc.discovery.require-pushed-authorization-requests=false if you do not actually need PAR
  3. Verify the request carries a non-blank request_uri parameter if it is a follow-up authorize call
  4. Upgrade the RP's OIDC client library to one supporting RFC 9126 PAR

Example fix

// before
GET /oidc/authorize?response_type=code&client_id=client&scope=openid&redirect_uri=...
// after
POST /oidc/pushAuthRequest (response_type=code&client_id=client&...) -> {"request_uri":"urn:ietf:params:oauth:request_uri:..."}
GET /oidc/authorize?client_id=client&request_uri=urn:ietf:params:oauth:request_uri:...
Defensive patterns

Strategy: validation

Validate before calling

const isParMode = casProperties.authn.oidc.discovery.requirePushedAuthorizationRequests;
const isAuthorizeWithUri = url.searchParams.get('request_uri')?.trim() !== '';
if (isParMode && method !== 'POST' && !isAuthorizeWithUri) throw new Error('PAR required: POST parameters to the PAR endpoint first');

Type guard

function hasRequestUri(params) {
  return typeof params.request_uri === 'string' && params.request_uri.trim().length > 0;
}

Prevention

When it happens

Trigger: A GET to the OIDC /authorize endpoint (or any non-POST authorize request) while cas.authn.oidc.discovery.require-pushed-authorization-requests=true, the request has no 'request_uri' parameter, and it looks like an authorization request.

Common situations: Deployers flip on requirePushedAuthorizationRequests but existing client applications still perform plain GET-based browser redirects to /authorize; legacy clients or tutorials that never adopted PAR; misconfigured RP libraries that ignore the 'require_pushed_authorization_requests' discovery flag.

Related errors


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

Appendix: source

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

            oauthRequestParameterResolver);

        this.requiresAuthenticationDynamicRegistrationInterceptor = requiresAuthenticationDynamicRegistrationInterceptor;
        this.casProperties = casProperties;
        this.requiresAuthenticationClientConfigurationInterceptor = requiresAuthenticationClientConfigurationInterceptor;
    }

    @Override
    public boolean preHandle(final HttpServletRequest request, final HttpServletResponse response,
                             final Object handler) throws Exception {

        LOGGER.trace("Attempting to pre-handle OIDC request at [{}] with parameters [{}]",
            request.getRequestURI(), request.getParameterMap().keySet());

        if (casProperties.getAuthn().getOidc().getDiscovery().isRequirePushedAuthorizationRequests()
            && !HttpMethod.valueOf(request.getMethod()).equals(HttpMethod.POST)
            && StringUtils.isBlank(request.getParameter(OidcConstants.REQUEST_URI))
            && isAuthorizationRequest(request, response)) {
            LOGGER.warn("CAS is configured to only accept pushed authorization requests and this is not a POST");
            response.setStatus(HttpStatus.SC_FORBIDDEN);
            return false;
        }

        if (!isDynamicClientRegistrationEnabled() && (isClientConfigurationRequest(request.getRequestURI()) || isDynamicClientRegistrationRequest(request.getRequestURI()))) {
            LOGGER.debug("Dynamic client registration is disabled. OIDC request at [{}] is rejected.", request.getRequestURI());
            response.setStatus(HttpStatus.SC_NOT_IMPLEMENTED);
            return false;
        }

        if (isPushedAuthorizationRequest(request.getRequestURI()) && !isValidAuthorizeRequest(new JEEContext(request, response))) {
            LOGGER.warn("Invalid OIDC pushed authorization request at [{}]", request.getRequestURI());
            response.setStatus(HttpStatus.SC_FORBIDDEN);
            writeErrorResponseBody(response);
            return false;
        }

        if (isVerifiableCredentialTransactionRequest(request.getRequestURI()) || isPushedAuthorizationRequest(request.getRequestURI())) {

View on GitHub (pinned to e7288fc434)