{"record":{"id":"c4c945514c634e39","repo":"spring-projects/spring-security","slug":"invalid-client-c4c945","errorCode":"invalid_client","errorMessage":"Client authentication failed: client_id","messagePattern":"Client authentication failed: client_id","errorType":"error_code","errorClass":"OAuth2AuthenticationException","httpStatus":null,"severity":"error","filePath":"oauth2/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/authentication/PublicClientAuthenticationProvider.java","lineNumber":84,"sourceCode":"\t\t\tOAuth2AuthorizationService authorizationService) {\n\t\tAssert.notNull(registeredClientRepository, \"registeredClientRepository cannot be null\");\n\t\tAssert.notNull(authorizationService, \"authorizationService cannot be null\");\n\t\tthis.registeredClientRepository = registeredClientRepository;\n\t\tthis.codeVerifierAuthenticator = new CodeVerifierAuthenticator(authorizationService);\n\t}\n\n\t@Override\n\tpublic @Nullable Authentication authenticate(Authentication authentication) throws AuthenticationException {\n\t\tOAuth2ClientAuthenticationToken clientAuthentication = (OAuth2ClientAuthenticationToken) authentication;\n\n\t\tif (!ClientAuthenticationMethod.NONE.equals(clientAuthentication.getClientAuthenticationMethod())) {\n\t\t\treturn null;\n\t\t}\n\n\t\tString clientId = clientAuthentication.getPrincipal().toString();\n\t\tRegisteredClient registeredClient = this.registeredClientRepository.findByClientId(clientId);\n\t\tif (registeredClient == null) {\n\t\t\tthrow invalidClient(OAuth2ParameterNames.CLIENT_ID);\n\t\t}\n\n\t\tif (this.logger.isTraceEnabled()) {\n\t\t\tthis.logger.trace(\"Retrieved registered client\");\n\t\t}\n\n\t\tif (!registeredClient.getClientAuthenticationMethods()\n\t\t\t.contains(clientAuthentication.getClientAuthenticationMethod())) {\n\t\t\tthrow invalidClient(\"authentication_method\");\n\t\t}\n\n\t\tif (this.logger.isTraceEnabled()) {\n\t\t\tthis.logger.trace(\"Validated client authentication parameters\");\n\t\t}\n\n\t\t// Validate the \"code_verifier\" parameter for the public client\n\t\tthis.codeVerifierAuthenticator.authenticateRequired(clientAuthentication, registeredClient);\n","sourceCodeStart":66,"sourceCodeEnd":102,"githubUrl":"https://github.com/spring-projects/spring-security/blob/96852e8860138a482cb13d1479573f24ff6443c6/oauth2/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/authentication/PublicClientAuthenticationProvider.java#L66-L102","documentation":"PublicClientAuthenticationProvider.authenticate authenticates public OAuth2 clients (which send only client_id, no secret). It looks up the client_id via RegisteredClientRepository; if no RegisteredClient exists for that client_id, it throws an OAuth2AuthenticationException with error code invalid_client, message 'Client authentication failed: client_id'.","triggerScenarios":"A token request from a public client (e.g. PKCE authorization_code, refresh_token) whose clientAuthentication principal (client_id) is not found in the RegisteredClientRepository.","commonSituations":"Client deleted or renamed in the database while deployed apps still use the old id; typo in client_id; environment mismatch (client registered in prod but request hits staging); JdbcRegisteredClientRepository pointing at wrong schema/data.","solutions":["Verify the client_id sent by the client exactly matches a row in your RegisteredClientRepository.","Re-register the client or correct the client-side configuration to the right client_id.","Check the repository backend (JDBC/R2DBC/in-memory) is populated for the active environment/profile.","Enable trace logging on the provider and confirm which client_id value was received."],"exampleFix":"// before: request with unregistered client\n// POST /oauth2/token  client_id=my-public-app  (not registered)\n// after: register the client first\n// RegisteredClient.create().clientId(\"my-public-app\")\n//   .clientAuthenticationMethod(ClientAuthenticationMethod.NONE)\n//   .authorizationGrantType(AuthorizationGrantType.AUTHORIZATION_CODE)\n//   .clientSettings(ClientSettings.builder().requireAuthorizationConsent(true).build())\n//   .build();","handlingStrategy":"validation","validationCode":"RegisteredClient rc = registeredClientRepository.findByClientId(clientId);\nif (rc == null) { throw new IllegalStateException(\"client_id not registered: \" + clientId); }","typeGuard":null,"tryCatchPattern":"catch (OAuth2AuthenticationException e) { if (\"invalid_client\".equals(e.getError().getErrorCode())) { verifyClientRegistration(e); } }","preventionTips":["Keep client registrations in sync across environments","Validate client_id in client config at startup","Check repository data after migrations"],"tags":["oauth2","client-authentication","invalid-client","public-client"],"backgroundTag":"authentication-required","analyzedSha":"96852e8860138a482cb13d1479573f24ff6443c6","analyzedAt":"2026-09-10T23:25:23.477Z","contentChangedAt":"2026-09-10T23:25:23.477Z","schemaVersion":2},"datasetVersion":"2026-09-14T11:17:12.474Z"}