{"record":{"id":"e9c893f54b40f6be","repo":"spring-projects/spring-security","slug":"invalid-request-e9c893","errorCode":"invalid_request","errorMessage":"OpenID Connect 1.0 Logout Request Parameter: client_id","messagePattern":"OpenID Connect 1\\.0 Logout Request Parameter: client_id","errorType":"error_code","errorClass":"OAuth2AuthenticationException","httpStatus":400,"severity":"error","filePath":"oauth2/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/oidc/authentication/OidcLogoutAuthenticationProvider.java","lineNumber":134,"sourceCode":"\n\t\tRegisteredClient registeredClient = this.registeredClientRepository\n\t\t\t.findById(authorization.getRegisteredClientId());\n\t\tAssert.notNull(registeredClient, \"registeredClient cannot be null\");\n\n\t\tif (this.logger.isTraceEnabled()) {\n\t\t\tthis.logger.trace(\"Retrieved registered client\");\n\t\t}\n\n\t\tOidcIdToken idToken = authorizedIdToken.getToken();\n\n\t\t// Validate client identity\n\t\tList<String> audClaim = idToken.getAudience();\n\t\tif (CollectionUtils.isEmpty(audClaim) || !audClaim.contains(registeredClient.getClientId())) {\n\t\t\tthrow createException(OAuth2ErrorCodes.INVALID_TOKEN, IdTokenClaimNames.AUD);\n\t\t}\n\t\tif (StringUtils.hasText(oidcLogoutAuthentication.getClientId())\n\t\t\t\t&& !oidcLogoutAuthentication.getClientId().equals(registeredClient.getClientId())) {\n\t\t\tthrow createException(OAuth2ErrorCodes.INVALID_REQUEST, OAuth2ParameterNames.CLIENT_ID);\n\t\t}\n\n\t\tOidcLogoutAuthenticationContext context = OidcLogoutAuthenticationContext.with(oidcLogoutAuthentication)\n\t\t\t.registeredClient(registeredClient)\n\t\t\t.build();\n\t\tthis.authenticationValidator.accept(context);\n\n\t\tif (this.logger.isTraceEnabled()) {\n\t\t\tthis.logger.trace(\"Validated logout request parameters\");\n\t\t}\n\n\t\t// Validate user identity\n\t\tif (oidcLogoutAuthentication.isPrincipalAuthenticated()) {\n\t\t\tAuthentication currentUserPrincipal = (Authentication) oidcLogoutAuthentication.getPrincipal();\n\t\t\tAuthentication authorizedUserPrincipal = authorization.getAttribute(Principal.class.getName());\n\t\t\tAssert.notNull(authorizedUserPrincipal, \"authorizedUserPrincipal cannot be null\");\n\t\t\tif (!StringUtils.hasText(idToken.getSubject())\n\t\t\t\t\t|| !currentUserPrincipal.getName().equals(authorizedUserPrincipal.getName())) {","sourceCodeStart":116,"sourceCodeEnd":152,"githubUrl":"https://github.com/spring-projects/spring-security/blob/96852e8860138a482cb13d1479573f24ff6443c6/oauth2/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/oidc/authentication/OidcLogoutAuthenticationProvider.java#L116-L152","documentation":"When the logout request includes an explicit client_id parameter, OidcLogoutAuthenticationProvider requires it to match the clientId of the registered client that owns the ID token's authorization. A mismatch throws invalid_request naming client_id — the request parameters are internally inconsistent.","triggerScenarios":"Posting to the OIDC logout endpoint with id_token_hint from client A but client_id parameter set to client B (any non-empty client_id that differs from the token's registered client).","commonSituations":"Hardcoded client_id in the logout template not matching the currently logged-in client; multi-client apps sending the wrong app's client_id; copy-paste of logout URLs between environments where client ids differ.","solutions":["Make the client_id in the logout request match the client the id_token_hint was issued to","Dynamically render client_id from the current client's registration instead of hardcoding it","Omit client_id if the application cannot guarantee the correct value (the token alone identifies the client)"],"exampleFix":"// before\n<a href=\"/oauth2/logout?id_token_hint=${idToken}&client_id=old-client-id\">Log out</a>\n// after\n<a href=\"/oauth2/logout?id_token_hint=${idToken}&client_id=${clientId}\">Log out</a>","handlingStrategy":"validation","validationCode":"if (clientId != null && !clientId.equals(clientIdOfIdTokenHint)) {\n    throw new IllegalArgumentException(\"client_id does not match id_token_hint issuer client\");\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Render client_id dynamically from the current client registration, never hardcode it","Keep logout URLs per-environment generated rather than copy-pasted","Omit client_id when unsure — the id_token_hint already identifies the client"],"tags":["oauth2","oidc","logout","client-id"],"backgroundTag":"invalid-argument-value","analyzedSha":"96852e8860138a482cb13d1479573f24ff6443c6","analyzedAt":"2026-09-10T23:25:23.477Z","contentChangedAt":"2026-09-10T23:25:23.477Z","schemaVersion":2},"datasetVersion":"2026-09-14T16:17:12.679Z"}