{"record":{"id":"2523543394727485","repo":"wuyouzhuguli/SpringAll","slug":"clientid-clientid","errorCode":null,"errorMessage":"clientId:{clientId}对应的信息不存在","messagePattern":"clientId:(.+?)对应的信息不存在","errorType":"exception","errorClass":"UnapprovedClientAuthenticationException","httpStatus":null,"severity":"error","filePath":"64.Spring-Security-OAuth2-Customize/src/main/java/cc/mrbird/security/handler/MyAuthenticationSucessHandler.java","lineNumber":53,"sourceCode":"    public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException {\n        // 1. 从请求头中获取 ClientId\n        String header = request.getHeader(\"Authorization\");\n        if (header == null || !header.startsWith(\"Basic \")) {\n            throw new UnapprovedClientAuthenticationException(\"请求头中无client信息\");\n        }\n\n        String[] tokens = this.extractAndDecodeHeader(header, request);\n        String clientId = tokens[0];\n        String clientSecret = tokens[1];\n\n        TokenRequest tokenRequest = null;\n\n        // 2. 通过 ClientDetailsService 获取 ClientDetails\n        ClientDetails clientDetails = clientDetailsService.loadClientByClientId(clientId);\n\n        // 3. 校验 ClientId和 ClientSecret的正确性\n        if (clientDetails == null) {\n            throw new UnapprovedClientAuthenticationException(\"clientId:\" + clientId + \"对应的信息不存在\");\n        } else if (!StringUtils.equals(clientDetails.getClientSecret(), clientSecret)) {\n            throw new UnapprovedClientAuthenticationException(\"clientSecret不正确\");\n        } else {\n            // 4. 通过 TokenRequest构造器生成 TokenRequest\n            tokenRequest = new TokenRequest(new HashMap<>(), clientId, clientDetails.getScope(), \"custom\");\n        }\n\n        // 5. 通过 TokenRequest的 createOAuth2Request方法获取 OAuth2Request\n        OAuth2Request oAuth2Request = tokenRequest.createOAuth2Request(clientDetails);\n        // 6. 通过 Authentication和 OAuth2Request构造出 OAuth2Authentication\n        OAuth2Authentication auth2Authentication = new OAuth2Authentication(oAuth2Request, authentication);\n\n        // 7. 通过 AuthorizationServerTokenServices 生成 OAuth2AccessToken\n        OAuth2AccessToken token = authorizationServerTokenServices.createAccessToken(auth2Authentication);\n\n        // 8. 返回 Token\n        log.info(\"登录成功\");\n        response.setContentType(\"application/json;charset=UTF-8\");","sourceCodeStart":35,"sourceCodeEnd":71,"githubUrl":"https://github.com/wuyouzhuguli/SpringAll/blob/614d2578d9495acf53cc02f2dee9c6131cc5e51a/64.Spring-Security-OAuth2-Customize/src/main/java/cc/mrbird/security/handler/MyAuthenticationSucessHandler.java#L35-L71","documentation":"UnapprovedClientAuthenticationException thrown when clientDetailsService.loadClientByClientId(clientId) returns null. The clientId came from decoding the Basic Authorization header. Note the message uses string concatenation (\"clientId:\" + clientId + ...) not a placeholder, so the literal '{clientId}' in the template is not templating — the actual clientId is interpolated.","triggerScenarios":"The clientId in the Basic header does not exist in the ClientDetailsService backing store (often the oauth_client_details table for JDBC, or an in-memory client registry); the client was deleted; a typo in the client id.","commonSituations":"Using a JDBC ClientDetailsService but the row was never inserted; configured clients in-memory while the app wires a JDBC details service (or vice versa); copied sample credentials that do not match this deployment.","solutions":["Verify the clientId exists in the client store — for JDBC, SELECT * FROM oauth_client_details WHERE client_id = ?.","Match the Basic header's clientId exactly to a registered client (mind trailing spaces from base64 decode).","Confirm the ClientDetailsService bean your success handler autowires is the same one Spring Security OAuth2 configures (JDBC vs in-memory).","Seed the client via the configured client store or add it in AuthorizationServerConfigurerAdapter."],"exampleFix":"-- add the missing client (JDBC store)\nINSERT INTO oauth_client_details\n  (client_id, client_secret, scope, authorized_grant_types, web_server_redirect_uri, authorities, access_token_validity, refresh_token_validity, additional_information, autoapprove)\nVALUES\n  ('my-client', '{noop}my-secret', 'all', 'password,refresh_token', null, null, 3600, 2592000, null, true);","handlingStrategy":"validation","validationCode":"// Validate client id format/whitelist before sending (basic guard).\nconst KNOWN_CLIENTS = new Set(['web','mobile']);\nif (!KNOWN_CLIENTS.has(clientId)) { throw new Error('unknown clientId'); }","typeGuard":null,"tryCatchPattern":"try { await login(); }\ncatch (e) {\n  if (/对应的信息不存在/.test(e.message)) { /* check oauth_client_details, fix clientId */ }\n  else handleError(e);\n}","preventionTips":["Seed oauth_client_details with every client your apps use.","Keep the ClientDetailsService bean consistent (JDBC vs in-memory) across config.","Trim decoded clientId to avoid whitespace mismatches."],"tags":["oauth2","client","configuration","spring-security"],"backgroundTag":null,"analyzedSha":"614d2578d9495acf53cc02f2dee9c6131cc5e51a","analyzedAt":"2026-08-14T04:40:03.488Z","schemaVersion":2},"datasetVersion":"2026-08-14T05:17:29.042Z"}