{"record":{"id":"176a63fa1513f8b1","repo":"paascloud/paascloud-master","slug":"clientsecret","errorCode":null,"errorMessage":"clientSecret不匹配:","messagePattern":"clientSecret不匹配:","errorType":"http","errorClass":"UnapprovedClientAuthenticationException","httpStatus":401,"severity":"error","filePath":"paascloud-provider/paascloud-provider-uac/src/main/java/com/paascloud/provider/security/PcAuthenticationSuccessHandler.java","lineNumber":70,"sourceCode":"\n\t\tString header = request.getHeader(HttpHeaders.AUTHORIZATION);\n\n\t\tif (header == null || !header.startsWith(BEARER_TOKEN_TYPE)) {\n\t\t\tthrow new UnapprovedClientAuthenticationException(\"请求头中无client信息\");\n\t\t}\n\n\t\tString[] tokens = RequestUtil.extractAndDecodeHeader(header);\n\t\tassert tokens.length == 2;\n\n\t\tString clientId = tokens[0];\n\t\tString clientSecret = tokens[1];\n\n\t\tClientDetails clientDetails = clientDetailsService.loadClientByClientId(clientId);\n\n\t\tif (clientDetails == null) {\n\t\t\tthrow new UnapprovedClientAuthenticationException(\"clientId对应的配置信息不存在:\" + clientId);\n\t\t} else if (!StringUtils.equals(clientDetails.getClientSecret(), clientSecret)) {\n\t\t\tthrow new UnapprovedClientAuthenticationException(\"clientSecret不匹配:\" + clientId);\n\t\t}\n\n\t\tTokenRequest tokenRequest = new TokenRequest(MapUtils.EMPTY_MAP, clientId, clientDetails.getScope(), \"custom\");\n\n\t\tOAuth2Request oAuth2Request = tokenRequest.createOAuth2Request(clientDetails);\n\n\t\tOAuth2Authentication oAuth2Authentication = new OAuth2Authentication(oAuth2Request, authentication);\n\n\t\tOAuth2AccessToken token = authorizationServerTokenServices.createAccessToken(oAuth2Authentication);\n\t\tSecurityUser principal = (SecurityUser) authentication.getPrincipal();\n\t\tuacUserService.handlerLoginData(token, principal, request);\n\n\t\tlog.info(\"用户【 {} 】记录登录日志\", principal.getUsername());\n\n\t\tresponse.setContentType(\"application/json;charset=UTF-8\");\n\t\tresponse.getWriter().write((objectMapper.writeValueAsString(WrapMapper.ok(token))));\n\n\t}","sourceCodeStart":52,"sourceCodeEnd":88,"githubUrl":"https://github.com/paascloud/paascloud-master/blob/781281a9503332ed3cef44ea618349d14230a127/paascloud-provider/paascloud-provider-uac/src/main/java/com/paascloud/provider/security/PcAuthenticationSuccessHandler.java#L52-L88","documentation":"Thrown by PcAuthenticationSuccessHandler.onAuthenticationSuccess when the stored ClientDetails secret does not equal the clientSecret decoded from the Authorization header. Message is \"clientSecret不匹配:\" plus the clientId, signaling a failed OAuth2 client credential check after successful form login.","triggerScenarios":"The base64 clientSecret in the Authorization header differs from the client_secret stored for that clientId in the client details store (plain comparison via StringUtils.equals, so encoding differences also trigger it).","commonSituations":"Client rotated its secret in the DB but the frontend still ships the old one; secret stored encrypted/BCrypt in DB while compared plainly (or vice versa); copy-paste with whitespace; different secret per environment.","solutions":["Regenerate the Authorization header using the exact current clientId:clientSecret stored in uac_oauth_client_details","Check whether stored secrets are encrypted (PasswordEncoder) and that comparison logic matches the storage scheme","Trim whitespace/newlines from the secret in config and when base64-encoding","Sync frontend client credentials with the environment's DB (dev/prod secrets differ)"],"exampleFix":"// before\nString basic = clientId + \":\" + oldSecret;\n// after\nString basic = clientId + \":\" + currentSecretFromConfig.trim();\nString header = \"Basic \" + Base64.getEncoder().encodeToString(basic.getBytes(StandardCharsets.UTF_8));","handlingStrategy":"validation","validationCode":"String expected = jdbc.queryForObject(\"SELECT client_secret FROM uac_oauth_client_details WHERE client_id=?\", String.class, clientId);\nif (!Objects.equals(expected, mySecret.trim())) { /* refresh credentials before calling login */ }","typeGuard":null,"tryCatchPattern":"try { return authClient.login(user, pwd); } catch (UnapprovedClientAuthenticationException e) { if (e.getMessage().contains(\"clientSecret不匹配\")) { refreshClientCredentials(); } throw e; }","preventionTips":["Rotate client secrets on both DB and client config in one coordinated change","Trim secrets and use a single encoding (UTF-8) when base64-encoding the header","Know whether secrets are stored encrypted/BCrypt and compare with the matching checker","Keep dev/prod client credentials in separate config files to avoid cross-env secrets"],"tags":["oauth2","client-secret","authentication","security"],"backgroundTag":"invalid-credentials","analyzedSha":"781281a9503332ed3cef44ea618349d14230a127","analyzedAt":"2026-09-10T10:59:02.070Z","contentChangedAt":"2026-09-10T10:59:02.070Z","schemaVersion":2},"datasetVersion":"2026-09-16T04:17:20.429Z"}