spring-projects/spring-security · error · InvalidClientRegistrationIdException

Invalid Client Registration with Id: ${registrationId}

Error message

Invalid Client Registration with Id: ${registrationId}

What it means

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.

Source

Thrown at oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/web/DefaultOAuth2AuthorizationRequestResolver.java:170

		this.authorizationRequestCustomizer = authorizationRequestCustomizer;
	}

	private String getAction(HttpServletRequest request, String defaultAction) {
		String action = request.getParameter("action");
		if (action == null) {
			return defaultAction;
		}
		return action;
	}

	private @Nullable OAuth2AuthorizationRequest resolve(HttpServletRequest request, String registrationId,
			String redirectUriAction) {
		if (registrationId == null) {
			return null;
		}
		ClientRegistration clientRegistration = this.clientRegistrationRepository.findByRegistrationId(registrationId);
		if (clientRegistration == null) {
			throw new InvalidClientRegistrationIdException("Invalid Client Registration with Id: " + registrationId);
		}
		OAuth2AuthorizationRequest.Builder builder = getBuilder(clientRegistration);

		String redirectUriStr = expandRedirectUri(request, clientRegistration, redirectUriAction);

		String authorizationUri = clientRegistration.getProviderDetails().getAuthorizationUri();
		Assert.hasText(authorizationUri, "Authorization URI is required");
		// @formatter:off
		builder.clientId(clientRegistration.getClientId())
				.authorizationUri(authorizationUri)
				.redirectUri(redirectUriStr)
				.scopes(clientRegistration.getScopes())
				.state(DEFAULT_STATE_GENERATOR.generateKey());
		// @formatter:on

		this.authorizationRequestCustomizer.accept(builder);

		return builder.build();

View on GitHub (pinned to 96852e8860)

Solutions

  1. 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.
  2. Log/inspect registrationId at the resolver or add a custom OAuth2AuthorizationRequestResolver to validate ids against your tenant store before delegating.
  3. If registrations are dynamic/multi-tenant, implement a ClientRegistrationRepository (e.g. JdbcClientRegistrationRepository or custom findByRegistrationId) that resolves tenant ids at runtime.
  4. Return a friendly 404/redirect for unknown registration ids by catching InvalidClientRegistrationIdException in an AuthenticationFailureHandler or error controller instead of an unhandled 500.

Example fix

// before
<a href="/oauth2/authorization/google">Login</a>
// config: spring.security.oauth2.client.registration.google-idp.client-id=...

// after
<a href="/oauth2/authorization/google-idp">Login</a>
// registrationId in URL must exactly match a configured registration
Defensive patterns

Strategy: validation

Validate before calling

String registrationId = "google-idp";
ClientRegistration reg = clientRegistrationRepository.findByRegistrationId(registrationId);
if (reg == null) {
    throw new IllegalStateException("No ClientRegistration for id " + registrationId
        + "; configured ids must match links like /oauth2/authorization/<id>");
}

Try / catch

try {
    OAuth2AuthorizationRequest req = resolver.resolve(request);
} catch (InvalidClientRegistrationIdException ex) {
    // log the attempted id and redirect the user to a friendly error page (404)
    response.sendRedirect("/login?error=unknown_provider");
}

Prevention

When it happens

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

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

Understand the failure class

Background: Record Not Found Errors: "not found", RecordNotFound, and "was not found" — what they mean and how to fix them — this error's family across 28 libraries.

Related errors


AI-assisted analysis of spring-projects/spring-security@96852e8860 (2026-09-10). Data as JSON: /api/errors/f1e1bb163b179ae7. Report an issue: GitHub.