paascloud/paascloud-master · error · UnapprovedClientAuthenticationException

clientSecret不匹配:

Error message

clientSecret不匹配:

What it means

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.

Solutions

  1. Regenerate the Authorization header using the exact current clientId:clientSecret stored in uac_oauth_client_details
  2. Check whether stored secrets are encrypted (PasswordEncoder) and that comparison logic matches the storage scheme
  3. Trim whitespace/newlines from the secret in config and when base64-encoding
  4. Sync frontend client credentials with the environment's DB (dev/prod secrets differ)

Example fix

// before
String basic = clientId + ":" + oldSecret;
// after
String basic = clientId + ":" + currentSecretFromConfig.trim();
String header = "Basic " + Base64.getEncoder().encodeToString(basic.getBytes(StandardCharsets.UTF_8));
Defensive patterns

Strategy: validation

Validate before calling

String expected = jdbc.queryForObject("SELECT client_secret FROM uac_oauth_client_details WHERE client_id=?", String.class, clientId);
if (!Objects.equals(expected, mySecret.trim())) { /* refresh credentials before calling login */ }

Try / catch

try { return authClient.login(user, pwd); } catch (UnapprovedClientAuthenticationException e) { if (e.getMessage().contains("clientSecret不匹配")) { refreshClientCredentials(); } throw e; }

Prevention

When it happens

Trigger: 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).

Common situations: 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.

Related errors


AI-assisted analysis of paascloud/paascloud-master@781281a950 (2026-09-10). Data as JSON: /api/errors/176a63fa1513f8b1. Report an issue: GitHub.

Appendix: source

Thrown at paascloud-provider/paascloud-provider-uac/src/main/java/com/paascloud/provider/security/PcAuthenticationSuccessHandler.java:70

		String header = request.getHeader(HttpHeaders.AUTHORIZATION);

		if (header == null || !header.startsWith(BEARER_TOKEN_TYPE)) {
			throw new UnapprovedClientAuthenticationException("请求头中无client信息");
		}

		String[] tokens = RequestUtil.extractAndDecodeHeader(header);
		assert tokens.length == 2;

		String clientId = tokens[0];
		String clientSecret = tokens[1];

		ClientDetails clientDetails = clientDetailsService.loadClientByClientId(clientId);

		if (clientDetails == null) {
			throw new UnapprovedClientAuthenticationException("clientId对应的配置信息不存在:" + clientId);
		} else if (!StringUtils.equals(clientDetails.getClientSecret(), clientSecret)) {
			throw new UnapprovedClientAuthenticationException("clientSecret不匹配:" + clientId);
		}

		TokenRequest tokenRequest = new TokenRequest(MapUtils.EMPTY_MAP, clientId, clientDetails.getScope(), "custom");

		OAuth2Request oAuth2Request = tokenRequest.createOAuth2Request(clientDetails);

		OAuth2Authentication oAuth2Authentication = new OAuth2Authentication(oAuth2Request, authentication);

		OAuth2AccessToken token = authorizationServerTokenServices.createAccessToken(oAuth2Authentication);
		SecurityUser principal = (SecurityUser) authentication.getPrincipal();
		uacUserService.handlerLoginData(token, principal, request);

		log.info("用户【 {} 】记录登录日志", principal.getUsername());

		response.setContentType("application/json;charset=UTF-8");
		response.getWriter().write((objectMapper.writeValueAsString(WrapMapper.ok(token))));

	}

View on GitHub (pinned to 781281a950)