Browse Source

ClientRegistrations supports hostnames with underscores

Issue gh-15852
Josh Cummings 6 months ago
parent
commit
b6c813c5a2

+ 32 - 24
oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/registration/ClientRegistrations.java

@@ -17,7 +17,6 @@
 package org.springframework.security.oauth2.client.registration;
 
 import java.net.URI;
-import java.util.Collections;
 import java.util.LinkedHashMap;
 import java.util.List;
 import java.util.Map;
@@ -146,7 +145,7 @@ public final class ClientRegistrations {
 	 */
 	public static ClientRegistration.Builder fromOidcIssuerLocation(String issuer) {
 		Assert.hasText(issuer, "issuer cannot be empty");
-		return getBuilder(issuer, oidc(URI.create(issuer)));
+		return getBuilder(issuer, oidc(issuer));
 	}
 
 	/**
@@ -189,21 +188,17 @@ public final class ClientRegistrations {
 	 */
 	public static ClientRegistration.Builder fromIssuerLocation(String issuer) {
 		Assert.hasText(issuer, "issuer cannot be empty");
-		URI uri = URI.create(issuer);
-		return getBuilder(issuer, oidc(uri), oidcRfc8414(uri), oauth(uri));
+		return getBuilder(issuer, oidc(issuer), oidcRfc8414(issuer), oauth(issuer));
 	}
 
-	private static Supplier<ClientRegistration.Builder> oidc(URI issuer) {
-		// @formatter:off
-		URI uri = UriComponentsBuilder.fromUri(issuer)
-				.replacePath(issuer.getPath() + OIDC_METADATA_PATH)
-				.build(Collections.emptyMap());
+	static Supplier<ClientRegistration.Builder> oidc(String issuer) {
+		UriComponents uri = oidcUri(issuer);
 		// @formatter:on
 		return () -> {
-			RequestEntity<Void> request = RequestEntity.get(uri).build();
+			RequestEntity<Void> request = RequestEntity.get(uri.toUriString()).build();
 			Map<String, Object> configuration = rest.exchange(request, typeReference).getBody();
 			OIDCProviderMetadata metadata = parse(configuration, OIDCProviderMetadata::parse);
-			ClientRegistration.Builder builder = withProviderConfiguration(metadata, issuer.toASCIIString())
+			ClientRegistration.Builder builder = withProviderConfiguration(metadata, issuer)
 				.jwkSetUri(metadata.getJWKSetURI().toASCIIString());
 			if (metadata.getUserInfoEndpointURI() != null) {
 				builder.userInfoUri(metadata.getUserInfoEndpointURI().toASCIIString());
@@ -212,35 +207,48 @@ public final class ClientRegistrations {
 		};
 	}
 
-	private static Supplier<ClientRegistration.Builder> oidcRfc8414(String issuer) {
-		URI uri = oidcRfc8414Uri(issuer);
+	static UriComponents oidcUri(String issuer) {
+		UriComponents uri = UriComponentsBuilder.fromUriString(issuer).build();
+		// @formatter:off
+		return UriComponentsBuilder.newInstance().uriComponents(uri)
+				.replacePath(uri.getPath() + OIDC_METADATA_PATH)
+				.build();
+	}
+
+	static Supplier<ClientRegistration.Builder> oidcRfc8414(String issuer) {
+		UriComponents uri = oidcRfc8414Uri(issuer);
+		// @formatter:on
 		return getRfc8414Builder(issuer, uri);
 	}
 
-	static URI oidcRfc8414Uri(String issuer) {
+	static UriComponents oidcRfc8414Uri(String issuer) {
 		UriComponents uri = UriComponentsBuilder.fromUriString(issuer).build();
 		// @formatter:off
 		return UriComponentsBuilder.newInstance().uriComponents(uri)
 				.replacePath(OIDC_METADATA_PATH + uri.getPath())
-				.build(Collections.emptyMap());
-		// @formatter:on
+				.build();
+	}
+
+	static Supplier<ClientRegistration.Builder> oauth(String issuer) {
+		UriComponents uri = oauthUri(issuer);
+		return getRfc8414Builder(issuer, uri);
 	}
 
-	private static Supplier<ClientRegistration.Builder> oauth(URI issuer) {
+	static UriComponents oauthUri(String issuer) {
+		UriComponents uri = UriComponentsBuilder.fromUriString(issuer).build();
 		// @formatter:off
-		URI uri = UriComponentsBuilder.fromUri(issuer)
-				.replacePath(OAUTH_METADATA_PATH + issuer.getPath())
-				.build(Collections.emptyMap());
+		return UriComponentsBuilder.newInstance().uriComponents(uri)
+				.replacePath(OAUTH_METADATA_PATH + uri.getPath())
+				.build();
 		// @formatter:on
-		return getRfc8414Builder(issuer, uri);
 	}
 
-	private static Supplier<ClientRegistration.Builder> getRfc8414Builder(URI issuer, URI uri) {
+	private static Supplier<ClientRegistration.Builder> getRfc8414Builder(String issuer, UriComponents uri) {
 		return () -> {
-			RequestEntity<Void> request = RequestEntity.get(uri).build();
+			RequestEntity<Void> request = RequestEntity.get(uri.toUriString()).build();
 			Map<String, Object> configuration = rest.exchange(request, typeReference).getBody();
 			AuthorizationServerMetadata metadata = parse(configuration, AuthorizationServerMetadata::parse);
-			ClientRegistration.Builder builder = withProviderConfiguration(metadata, issuer.toASCIIString());
+			ClientRegistration.Builder builder = withProviderConfiguration(metadata, issuer);
 			URI jwkSetUri = metadata.getJWKSetURI();
 			if (jwkSetUri != null) {
 				builder.jwkSetUri(jwkSetUri.toASCIIString());

+ 12 - 0
oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/registration/ClientRegistrationsTests.java

@@ -34,6 +34,7 @@ import org.springframework.http.HttpHeaders;
 import org.springframework.http.MediaType;
 import org.springframework.security.oauth2.core.AuthorizationGrantType;
 import org.springframework.security.oauth2.core.ClientAuthenticationMethod;
+import org.springframework.web.util.UriComponents;
 
 import static org.assertj.core.api.Assertions.assertThat;
 import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException;
@@ -569,6 +570,17 @@ public class ClientRegistrationsTests {
 			.isEqualTo(ClientAuthenticationMethod.CLIENT_SECRET_BASIC);
 	}
 
+	// gh-15852
+	@Test
+	public void oidcWhenHostContainsUnderscoreThenRetains() {
+		UriComponents oidc = ClientRegistrations.oidcUri("https://elated_sutherland:8080/path");
+		assertThat(oidc.getHost()).isEqualTo("elated_sutherland");
+		UriComponents oauth = ClientRegistrations.oauthUri("https://elated_sutherland:8080/path");
+		assertThat(oauth.getHost()).isEqualTo("elated_sutherland");
+		UriComponents oidcRfc8414 = ClientRegistrations.oidcRfc8414Uri("https://elated_sutherland:8080/path");
+		assertThat(oidcRfc8414.getHost()).isEqualTo("elated_sutherland");
+	}
+
 	private ClientRegistration.Builder registration(String path) throws Exception {
 		this.issuer = createIssuerFromServer(path);
 		this.response.put("issuer", this.issuer);