Browse Source

Make OAuth2AuthenticationContext an interface

Closes gh-890
Joe Grandja 2 năm trước cách đây
mục cha
commit
1db05991af

+ 6 - 49
oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/authentication/OAuth2AuthenticationContext.java

@@ -15,54 +15,24 @@
  */
 package org.springframework.security.oauth2.server.authorization.authentication;
 
-import java.util.Collections;
 import java.util.HashMap;
 import java.util.Map;
 import java.util.function.Consumer;
 
-import org.springframework.lang.Nullable;
+import org.springframework.security.authentication.AuthenticationProvider;
 import org.springframework.security.core.Authentication;
 import org.springframework.security.oauth2.server.authorization.context.Context;
 import org.springframework.util.Assert;
-import org.springframework.util.CollectionUtils;
 
 /**
- * A context that holds an {@link Authentication} and (optionally) additional information.
+ * A context that holds an {@link Authentication} and (optionally) additional information
+ * and is used in an {@link AuthenticationProvider}.
  *
  * @author Joe Grandja
  * @since 0.2.0
  * @see Context
  */
-public class OAuth2AuthenticationContext implements Context {
-	private final Map<Object, Object> context;
-
-	/**
-	 * Constructs an {@code OAuth2AuthenticationContext} using the provided parameters.
-	 *
-	 * @param authentication the {@code Authentication}
-	 * @param context a {@code Map} of additional context information
-	 */
-	public OAuth2AuthenticationContext(Authentication authentication, @Nullable Map<Object, Object> context) {
-		Assert.notNull(authentication, "authentication cannot be null");
-		Map<Object, Object> ctx = new HashMap<>();
-		if (!CollectionUtils.isEmpty(context)) {
-			ctx.putAll(context);
-		}
-		ctx.put(Authentication.class, authentication);
-		this.context = Collections.unmodifiableMap(ctx);
-	}
-
-	/**
-	 * Constructs an {@code OAuth2AuthenticationContext} using the provided parameters.
-	 *
-	 * @param context a {@code Map} of context information, must contain the {@code Authentication}
-	 * @since 0.2.1
-	 */
-	public OAuth2AuthenticationContext(Map<Object, Object> context) {
-		Assert.notEmpty(context, "context cannot be empty");
-		Assert.notNull(context.get(Authentication.class), "authentication cannot be null");
-		this.context = Collections.unmodifiableMap(new HashMap<>(context));
-	}
+public interface OAuth2AuthenticationContext extends Context {
 
 	/**
 	 * Returns the {@link Authentication} associated to the context.
@@ -71,23 +41,10 @@ public class OAuth2AuthenticationContext implements Context {
 	 * @return the {@link Authentication}
 	 */
 	@SuppressWarnings("unchecked")
-	public <T extends Authentication> T getAuthentication() {
+	default <T extends Authentication> T getAuthentication() {
 		return (T) get(Authentication.class);
 	}
 
-	@SuppressWarnings("unchecked")
-	@Nullable
-	@Override
-	public <V> V get(Object key) {
-		return hasKey(key) ? (V) this.context.get(key) : null;
-	}
-
-	@Override
-	public boolean hasKey(Object key) {
-		Assert.notNull(key, "key cannot be null");
-		return this.context.containsKey(key);
-	}
-
 	/**
 	 * A builder for subclasses of {@link OAuth2AuthenticationContext}.
 	 *
@@ -95,7 +52,7 @@ public class OAuth2AuthenticationContext implements Context {
 	 * @param <B> the type of the builder
 	 * @since 0.2.1
 	 */
-	protected static abstract class AbstractBuilder<T extends OAuth2AuthenticationContext, B extends AbstractBuilder<T, B>> {
+	abstract class AbstractBuilder<T extends OAuth2AuthenticationContext, B extends AbstractBuilder<T, B>> {
 		private final Map<Object, Object> context = new HashMap<>();
 
 		protected AbstractBuilder(Authentication authentication) {

+ 105 - 0
oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/authentication/OAuth2AuthorizationCodeRequestAuthenticationContext.java

@@ -0,0 +1,105 @@
+/*
+ * Copyright 2020-2022 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.
+ * You may obtain a copy of the License at
+ *
+ *      https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.springframework.security.oauth2.server.authorization.authentication;
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.springframework.lang.Nullable;
+import org.springframework.security.oauth2.server.authorization.client.RegisteredClient;
+import org.springframework.util.Assert;
+
+/**
+ * An {@link OAuth2AuthenticationContext} that holds an {@link OAuth2AuthorizationCodeRequestAuthenticationToken} and additional information
+ * and is used when validating the OAuth 2.0 Authorization Request used in the Authorization Code Grant.
+ *
+ * @author Joe Grandja
+ * @since 0.4.0
+ * @see OAuth2AuthenticationContext
+ * @see OAuth2AuthorizationCodeRequestAuthenticationProvider
+ */
+public final class OAuth2AuthorizationCodeRequestAuthenticationContext implements OAuth2AuthenticationContext {
+	private final Map<Object, Object> context;
+
+	private OAuth2AuthorizationCodeRequestAuthenticationContext(Map<Object, Object> context) {
+		this.context = Collections.unmodifiableMap(new HashMap<>(context));
+	}
+
+	@SuppressWarnings("unchecked")
+	@Nullable
+	@Override
+	public <V> V get(Object key) {
+		return hasKey(key) ? (V) this.context.get(key) : null;
+	}
+
+	@Override
+	public boolean hasKey(Object key) {
+		Assert.notNull(key, "key cannot be null");
+		return this.context.containsKey(key);
+	}
+
+	/**
+	 * Returns the {@link RegisteredClient registered client}.
+	 *
+	 * @return the {@link RegisteredClient}
+	 */
+	public RegisteredClient getRegisteredClient() {
+		return get(RegisteredClient.class);
+	}
+
+	/**
+	 * Constructs a new {@link Builder} with the provided {@link OAuth2AuthorizationCodeRequestAuthenticationToken}.
+	 *
+	 * @param authentication the {@link OAuth2AuthorizationCodeRequestAuthenticationToken}
+	 * @return the {@link Builder}
+	 */
+	public static Builder with(OAuth2AuthorizationCodeRequestAuthenticationToken authentication) {
+		return new Builder(authentication);
+	}
+
+	/**
+	 * A builder for {@link OAuth2AuthorizationCodeRequestAuthenticationContext}.
+	 */
+	public static final class Builder extends AbstractBuilder<OAuth2AuthorizationCodeRequestAuthenticationContext, Builder> {
+
+		private Builder(OAuth2AuthorizationCodeRequestAuthenticationToken authentication) {
+			super(authentication);
+		}
+
+		/**
+		 * Sets the {@link RegisteredClient registered client}.
+		 *
+		 * @param registeredClient the {@link RegisteredClient}
+		 * @return the {@link Builder} for further configuration
+		 */
+		public Builder registeredClient(RegisteredClient registeredClient) {
+			return put(RegisteredClient.class, registeredClient);
+		}
+
+		/**
+		 * Builds a new {@link OAuth2AuthorizationCodeRequestAuthenticationContext}.
+		 *
+		 * @return the {@link OAuth2AuthorizationCodeRequestAuthenticationContext}
+		 */
+		public OAuth2AuthorizationCodeRequestAuthenticationContext build() {
+			Assert.notNull(get(RegisteredClient.class), "registeredClient cannot be null");
+			return new OAuth2AuthorizationCodeRequestAuthenticationContext(getContext());
+		}
+
+	}
+
+}

+ 4 - 4
oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/authentication/OAuth2AuthorizationCodeRequestAuthenticationProvider.java

@@ -186,10 +186,10 @@ public final class OAuth2AuthorizationCodeRequestAuthenticationProvider implemen
 					authorizationCodeRequestAuthentication, null);
 		}
 
-		Map<Object, Object> context = new HashMap<>();
-		context.put(RegisteredClient.class, registeredClient);
-		OAuth2AuthenticationContext authenticationContext = new OAuth2AuthenticationContext(
-				authorizationCodeRequestAuthentication, context);
+		OAuth2AuthenticationContext authenticationContext =
+				OAuth2AuthorizationCodeRequestAuthenticationContext.with(authorizationCodeRequestAuthentication)
+						.registeredClient(registeredClient)
+						.build();
 
 		OAuth2AuthenticationValidator redirectUriValidator = resolveAuthenticationValidator(OAuth2ParameterNames.REDIRECT_URI);
 		redirectUriValidator.validate(authenticationContext);

+ 21 - 2
oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/authentication/OAuth2AuthorizationConsentAuthenticationContext.java

@@ -15,8 +15,12 @@
  */
 package org.springframework.security.oauth2.server.authorization.authentication;
 
+import java.util.Collections;
+import java.util.HashMap;
 import java.util.Map;
+import java.util.function.Consumer;
 
+import org.springframework.lang.Nullable;
 import org.springframework.security.oauth2.core.endpoint.OAuth2AuthorizationRequest;
 import org.springframework.security.oauth2.server.authorization.OAuth2Authorization;
 import org.springframework.security.oauth2.server.authorization.OAuth2AuthorizationConsent;
@@ -32,11 +36,26 @@ import org.springframework.util.Assert;
  * @since 0.2.1
  * @see OAuth2AuthenticationContext
  * @see OAuth2AuthorizationConsent
+ * @see OAuth2AuthorizationCodeRequestAuthenticationProvider#setAuthorizationConsentCustomizer(Consumer)
  */
-public final class OAuth2AuthorizationConsentAuthenticationContext extends OAuth2AuthenticationContext {
+public final class OAuth2AuthorizationConsentAuthenticationContext implements OAuth2AuthenticationContext {
+	private final Map<Object, Object> context;
 
 	private OAuth2AuthorizationConsentAuthenticationContext(Map<Object, Object> context) {
-		super(context);
+		this.context = Collections.unmodifiableMap(new HashMap<>(context));
+	}
+
+	@SuppressWarnings("unchecked")
+	@Nullable
+	@Override
+	public <V> V get(Object key) {
+		return hasKey(key) ? (V) this.context.get(key) : null;
+	}
+
+	@Override
+	public boolean hasKey(Object key) {
+		Assert.notNull(key, "key cannot be null");
+		return this.context.containsKey(key);
 	}
 
 	/**

+ 20 - 2
oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/oidc/authentication/OidcUserInfoAuthenticationContext.java

@@ -15,9 +15,12 @@
  */
 package org.springframework.security.oauth2.server.authorization.oidc.authentication;
 
+import java.util.Collections;
+import java.util.HashMap;
 import java.util.Map;
 import java.util.function.Function;
 
+import org.springframework.lang.Nullable;
 import org.springframework.security.oauth2.core.OAuth2AccessToken;
 import org.springframework.security.oauth2.core.oidc.OidcUserInfo;
 import org.springframework.security.oauth2.server.authorization.OAuth2Authorization;
@@ -31,12 +34,27 @@ import org.springframework.util.Assert;
  * @author Joe Grandja
  * @since 0.2.1
  * @see OAuth2AuthenticationContext
+ * @see OidcUserInfo
  * @see OidcUserInfoAuthenticationProvider#setUserInfoMapper(Function)
  */
-public final class OidcUserInfoAuthenticationContext extends OAuth2AuthenticationContext {
+public final class OidcUserInfoAuthenticationContext implements OAuth2AuthenticationContext {
+	private final Map<Object, Object> context;
 
 	private OidcUserInfoAuthenticationContext(Map<Object, Object> context) {
-		super(context);
+		this.context = Collections.unmodifiableMap(new HashMap<>(context));
+	}
+
+	@SuppressWarnings("unchecked")
+	@Nullable
+	@Override
+	public <V> V get(Object key) {
+		return hasKey(key) ? (V) this.context.get(key) : null;
+	}
+
+	@Override
+	public boolean hasKey(Object key) {
+		Assert.notNull(key, "key cannot be null");
+		return this.context.containsKey(key);
 	}
 
 	/**