浏览代码

Refactor OAuth2 AuthenticationProvider's

Fixes gh-4689
Joe Grandja 7 年之前
父节点
当前提交
049080290e

+ 27 - 34
config/src/main/java/org/springframework/security/config/annotation/web/configurers/oauth2/client/OAuth2LoginConfigurer.java

@@ -29,7 +29,6 @@ import org.springframework.security.oauth2.client.authentication.jwt.NimbusJwtDe
 import org.springframework.security.oauth2.client.authentication.userinfo.CustomUserTypesOAuth2UserService;
 import org.springframework.security.oauth2.client.authentication.userinfo.DefaultOAuth2UserService;
 import org.springframework.security.oauth2.client.authentication.userinfo.DelegatingOAuth2UserService;
-import org.springframework.security.oauth2.client.authentication.userinfo.OAuth2UserAuthenticationProvider;
 import org.springframework.security.oauth2.client.authentication.userinfo.OAuth2UserService;
 import org.springframework.security.oauth2.client.registration.ClientRegistration;
 import org.springframework.security.oauth2.client.registration.ClientRegistrationRepository;
@@ -42,7 +41,6 @@ import org.springframework.security.oauth2.core.AccessToken;
 import org.springframework.security.oauth2.core.endpoint.AuthorizationRequestUriBuilder;
 import org.springframework.security.oauth2.core.user.OAuth2User;
 import org.springframework.security.oauth2.oidc.client.authentication.OidcAuthorizationCodeAuthenticationProvider;
-import org.springframework.security.oauth2.oidc.client.authentication.userinfo.OidcUserAuthenticationProvider;
 import org.springframework.security.oauth2.oidc.client.authentication.userinfo.OidcUserService;
 import org.springframework.security.web.authentication.ui.DefaultLoginPageGeneratingFilter;
 import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
@@ -232,57 +230,52 @@ public final class OAuth2LoginConfigurer<B extends HttpSecurityBuilder<B>> exten
 			authorizationCodeTokenExchanger = new NimbusAuthorizationCodeTokenExchanger();
 		}
 
+		OAuth2UserService oauth2UserService = this.userInfoEndpointConfig.userService;
+		if (oauth2UserService == null) {
+			if (!this.userInfoEndpointConfig.customUserTypes.isEmpty()) {
+				List<OAuth2UserService> userServices = new ArrayList<>();
+				userServices.add(new CustomUserTypesOAuth2UserService(this.userInfoEndpointConfig.customUserTypes));
+				userServices.add(new DefaultOAuth2UserService());
+				oauth2UserService = new DelegatingOAuth2UserService(userServices);
+			} else {
+				oauth2UserService = new DefaultOAuth2UserService();
+			}
+		}
+
 		JwtDecoderRegistry jwtDecoderRegistry = this.tokenEndpointConfig.jwtDecoderRegistry;
 		if (jwtDecoderRegistry == null) {
 			jwtDecoderRegistry = new NimbusJwtDecoderRegistry();
 		}
 
 		AuthorizationCodeAuthenticationProvider oauth2AuthorizationCodeAuthenticationProvider =
-			new AuthorizationCodeAuthenticationProvider(authorizationCodeTokenExchanger);
+			new AuthorizationCodeAuthenticationProvider(authorizationCodeTokenExchanger, oauth2UserService);
 		if (this.tokenEndpointConfig.accessTokenRepository != null) {
 			oauth2AuthorizationCodeAuthenticationProvider.setAccessTokenRepository(
 				this.tokenEndpointConfig.accessTokenRepository);
 		}
+		if (this.userInfoEndpointConfig.userAuthoritiesMapper != null) {
+			oauth2AuthorizationCodeAuthenticationProvider.setAuthoritiesMapper(
+				this.userInfoEndpointConfig.userAuthoritiesMapper);
+		}
 		http.authenticationProvider(this.postProcess(oauth2AuthorizationCodeAuthenticationProvider));
 
+		OAuth2UserService oidcUserService = this.userInfoEndpointConfig.userService;
+		if (oidcUserService == null) {
+			oidcUserService = new OidcUserService();
+		}
+
 		OidcAuthorizationCodeAuthenticationProvider oidcAuthorizationCodeAuthenticationProvider =
-			new OidcAuthorizationCodeAuthenticationProvider(authorizationCodeTokenExchanger, jwtDecoderRegistry);
+			new OidcAuthorizationCodeAuthenticationProvider(
+				authorizationCodeTokenExchanger, oidcUserService, jwtDecoderRegistry);
 		if (this.tokenEndpointConfig.accessTokenRepository != null) {
 			oidcAuthorizationCodeAuthenticationProvider.setAccessTokenRepository(
 				this.tokenEndpointConfig.accessTokenRepository);
 		}
