spring-projects/spring-security · error · IllegalArgumentException

Unable to resolve Configuration with the provided Issuer of

Error message

Unable to resolve Configuration with the provided Issuer of "${issuer}"

What it means

ClientRegistrations.getBuilder fetches the OpenID/OAuth2 discovery document (.well-known/openid-configuration and .well-known/oauth-authorization-server) for the issuer and builds a registration from it. When no endpoint responds with a parseable configuration and no per-endpoint errors were collected, it throws this IllegalArgumentException with the issuer in the message.

Solutions

  1. Verify the issuer URL in a browser/curl: https://issuer/.well-known/openid-configuration should return JSON with authorization_endpoint, token_endpoint, jwks_uri.
  2. Fix network/TLS reachability (VPN, proxy, truststore) for the discovery host.
  3. If the provider has no discovery endpoint, construct the ClientRegistration manually with explicit endpoints instead of ClientRegistrations.fromIssuerLocation.
  4. Check for issuer path issues: discovery is fetched at issuer + '/.well-known/openid-configuration'; trailing slashes or path segments can break the lookup.

Example fix

// before
ClientRegistration reg = ClientRegistrations.fromOidcIssuerLocation("https://idp.internal"); // unreachable
// after
ClientRegistration.withRegistrationId("idp")
    .authorizationUri("https://idp.internal/authorize")
    .tokenUri("https://idp.internal/token")
    .jwkSetUri("https://idp.internal/jwks")
    .userInfoUri("https://idp.internal/userinfo")
    .build();
Defensive patterns

Strategy: validation

Validate before calling

// before calling ClientRegistrations, verify discovery is reachable
RestTemplate rest = new RestTemplate();
String meta = rest.getForEntity("https://issuer/.well-known/openid-configuration", String.class).getBody();
if (meta == null || !meta.trim().startsWith("{")) throw new IllegalStateException("issuer has no discovery metadata");

Try / catch

try { ClientRegistrations.fromIssuerLocation(issuer); } catch (IllegalArgumentException e) { if (e.getMessage().startsWith("Unable to resolve Configuration")) { /* use manual registration */ } throw e; }

Prevention

When it happens

Trigger: fromOidcIssuerLocation(issuer) or fromIssuerLocation(issuer) where every discovery URL fails (404, connection failure, non-JSON body) but no structured errors list was populated, falling through to the final throw.

Common situations: Typo in the issuer URL; issuer behind a firewall/VPN not reachable at build time; provider does not publish discovery metadata; HTTPS certificate issues; non-JSON responses failing silently.

Understand the failure class

Background: 'Could not be found', 'does not exist', 'not found in database': the resource-not-found family when an ID, slug, key, or URI lookup comes back empty — this error's family across 20 libraries.

Related errors


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

Appendix: source

Thrown at oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/registration/ClientRegistrations.java:290

			Supplier<ClientRegistration.Builder>... suppliers) {
		String errorMessage = "Unable to resolve Configuration with the provided Issuer of \"" + issuer + "\"";
		List<String> errors = new ArrayList<>();
		for (Supplier<ClientRegistration.Builder> supplier : suppliers) {
			try {
				return supplier.get();
			}
			catch (HttpClientErrorException ex) {
				if (!ex.getStatusCode().is4xxClientError()) {
					throw ex;
				}
				errors.add(ex.getMessage());
				// else try another endpoint
			}
			catch (IllegalArgumentException | IllegalStateException ex) {
				throw ex;
			}
			catch (RuntimeException ex) {
				throw new IllegalArgumentException(errorMessage, ex);
			}
		}
		if (!errors.isEmpty()) {
			throw new IllegalArgumentException(errorMessage + ", errors: " + errors);
		}
		throw new IllegalArgumentException(errorMessage);
	}

	private static <T> T parseInput(Map<String, Object> body, ThrowingFunction<JSONObject, T, ParseException> parser) {
		try {
			return parse(body, parser);
		}
		catch (RuntimeException ex) {
			throw new IllegalArgumentException(ex);
		}
	}

	private static <T> T parse(Map<String, Object> body, ThrowingFunction<JSONObject, T, ParseException> parser) {

View on GitHub (pinned to 96852e8860)