apereo/cas · warning

Provided scopes [ ] are undefined by OpenID Connect, which…

Error message

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.

What it means

The OIDC specification requires that every authorization request include the 'openid' scope. CAS resolves the requested scopes and logs a warning if the scope set is empty or lacks 'openid'; it does not hard-fail (the spec says CAS MAY still process the request). This is a compliance warning, not a rejection.

Solutions

  1. Add 'openid' to the scope parameter of the authorization request
  2. Ensure the RP library defaults include the openid scope for OIDC flows
  3. Keep scope values space-delimited and URL-encoded properly (scope=openid%20profile)
  4. If purely OAuth2 (non-OIDC) usage is intended, use the plain /oauth2.0/authorize endpoint instead

Example fix

// before
GET /oidc/authorize?client_id=client&response_type=code&scope=profile&redirect_uri=...
// after
GET /oidc/authorize?client_id=client&response_type=code&scope=openid%20profile&redirect_uri=...
Defensive patterns

Strategy: validation

Validate before calling

const scopes = (params.get('scope') ?? '').split(' ').filter(Boolean);
if (!scopes.includes('openid')) throw new Error('OIDC authorization requests must include scope "openid"');

Type guard

function hasOpenIdScope(scopeStr) {
  return typeof scopeStr === 'string' && scopeStr.split(' ').includes('openid');
}

Prevention

When it happens

Trigger: Any authorization request (or PAR request reaching authorize) whose resolved scope list is empty or does not contain the 'openid' scope, e.g. scope=profile email or no scope at all.

Common situations: RP libraries defaulting to plain OAuth2 scope requests; developers testing with only 'profile'; clients copying OAuth2 examples that omit scope; PAR flows dropping the scope parameter.

Understand the failure class

Background: "missing required argument" and "the following required arguments were not provided": what required-argument errors mean and how to fix them — this error's family across 20 libraries.

Related errors


AI-assisted analysis of apereo/cas@e7288fc434 (2026-09-08). Data as JSON: /api/errors/41bbd288c09b87ed. 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:57

    @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")
    public ModelAndView handleRequestPost(final HttpServletRequest request,
                                          final HttpServletResponse response) throws Throwable {
        return handleRequest(request, response);
    }
}

View on GitHub (pinned to e7288fc434)