소스 검색

Add ClientRegistration's RestClient failed attempts information to exception message

Closes gh-16860

Signed-off-by: Evgeniy Cheban <mister.cheban@gmail.com>
Evgeniy Cheban 4 달 전
부모
커밋
0e84f31a00

+ 8 - 1
oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/registration/ClientRegistrations.java

@@ -1,5 +1,5 @@
 /*
- * Copyright 2002-2021 the original author or authors.
+ * Copyright 2002-2025 the original author or authors.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -17,6 +17,7 @@
 package org.springframework.security.oauth2.client.registration;
 
 import java.net.URI;
+import java.util.ArrayList;
 import java.util.Collections;
 import java.util.LinkedHashMap;
 import java.util.List;
@@ -49,6 +50,7 @@ import org.springframework.web.util.UriComponentsBuilder;
  * @author Rob Winch
  * @author Josh Cummings
  * @author Rafiullah Hamedy
+ * @author Evgeniy Cheban
  * @since 5.1
  */
 public final class ClientRegistrations {
@@ -211,6 +213,7 @@ public final class ClientRegistrations {
 	private static ClientRegistration.Builder getBuilder(String issuer,
 			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();
@@ -219,6 +222,7 @@ public final class ClientRegistrations {
 				if (!ex.getStatusCode().is4xxClientError()) {
 					throw ex;
 				}
+				errors.add(ex.getMessage());
 				// else try another endpoint
 			}
 			catch (IllegalArgumentException | IllegalStateException ex) {
@@ -228,6 +232,9 @@ public final class ClientRegistrations {
 				throw new IllegalArgumentException(errorMessage, ex);
 			}
 		}
+		if (!errors.isEmpty()) {
+			throw new IllegalArgumentException(errorMessage + ", errors: " + errors);
+		}
 		throw new IllegalArgumentException(errorMessage);
 	}
 

+ 28 - 1
oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/registration/ClientRegistrationsTests.java

@@ -1,5 +1,5 @@
 /*
- * Copyright 2002-2021 the original author or authors.
+ * Copyright 2002-2025 the original author or authors.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -36,12 +36,14 @@ import org.springframework.security.oauth2.core.AuthorizationGrantType;
 import org.springframework.security.oauth2.core.ClientAuthenticationMethod;
 
 import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
 import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException;
 import static org.assertj.core.api.Assertions.assertThatIllegalStateException;
 
 /**
  * @author Rob Winch
  * @author Rafiullah Hamedy
+ * @author Evgeniy Cheban
  * @since 5.1
  */
 public class ClientRegistrationsTests {
@@ -455,6 +457,31 @@ public class ClientRegistrationsTests {
 		// @formatter:on
 	}
 
+	@Test
+	public void issuerWhenAllEndpointsFailedThenExceptionIncludesFailureInformation() {
+		this.issuer = createIssuerFromServer("issuer1");
+		this.server.setDispatcher(new Dispatcher() {
+			@Override
+			public MockResponse dispatch(RecordedRequest request) {
+				int responseCode = switch (request.getPath()) {
+					case "/issuer1/.well-known/openid-configuration" -> 405;
+					case "/.well-known/openid-configuration/issuer1" -> 400;
+					default -> 404;
+				};
+				return new MockResponse().setResponseCode(responseCode);
+			}
+		});
+		String message = """
+				Unable to resolve Configuration with the provided Issuer of "%s", errors: [\
+				405 Client Error: [no body], \
+				400 Client Error: [no body], \
+				404 Client Error: [no body]]\
+				""".formatted(this.issuer);
+		assertThatExceptionOfType(IllegalArgumentException.class)
+			.isThrownBy(() -> ClientRegistrations.fromIssuerLocation(this.issuer).build())
+			.withMessage(message);
+	}
+
 	private ClientRegistration.Builder registration(String path) throws Exception {
 		this.issuer = createIssuerFromServer(path);
 		this.response.put("issuer", this.issuer);