{"record":{"id":"639bf2ac94f64d13","repo":"justauth/JustAuth","slug":"5008-639bf2","errorCode":"5008","errorMessage":"Illegal code","messagePattern":"Illegal code","errorType":"validation","errorClass":"AuthException","httpStatus":null,"severity":"error","filePath":"src/main/java/me/zhyd/oauth/utils/AuthChecker.java","lineNumber":87,"sourceCode":"     * 校验回调传回的code\n     * <p>\n     * {@code v1.10.0}版本中改为传入{@code source}和{@code callback}，对于不同平台使用不同参数接受code的情况统一做处理\n     *\n     * @param source   当前授权平台\n     * @param callback 从第三方授权回调回来时传入的参数集合\n     * @since 1.8.0\n     */\n    public static void checkCode(AuthSource source, AuthCallback callback) {\n        // 推特平台不支持回调 code 和 state\n        if (source == AuthDefaultSource.TWITTER) {\n            return;\n        }\n        String code = callback.getCode();\n        if (StringUtils.isEmpty(code) && source == AuthDefaultSource.HUAWEI) {\n            code = callback.getAuthorization_code();\n        }\n        if (StringUtils.isEmpty(code)) {\n            throw new AuthException(AuthResponseStatus.ILLEGAL_CODE, source);\n        }\n    }\n\n    /**\n     * 校验回调传回的{@code state}，为空或者不存在\n     * <p>\n     * {@code state}不存在的情况只有两种：\n     * 1. {@code state}已使用，被正常清除\n     * 2. {@code state}为前端伪造，本身就不存在\n     *\n     * @param state          {@code state}一定不为空\n     * @param source         {@code source}当前授权平台\n     * @param authStateCache {@code authStateCache} state缓存实现\n     */\n    public static void checkState(String state, AuthSource source, AuthStateCache authStateCache) {\n        // 推特平台不支持回调 code 和 state\n        if (source == AuthDefaultSource.TWITTER) {\n            return;","sourceCodeStart":69,"sourceCodeEnd":105,"githubUrl":"https://github.com/justauth/JustAuth/blob/694bbf1b010d93404e3bfb4824d90e9ddfaebebb/src/main/java/me/zhyd/oauth/utils/AuthChecker.java#L69-L105","documentation":"Thrown by AuthChecker.checkCode when processing the provider callback: the code that the platform is supposed to return in the callback request is absent. JustAuth reads callback.getCode() (falling back to getAuthorization_code() for Huawei) and refuses to continue without it, since code is the credential exchanged for a token. Code 5008 (ILLEGAL_CODE). Twitter is exempt because its flow passes a token+oauthVerifier instead of code.","triggerScenarios":"Calling request.getAccessToken(AuthCallback) where the callback object was built from a request missing the code parameter: user clicked 'deny/cancel' on the consent page, the controller mapped /callback but did not bind the code query param (e.g. missing @RequestParam or wrong param name), or for Huawei the code arrived under 'authorization_code' and both getters are empty.","commonSituations":"Users cancelling the authorization dialog and being redirected back without code (often with error=access_denied instead); Spring/Servlet controllers that read the wrong parameter name or swallow query params; reverse proxies or gateways stripping query strings on the callback route; provider returning oauth_verifier (Twitter-style) to a non-Twitter request; Huawei integrations where the callback param is named authorization_code.","solutions":["Inspect the raw callback URL/query string in your controller and log all params — if the user denied access, surface a friendly 'authorization cancelled' message instead of proceeding.","Make sure the AuthCallback passed in actually carries the code: for Huawei also populate authorization_code; for Twitter pass oauthToken/oauthVerifier (or use its dedicated callback handling).","Verify the redirectUri registered with the provider matches the endpoint that receives code — a mismatch often causes the provider to redirect to an error path without code.","Check proxies/filters are not consuming or rewriting the query string before your handler."],"exampleFix":"// before\n@GetMapping('/oauth/callback/huawei')\npublic Object callback(AuthCallback callback) {\n    return new AuthHuaweiRequest(config, cache).getAccessToken(callback);\n}\n\n// after\n@GetMapping('/oauth/callback/huawei')\npublic Object callback(AuthCallback callback) {\n    if (StringUtils.isEmpty(callback.getCode())\n            && StringUtils.isEmpty(callback.getAuthorization_code())) {\n        return \"authorization was cancelled or invalid\"; // user denied / param lost\n    }\n    return new AuthHuaweiRequest(config, cache).getAccessToken(callback);\n}","handlingStrategy":"validation","validationCode":"String code = callback.getCode();\nif (StringUtils.isEmpty(code) && source == AuthDefaultSource.HUAWEI) code = callback.getAuthorization_code();\nif (StringUtils.isEmpty(code)) {\n    // user denied, or param lost — do NOT call getAccessToken\n    return redirect(\"/login?error=cancelled\");\n}","typeGuard":null,"tryCatchPattern":"catch (AuthException e) { if (e.getErrorCode() == AuthResponseStatus.ILLEGAL_CODE.getCode()) { /* treat as user-cancelled / broken callback binding */ } }","preventionTips":["Log the full callback query string (minus secrets) before invoking the SDK.","Bind callback params explicitly in controllers instead of relying on loose binding.","Handle the provider's 'denied' redirect (error=access_denied) as a first-class route."],"tags":["java","justauth","oauth","callback","authorization-code"],"backgroundTag":null,"analyzedSha":"694bbf1b010d93404e3bfb4824d90e9ddfaebebb","analyzedAt":"2026-08-14T15:16:59.945Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}