mirror of
https://github.com/spring-projects/spring-security.git
synced 2025-06-29 15:22:15 +00:00
Fix package tangles -> OAuth2/Oidc AuthenticationProvider's
Fixes gh-4614
This commit is contained in:
parent
983d019ee8
commit
7b8d131386
@ -36,6 +36,7 @@ import org.springframework.security.oauth2.client.web.AuthorizationRequestReposi
|
|||||||
import org.springframework.security.oauth2.client.web.AuthorizationRequestUriBuilder;
|
import org.springframework.security.oauth2.client.web.AuthorizationRequestUriBuilder;
|
||||||
import org.springframework.security.oauth2.core.AccessToken;
|
import org.springframework.security.oauth2.core.AccessToken;
|
||||||
import org.springframework.security.oauth2.core.user.OAuth2User;
|
import org.springframework.security.oauth2.core.user.OAuth2User;
|
||||||
|
import org.springframework.security.oauth2.oidc.client.authentication.userinfo.OidcUserAuthenticationProvider;
|
||||||
import org.springframework.security.oauth2.oidc.client.authentication.userinfo.OidcUserService;
|
import org.springframework.security.oauth2.oidc.client.authentication.userinfo.OidcUserService;
|
||||||
import org.springframework.security.web.authentication.ui.DefaultLoginPageGeneratingFilter;
|
import org.springframework.security.web.authentication.ui.DefaultLoginPageGeneratingFilter;
|
||||||
import org.springframework.security.web.util.matcher.RequestMatcher;
|
import org.springframework.security.web.util.matcher.RequestMatcher;
|
||||||
@ -195,19 +196,6 @@ public final class OAuth2LoginConfigurer<B extends HttpSecurityBuilder<B>> exten
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
private OAuth2UserService getUserService() {
|
|
||||||
if (this.userService == null) {
|
|
||||||
List<OAuth2UserService> userServices = new ArrayList<>();
|
|
||||||
userServices.add(new DefaultOAuth2UserService());
|
|
||||||
userServices.add(new OidcUserService());
|
|
||||||
if (!this.customUserTypes.isEmpty()) {
|
|
||||||
userServices.add(new CustomUserTypesOAuth2UserService(this.customUserTypes));
|
|
||||||
}
|
|
||||||
this.userService = new DelegatingOAuth2UserService(userServices);
|
|
||||||
}
|
|
||||||
return this.userService;
|
|
||||||
}
|
|
||||||
|
|
||||||
public OAuth2LoginConfigurer<B> and() {
|
public OAuth2LoginConfigurer<B> and() {
|
||||||
return OAuth2LoginConfigurer.this;
|
return OAuth2LoginConfigurer.this;
|
||||||
}
|
}
|
||||||
@ -219,13 +207,35 @@ public final class OAuth2LoginConfigurer<B extends HttpSecurityBuilder<B>> exten
|
|||||||
this.authorizationCodeGrantConfigurer.setBuilder(http);
|
this.authorizationCodeGrantConfigurer.setBuilder(http);
|
||||||
this.authorizationCodeGrantConfigurer.init(http);
|
this.authorizationCodeGrantConfigurer.init(http);
|
||||||
|
|
||||||
|
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 =
|
OAuth2UserAuthenticationProvider oauth2UserAuthenticationProvider =
|
||||||
new OAuth2UserAuthenticationProvider(this.userInfoEndpointConfig.getUserService());
|
new OAuth2UserAuthenticationProvider(userService);
|
||||||
if (this.userInfoEndpointConfig.userAuthoritiesMapper != null) {
|
if (this.userInfoEndpointConfig.userAuthoritiesMapper != null) {
|
||||||
oauth2UserAuthenticationProvider.setAuthoritiesMapper(this.userInfoEndpointConfig.userAuthoritiesMapper);
|
oauth2UserAuthenticationProvider.setAuthoritiesMapper(this.userInfoEndpointConfig.userAuthoritiesMapper);
|
||||||
}
|
}
|
||||||
http.authenticationProvider(this.postProcess(oauth2UserAuthenticationProvider));
|
http.authenticationProvider(this.postProcess(oauth2UserAuthenticationProvider));
|
||||||
|
|
||||||
|
userService = this.userInfoEndpointConfig.userService;
|
||||||
|
if (userService == null) {
|
||||||
|
userService = new OidcUserService();
|
||||||
|
}
|
||||||
|
OidcUserAuthenticationProvider oidcUserAuthenticationProvider =
|
||||||
|
new OidcUserAuthenticationProvider(userService);
|
||||||
|
if (this.userInfoEndpointConfig.userAuthoritiesMapper != null) {
|
||||||
|
oidcUserAuthenticationProvider.setAuthoritiesMapper(this.userInfoEndpointConfig.userAuthoritiesMapper);
|
||||||
|
}
|
||||||
|
http.authenticationProvider(this.postProcess(oidcUserAuthenticationProvider));
|
||||||
|
|
||||||
this.initDefaultLoginFilter(http);
|
this.initDefaultLoginFilter(http);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -65,10 +65,9 @@ public class AuthorizationCodeAuthenticationProvider implements AuthenticationPr
|
|||||||
// Section 3.1.2.1 Authentication Request - http://openid.net/specs/openid-connect-core-1_0.html#AuthRequest
|
// Section 3.1.2.1 Authentication Request - http://openid.net/specs/openid-connect-core-1_0.html#AuthRequest
|
||||||
// scope
|
// scope
|
||||||
// REQUIRED. OpenID Connect requests MUST contain the "openid" scope value.
|
// REQUIRED. OpenID Connect requests MUST contain the "openid" scope value.
|
||||||
// If the openid scope value is not present, the behavior is entirely unspecified.
|
|
||||||
if (authorizationCodeAuthentication.getAuthorizationRequest().getScope().contains("openid")) {
|
if (authorizationCodeAuthentication.getAuthorizationRequest().getScope().contains("openid")) {
|
||||||
// The OpenID Connect implementation of Authorization Code AuthenticationProvider
|
// This is an OpenID Connect Authentication Request so return null
|
||||||
// should handle OpenID Connect Authentication Requests so don't handle and return null
|
// and let OidcAuthorizationCodeAuthenticationProvider handle it instead
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -20,7 +20,6 @@ import org.springframework.beans.PropertyAccessorFactory;
|
|||||||
import org.springframework.security.oauth2.client.authentication.OAuth2AuthenticationException;
|
import org.springframework.security.oauth2.client.authentication.OAuth2AuthenticationException;
|
||||||
import org.springframework.security.oauth2.client.authentication.OAuth2ClientAuthenticationToken;
|
import org.springframework.security.oauth2.client.authentication.OAuth2ClientAuthenticationToken;
|
||||||
import org.springframework.security.oauth2.core.user.OAuth2User;
|
import org.springframework.security.oauth2.core.user.OAuth2User;
|
||||||
import org.springframework.security.oauth2.oidc.client.authentication.OidcClientAuthenticationToken;
|
|
||||||
import org.springframework.util.Assert;
|
import org.springframework.util.Assert;
|
||||||
|
|
||||||
import java.net.URI;
|
import java.net.URI;
|
||||||
@ -70,9 +69,6 @@ public class CustomUserTypesOAuth2UserService implements OAuth2UserService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Map<String, Object> userAttributes = this.userInfoRetriever.retrieve(clientAuthentication);
|
Map<String, Object> userAttributes = this.userInfoRetriever.retrieve(clientAuthentication);
|
||||||
if (OidcClientAuthenticationToken.class.isAssignableFrom(clientAuthentication.getClass())) {
|
|
||||||
userAttributes.putAll(((OidcClientAuthenticationToken)clientAuthentication).getIdToken().getClaims());
|
|
||||||
}
|
|
||||||
|
|
||||||
BeanWrapper wrapper = PropertyAccessorFactory.forBeanPropertyAccess(customUser);
|
BeanWrapper wrapper = PropertyAccessorFactory.forBeanPropertyAccess(customUser);
|
||||||
wrapper.setAutoGrowNestedPaths(true);
|
wrapper.setAutoGrowNestedPaths(true);
|
||||||
|
@ -22,7 +22,6 @@ import org.springframework.security.oauth2.client.registration.ClientRegistratio
|
|||||||
import org.springframework.security.oauth2.core.user.DefaultOAuth2User;
|
import org.springframework.security.oauth2.core.user.DefaultOAuth2User;
|
||||||
import org.springframework.security.oauth2.core.user.OAuth2User;
|
import org.springframework.security.oauth2.core.user.OAuth2User;
|
||||||
import org.springframework.security.oauth2.core.user.OAuth2UserAuthority;
|
import org.springframework.security.oauth2.core.user.OAuth2UserAuthority;
|
||||||
import org.springframework.security.oauth2.oidc.client.authentication.OidcClientAuthenticationToken;
|
|
||||||
import org.springframework.util.Assert;
|
import org.springframework.util.Assert;
|
||||||
import org.springframework.util.StringUtils;
|
import org.springframework.util.StringUtils;
|
||||||
|
|
||||||
@ -54,10 +53,6 @@ public class DefaultOAuth2UserService implements OAuth2UserService {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public OAuth2User loadUser(OAuth2ClientAuthenticationToken clientAuthentication) throws OAuth2AuthenticationException {
|
public OAuth2User loadUser(OAuth2ClientAuthenticationToken clientAuthentication) throws OAuth2AuthenticationException {
|
||||||
if (OidcClientAuthenticationToken.class.isAssignableFrom(clientAuthentication.getClass())) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
String userNameAttributeName = clientAuthentication.getClientRegistration().getProviderDetails().getUserInfoEndpoint().getUserNameAttributeName();
|
String userNameAttributeName = clientAuthentication.getClientRegistration().getProviderDetails().getUserInfoEndpoint().getUserNameAttributeName();
|
||||||
if (!StringUtils.hasText(userNameAttributeName)) {
|
if (!StringUtils.hasText(userNameAttributeName)) {
|
||||||
throw new IllegalArgumentException(
|
throw new IllegalArgumentException(
|
||||||
|
@ -20,6 +20,8 @@ import org.springframework.security.oauth2.client.authentication.OAuth2ClientAut
|
|||||||
import org.springframework.security.oauth2.core.user.OAuth2User;
|
import org.springframework.security.oauth2.core.user.OAuth2User;
|
||||||
import org.springframework.util.Assert;
|
import org.springframework.util.Assert;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
|
||||||
@ -41,7 +43,7 @@ public class DelegatingOAuth2UserService implements OAuth2UserService {
|
|||||||
|
|
||||||
public DelegatingOAuth2UserService(List<OAuth2UserService> userServices) {
|
public DelegatingOAuth2UserService(List<OAuth2UserService> userServices) {
|
||||||
Assert.notEmpty(userServices, "userServices cannot be empty");
|
Assert.notEmpty(userServices, "userServices cannot be empty");
|
||||||
this.userServices = userServices;
|
this.userServices = Collections.unmodifiableList(new ArrayList<>(userServices));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -25,10 +25,6 @@ import org.springframework.security.oauth2.client.authentication.OAuth2ClientAut
|
|||||||
import org.springframework.security.oauth2.client.registration.ClientRegistration;
|
import org.springframework.security.oauth2.client.registration.ClientRegistration;
|
||||||
import org.springframework.security.oauth2.client.registration.ClientRegistrationIdentifierStrategy;
|
import org.springframework.security.oauth2.client.registration.ClientRegistrationIdentifierStrategy;
|
||||||
import org.springframework.security.oauth2.core.user.OAuth2User;
|
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.client.authentication.userinfo.OidcUserService;
|
|
||||||
import org.springframework.security.oauth2.oidc.core.user.OidcUser;
|
|
||||||
import org.springframework.util.Assert;
|
import org.springframework.util.Assert;
|
||||||
|
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
@ -47,13 +43,9 @@ import java.util.Collection;
|
|||||||
* @author Joe Grandja
|
* @author Joe Grandja
|
||||||
* @since 5.0
|
* @since 5.0
|
||||||
* @see OAuth2UserAuthenticationToken
|
* @see OAuth2UserAuthenticationToken
|
||||||
* @see OidcUserAuthenticationToken
|
|
||||||
* @see OAuth2ClientAuthenticationToken
|
* @see OAuth2ClientAuthenticationToken
|
||||||
* @see OidcClientAuthenticationToken
|
|
||||||
* @see OAuth2UserService
|
* @see OAuth2UserService
|
||||||
* @see OidcUserService
|
|
||||||
* @see OAuth2User
|
* @see OAuth2User
|
||||||
* @see OidcUser
|
|
||||||
*/
|
*/
|
||||||
public class OAuth2UserAuthenticationProvider implements AuthenticationProvider {
|
public class OAuth2UserAuthenticationProvider implements AuthenticationProvider {
|
||||||
private final ClientRegistrationIdentifierStrategy<String> providerIdentifierStrategy = new ProviderIdentifierStrategy();
|
private final ClientRegistrationIdentifierStrategy<String> providerIdentifierStrategy = new ProviderIdentifierStrategy();
|
||||||
@ -67,14 +59,26 @@ public class OAuth2UserAuthenticationProvider implements AuthenticationProvider
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Authentication authenticate(Authentication authentication) throws AuthenticationException {
|
public Authentication authenticate(Authentication authentication) throws AuthenticationException {
|
||||||
OAuth2UserAuthenticationToken userAuthentication = (OAuth2UserAuthenticationToken) authentication;
|
OAuth2ClientAuthenticationToken clientAuthentication = (OAuth2ClientAuthenticationToken)authentication;
|
||||||
OAuth2ClientAuthenticationToken clientAuthentication = userAuthentication.getClientAuthentication();
|
|
||||||
|
// 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.getAuthorizedScope().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)) {
|
if (this.userAuthenticated() && this.userAuthenticatedSameProviderAs(clientAuthentication)) {
|
||||||
// Create a new user authentication (using same principal)
|
// Create a new user authentication (using same principal)
|
||||||
// but with a different client authentication association
|
// but with a different client authentication association
|
||||||
return this.createUserAuthentication(
|
OAuth2UserAuthenticationToken currentUserAuthentication =
|
||||||
(OAuth2UserAuthenticationToken)SecurityContextHolder.getContext().getAuthentication(),
|
(OAuth2UserAuthenticationToken)SecurityContextHolder.getContext().getAuthentication();
|
||||||
|
|
||||||
|
return new OAuth2UserAuthenticationToken(
|
||||||
|
(OAuth2User)currentUserAuthentication.getPrincipal(),
|
||||||
|
currentUserAuthentication.getAuthorities(),
|
||||||
clientAuthentication);
|
clientAuthentication);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -83,29 +87,23 @@ public class OAuth2UserAuthenticationProvider implements AuthenticationProvider
|
|||||||
Collection<? extends GrantedAuthority> mappedAuthorities =
|
Collection<? extends GrantedAuthority> mappedAuthorities =
|
||||||
this.authoritiesMapper.mapAuthorities(oauth2User.getAuthorities());
|
this.authoritiesMapper.mapAuthorities(oauth2User.getAuthorities());
|
||||||
|
|
||||||
OAuth2UserAuthenticationToken authenticationResult;
|
OAuth2UserAuthenticationToken authenticationResult = new OAuth2UserAuthenticationToken(
|
||||||
if (OidcUser.class.isAssignableFrom(oauth2User.getClass())) {
|
|
||||||
authenticationResult = new OidcUserAuthenticationToken(
|
|
||||||
(OidcUser)oauth2User, mappedAuthorities, (OidcClientAuthenticationToken)clientAuthentication);
|
|
||||||
} else {
|
|
||||||
authenticationResult = new OAuth2UserAuthenticationToken(
|
|
||||||
oauth2User, mappedAuthorities, clientAuthentication);
|
oauth2User, mappedAuthorities, clientAuthentication);
|
||||||
}
|
|
||||||
authenticationResult.setDetails(clientAuthentication.getDetails());
|
authenticationResult.setDetails(clientAuthentication.getDetails());
|
||||||
|
|
||||||
return authenticationResult;
|
return authenticationResult;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean supports(Class<?> authentication) {
|
||||||
|
return OAuth2ClientAuthenticationToken.class.isAssignableFrom(authentication);
|
||||||
|
}
|
||||||
|
|
||||||
public final void setAuthoritiesMapper(GrantedAuthoritiesMapper authoritiesMapper) {
|
public final void setAuthoritiesMapper(GrantedAuthoritiesMapper authoritiesMapper) {
|
||||||
Assert.notNull(authoritiesMapper, "authoritiesMapper cannot be null");
|
Assert.notNull(authoritiesMapper, "authoritiesMapper cannot be null");
|
||||||
this.authoritiesMapper = authoritiesMapper;
|
this.authoritiesMapper = authoritiesMapper;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean supports(Class<?> authentication) {
|
|
||||||
return OAuth2UserAuthenticationToken.class.isAssignableFrom(authentication);
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean userAuthenticated() {
|
private boolean userAuthenticated() {
|
||||||
Authentication currentAuthentication = SecurityContextHolder.getContext().getAuthentication();
|
Authentication currentAuthentication = SecurityContextHolder.getContext().getAuthentication();
|
||||||
return currentAuthentication != null &&
|
return currentAuthentication != null &&
|
||||||
@ -125,23 +123,6 @@ public class OAuth2UserAuthenticationProvider implements AuthenticationProvider
|
|||||||
return userProviderId.equals(clientProviderId);
|
return userProviderId.equals(clientProviderId);
|
||||||
}
|
}
|
||||||
|
|
||||||
private OAuth2UserAuthenticationToken createUserAuthentication(
|
|
||||||
OAuth2UserAuthenticationToken currentUserAuthentication,
|
|
||||||
OAuth2ClientAuthenticationToken newClientAuthentication) {
|
|
||||||
|
|
||||||
if (OidcUserAuthenticationToken.class.isAssignableFrom(currentUserAuthentication.getClass())) {
|
|
||||||
return new OidcUserAuthenticationToken(
|
|
||||||
(OidcUser) currentUserAuthentication.getPrincipal(),
|
|
||||||
currentUserAuthentication.getAuthorities(),
|
|
||||||
newClientAuthentication);
|
|
||||||
} else {
|
|
||||||
return new OAuth2UserAuthenticationToken(
|
|
||||||
(OAuth2User)currentUserAuthentication.getPrincipal(),
|
|
||||||
currentUserAuthentication.getAuthorities(),
|
|
||||||
newClientAuthentication);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static class ProviderIdentifierStrategy implements ClientRegistrationIdentifierStrategy<String> {
|
private static class ProviderIdentifierStrategy implements ClientRegistrationIdentifierStrategy<String> {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -24,7 +24,6 @@ import org.springframework.security.oauth2.core.user.OAuth2User;
|
|||||||
import org.springframework.util.Assert;
|
import org.springframework.util.Assert;
|
||||||
|
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Collections;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An implementation of an {@link AbstractAuthenticationToken}
|
* An implementation of an {@link AbstractAuthenticationToken}
|
||||||
@ -44,10 +43,6 @@ public class OAuth2UserAuthenticationToken extends AbstractAuthenticationToken {
|
|||||||
private final OAuth2User principal;
|
private final OAuth2User principal;
|
||||||
private final OAuth2ClientAuthenticationToken clientAuthentication;
|
private final OAuth2ClientAuthenticationToken clientAuthentication;
|
||||||
|
|
||||||
public OAuth2UserAuthenticationToken(OAuth2ClientAuthenticationToken clientAuthentication) {
|
|
||||||
this(null, Collections.emptyList(), clientAuthentication);
|
|
||||||
}
|
|
||||||
|
|
||||||
public OAuth2UserAuthenticationToken(OAuth2User principal, Collection<? extends GrantedAuthority> authorities,
|
public OAuth2UserAuthenticationToken(OAuth2User principal, Collection<? extends GrantedAuthority> authorities,
|
||||||
OAuth2ClientAuthenticationToken clientAuthentication) {
|
OAuth2ClientAuthenticationToken clientAuthentication) {
|
||||||
super(authorities);
|
super(authorities);
|
||||||
|
@ -22,7 +22,6 @@ import org.springframework.security.oauth2.client.authentication.AuthorizationCo
|
|||||||
import org.springframework.security.oauth2.client.authentication.AuthorizationCodeAuthenticationToken;
|
import org.springframework.security.oauth2.client.authentication.AuthorizationCodeAuthenticationToken;
|
||||||
import org.springframework.security.oauth2.client.authentication.OAuth2AuthenticationException;
|
import org.springframework.security.oauth2.client.authentication.OAuth2AuthenticationException;
|
||||||
import org.springframework.security.oauth2.client.authentication.OAuth2ClientAuthenticationToken;
|
import org.springframework.security.oauth2.client.authentication.OAuth2ClientAuthenticationToken;
|
||||||
import org.springframework.security.oauth2.client.authentication.userinfo.OAuth2UserAuthenticationToken;
|
|
||||||
import org.springframework.security.oauth2.client.registration.ClientRegistration;
|
import org.springframework.security.oauth2.client.registration.ClientRegistration;
|
||||||
import org.springframework.security.oauth2.client.registration.ClientRegistrationRepository;
|
import org.springframework.security.oauth2.client.registration.ClientRegistrationRepository;
|
||||||
import org.springframework.security.oauth2.core.OAuth2Error;
|
import org.springframework.security.oauth2.core.OAuth2Error;
|
||||||
@ -129,8 +128,7 @@ public class AuthorizationCodeAuthenticationFilter extends AbstractAuthenticatio
|
|||||||
OAuth2ClientAuthenticationToken clientAuthentication =
|
OAuth2ClientAuthenticationToken clientAuthentication =
|
||||||
(OAuth2ClientAuthenticationToken)this.getAuthenticationManager().authenticate(authorizationCodeAuthentication);
|
(OAuth2ClientAuthenticationToken)this.getAuthenticationManager().authenticate(authorizationCodeAuthentication);
|
||||||
|
|
||||||
return this.getAuthenticationManager().authenticate(
|
return this.getAuthenticationManager().authenticate(clientAuthentication);
|
||||||
new OAuth2UserAuthenticationToken(clientAuthentication));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public final RequestMatcher getAuthorizationResponseMatcher() {
|
public final RequestMatcher getAuthorizationResponseMatcher() {
|
||||||
|
@ -79,9 +79,9 @@ public class OidcAuthorizationCodeAuthenticationProvider implements Authenticati
|
|||||||
// Section 3.1.2.1 Authentication Request - http://openid.net/specs/openid-connect-core-1_0.html#AuthRequest
|
// Section 3.1.2.1 Authentication Request - http://openid.net/specs/openid-connect-core-1_0.html#AuthRequest
|
||||||
// scope
|
// scope
|
||||||
// REQUIRED. OpenID Connect requests MUST contain the "openid" scope value.
|
// REQUIRED. OpenID Connect requests MUST contain the "openid" scope value.
|
||||||
// If the openid scope value is not present, the behavior is entirely unspecified.
|
|
||||||
if (!authorizationCodeAuthentication.getAuthorizationRequest().getScope().contains(OidcScope.OPENID)) {
|
if (!authorizationCodeAuthentication.getAuthorizationRequest().getScope().contains(OidcScope.OPENID)) {
|
||||||
// Let the standard OAuth 2.0 Authorization Code AuthenticationProvider handle this
|
// This is NOT an OpenID Connect Authentication Request so return null
|
||||||
|
// and let AuthorizationCodeAuthenticationProvider handle it instead
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -17,12 +17,10 @@ package org.springframework.security.oauth2.oidc.client.authentication;
|
|||||||
|
|
||||||
import org.springframework.security.core.Authentication;
|
import org.springframework.security.core.Authentication;
|
||||||
import org.springframework.security.core.GrantedAuthority;
|
import org.springframework.security.core.GrantedAuthority;
|
||||||
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.OAuth2UserAuthenticationToken;
|
||||||
import org.springframework.security.oauth2.oidc.core.user.OidcUser;
|
import org.springframework.security.oauth2.oidc.core.user.OidcUser;
|
||||||
|
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Collections;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An {@link OAuth2UserAuthenticationToken} that represents an
|
* An {@link OAuth2UserAuthenticationToken} that represents an
|
||||||
@ -40,17 +38,9 @@ import java.util.Collections;
|
|||||||
*/
|
*/
|
||||||
public class OidcUserAuthenticationToken extends OAuth2UserAuthenticationToken {
|
public class OidcUserAuthenticationToken extends OAuth2UserAuthenticationToken {
|
||||||
|
|
||||||
public OidcUserAuthenticationToken(OidcClientAuthenticationToken clientAuthentication) {
|
|
||||||
this(null, Collections.emptyList(), clientAuthentication);
|
|
||||||
}
|
|
||||||
|
|
||||||
public OidcUserAuthenticationToken(OidcUser principal, Collection<? extends GrantedAuthority> authorities,
|
public OidcUserAuthenticationToken(OidcUser principal, Collection<? extends GrantedAuthority> authorities,
|
||||||
OidcClientAuthenticationToken clientAuthentication) {
|
OidcClientAuthenticationToken clientAuthentication) {
|
||||||
this(principal, authorities, (OAuth2ClientAuthenticationToken)clientAuthentication);
|
|
||||||
}
|
|
||||||
|
|
||||||
public OidcUserAuthenticationToken(OidcUser principal, Collection<? extends GrantedAuthority> authorities,
|
|
||||||
OAuth2ClientAuthenticationToken clientAuthentication) {
|
|
||||||
super(principal, authorities, clientAuthentication);
|
super(principal, authorities, clientAuthentication);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,104 @@
|
|||||||
|
/*
|
||||||
|
* 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();
|
||||||
|
}
|
||||||
|
}
|
@ -18,9 +18,9 @@ package org.springframework.security.oauth2.oidc.client.authentication.userinfo;
|
|||||||
import org.springframework.security.core.GrantedAuthority;
|
import org.springframework.security.core.GrantedAuthority;
|
||||||
import org.springframework.security.oauth2.client.authentication.OAuth2AuthenticationException;
|
import org.springframework.security.oauth2.client.authentication.OAuth2AuthenticationException;
|
||||||
import org.springframework.security.oauth2.client.authentication.OAuth2ClientAuthenticationToken;
|
import org.springframework.security.oauth2.client.authentication.OAuth2ClientAuthenticationToken;
|
||||||
|
import org.springframework.security.oauth2.client.authentication.userinfo.NimbusUserInfoRetriever;
|
||||||
import org.springframework.security.oauth2.client.authentication.userinfo.OAuth2UserService;
|
import org.springframework.security.oauth2.client.authentication.userinfo.OAuth2UserService;
|
||||||
import org.springframework.security.oauth2.client.authentication.userinfo.UserInfoRetriever;
|
import org.springframework.security.oauth2.client.authentication.userinfo.UserInfoRetriever;
|
||||||
import org.springframework.security.oauth2.client.authentication.userinfo.NimbusUserInfoRetriever;
|
|
||||||
import org.springframework.security.oauth2.core.AuthorizationGrantType;
|
import org.springframework.security.oauth2.core.AuthorizationGrantType;
|
||||||
import org.springframework.security.oauth2.core.user.OAuth2User;
|
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.OidcClientAuthenticationToken;
|
||||||
@ -58,9 +58,6 @@ public class OidcUserService implements OAuth2UserService {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public OAuth2User loadUser(OAuth2ClientAuthenticationToken clientAuthentication) throws OAuth2AuthenticationException {
|
public OAuth2User loadUser(OAuth2ClientAuthenticationToken clientAuthentication) throws OAuth2AuthenticationException {
|
||||||
if (!OidcClientAuthenticationToken.class.isAssignableFrom(clientAuthentication.getClass())) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
OidcClientAuthenticationToken oidcClientAuthentication = (OidcClientAuthenticationToken)clientAuthentication;
|
OidcClientAuthenticationToken oidcClientAuthentication = (OidcClientAuthenticationToken)clientAuthentication;
|
||||||
|
|
||||||
UserInfo userInfo = null;
|
UserInfo userInfo = null;
|
||||||
|
@ -359,7 +359,6 @@ public class OAuth2LoginApplicationTests {
|
|||||||
TokenResponse tokenResponse = TokenResponse.withToken("access-token-1234")
|
TokenResponse tokenResponse = TokenResponse.withToken("access-token-1234")
|
||||||
.tokenType(AccessToken.TokenType.BEARER)
|
.tokenType(AccessToken.TokenType.BEARER)
|
||||||
.expiresIn(60 * 1000)
|
.expiresIn(60 * 1000)
|
||||||
.scope(Collections.singleton("openid"))
|
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
AuthorizationGrantTokenExchanger mock = mock(AuthorizationGrantTokenExchanger.class);
|
AuthorizationGrantTokenExchanger mock = mock(AuthorizationGrantTokenExchanger.class);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user