-		http.authenticationProvider(this.postProcess(oidcAuthorizationCodeAuthenticationProvider));
-
-		OAuth2UserService userService = this.userInfoEndpointConfig.userService;
-		if (userService == null) {
-			if (!this.userInfoEndpointConfig.customUserTypes.isEmpty()) {
-				List<OAuth2UserService> userServices = new ArrayList<>();
-				userServices.add(new CustomUserTypesOAuth2UserService(this.userInfoEndpointConfig.customUserTypes));
-				userServices.add(new DefaultOAuth2UserService());
-				userService = new DelegatingOAuth2UserService(userServices);
-			} else {
-				userService = new DefaultOAuth2UserService();
-			}
-		}
-
-		OAuth2UserAuthenticationProvider oauth2UserAuthenticationProvider =
-			new OAuth2UserAuthenticationProvider(userService);
 		if (this.userInfoEndpointConfig.userAuthoritiesMapper != null) {
-			oauth2UserAuthenticationProvider.setAuthoritiesMapper(this.userInfoEndpointConfig.userAuthoritiesMapper);
-		}
-		http.authenticationProvider(this.postProcess(oauth2UserAuthenticationProvider));
-
-		userService = this.userInfoEndpointConfig.userService;
-		if (userService == null) {
-			userService = new OidcUserService();
+			oidcAuthorizationCodeAuthenticationProvider.setAuthoritiesMapper(
+				this.userInfoEndpointConfig.userAuthoritiesMapper);
 		}
-
-		OidcUserAuthenticationProvider oidcUserAuthenticationProvider =
-			new OidcUserAuthenticationProvider(userService);
-		if (this.userInfoEndpointConfig.userAuthoritiesMapper != null) {
-			oidcUserAuthenticationProvider.setAuthoritiesMapper(this.userInfoEndpointConfig.userAuthoritiesMapper);
-		}
-		http.authenticationProvider(this.postProcess(oidcUserAuthenticationProvider));
+		http.authenticationProvider(this.postProcess(oidcAuthorizationCodeAuthenticationProvider));
 
 		this.initDefaultLoginFilter(http);
 	}

+ 36 - 3
oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/authentication/AuthorizationCodeAuthenticationProvider.java

@@ -18,6 +18,10 @@ package org.springframework.security.oauth2.client.authentication;
 import org.springframework.security.authentication.AuthenticationProvider;
 import org.springframework.security.core.Authentication;
 import org.springframework.security.core.AuthenticationException;
+import org.springframework.security.core.GrantedAuthority;
+import org.springframework.security.core.authority.mapping.GrantedAuthoritiesMapper;
+import org.springframework.security.oauth2.client.authentication.userinfo.OAuth2AuthenticationToken;
+import org.springframework.security.oauth2.client.authentication.userinfo.OAuth2UserService;
 import org.springframework.security.oauth2.client.token.InMemoryAccessTokenRepository;
 import org.springframework.security.oauth2.client.token.SecurityTokenRepository;
 import org.springframework.security.oauth2.core.AccessToken;
@@ -25,8 +29,11 @@ import org.springframework.security.oauth2.core.OAuth2Error;
 import org.springframework.security.oauth2.core.endpoint.AuthorizationRequest;
 import org.springframework.security.oauth2.core.endpoint.AuthorizationResponse;
 import org.springframework.security.oauth2.core.endpoint.TokenResponse;
+import org.springframework.security.oauth2.core.user.OAuth2User;
 import org.springframework.util.Assert;
 
