{"record":{"id":"d1256843bded1547","repo":"apereo/cas","slug":"missing-access-token","errorCode":"missing_access_token","errorMessage":"Access token cannot be found in the request","messagePattern":"Access token cannot be found in the request","errorType":"error_code","errorClass":null,"httpStatus":400,"severity":"warning","filePath":"support/cas-server-support-oauth-core-api/src/main/java/org/apereo/cas/support/oauth/web/endpoints/OAuth20IntrospectionEndpointController.java","lineNumber":168,"sourceCode":"        return null;\n    }\n\n    protected Optional<Credentials> extractCredentials(final JEEContext context) {\n        val authExtractor = new BasicAuthExtractor();\n        val callContext = new CallContext(context, getConfigurationContext().getSessionStore(),\n            getConfigurationContext().getOauthConfig().getProfileManagerFactory());\n        return authExtractor.extract(callContext);\n    }\n\n\n    private Optional<ResponseEntity<? extends @NonNull BaseOAuth20IntrospectionAccessTokenResponse>> validateIntrospectionRequest(\n        final OAuthRegisteredService registeredService, final UsernamePasswordCredentials credentials,\n        final HttpServletRequest request) throws Throwable {\n        val tokenExists = HttpRequestUtils.doesParameterExist(request, OAuth20Constants.TOKEN)\n            || HttpRequestUtils.doesParameterExist(request, OAuth20Constants.ACCESS_TOKEN);\n\n        if (!tokenExists) {\n            LOGGER.warn(\"Access token cannot be found in the request\");\n            return Optional.of(buildBadRequestResponseEntity(OAuth20Constants.MISSING_ACCESS_TOKEN));\n        }\n\n        if (getConfigurationContext().getClientSecretValidator().validate(registeredService, credentials.getPassword())) {\n            val service = getConfigurationContext().getWebApplicationServiceServiceFactory().createService(registeredService.getServiceId());\n            val audit = AuditableContext.builder()\n                .service(service)\n                .registeredService(registeredService)\n                .build();\n            val accessResult = getConfigurationContext().getRegisteredServiceAccessStrategyEnforcer().execute(audit);\n            return accessResult.isExecutionFailure()\n                ? Optional.of(buildUnauthorizedResponseEntity(OAuth20Constants.UNAUTHORIZED_CLIENT, false))\n                : Optional.empty();\n        }\n        LOGGER.warn(\"Unable to match client secret for registered service [{}] with client id [{}]\",\n            registeredService.getName(), registeredService.getClientId());\n        return Optional.of(buildUnauthorizedResponseEntity(OAuth20Constants.INVALID_CLIENT, true));\n    }","sourceCodeStart":150,"sourceCodeEnd":186,"githubUrl":"https://github.com/apereo/cas/blob/e7288fc434b4f4505b8452e1a57e8fb3111bb863/support/cas-server-support-oauth-core-api/src/main/java/org/apereo/cas/support/oauth/web/endpoints/OAuth20IntrospectionEndpointController.java#L150-L186","documentation":"The introspection request passed client authentication checks but did not include the access token to introspect. CAS requires either a 'token' or 'access_token' request parameter; when neither is present it returns a 400 with error 'missing_access_token' (OAuth 2.0 Token Introspection RFC 7662 requires the token parameter).","triggerScenarios":"POSTing to /oauth2.0/introspect with valid client credentials but no 'token' (or 'access_token') form parameter, or sending the token in a header/JSON body where CAS does not look for it.","commonSituations":"Client SDK sends token under a custom field name; token put in the Authorization: Bearer header instead of a form parameter; truncation of the request body; developer assuming GET-style query params are checked when doing a POST without form encoding.","solutions":["Include the token as a form parameter: token=<access-token> in the introspection POST body","Alternatively use the access_token parameter name","Send the request as application/x-www-form-urlencoded so parameters are parsed","Do not rely on the Authorization: Bearer header to carry the token to introspect"],"exampleFix":"// before\ncurl -u myClient:mySecret -X POST https://cas.example.org/cas/oauth2.0/introspect\n// after\ncurl -u myClient:mySecret -X POST https://cas.example.org/cas/oauth2.0/introspect -d 'token=AT-xxxx'","handlingStrategy":"validation","validationCode":"function validateIntrospectionParams(params) {\n  if (!params.token && !params.access_token) {\n    throw new Error('introspection requires a token or access_token parameter');\n  }\n  const body = new URLSearchParams(params);\n  return body;\n}","typeGuard":"function hasToken(params) {\n  return params instanceof URLSearchParams && (params.has('token') || params.has('access_token'));\n}","tryCatchPattern":"try {\n  await introspect(params);\n} catch (e) {\n  if (e.response?.status === 400 && e.response.data?.error === 'missing_access_token') {\n    // add token parameter and retry once\n  }\n}","preventionTips":["Always pass the token as a form parameter named 'token'","Do not send the token in the Authorization: Bearer header for introspection","Use URLSearchParams / form encoding, not JSON body","Check parameter names against RFC 7662"],"tags":["oauth2","rfc7662","missing-parameter","introspection"],"backgroundTag":"missing-required-argument","analyzedSha":"e7288fc434b4f4505b8452e1a57e8fb3111bb863","analyzedAt":"2026-09-08T15:39:16.015Z","contentChangedAt":"2026-09-08T15:39:16.015Z","schemaVersion":2},"datasetVersion":"2026-09-15T23:17:13.987Z"}