Bladeren bron

Validate Scopes in ClientRegistrationBuilder

Fixes: gh-6256
Josh Cummings 6 jaren geleden
bovenliggende
commit
1bfa38b1bd

+ 30 - 7
oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/registration/ClientRegistration.java

@@ -15,13 +15,6 @@
  */
 package org.springframework.security.oauth2.client.registration;
 
-import org.springframework.security.core.SpringSecurityCoreVersion;
-import org.springframework.security.oauth2.core.AuthenticationMethod;
-import org.springframework.security.oauth2.core.AuthorizationGrantType;
-import org.springframework.security.oauth2.core.ClientAuthenticationMethod;
-import org.springframework.util.Assert;
-import org.springframework.util.StringUtils;
-
 import java.io.Serializable;
 import java.util.Arrays;
 import java.util.Collection;
@@ -31,6 +24,13 @@ import java.util.LinkedHashSet;
 import java.util.Map;
 import java.util.Set;
 
+import org.springframework.security.core.SpringSecurityCoreVersion;
+import org.springframework.security.oauth2.core.AuthenticationMethod;
+import org.springframework.security.oauth2.core.AuthorizationGrantType;
+import org.springframework.security.oauth2.core.ClientAuthenticationMethod;
+import org.springframework.util.Assert;
+import org.springframework.util.StringUtils;
+
 /**
  * A representation of a client registration with an OAuth 2.0 or OpenID Connect 1.0 Provider.
  *
@@ -489,6 +489,7 @@ public final class ClientRegistration implements Serializable {
 			} else {
 				this.validateAuthorizationCodeGrantType();
 			}
+			this.validateScopes();
 			return this.create();
 		}
 
@@ -545,5 +546,27 @@ public final class ClientRegistration implements Serializable {
 			Assert.hasText(this.clientId, "clientId cannot be empty");
 			Assert.hasText(this.tokenUri, "tokenUri cannot be empty");
 		}
+
+		private void validateScopes() {
+			if (this.scopes == null) {
+				return;
+			}
+
+			for (String scope : this.scopes) {
+				Assert.isTrue(validateScope(scope), "scope \"" + scope + "\" contains invalid characters");
+			}
+		}
+
+		private static boolean validateScope(String scope) {
+			return scope == null ||
+					scope.chars().allMatch(c ->
+							withinTheRangeOf(c, 0x21, 0x21) ||
+							withinTheRangeOf(c, 0x23, 0x5B) ||
+							withinTheRangeOf(c, 0x5D, 0x7E));
+		}
+
+		private static boolean withinTheRangeOf(int c, int min, int max) {
+			return c >= min && c <= max;
+		}
 	}
 }

+ 19 - 0
oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/registration/ClientRegistrationTests.java

@@ -535,4 +535,23 @@ public class ClientRegistrationTests {
 						.build()
 		).isInstanceOf(IllegalArgumentException.class);
 	}
+
+	// gh-6256
+	@Test
+	public void buildWhenScopesContainASpaceThenThrowIllegalArgumentException() {
+		assertThatThrownBy(() ->
+				TestClientRegistrations.clientCredentials()
+						.scope("openid profile email")
+						.build()
+		).isInstanceOf(IllegalArgumentException.class);
+	}
+
+	@Test
+	public void buildWhenScopesContainAnInvalidCharacterThenThrowIllegalArgumentException() {
+		assertThatThrownBy(() ->
+				TestClientRegistrations.clientCredentials()
+						.scope("an\"invalid\"scope")
+						.build()
+		).isInstanceOf(IllegalArgumentException.class);
+	}
 }