+import java.util.Collection;
+
 /**
  * An implementation of an {@link AuthenticationProvider}
  * for the <i>OAuth 2.0 Authorization Code Grant Flow</i>.
@@ -34,12 +41,19 @@ import org.springframework.util.Assert;
  * This {@link AuthenticationProvider} is responsible for authenticating
  * an <i>authorization code</i> credential with the authorization server's <i>Token Endpoint</i>
  * and if valid, exchanging it for an <i>access token</i> credential.
+ * <p>
+ * It will also obtain the user attributes of the <i>End-User</i> (resource owner)
+ * from the <i>UserInfo Endpoint</i> using an {@link OAuth2UserService}
+ * which will create a <code>Principal</code> in the form of an {@link OAuth2User}.
  *
  * @author Joe Grandja
  * @since 5.0
  * @see AuthorizationCodeAuthenticationToken
- * @see OAuth2ClientAuthenticationToken
  * @see SecurityTokenRepository
+ * @see OAuth2AuthenticationToken
+ * @see OAuth2ClientAuthenticationToken
+ * @see OAuth2UserService
+ * @see OAuth2User
  * @see <a target="_blank" href="https://tools.ietf.org/html/rfc6749#section-4.1">Section 4.1 Authorization Code Grant Flow</a>
  * @see <a target="_blank" href="https://tools.ietf.org/html/rfc6749#section-4.1.3">Section 4.1.3 Access Token Request</a>
  * @see <a target="_blank" href="https://tools.ietf.org/html/rfc6749#section-4.1.4">Section 4.1.4 Access Token Response</a>
@@ -48,13 +62,18 @@ public class AuthorizationCodeAuthenticationProvider implements AuthenticationPr
 	private static final String INVALID_STATE_PARAMETER_ERROR_CODE = "invalid_state_parameter";
 	private static final String INVALID_REDIRECT_URI_PARAMETER_ERROR_CODE = "invalid_redirect_uri_parameter";
 	private final AuthorizationGrantTokenExchanger<AuthorizationCodeAuthenticationToken> authorizationCodeTokenExchanger;
+	private final OAuth2UserService userService;
 	private SecurityTokenRepository<AccessToken> accessTokenRepository = new InMemoryAccessTokenRepository();
+	private GrantedAuthoritiesMapper authoritiesMapper = (authorities -> authorities);
 
 	public AuthorizationCodeAuthenticationProvider(
-		AuthorizationGrantTokenExchanger<AuthorizationCodeAuthenticationToken> authorizationCodeTokenExchanger) {
+		AuthorizationGrantTokenExchanger<AuthorizationCodeAuthenticationToken> authorizationCodeTokenExchanger,
+		OAuth2UserService userService) {
 
 		Assert.notNull(authorizationCodeTokenExchanger, "authorizationCodeTokenExchanger cannot be null");
+		Assert.notNull(userService, "userService cannot be null");
 		this.authorizationCodeTokenExchanger = authorizationCodeTokenExchanger;
+		this.userService = userService;
 	}
 
 	@Override
@@ -107,7 +126,16 @@ public class AuthorizationCodeAuthenticationProvider implements AuthenticationPr
 			clientAuthentication.getAccessToken(),
 			clientAuthentication.getClientRegistration());
 
-		return clientAuthentication;
+		OAuth2User oauth2User = this.userService.loadUser(clientAuthentication);
+
+		Collection<? extends GrantedAuthority> mappedAuthorities =
+			this.authoritiesMapper.mapAuthorities(oauth2User.getAuthorities());
+
+		OAuth2AuthenticationToken authenticationResult = new OAuth2AuthenticationToken(
+			oauth2User, mappedAuthorities, clientAuthentication);
+		authenticationResult.setDetails(clientAuthentication.getDetails());
+
+		return authenticationResult;
 	}
 
 	public final void setAccessTokenRepository(SecurityTokenRepository<AccessToken> accessTokenRepository) {
@@ -115,6 +143,11 @@ public class AuthorizationCodeAuthenticationProvider implements AuthenticationPr
 		this.accessTokenRepository = accessTokenRepository;
 	}
 
+	public final void setAuthoritiesMapper(GrantedAuthoritiesMapper authoritiesMapper) {
+		Assert.notNull(authoritiesMapper, "authoritiesMapper cannot be null");
+		this.authoritiesMapper = authoritiesMapper;
+	}
+
 	@Override
 	public boolean supports(Class<?> authentication) {
 		return AuthorizationCodeAuthenticationToken.class.isAssignableFrom(authentication);

+ 4 - 4
oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/authentication/userinfo/OAuth2UserAuthenticationToken.java → oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/authentication/userinfo/OAuth2AuthenticationToken.java

@@ -27,7 +27,7 @@ import java.util.Collection;
 
 /**
  * An implementation of an {@link AbstractAuthenticationToken}
- * that represents an <i>OAuth 2.0 User</i> {@link Authentication}.
+ * that represents an <i>OAuth 2.0</i> {@link Authentication}.
  *
  * <p>
  * This {@link Authentication} associates an {@link OAuth2User} principal to an
@@ -38,13 +38,13 @@ import java.util.Collection;
  * @see OAuth2User
  * @see OAuth2ClientAuthenticationToken
  */
