{"record":{"id":"f1e1bb163b179ae7","repo":"spring-projects/spring-security","slug":"invalid-client-registration-with-id-registratio","errorCode":null,"errorMessage":"Invalid Client Registration with Id: ${registrationId}","messagePattern":"Invalid Client Registration with Id: (.+?)","errorType":"exception","errorClass":"InvalidClientRegistrationIdException","httpStatus":null,"severity":"error","filePath":"oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/web/DefaultOAuth2AuthorizationRequestResolver.java","lineNumber":170,"sourceCode":"\t\tthis.authorizationRequestCustomizer = authorizationRequestCustomizer;\n\t}\n\n\tprivate String getAction(HttpServletRequest request, String defaultAction) {\n\t\tString action = request.getParameter(\"action\");\n\t\tif (action == null) {\n\t\t\treturn defaultAction;\n\t\t}\n\t\treturn action;\n\t}\n\n\tprivate @Nullable OAuth2AuthorizationRequest resolve(HttpServletRequest request, String registrationId,\n\t\t\tString redirectUriAction) {\n\t\tif (registrationId == null) {\n\t\t\treturn null;\n\t\t}\n\t\tClientRegistration clientRegistration = this.clientRegistrationRepository.findByRegistrationId(registrationId);\n\t\tif (clientRegistration == null) {\n\t\t\tthrow new InvalidClientRegistrationIdException(\"Invalid Client Registration with Id: \" + registrationId);\n\t\t}\n\t\tOAuth2AuthorizationRequest.Builder builder = getBuilder(clientRegistration);\n\n\t\tString redirectUriStr = expandRedirectUri(request, clientRegistration, redirectUriAction);\n\n\t\tString authorizationUri = clientRegistration.getProviderDetails().getAuthorizationUri();\n\t\tAssert.hasText(authorizationUri, \"Authorization URI is required\");\n\t\t// @formatter:off\n\t\tbuilder.clientId(clientRegistration.getClientId())\n\t\t\t\t.authorizationUri(authorizationUri)\n\t\t\t\t.redirectUri(redirectUriStr)\n\t\t\t\t.scopes(clientRegistration.getScopes())\n\t\t\t\t.state(DEFAULT_STATE_GENERATOR.generateKey());\n\t\t// @formatter:on\n\n\t\tthis.authorizationRequestCustomizer.accept(builder);\n\n\t\treturn builder.build();","sourceCodeStart":152,"sourceCodeEnd":188,"githubUrl":"https://github.com/spring-projects/spring-security/blob/96852e8860138a482cb13d1479573f24ff6443c6/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/web/DefaultOAuth2AuthorizationRequestResolver.java#L152-L188","documentation":"DefaultOAuth2AuthorizationRequestResolver.resolve looks up the ClientRegistration by the registrationId extracted from the request (e.g. /oauth2/authorization/{registrationId}) in the clientRegistrationRepository. When no registration exists for that id it throws InvalidClientRegistrationIdException with 'Invalid Client Registration with Id: <id>'. The library throws this to prevent building an authorization request against an unknown client registration.","triggerScenarios":"A request hits /oauth2/authorization/{id} or /login/oauth2/code/{id} with a registrationId that has no matching entry in the configured ClientRegistrationRepository (InMemoryClientRegistrationRepository or discovery-based repository).","commonSituations":"Typo in the login link's registration id (e.g. /oauth2/authorization/google vs configured 'google-idp'); registration removed/renamed in config while cached pages still link to the old id; multi-tenant dynamic registration not returning the requested id; case mismatch in the id.","solutions":["Compare the id in the failing URL with spring.security.oauth2.client.registration.* keys (or the registrations registered in the ClientRegistrationRepository) and fix the mismatch.","Log/inspect registrationId at the resolver or add a custom OAuth2AuthorizationRequestResolver to validate ids against your tenant store before delegating.","If registrations are dynamic/multi-tenant, implement a ClientRegistrationRepository (e.g. JdbcClientRegistrationRepository or custom findByRegistrationId) that resolves tenant ids at runtime.","Return a friendly 404/redirect for unknown registration ids by catching InvalidClientRegistrationIdException in an AuthenticationFailureHandler or error controller instead of an unhandled 500."],"exampleFix":"// before\n<a href=\"/oauth2/authorization/google\">Login</a>\n// config: spring.security.oauth2.client.registration.google-idp.client-id=...\n\n// after\n<a href=\"/oauth2/authorization/google-idp\">Login</a>\n// registrationId in URL must exactly match a configured registration","handlingStrategy":"validation","validationCode":"String registrationId = \"google-idp\";\nClientRegistration reg = clientRegistrationRepository.findByRegistrationId(registrationId);\nif (reg == null) {\n    throw new IllegalStateException(\"No ClientRegistration for id \" + registrationId\n        + \"; configured ids must match links like /oauth2/authorization/<id>\");\n}","typeGuard":null,"tryCatchPattern":"try {\n    OAuth2AuthorizationRequest req = resolver.resolve(request);\n} catch (InvalidClientRegistrationIdException ex) {\n    // log the attempted id and redirect the user to a friendly error page (404)\n    response.sendRedirect(\"/login?error=unknown_provider\");\n}","preventionTips":["Generate login links from configured registration ids, never hardcode them","Validate all login links in templates against current registration config in tests","Keep registration ids stable when refactoring provider config","For multi-tenant apps, resolve ids dynamically via a custom ClientRegistrationRepository"],"tags":["oauth2","client-registration","configuration","spring-security","authorization-request"],"backgroundTag":"record-not-found","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"}