apereo/cas · error
CAS is configured to only accept pushed authorization…
Error message
CAS is configured to only accept pushed authorization requests
What it means
When requirePushedAuthorizationRequests is enabled, the authorize endpoint only accepts requests that supply a request_uri (produced by a prior PAR call). A direct authorize request without request_uri is rejected with HTTP 403 and an error view.
Solutions
- Have clients obtain a request_uri via the PAR endpoint and pass it on /authorize
- Disable the mode: cas.authn.oidc.discovery.require-pushed-authorization-requests=false
- Ensure the PAR request_uri is not blank/truncated when forwarded
- Adopt an RP library that advertises and honors 'require_pushed_authorization_requests' in discovery metadata
Example fix
// before GET /oidc/authorize?response_type=code&client_id=client&scope=openid&redirect_uri=... // after POST /oidc/pushAuthRequest?... -> request_uri GET /oidc/authorize?client_id=client&request_uri=urn:ietf:params:oauth:request_uri:xyz
Defensive patterns
Strategy: validation
Validate before calling
if (requirePar && !params.get('request_uri')) {
throw new Error('PAR enabled: call the pushed authorization endpoint first and pass request_uri');
} Type guard
function isParAuthorizeUrl(url, requirePar) {
return !requirePar || new URL(url).searchParams.has('request_uri');
} Prevention
- Enable PAR in the RP client library when the CAS flag is on
- Do the PAR POST and cache the returned request_uri
- Disable the flag if legacy GET-based authorize must keep working
- Verify discovery metadata flags consumed by the RP
When it happens
Trigger: A browser navigation (GET) to /oidc/authorize whose URL ends with 'authorize' and whose parameter map lacks a non-blank request_uri, while requirePushedAuthorizationRequests=true.
Common situations: Same misconfiguration as error 530: PAR enforcement turned on but clients still doing classic front-channel redirects; forgot that even POST-based authorize without request_uri is rejected; discovery metadata not consumed by the RP.
Related errors
- CAS is configured to only accept pushed authorization…
- Invalid OIDC pushed authorization request at
- Resource-set owner does not match the authenticated profile
- JWKS cannot contain expressions
- Unable to use 'none' as introspection signing algorithm
AI-assisted analysis of apereo/cas@e7288fc434 (2026-09-08).
Data as JSON: /api/errors/361fc20027e90bee.
Report an issue: GitHub.
Appendix: source
Thrown at support/cas-server-support-oidc-core-api/src/main/java/org/apereo/cas/oidc/web/controllers/authorize/OidcAuthorizeEndpointController.java:51
}
@GetMapping({
'/' + OidcConstants.BASE_OIDC_URL + '/' + OAuth20Constants.AUTHORIZE_URL,
"/**/" + OidcConstants.AUTHORIZE_URL
})
@Operation(summary = "Handle OIDC authorization request")
@Override
public ModelAndView handleRequest(final HttpServletRequest request, final HttpServletResponse response) throws Throwable {
val webContext = new JEEContext(request, response);
if (!getConfigurationContext().getIssuerService().validateIssuer(webContext, List.of(OidcConstants.AUTHORIZE_URL, OAuth20Constants.AUTHORIZE_URL))) {
LOGGER.warn("CAS cannot accept the authorization request given the issuer is invalid.");
return OAuth20Utils.writeError(response, OAuth20Constants.INVALID_REQUEST, "Invalid issuer");
}
if (getConfigurationContext().getDiscoverySettings().isRequirePushedAuthorizationRequests()
&& webContext.getRequestURL().endsWith(OidcConstants.AUTHORIZE_URL)
&& StringUtils.isBlank(request.getParameter(OidcConstants.REQUEST_URI))) {
LOGGER.warn("CAS is configured to only accept pushed authorization requests");
return OAuth20Utils.produceUnauthorizedErrorView(HttpStatus.FORBIDDEN);
}
val scopes = getConfigurationContext().getRequestParameterResolver().resolveRequestedScopes(webContext);
if (scopes.isEmpty() || !scopes.contains(OidcConstants.StandardScopes.OPENID.getScope())) {
LOGGER.warn("Provided scopes [{}] are undefined by OpenID Connect, which requires that scope [{}] MUST be specified, "
+ "or the behavior is unspecified. CAS MAY allow this request to be processed for now.",
scopes, OidcConstants.StandardScopes.OPENID.getScope());
}
return super.handleRequest(request, response);
}
@PostMapping({
'/' + OidcConstants.BASE_OIDC_URL + '/' + OAuth20Constants.AUTHORIZE_URL,
"/**/" + OidcConstants.AUTHORIZE_URL
})
@Override
@Operation(summary = "Handle OIDC authorization request")View on GitHub (pinned to e7288fc434)