wuyouzhuguli/SpringAll · error · UnapprovedClientAuthenticationException

clientId:{clientId}对应的信息不存在

Error message

clientId:{clientId}对应的信息不存在

What it means

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.

Source

Thrown at 64.Spring-Security-OAuth2-Customize/src/main/java/cc/mrbird/security/handler/MyAuthenticationSucessHandler.java:53

    public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException {
        // 1. 从请求头中获取 ClientId
        String header = request.getHeader("Authorization");
        if (header == null || !header.startsWith("Basic ")) {
            throw new UnapprovedClientAuthenticationException("请求头中无client信息");
        }

        String[] tokens = this.extractAndDecodeHeader(header, request);
        String clientId = tokens[0];
        String clientSecret = tokens[1];

        TokenRequest tokenRequest = null;

        // 2. 通过 ClientDetailsService 获取 ClientDetails
        ClientDetails clientDetails = clientDetailsService.loadClientByClientId(clientId);

        // 3. 校验 ClientId和 ClientSecret的正确性
        if (clientDetails == null) {
            throw new UnapprovedClientAuthenticationException("clientId:" + clientId + "对应的信息不存在");
        } else if (!StringUtils.equals(clientDetails.getClientSecret(), clientSecret)) {
            throw new UnapprovedClientAuthenticationException("clientSecret不正确");
        } else {
            // 4. 通过 TokenRequest构造器生成 TokenRequest
            tokenRequest = new TokenRequest(new HashMap<>(), clientId, clientDetails.getScope(), "custom");
        }

        // 5. 通过 TokenRequest的 createOAuth2Request方法获取 OAuth2Request
        OAuth2Request oAuth2Request = tokenRequest.createOAuth2Request(clientDetails);
        // 6. 通过 Authentication和 OAuth2Request构造出 OAuth2Authentication
        OAuth2Authentication auth2Authentication = new OAuth2Authentication(oAuth2Request, authentication);

        // 7. 通过 AuthorizationServerTokenServices 生成 OAuth2AccessToken
        OAuth2AccessToken token = authorizationServerTokenServices.createAccessToken(auth2Authentication);

        // 8. 返回 Token
        log.info("登录成功");
        response.setContentType("application/json;charset=UTF-8");

View on GitHub (pinned to 614d2578d9)

Solutions

  1. Verify the clientId exists in the client store — for JDBC, SELECT * FROM oauth_client_details WHERE client_id = ?.
  2. Match the Basic header's clientId exactly to a registered client (mind trailing spaces from base64 decode).
  3. Confirm the ClientDetailsService bean your success handler autowires is the same one Spring Security OAuth2 configures (JDBC vs in-memory).
  4. Seed the client via the configured client store or add it in AuthorizationServerConfigurerAdapter.

Example fix

-- add the missing client (JDBC store)
INSERT INTO oauth_client_details
  (client_id, client_secret, scope, authorized_grant_types, web_server_redirect_uri, authorities, access_token_validity, refresh_token_validity, additional_information, autoapprove)
VALUES
  ('my-client', '{noop}my-secret', 'all', 'password,refresh_token', null, null, 3600, 2592000, null, true);
Defensive patterns

Strategy: validation

Validate before calling

// Validate client id format/whitelist before sending (basic guard).
const KNOWN_CLIENTS = new Set(['web','mobile']);
if (!KNOWN_CLIENTS.has(clientId)) { throw new Error('unknown clientId'); }

Try / catch

try { await login(); }
catch (e) {
  if (/对应的信息不存在/.test(e.message)) { /* check oauth_client_details, fix clientId */ }
  else handleError(e);
}

Prevention

When it happens

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

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

Related errors


AI-assisted analysis of wuyouzhuguli/SpringAll@614d2578d9 (2026-08-14). Data as JSON: /api/errors/2523543394727485. Report an issue: GitHub.