{"record":{"id":"4d815d7f91e03932","repo":"alibaba/nacos","slug":"token-is-empty","errorCode":null,"errorMessage":"Token is empty","messagePattern":"Token is empty","errorType":"exception","errorClass":"AccessException","httpStatus":null,"severity":"warning","filePath":"plugin-default-impl/nacos-oidc-auth-plugin/src/main/java/com/alibaba/nacos/plugin/auth/impl/oidc/token/JwtTokenValidator.java","lineNumber":89,"sourceCode":"        JWSAlgorithm.RS256, JWSAlgorithm.RS384, JWSAlgorithm.RS512,\n        JWSAlgorithm.ES256, JWSAlgorithm.ES384, JWSAlgorithm.ES512,\n        JWSAlgorithm.PS256, JWSAlgorithm.PS384, JWSAlgorithm.PS512));\n    \n    public JwtTokenValidator(OidcAuthPluginConfig config, JwksProvider jwksProvider) {\n        this.config = config;\n        this.jwksProvider = jwksProvider;\n    }\n    \n    /**\n     * Validate a JWT token and return the claims.\n     *\n     * @param token JWT token string\n     * @return validated JWT claims\n     * @throws AccessException if validation fails\n     */\n    public JWTClaimsSet validate(String token) throws AccessException {\n        if (StringUtils.isBlank(token)) {\n            throw new AccessException(\"Token is empty\");\n        }\n        \n        try {\n            // Ensure processor is initialized (lazy init)\n            ConfigurableJWTProcessor<SecurityContext> processor = getJwtProcessor();\n            \n            // Process and validate the token (Parsing also happens inside process but we parse handled inside)\n            // Note: process(String) parses it.\n            JWTClaimsSet claims = processor.process(token, null);\n            \n            // Additional validation\n            validateClaims(claims);\n            \n            LOGGER.debug(\"Token validated successfully for subject: {}\", claims.getSubject());\n            return claims;\n            \n        } catch (ParseException e) {\n            LOGGER.warn(\"Failed to parse JWT token: {}\", e.getMessage());","sourceCodeStart":71,"sourceCodeEnd":107,"githubUrl":"https://github.com/alibaba/nacos/blob/9b989acdf181d00898f2e8839257bb2b2a3cefe3/plugin-default-impl/nacos-oidc-auth-plugin/src/main/java/com/alibaba/nacos/plugin/auth/impl/oidc/token/JwtTokenValidator.java#L71-L107","documentation":"Thrown by JwtTokenValidator.validate() when the token argument is null, empty, or whitespace. The validator refuses to process a missing credential before doing any signature or claims work, so this is a client-side precondition failure rather than a crypto failure.","triggerScenarios":"An API call reaches the OIDC auth plugin with no Bearer token: a missing or empty Authorization header, a header that contains only 'Bearer ' with no value, or code passing null/\"\" into JwtTokenValidator.validate(String).","commonSituations":"Frontend forgets to attach the access token after OIDC login; a reverse proxy strips the Authorization header; the client obtained an opaque/session cookie but sent it where a JWT is expected; integration tests call a protected endpoint without authenticating first.","solutions":["Ensure the client sends 'Authorization: Bearer <jwt>' on every protected request.","Confirm the token flow completed (OIDC authorization code / token exchange returned an access_token) before calling protected APIs.","Check that no proxy/load balancer strips the Authorization header.","If writing plugin code that calls validate() directly, guard the token source and surface a clear 401 instead of passing null.","Verify the token is being read from the correct request attribute/cookie if a gateway injects it."],"exampleFix":"// before\nString token = request.getHeader(\"Authorization\"); // \"Bearer \" with nothing after\nvalidator.validate(token);\n\n// after\nString raw = request.getHeader(\"Authorization\");\nString token = (raw != null && raw.startsWith(\"Bearer \")) ? raw.substring(7).trim() : null;\nif (StringUtils.isBlank(token)) {\n    throw new AccessException(\"Missing Bearer token\");\n}\nvalidator.validate(token);","handlingStrategy":"validation","validationCode":"import org.apache.commons.lang3.StringUtils;\n\nString raw = request.getHeader(\"Authorization\");\nString token = (raw != null && raw.startsWith(\"Bearer \")) ? raw.substring(7).trim() : null;\nif (StringUtils.isBlank(token)) {\n    // return 401 instead of calling validate()\n    throw new AccessException(\"Missing Bearer token\");\n}","typeGuard":null,"tryCatchPattern":"try {\n    JWTClaimsSet claims = validator.validate(token);\n} catch (AccessException e) {\n    if (\"Token is empty\".equals(e.getMessage())) {\n        // 401 missing credential\n    }\n    throw e;\n}","preventionTips":["Always require a Bearer token on protected endpoints before delegating to the validator.","Strip and trim the 'Bearer ' prefix consistently in one helper.","Return a clear 401 for missing tokens rather than letting the validator reject null."],"tags":["oidc","authentication","jwt","token","authorization-header"],"backgroundTag":null,"analyzedSha":"9b989acdf181d00898f2e8839257bb2b2a3cefe3","analyzedAt":"2026-08-14T07:17:31.569Z","schemaVersion":2},"datasetVersion":"2026-08-14T10:17:34.591Z"}