-public class OAuth2UserAuthenticationToken extends AbstractAuthenticationToken {
+public class OAuth2AuthenticationToken extends AbstractAuthenticationToken {
 	private static final long serialVersionUID = SpringSecurityCoreVersion.SERIAL_VERSION_UID;
 	private final OAuth2User principal;
 	private final OAuth2ClientAuthenticationToken clientAuthentication;
 
-	public OAuth2UserAuthenticationToken(OAuth2User principal, Collection<? extends GrantedAuthority> authorities,
-											OAuth2ClientAuthenticationToken clientAuthentication) {
+	public OAuth2AuthenticationToken(OAuth2User principal, Collection<? extends GrantedAuthority> authorities,
+										OAuth2ClientAuthenticationToken clientAuthentication) {
 		super(authorities);
 		Assert.notNull(clientAuthentication, "clientAuthentication cannot be null");
 		this.principal = principal;

+ 0 - 131
oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/authentication/userinfo/OAuth2UserAuthenticationProvider.java

@@ -1,131 +0,0 @@
-/*
- * Copyright 2012-2017 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
- *
- *      http://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.client.authentication.userinfo;
-
-import org.springframework.security.authentication.AuthenticationProvider;
-import org.springframework.security.core.Authentication;
-import org.springframework.security.core.AuthenticationException;
-import org.springframework.security.core.GrantedAuthority;
-import org.springframework.security.core.authority.mapping.GrantedAuthoritiesMapper;
-import org.springframework.security.core.context.SecurityContextHolder;
-import org.springframework.security.oauth2.client.authentication.OAuth2ClientAuthenticationToken;
-import org.springframework.security.oauth2.client.registration.ClientRegistration;
-import org.springframework.security.oauth2.core.user.OAuth2User;
-import org.springframework.util.Assert;
-
-import java.util.Collection;
-
-/**
- * An implementation of an {@link AuthenticationProvider} that is responsible
- * for obtaining the user attributes of the <i>End-User</i> (resource owner)
- * from the <i>UserInfo Endpoint</i> and creating a <code>Principal</code>
- * in the form of an {@link OAuth2User}.
- *
- * <p>
- * The {@link OAuth2UserAuthenticationProvider} uses an {@link OAuth2UserService}
- * for loading the {@link OAuth2User} and then associating it
- * to the returned {@link OAuth2UserAuthenticationToken}.
- *
- * @author Joe Grandja
- * @since 5.0
- * @see OAuth2UserAuthenticationToken
- * @see OAuth2ClientAuthenticationToken
- * @see OAuth2UserService
- * @see OAuth2User
- */
-public class OAuth2UserAuthenticationProvider implements AuthenticationProvider {
-	private final OAuth2UserService userService;
-	private GrantedAuthoritiesMapper authoritiesMapper = (authorities -> authorities);
-
-	public OAuth2UserAuthenticationProvider(OAuth2UserService userService) {
-		Assert.notNull(userService, "userService cannot be null");
-		this.userService = userService;
-	}
-
-	@Override
-	public Authentication authenticate(Authentication authentication) throws AuthenticationException {
-		OAuth2ClientAuthenticationToken clientAuthentication = (OAuth2ClientAuthenticationToken)authentication;
-
-		// Section 3.1.2.1 Authentication Request - http://openid.net/specs/openid-connect-core-1_0.html#AuthRequest
-		// scope
-		// 		REQUIRED. OpenID Connect requests MUST contain the "openid" scope value.
-		if (clientAuthentication.getAuthorizedScopes().contains("openid")) {
-			// This is an OpenID Connect Authentication Request so return null
-			// and let OidcUserAuthenticationProvider handle it instead
-			return null;
-		}
-
-		if (this.userAuthenticated() && this.userAuthenticatedSameProviderAs(clientAuthentication)) {
-			// Create a new user authentication (using same principal)
-			// but with a different client authentication association
-			OAuth2UserAuthenticationToken currentUserAuthentication =
-				(OAuth2UserAuthenticationToken)SecurityContextHolder.getContext().getAuthentication();
-
-			return new OAuth2UserAuthenticationToken(
-				(OAuth2User)currentUserAuthentication.getPrincipal(),
-				currentUserAuthentication.getAuthorities(),
-				clientAuthentication);
-		}
-
-		OAuth2User oauth2User = this.userService.loadUser(clientAuthentication);
-
-		Collection<? extends GrantedAuthority> mappedAuthorities =
-				this.authoritiesMapper.mapAuthorities(oauth2User.getAuthorities());
-
-		OAuth2UserAuthenticationToken authenticationResult = new OAuth2UserAuthenticationToken(
-				oauth2User, mappedAuthorities, clientAuthentication);
-		authenticationResult.setDetails(clientAuthentication.getDetails());
-
-		return authenticationResult;
-	}
-
-	@Override
-	public boolean supports(Class<?> authentication) {
-		return OAuth2ClientAuthenticationToken.class.isAssignableFrom(authentication);
-	}
-
-	public final void setAuthoritiesMapper(GrantedAuthoritiesMapper authoritiesMapper) {
-		Assert.notNull(authoritiesMapper, "authoritiesMapper cannot be null");
-		this.authoritiesMapper = authoritiesMapper;
-	}
-
-	private boolean userAuthenticated() {
-		Authentication currentAuthentication = SecurityContextHolder.getContext().getAuthentication();
-		return currentAuthentication != null &&
-			currentAuthentication instanceof OAuth2UserAuthenticationToken &&
-			currentAuthentication.isAuthenticated();
-	}
-
-	private boolean userAuthenticatedSameProviderAs(OAuth2ClientAuthenticationToken clientAuthentication) {
-		OAuth2UserAuthenticationToken currentUserAuthentication =
-			(OAuth2UserAuthenticationToken)SecurityContextHolder.getContext().getAuthentication();
-
-		String userProviderId = this.getProviderIdentifier(
-			currentUserAuthentication.getClientAuthentication().getClientRegistration());
-		String clientProviderId = this.getProviderIdentifier(
-			clientAuthentication.getClientRegistration());
-
-		return userProviderId.equals(clientProviderId);
-	}
-
-	private String getProviderIdentifier(ClientRegistration clientRegistration) {
-		StringBuilder builder = new StringBuilder();
-		builder.append("[").append(clientRegistration.getProviderDetails().getAuthorizationUri()).append("]");
-		builder.append("[").append(clientRegistration.getProviderDetails().getTokenUri()).append("]");
-		builder.append("[").append(clientRegistration.getProviderDetails().getUserInfoEndpoint().getUri()).append("]");
-		return builder.toString();
-	}
-}

+ 1 - 5
oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/web/OAuth2LoginAuthenticationFilter.java

@@ -21,7 +21,6 @@ import org.springframework.security.core.AuthenticationException;
 import org.springframework.security.oauth2.client.authentication.AuthorizationCodeAuthenticationProvider;
 import org.springframework.security.oauth2.client.authentication.AuthorizationCodeAuthenticationToken;
 import org.springframework.security.oauth2.client.authentication.OAuth2AuthenticationException;
-import org.springframework.security.oauth2.client.authentication.OAuth2ClientAuthenticationToken;
 import org.springframework.security.oauth2.client.registration.ClientRegistration;
 import org.springframework.security.oauth2.client.registration.ClientRegistrationRepository;
 import org.springframework.security.oauth2.core.OAuth2Error;
@@ -128,10 +127,7 @@ public class OAuth2LoginAuthenticationFilter extends AbstractAuthenticationProce
 				clientRegistration, new AuthorizationExchange(authorizationRequest, authorizationResponse));
 		authorizationCodeAuthentication.setDetails(this.authenticationDetailsSource.buildDetails(request));
 
-		OAuth2ClientAuthenticationToken clientAuthentication =
-			(OAuth2ClientAuthenticationToken)this.getAuthenticationManager().authenticate(authorizationCodeAuthentication);
-
-		return this.getAuthenticationManager().authenticate(clientAuthentication);
+		return this.getAuthenticationManager().authenticate(authorizationCodeAuthentication);
 	}
 
 	public final void setClientRegistrationRepository(ClientRegistrationRepository clientRegistrationRepository) {

+ 37 - 3
oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/oidc/client/authentication/OidcAuthorizationCodeAuthenticationProvider.java

@@ -18,10 +18,14 @@ package org.springframework.security.oauth2.oidc.client.authentication;
 import org.springframework.security.authentication.AuthenticationProvider;
 import org.springframework.security.core.Authentication;
 import org.springframework.security.core.AuthenticationException;
+import org.springframework.security.core.GrantedAuthority;
+import org.springframework.security.core.authority.mapping.GrantedAuthoritiesMapper;
 import org.springframework.security.oauth2.client.authentication.AuthorizationCodeAuthenticationToken;
 import org.springframework.security.oauth2.client.authentication.AuthorizationGrantTokenExchanger;
 import org.springframework.security.oauth2.client.authentication.OAuth2AuthenticationException;
 import org.springframework.security.oauth2.client.authentication.jwt.JwtDecoderRegistry;
+import org.springframework.security.oauth2.client.authentication.userinfo.OAuth2AuthenticationToken;
+import org.springframework.security.oauth2.client.authentication.userinfo.OAuth2UserService;
 import org.springframework.security.oauth2.client.registration.ClientRegistration;
 import org.springframework.security.oauth2.client.token.InMemoryAccessTokenRepository;
 import org.springframework.security.oauth2.client.token.SecurityTokenRepository;
@@ -30,26 +34,37 @@ import org.springframework.security.oauth2.core.OAuth2Error;
 import org.springframework.security.oauth2.core.endpoint.AuthorizationRequest;
 import org.springframework.security.oauth2.core.endpoint.AuthorizationResponse;
 import org.springframework.security.oauth2.core.endpoint.TokenResponse;
+import org.springframework.security.oauth2.core.user.OAuth2User;
 import org.springframework.security.oauth2.jwt.Jwt;
 import org.springframework.security.oauth2.jwt.JwtDecoder;
+import org.springframework.security.oauth2.oidc.client.authentication.userinfo.OidcUserService;
 import org.springframework.security.oauth2.oidc.core.IdToken;
 import org.springframework.security.oauth2.oidc.core.OidcScope;
 import org.springframework.security.oauth2.oidc.core.endpoint.OidcParameter;
+import org.springframework.security.oauth2.oidc.core.user.OidcUser;
 import org.springframework.util.Assert;
 
+import java.util.Collection;
+
 /**
  * An implementation of an {@link AuthenticationProvider}
  * for the <i>OpenID Connect Core 1.0 Authorization Code Grant Flow</i>.
- *
+ * <p>
  * This {@link AuthenticationProvider} is responsible for authenticating
  * an <i>authorization code</i> credential with the authorization server's <i>Token Endpoint</i>
  * and if valid, exchanging it for an <i>access token</i> credential.
+ * <p>
+ * It will also obtain the user attributes of the <i>End-User</i> (resource owner)
+ * from the <i>UserInfo Endpoint</i> using an {@link OAuth2UserService}
+ * which will create a <code>Principal</code> in the form of an {@link OidcUser}.
  *
  * @author Joe Grandja
  * @since 5.0
  * @see AuthorizationCodeAuthenticationToken
- * @see OidcClientAuthenticationToken
  * @see SecurityTokenRepository
+ * @see OidcClientAuthenticationToken
+ * @see OidcUserService
+ * @see OidcUser
  * @see <a target="_blank" href="http://openid.net/specs/openid-connect-core-1_0.html#CodeFlowAuth">Section 3.1 Authorization Code Grant Flow</a>
  * @see <a target="_blank" href="http://openid.net/specs/openid-connect-core-1_0.html#TokenRequest">Section 3.1.3.1 Token Request</a>
  * @see <a target="_blank" href="http://openid.net/specs/openid-connect-core-1_0.html#TokenResponse">Section 3.1.3.3 Token Response</a>
@@ -58,16 +73,21 @@ public class OidcAuthorizationCodeAuthenticationProvider implements Authenticati
 	private static final String INVALID_STATE_PARAMETER_ERROR_CODE = "invalid_state_parameter";
 	private static final String INVALID_REDIRECT_URI_PARAMETER_ERROR_CODE = "invalid_redirect_uri_parameter";
 	private final AuthorizationGrantTokenExchanger<AuthorizationCodeAuthenticationToken> authorizationCodeTokenExchanger;
+	private final OAuth2UserService userService;
 	private final JwtDecoderRegistry jwtDecoderRegistry;
 	private SecurityTokenRepository<AccessToken> accessTokenRepository = new InMemoryAccessTokenRepository();
+	private GrantedAuthoritiesMapper authoritiesMapper = (authorities -> authorities);
 
 	public OidcAuthorizationCodeAuthenticationProvider(
 		AuthorizationGrantTokenExchanger<AuthorizationCodeAuthenticationToken> authorizationCodeTokenExchanger,
+		OAuth2UserService userService,
 		JwtDecoderRegistry jwtDecoderRegistry) {
 
 		Assert.notNull(authorizationCodeTokenExchanger, "authorizationCodeTokenExchanger cannot be null");
+		Assert.notNull(userService, "userService cannot be null");
 		Assert.notNull(jwtDecoderRegistry, "jwtDecoderRegistry cannot be null");
 		this.authorizationCodeTokenExchanger = authorizationCodeTokenExchanger;
+		this.userService = userService;
 		this.jwtDecoderRegistry = jwtDecoderRegistry;
 	}
 
@@ -136,7 +156,16 @@ public class OidcAuthorizationCodeAuthenticationProvider implements Authenticati
 			clientAuthentication.getAccessToken(),
 			clientAuthentication.getClientRegistration());
 
-		return clientAuthentication;
+		OAuth2User oauth2User = this.userService.loadUser(clientAuthentication);
+
+		Collection<? extends GrantedAuthority> mappedAuthorities =
+			this.authoritiesMapper.mapAuthorities(oauth2User.getAuthorities());
+
+		OAuth2AuthenticationToken authenticationResult = new OAuth2AuthenticationToken(
+			oauth2User, mappedAuthorities, clientAuthentication);
+		authenticationResult.setDetails(clientAuthentication.getDetails());
+
+		return authenticationResult;
 	}
 
 	public final void setAccessTokenRepository(SecurityTokenRepository<AccessToken> accessTokenRepository) {
@@ -144,6 +173,11 @@ public class OidcAuthorizationCodeAuthenticationProvider implements Authenticati
 		this.accessTokenRepository = accessTokenRepository;
 	}
 
+	public final void setAuthoritiesMapper(GrantedAuthoritiesMapper authoritiesMapper) {
+		Assert.notNull(authoritiesMapper, "authoritiesMapper cannot be null");
+		this.authoritiesMapper = authoritiesMapper;
+	}
+
 	@Override
 	public boolean supports(Class<?> authentication) {
 		return AuthorizationCodeAuthenticationToken.class.isAssignableFrom(authentication);

+ 0 - 46
oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/oidc/client/authentication/OidcUserAuthenticationToken.java

@@ -1,46 +0,0 @@
-/*
- * Copyright 2012-2017 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
- *
- *      http://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.oidc.client.authentication;
-
-import org.springframework.security.core.Authentication;
-import org.springframework.security.core.GrantedAuthority;
-import org.springframework.security.oauth2.client.authentication.userinfo.OAuth2UserAuthenticationToken;
-import org.springframework.security.oauth2.oidc.core.user.OidcUser;
-
-import java.util.Collection;
-
-/**
- * An {@link OAuth2UserAuthenticationToken} that represents an
- * <i>OpenID Connect 1.0 User</i> {@link Authentication}.
- *
- * <p>
- * This {@link Authentication} associates an {@link OidcUser} principal to an
- * {@link OidcClientAuthenticationToken} which represents the <i>&quot;Authorized Client&quot;</i>.
- *
- * @author Joe Grandja
- * @since 5.0
- * @see OidcUser
- * @see OidcClientAuthenticationToken
- * @see OAuth2UserAuthenticationToken
- */
-public class OidcUserAuthenticationToken extends OAuth2UserAuthenticationToken {
-
-	public OidcUserAuthenticationToken(OidcUser principal, Collection<? extends GrantedAuthority> authorities,
-										OidcClientAuthenticationToken clientAuthentication) {
-		super(principal, authorities, clientAuthentication);
-	}
-
-}

+ 0 - 104
oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/oidc/client/authentication/userinfo/OidcUserAuthenticationProvider.java

@@ -1,104 +0,0 @@
-/*
- * Copyright 2012-2017 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
- *
- *      http://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.oidc.client.authentication.userinfo;
-
-import org.springframework.security.authentication.AuthenticationProvider;
-import org.springframework.security.core.Authentication;
-import org.springframework.security.core.AuthenticationException;
-import org.springframework.security.core.GrantedAuthority;
-import org.springframework.security.core.authority.mapping.GrantedAuthoritiesMapper;
-import org.springframework.security.core.context.SecurityContextHolder;
-import org.springframework.security.oauth2.client.authentication.userinfo.OAuth2UserService;
-import org.springframework.security.oauth2.core.user.OAuth2User;
-import org.springframework.security.oauth2.oidc.client.authentication.OidcClientAuthenticationToken;
-import org.springframework.security.oauth2.oidc.client.authentication.OidcUserAuthenticationToken;
-import org.springframework.security.oauth2.oidc.core.user.OidcUser;
-import org.springframework.util.Assert;
-
-import java.util.Collection;
-
-/**
- * An implementation of an {@link AuthenticationProvider} that is responsible
- * for obtaining the user attributes of the <i>End-User</i> (resource owner)
- * from the <i>UserInfo Endpoint</i> and creating a <code>Principal</code>
- * in the form of an {@link OidcUser}.
- *
- * <p>
- * The {@link OidcUserAuthenticationProvider} uses an {@link OidcUserService}
- * for loading the {@link OidcUser} and then associating it
- * to the returned {@link OidcUserAuthenticationToken}.
- *
- * @author Joe Grandja
- * @since 5.0
- * @see OidcUserAuthenticationToken
- * @see OidcClientAuthenticationToken
- * @see OidcUserService
- * @see OidcUser
- */
-public class OidcUserAuthenticationProvider implements AuthenticationProvider {
-	private final OAuth2UserService userService;
-	private GrantedAuthoritiesMapper authoritiesMapper = (authorities -> authorities);
-
-	public OidcUserAuthenticationProvider(OAuth2UserService userService) {
-		Assert.notNull(userService, "userService cannot be null");
-		this.userService = userService;
-	}
-
-	@Override
-	public Authentication authenticate(Authentication authentication) throws AuthenticationException {
-		OidcClientAuthenticationToken clientAuthentication = (OidcClientAuthenticationToken) authentication;
-
-		if (this.userAuthenticated()) {
-			// Create a new user authentication (using same principal)
-			// but with a different client authentication association
-			OidcUserAuthenticationToken currentUserAuthentication =
-				(OidcUserAuthenticationToken) SecurityContextHolder.getContext().getAuthentication();
-
-			return new OidcUserAuthenticationToken(
-				(OidcUser) currentUserAuthentication.getPrincipal(),
-				currentUserAuthentication.getAuthorities(),
-				clientAuthentication);
-		}
-
-		OAuth2User oauth2User = this.userService.loadUser(clientAuthentication);
-
-		Collection<? extends GrantedAuthority> mappedAuthorities =
-				this.authoritiesMapper.mapAuthorities(oauth2User.getAuthorities());
-
-		OidcUserAuthenticationToken authenticationResult = new OidcUserAuthenticationToken(
-				(OidcUser)oauth2User, mappedAuthorities, clientAuthentication);
-		authenticationResult.setDetails(clientAuthentication.getDetails());
-
-		return authenticationResult;
-	}
-
-	@Override
-	public boolean supports(Class<?> authentication) {
-		return OidcClientAuthenticationToken.class.isAssignableFrom(authentication);
-	}
-
-	public final void setAuthoritiesMapper(GrantedAuthoritiesMapper authoritiesMapper) {
-		Assert.notNull(authoritiesMapper, "authoritiesMapper cannot be null");
-		this.authoritiesMapper = authoritiesMapper;
-	}
-
-	private boolean userAuthenticated() {
-		Authentication currentAuthentication = SecurityContextHolder.getContext().getAuthentication();
-		return currentAuthentication != null &&
-			currentAuthentication instanceof OidcUserAuthenticationToken &&
-			currentAuthentication.isAuthenticated();
-	}
-}

+ 2 - 2
oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/web/OAuth2LoginAuthenticationFilterTests.java

@@ -29,7 +29,7 @@ import org.springframework.security.core.authority.AuthorityUtils;
 import org.springframework.security.core.context.SecurityContextHolder;
 import org.springframework.security.oauth2.client.authentication.OAuth2AuthenticationException;
 import org.springframework.security.oauth2.client.authentication.OAuth2ClientAuthenticationToken;
-import org.springframework.security.oauth2.client.authentication.userinfo.OAuth2UserAuthenticationToken;
+import org.springframework.security.oauth2.client.authentication.userinfo.OAuth2AuthenticationToken;
 import org.springframework.security.oauth2.client.registration.ClientRegistration;
 import org.springframework.security.oauth2.client.registration.ClientRegistrationRepository;
 import org.springframework.security.oauth2.core.AccessToken;
@@ -100,7 +100,7 @@ public class OAuth2LoginAuthenticationFilterTests {
 		ClientRegistration clientRegistration = TestUtil.githubClientRegistration();
 		OAuth2ClientAuthenticationToken clientAuthentication = new OAuth2ClientAuthenticationToken(
 			clientRegistration, mock(AccessToken.class));
-		OAuth2UserAuthenticationToken userAuthentication = new OAuth2UserAuthenticationToken(
+		OAuth2AuthenticationToken userAuthentication = new OAuth2AuthenticationToken(
 			mock(OAuth2User.class), AuthorityUtils.createAuthorityList("ROLE_USER"), clientAuthentication);
 		SecurityContextHolder.getContext().setAuthentication(userAuthentication);
 		AuthenticationManager authenticationManager = mock(AuthenticationManager.class);

+ 4 - 4
samples/boot/oauth2login/src/main/java/sample/web/MainController.java

@@ -17,7 +17,7 @@ package sample.web;
 
 import org.springframework.http.HttpHeaders;
 import org.springframework.security.core.annotation.AuthenticationPrincipal;
-import org.springframework.security.oauth2.client.authentication.userinfo.OAuth2UserAuthenticationToken;
+import org.springframework.security.oauth2.client.authentication.userinfo.OAuth2AuthenticationToken;
 import org.springframework.security.oauth2.core.user.OAuth2User;
 import org.springframework.stereotype.Controller;
 import org.springframework.ui.Model;
@@ -38,14 +38,14 @@ import java.util.Map;
 public class MainController {
 
 	@RequestMapping("/")
-	public String index(Model model, @AuthenticationPrincipal OAuth2User user, OAuth2UserAuthenticationToken authentication) {
+	public String index(Model model, @AuthenticationPrincipal OAuth2User user, OAuth2AuthenticationToken authentication) {
 		model.addAttribute("userName", user.getName());
 		model.addAttribute("clientName", authentication.getClientAuthentication().getClientRegistration().getClientName());
 		return "index";
 	}
 
 	@RequestMapping("/userinfo")
-	public String userinfo(Model model, OAuth2UserAuthenticationToken authentication) {
+	public String userinfo(Model model, OAuth2AuthenticationToken authentication) {
 		Map userAttributes = Collections.emptyMap();
 		String userInfoEndpointUri = authentication.getClientAuthentication().getClientRegistration()
 			.getProviderDetails().getUserInfoEndpoint().getUri();
@@ -63,7 +63,7 @@ public class MainController {
 		return "userinfo";
 	}
 
-	private ExchangeFilterFunction oauth2Credentials(OAuth2UserAuthenticationToken authentication) {
+	private ExchangeFilterFunction oauth2Credentials(OAuth2AuthenticationToken authentication) {
 		return ExchangeFilterFunction.ofRequestProcessor(
 			clientRequest -> {
 				ClientRequest authorizedRequest = ClientRequest.from(clientRequest)