{"record":{"id":"ad719b52698e6c24","repo":"justauth/JustAuth","slug":"5015","errorCode":"5015","errorMessage":"Invalid client secret","messagePattern":"Invalid client secret","errorType":"exception","errorClass":"AuthException","httpStatus":null,"severity":"error","filePath":"src/main/java/me/zhyd/oauth/request/AuthAppleRequest.java","lineNumber":102,"sourceCode":"        // https://developer.apple.com/documentation/sign_in_with_apple/sign_in_with_apple_rest_api/authenticating_users_with_sign_in_with_apple#3383773\n        return AuthUser.builder()\n            .rawUserInfo(object)\n            .uuid(object.getString(\"sub\"))\n            .email(object.getString(\"email\"))\n            .username(authToken.getUsername())\n            .token(authToken)\n            .source(source.toString())\n            .build();\n    }\n\n    @Override\n    protected void checkConfig(AuthConfig config) {\n        super.checkConfig(config);\n        if (StringUtils.isEmpty(config.getClientId())) {\n            throw new AuthException(AuthResponseStatus.ILLEGAL_CLIENT_ID, source);\n        }\n        if (StringUtils.isEmpty(config.getClientSecret())) {\n            throw new AuthException(AuthResponseStatus.ILLEGAL_CLIENT_SECRET, source);\n        }\n        if (StringUtils.isEmpty(config.getKid())) {\n            throw new AuthException(AuthResponseStatus.ILLEGAL_KID, source);\n        }\n        if (StringUtils.isEmpty(config.getTeamId())) {\n            throw new AuthException(AuthResponseStatus.ILLEGAL_TEAM_ID, source);\n        }\n    }\n\n    /**\n     * 获取token\n     * @see <a href=\"https://developer.apple.com/documentation/accountorganizationaldatasharing/creating-a-client-secret\">creating-a-client-secret</a>\n     * @return jwt token\n     */\n    private String getToken() {\n        return Jwts.builder().header().add(AbstractJwk.KID.getId(), this.config.getKid()).and()\n            .issuer(this.config.getTeamId())\n            .subject(this.config.getClientId())","sourceCodeStart":84,"sourceCodeEnd":120,"githubUrl":"https://github.com/justauth/JustAuth/blob/694bbf1b010d93404e3bfb4824d90e9ddfaebebb/src/main/java/me/zhyd/oauth/request/AuthAppleRequest.java#L84-L120","documentation":"AuthException with AuthResponseStatus.ILLEGAL_CLIENT_SECRET (code 5015) from AuthAppleRequest.checkConfig: config.getClientSecret() is empty. For Apple this field must hold the .p8 private key content — JustAuth itself builds the JWT client secret from it in getToken().","triggerScenarios":"Constructing AuthAppleRequest without clientSecret, or with a path to the .p8 file instead of the file's PEM content.","commonSituations":"Developer put the file path or key id into clientSecret instead of the PEM body; the .p8 content loaded with escaped newlines (\\n literals) making it 'present' but unusable — here it must merely be non-empty, but empty values fail this check; secret managed via vault and not injected.","solutions":["Paste the full contents of the .p8 key (including BEGIN/END PRIVATE KEY lines) into clientSecret","If loading from a file/vault, read it into the string at startup before building AuthConfig","Do not confuse clientSecret (.p8 PEM) with kid (key identifier) or teamId"],"exampleFix":"// before\n.clientSecret(\"/etc/keys/AuthKey_ABC123.p8\")\n\n// after\nString pem = new String(Files.readAllBytes(Path.of(\"/etc/keys/AuthKey_ABC123.p8\")), UTF_8);\nAuthConfig.builder().clientSecret(pem)...","handlingStrategy":"validation","validationCode":"String pem = config.getClientSecret();\nif (StringUtils.isEmpty(pem) || !pem.contains(\"BEGIN PRIVATE KEY\")) {\n    throw new IllegalStateException(\"APPLE clientSecret must be the .p8 PEM content\");\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Store the .p8 PEM as a whole unit (base64 in env vars or multiline secrets)","Do not put file paths or key ids into clientSecret","Automate .p8 loading from your secret manager at startup"],"tags":["apple","config","validation","p8-key"],"backgroundTag":null,"analyzedSha":"694bbf1b010d93404e3bfb4824d90e9ddfaebebb","analyzedAt":"2026-08-14T15:16:59.945Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}