Rename OAuth2/OIDC ClientAuthenticationToken -> AuthorizedClient
Fixes gh-4695
This commit is contained in:
parent
9b670882b7
commit
5a584e5ccb
|
@ -15,26 +15,22 @@
|
||||||
*/
|
*/
|
||||||
package org.springframework.security.oauth2.client.authentication;
|
package org.springframework.security.oauth2.client.authentication;
|
||||||
|
|
||||||
import org.springframework.security.authentication.AbstractAuthenticationToken;
|
|
||||||
import org.springframework.security.core.Authentication;
|
|
||||||
import org.springframework.security.core.SpringSecurityCoreVersion;
|
|
||||||
import org.springframework.security.oauth2.client.registration.ClientRegistration;
|
import org.springframework.security.oauth2.client.registration.ClientRegistration;
|
||||||
import org.springframework.security.oauth2.core.AccessToken;
|
import org.springframework.security.oauth2.core.AccessToken;
|
||||||
import org.springframework.util.Assert;
|
import org.springframework.util.Assert;
|
||||||
import org.springframework.util.CollectionUtils;
|
import org.springframework.util.CollectionUtils;
|
||||||
|
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An implementation of an {@link AbstractAuthenticationToken}
|
* A representation of an OAuth 2.0 <i>"Authorized Client"</i>.
|
||||||
* that represents an <i>OAuth 2.0 Client</i> {@link Authentication}.
|
|
||||||
*
|
|
||||||
* <p>
|
* <p>
|
||||||
* A client is considered <i>"authenticated"</i>,
|
* A client is considered <i>"authorized"</i>
|
||||||
* if it receives a successful response from the <i>Token Endpoint</i>.
|
* when it receives a successful response from the <i>Token Endpoint</i>.
|
||||||
* This {@link Authentication} associates the client identified in {@link #getClientRegistration()}
|
* <p>
|
||||||
* to the {@link #getAccessToken()} granted by the resource owner.
|
* This class associates the {@link #getClientRegistration() Client}
|
||||||
|
* to the {@link #getAccessToken() Access Token}
|
||||||
|
* granted/authorized by the {@link #getPrincipalName() Resource Owner}.
|
||||||
*
|
*
|
||||||
* @author Joe Grandja
|
* @author Joe Grandja
|
||||||
* @since 5.0
|
* @since 5.0
|
||||||
|
@ -42,34 +38,28 @@ import java.util.Set;
|
||||||
* @see AccessToken
|
* @see AccessToken
|
||||||
* @see <a target="_blank" href="https://tools.ietf.org/html/rfc6749#section-5.1">Section 5.1 Access Token Response</a>
|
* @see <a target="_blank" href="https://tools.ietf.org/html/rfc6749#section-5.1">Section 5.1 Access Token Response</a>
|
||||||
*/
|
*/
|
||||||
public class OAuth2ClientAuthenticationToken extends AbstractAuthenticationToken {
|
public class AuthorizedClient {
|
||||||
private static final long serialVersionUID = SpringSecurityCoreVersion.SERIAL_VERSION_UID;
|
|
||||||
private final ClientRegistration clientRegistration;
|
private final ClientRegistration clientRegistration;
|
||||||
|
private final String principalName;
|
||||||
private final AccessToken accessToken;
|
private final AccessToken accessToken;
|
||||||
|
|
||||||
public OAuth2ClientAuthenticationToken(ClientRegistration clientRegistration, AccessToken accessToken) {
|
public AuthorizedClient(ClientRegistration clientRegistration, String principalName, AccessToken accessToken) {
|
||||||
super(Collections.emptyList());
|
|
||||||
Assert.notNull(clientRegistration, "clientRegistration cannot be null");
|
Assert.notNull(clientRegistration, "clientRegistration cannot be null");
|
||||||
|
Assert.hasText(principalName, "principalName cannot be empty");
|
||||||
Assert.notNull(accessToken, "accessToken cannot be null");
|
Assert.notNull(accessToken, "accessToken cannot be null");
|
||||||
this.clientRegistration = clientRegistration;
|
this.clientRegistration = clientRegistration;
|
||||||
|
this.principalName = principalName;
|
||||||
this.accessToken = accessToken;
|
this.accessToken = accessToken;
|
||||||
this.setAuthenticated(true); // The Client is authenticated by the Authorization Server
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Object getPrincipal() {
|
|
||||||
return this.getClientRegistration().getClientId();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Object getCredentials() {
|
|
||||||
return ""; // No need to expose this.getClientRegistration().getClientSecret()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public ClientRegistration getClientRegistration() {
|
public ClientRegistration getClientRegistration() {
|
||||||
return this.clientRegistration;
|
return this.clientRegistration;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String getPrincipalName() {
|
||||||
|
return this.principalName;
|
||||||
|
}
|
||||||
|
|
||||||
public AccessToken getAccessToken() {
|
public AccessToken getAccessToken() {
|
||||||
return this.accessToken;
|
return this.accessToken;
|
||||||
}
|
}
|
|
@ -51,7 +51,7 @@ import java.util.Collection;
|
||||||
* @see AuthorizationCodeAuthenticationToken
|
* @see AuthorizationCodeAuthenticationToken
|
||||||
* @see SecurityTokenRepository
|
* @see SecurityTokenRepository
|
||||||
* @see OAuth2AuthenticationToken
|
* @see OAuth2AuthenticationToken
|
||||||
* @see OAuth2ClientAuthenticationToken
|
* @see AuthorizedClient
|
||||||
* @see OAuth2UserService
|
* @see OAuth2UserService
|
||||||
* @see OAuth2User
|
* @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">Section 4.1 Authorization Code Grant Flow</a>
|
||||||
|
@ -118,22 +118,25 @@ public class OAuth2LoginAuthenticationProvider implements AuthenticationProvider
|
||||||
tokenResponse.getTokenValue(), tokenResponse.getIssuedAt(),
|
tokenResponse.getTokenValue(), tokenResponse.getIssuedAt(),
|
||||||
tokenResponse.getExpiresAt(), tokenResponse.getScopes());
|
tokenResponse.getExpiresAt(), tokenResponse.getScopes());
|
||||||
|
|
||||||
OAuth2ClientAuthenticationToken clientAuthentication =
|
AuthorizedClient authorizedClient = new AuthorizedClient(
|
||||||
new OAuth2ClientAuthenticationToken(authorizationCodeAuthentication.getClientRegistration(), accessToken);
|
authorizationCodeAuthentication.getClientRegistration(), "unknown", accessToken);
|
||||||
clientAuthentication.setDetails(authorizationCodeAuthentication.getDetails());
|
|
||||||
|
|
||||||
this.accessTokenRepository.saveSecurityToken(
|
this.accessTokenRepository.saveSecurityToken(
|
||||||
clientAuthentication.getAccessToken(),
|
authorizedClient.getAccessToken(),
|
||||||
clientAuthentication.getClientRegistration());
|
authorizedClient.getClientRegistration());
|
||||||
|
|
||||||
OAuth2User oauth2User = this.userService.loadUser(clientAuthentication);
|
OAuth2User oauth2User = this.userService.loadUser(authorizedClient);
|
||||||
|
|
||||||
|
// Update AuthorizedClient now that we know the 'principalName'
|
||||||
|
authorizedClient = new AuthorizedClient(
|
||||||
|
authorizationCodeAuthentication.getClientRegistration(), oauth2User.getName(), accessToken);
|
||||||
|
|
||||||
Collection<? extends GrantedAuthority> mappedAuthorities =
|
Collection<? extends GrantedAuthority> mappedAuthorities =
|
||||||
this.authoritiesMapper.mapAuthorities(oauth2User.getAuthorities());
|
this.authoritiesMapper.mapAuthorities(oauth2User.getAuthorities());
|
||||||
|
|
||||||
OAuth2AuthenticationToken authenticationResult = new OAuth2AuthenticationToken(
|
OAuth2AuthenticationToken authenticationResult = new OAuth2AuthenticationToken(
|
||||||
oauth2User, mappedAuthorities, clientAuthentication);
|
oauth2User, mappedAuthorities, authorizedClient);
|
||||||
authenticationResult.setDetails(clientAuthentication.getDetails());
|
authenticationResult.setDetails(authorizationCodeAuthentication.getDetails());
|
||||||
|
|
||||||
return authenticationResult;
|
return authenticationResult;
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,10 +15,8 @@
|
||||||
*/
|
*/
|
||||||
package org.springframework.security.oauth2.client.authentication.userinfo;
|
package org.springframework.security.oauth2.client.authentication.userinfo;
|
||||||
|
|
||||||
import org.springframework.beans.BeanWrapper;
|
import org.springframework.security.oauth2.client.authentication.AuthorizedClient;
|
||||||
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.core.user.OAuth2User;
|
import org.springframework.security.oauth2.core.user.OAuth2User;
|
||||||
import org.springframework.util.Assert;
|
import org.springframework.util.Assert;
|
||||||
|
|
||||||
|
@ -53,14 +51,14 @@ public class CustomUserTypesOAuth2UserService implements OAuth2UserService {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public OAuth2User loadUser(OAuth2ClientAuthenticationToken clientAuthentication) throws OAuth2AuthenticationException {
|
public OAuth2User loadUser(AuthorizedClient authorizedClient) throws OAuth2AuthenticationException {
|
||||||
URI userInfoUri = URI.create(clientAuthentication.getClientRegistration().getProviderDetails().getUserInfoEndpoint().getUri());
|
URI userInfoUri = URI.create(authorizedClient.getClientRegistration().getProviderDetails().getUserInfoEndpoint().getUri());
|
||||||
Class<? extends OAuth2User> customUserType;
|
Class<? extends OAuth2User> customUserType;
|
||||||
if ((customUserType = this.customUserTypes.get(userInfoUri)) == null) {
|
if ((customUserType = this.customUserTypes.get(userInfoUri)) == null) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
return this.userInfoRetriever.retrieve(clientAuthentication, customUserType);
|
return this.userInfoRetriever.retrieve(authorizedClient, customUserType);
|
||||||
}
|
}
|
||||||
|
|
||||||
public final void setUserInfoRetriever(UserInfoRetriever userInfoRetriever) {
|
public final void setUserInfoRetriever(UserInfoRetriever userInfoRetriever) {
|
||||||
|
|
|
@ -17,7 +17,7 @@ package org.springframework.security.oauth2.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.AuthorizedClient;
|
||||||
import org.springframework.security.oauth2.client.registration.ClientRegistration;
|
import org.springframework.security.oauth2.client.registration.ClientRegistration;
|
||||||
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;
|
||||||
|
@ -52,15 +52,15 @@ public class DefaultOAuth2UserService implements OAuth2UserService {
|
||||||
private UserInfoRetriever userInfoRetriever = new NimbusUserInfoRetriever();
|
private UserInfoRetriever userInfoRetriever = new NimbusUserInfoRetriever();
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public OAuth2User loadUser(OAuth2ClientAuthenticationToken clientAuthentication) throws OAuth2AuthenticationException {
|
public OAuth2User loadUser(AuthorizedClient authorizedClient) throws OAuth2AuthenticationException {
|
||||||
String userNameAttributeName = clientAuthentication.getClientRegistration().getProviderDetails().getUserInfoEndpoint().getUserNameAttributeName();
|
String userNameAttributeName = authorizedClient.getClientRegistration().getProviderDetails().getUserInfoEndpoint().getUserNameAttributeName();
|
||||||
if (!StringUtils.hasText(userNameAttributeName)) {
|
if (!StringUtils.hasText(userNameAttributeName)) {
|
||||||
throw new IllegalArgumentException(
|
throw new IllegalArgumentException(
|
||||||
"Missing required \"user name\" attribute name in UserInfoEndpoint for Client Registration: " +
|
"Missing required \"user name\" attribute name in UserInfoEndpoint for Client Registration: " +
|
||||||
clientAuthentication.getClientRegistration().getRegistrationId());
|
authorizedClient.getClientRegistration().getRegistrationId());
|
||||||
}
|
}
|
||||||
|
|
||||||
Map<String, Object> userAttributes = this.userInfoRetriever.retrieve(clientAuthentication, Map.class);
|
Map<String, Object> userAttributes = this.userInfoRetriever.retrieve(authorizedClient, Map.class);
|
||||||
GrantedAuthority authority = new OAuth2UserAuthority(userAttributes);
|
GrantedAuthority authority = new OAuth2UserAuthority(userAttributes);
|
||||||
Set<GrantedAuthority> authorities = new HashSet<>();
|
Set<GrantedAuthority> authorities = new HashSet<>();
|
||||||
authorities.add(authority);
|
authorities.add(authority);
|
||||||
|
|
|
@ -16,7 +16,7 @@
|
||||||
package org.springframework.security.oauth2.client.authentication.userinfo;
|
package org.springframework.security.oauth2.client.authentication.userinfo;
|
||||||
|
|
||||||
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.AuthorizedClient;
|
||||||
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;
|
||||||
|
|
||||||
|
@ -30,7 +30,7 @@ import java.util.Objects;
|
||||||
* to it's internal <code>List</code> of {@link OAuth2UserService}'s.
|
* to it's internal <code>List</code> of {@link OAuth2UserService}'s.
|
||||||
* <p>
|
* <p>
|
||||||
* Each {@link OAuth2UserService} is given a chance to
|
* Each {@link OAuth2UserService} is given a chance to
|
||||||
* {@link OAuth2UserService#loadUser(OAuth2ClientAuthenticationToken) load} an {@link OAuth2User}
|
* {@link OAuth2UserService#loadUser(AuthorizedClient) load} an {@link OAuth2User}
|
||||||
* with the first <code>non-null</code> {@link OAuth2User} being returned.
|
* with the first <code>non-null</code> {@link OAuth2User} being returned.
|
||||||
*
|
*
|
||||||
* @author Joe Grandja
|
* @author Joe Grandja
|
||||||
|
@ -47,9 +47,9 @@ public class DelegatingOAuth2UserService implements OAuth2UserService {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public OAuth2User loadUser(OAuth2ClientAuthenticationToken clientAuthentication) throws OAuth2AuthenticationException {
|
public OAuth2User loadUser(AuthorizedClient authorizedClient) throws OAuth2AuthenticationException {
|
||||||
OAuth2User oauth2User = this.userServices.stream()
|
OAuth2User oauth2User = this.userServices.stream()
|
||||||
.map(userService -> userService.loadUser(clientAuthentication))
|
.map(userService -> userService.loadUser(authorizedClient))
|
||||||
.filter(Objects::nonNull)
|
.filter(Objects::nonNull)
|
||||||
.findFirst()
|
.findFirst()
|
||||||
.orElse(null);
|
.orElse(null);
|
||||||
|
|
|
@ -28,7 +28,7 @@ import org.springframework.http.converter.HttpMessageConverter;
|
||||||
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
|
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
|
||||||
import org.springframework.security.authentication.AuthenticationServiceException;
|
import org.springframework.security.authentication.AuthenticationServiceException;
|
||||||
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.AuthorizedClient;
|
||||||
import org.springframework.security.oauth2.core.OAuth2Error;
|
import org.springframework.security.oauth2.core.OAuth2Error;
|
||||||
import org.springframework.util.Assert;
|
import org.springframework.util.Assert;
|
||||||
|
|
||||||
|
@ -37,7 +37,6 @@ import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.net.URI;
|
import java.net.URI;
|
||||||
import java.nio.charset.Charset;
|
import java.nio.charset.Charset;
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An implementation of a {@link UserInfoRetriever} that uses the <b>Nimbus OAuth 2.0 SDK</b> internally.
|
* An implementation of a {@link UserInfoRetriever} that uses the <b>Nimbus OAuth 2.0 SDK</b> internally.
|
||||||
|
@ -52,9 +51,9 @@ public class NimbusUserInfoRetriever implements UserInfoRetriever {
|
||||||
private final HttpMessageConverter jackson2HttpMessageConverter = new MappingJackson2HttpMessageConverter();
|
private final HttpMessageConverter jackson2HttpMessageConverter = new MappingJackson2HttpMessageConverter();
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public <T> T retrieve(OAuth2ClientAuthenticationToken clientAuthentication, Class<T> returnType) throws OAuth2AuthenticationException {
|
public <T> T retrieve(AuthorizedClient authorizedClient, Class<T> returnType) throws OAuth2AuthenticationException {
|
||||||
URI userInfoUri = URI.create(clientAuthentication.getClientRegistration().getProviderDetails().getUserInfoEndpoint().getUri());
|
URI userInfoUri = URI.create(authorizedClient.getClientRegistration().getProviderDetails().getUserInfoEndpoint().getUri());
|
||||||
BearerAccessToken accessToken = new BearerAccessToken(clientAuthentication.getAccessToken().getTokenValue());
|
BearerAccessToken accessToken = new BearerAccessToken(authorizedClient.getAccessToken().getTokenValue());
|
||||||
|
|
||||||
UserInfoRequest userInfoRequest = new UserInfoRequest(userInfoUri, accessToken);
|
UserInfoRequest userInfoRequest = new UserInfoRequest(userInfoUri, accessToken);
|
||||||
HTTPRequest httpRequest = userInfoRequest.toHTTPRequest();
|
HTTPRequest httpRequest = userInfoRequest.toHTTPRequest();
|
||||||
|
|
|
@ -19,7 +19,7 @@ import org.springframework.security.authentication.AbstractAuthenticationToken;
|
||||||
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.core.SpringSecurityCoreVersion;
|
import org.springframework.security.core.SpringSecurityCoreVersion;
|
||||||
import org.springframework.security.oauth2.client.authentication.OAuth2ClientAuthenticationToken;
|
import org.springframework.security.oauth2.client.authentication.AuthorizedClient;
|
||||||
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;
|
||||||
|
|
||||||
|
@ -28,28 +28,28 @@ import java.util.Collection;
|
||||||
/**
|
/**
|
||||||
* An implementation of an {@link AbstractAuthenticationToken}
|
* An implementation of an {@link AbstractAuthenticationToken}
|
||||||
* that represents an <i>OAuth 2.0</i> {@link Authentication}.
|
* that represents an <i>OAuth 2.0</i> {@link Authentication}.
|
||||||
*
|
|
||||||
* <p>
|
* <p>
|
||||||
* This {@link Authentication} associates an {@link OAuth2User} principal to an
|
* This {@link Authentication} associates an {@link OAuth2User} principal
|
||||||
* {@link OAuth2ClientAuthenticationToken} which represents the <i>"Authorized Client"</i>.
|
* to an {@link AuthorizedClient}.
|
||||||
*
|
*
|
||||||
* @author Joe Grandja
|
* @author Joe Grandja
|
||||||
* @since 5.0
|
* @since 5.0
|
||||||
* @see OAuth2User
|
* @see OAuth2User
|
||||||
* @see OAuth2ClientAuthenticationToken
|
* @see AuthorizedClient
|
||||||
*/
|
*/
|
||||||
public class OAuth2AuthenticationToken extends AbstractAuthenticationToken {
|
public class OAuth2AuthenticationToken extends AbstractAuthenticationToken {
|
||||||
private static final long serialVersionUID = SpringSecurityCoreVersion.SERIAL_VERSION_UID;
|
private static final long serialVersionUID = SpringSecurityCoreVersion.SERIAL_VERSION_UID;
|
||||||
private final OAuth2User principal;
|
private final OAuth2User principal;
|
||||||
private final OAuth2ClientAuthenticationToken clientAuthentication;
|
private final AuthorizedClient authorizedClient;
|
||||||
|
|
||||||
public OAuth2AuthenticationToken(OAuth2User principal, Collection<? extends GrantedAuthority> authorities,
|
public OAuth2AuthenticationToken(OAuth2User principal, Collection<? extends GrantedAuthority> authorities,
|
||||||
OAuth2ClientAuthenticationToken clientAuthentication) {
|
AuthorizedClient authorizedClient) {
|
||||||
super(authorities);
|
super(authorities);
|
||||||
Assert.notNull(clientAuthentication, "clientAuthentication cannot be null");
|
Assert.notNull(principal, "principal cannot be null");
|
||||||
|
Assert.notNull(authorizedClient, "authorizedClient cannot be null");
|
||||||
this.principal = principal;
|
this.principal = principal;
|
||||||
this.clientAuthentication = clientAuthentication;
|
this.authorizedClient = authorizedClient;
|
||||||
this.setAuthenticated(principal != null);
|
this.setAuthenticated(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -63,7 +63,7 @@ public class OAuth2AuthenticationToken extends AbstractAuthenticationToken {
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
public OAuth2ClientAuthenticationToken getClientAuthentication() {
|
public AuthorizedClient getAuthorizedClient() {
|
||||||
return this.clientAuthentication;
|
return this.authorizedClient;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,24 +16,24 @@
|
||||||
package org.springframework.security.oauth2.client.authentication.userinfo;
|
package org.springframework.security.oauth2.client.authentication.userinfo;
|
||||||
|
|
||||||
import org.springframework.security.core.AuthenticatedPrincipal;
|
import org.springframework.security.core.AuthenticatedPrincipal;
|
||||||
|
import org.springframework.security.oauth2.client.authentication.AuthorizedClient;
|
||||||
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.core.user.OAuth2User;
|
import org.springframework.security.oauth2.core.user.OAuth2User;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Implementations of this interface are responsible for obtaining the user attributes
|
* Implementations of this interface are responsible for obtaining the user attributes
|
||||||
* of the <i>End-User</i> (resource owner) from the <i>UserInfo Endpoint</i>
|
* of the <i>End-User</i> (resource owner) from the <i>UserInfo Endpoint</i>
|
||||||
* using the provided {@link OAuth2ClientAuthenticationToken#getAccessToken()}
|
* using the provided {@link AuthorizedClient#getAccessToken()}
|
||||||
* and returning an {@link AuthenticatedPrincipal} in the form of an {@link OAuth2User}.
|
* and returning an {@link AuthenticatedPrincipal} in the form of an {@link OAuth2User}.
|
||||||
*
|
*
|
||||||
* @author Joe Grandja
|
* @author Joe Grandja
|
||||||
* @since 5.0
|
* @since 5.0
|
||||||
* @see OAuth2ClientAuthenticationToken
|
* @see AuthorizedClient
|
||||||
* @see AuthenticatedPrincipal
|
* @see AuthenticatedPrincipal
|
||||||
* @see OAuth2User
|
* @see OAuth2User
|
||||||
*/
|
*/
|
||||||
public interface OAuth2UserService {
|
public interface OAuth2UserService {
|
||||||
|
|
||||||
OAuth2User loadUser(OAuth2ClientAuthenticationToken clientAuthentication) throws OAuth2AuthenticationException;
|
OAuth2User loadUser(AuthorizedClient authorizedClient) throws OAuth2AuthenticationException;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,23 +15,22 @@
|
||||||
*/
|
*/
|
||||||
package org.springframework.security.oauth2.client.authentication.userinfo;
|
package org.springframework.security.oauth2.client.authentication.userinfo;
|
||||||
|
|
||||||
import org.springframework.core.ParameterizedTypeReference;
|
|
||||||
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.AuthorizedClient;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A strategy for retrieving the user attributes
|
* A strategy for retrieving the user attributes
|
||||||
* of the <i>End-User</i> (resource owner) from the <i>UserInfo Endpoint</i>
|
* of the <i>End-User</i> (resource owner) from the <i>UserInfo Endpoint</i>
|
||||||
* using the provided {@link OAuth2ClientAuthenticationToken#getAccessToken()}.
|
* using the provided {@link AuthorizedClient#getAccessToken()}.
|
||||||
*
|
*
|
||||||
* @author Joe Grandja
|
* @author Joe Grandja
|
||||||
* @author Rob Winch
|
* @author Rob Winch
|
||||||
* @since 5.0
|
* @since 5.0
|
||||||
* @see OAuth2ClientAuthenticationToken
|
* @see AuthorizedClient
|
||||||
* @see OAuth2UserService
|
* @see OAuth2UserService
|
||||||
*/
|
*/
|
||||||
public interface UserInfoRetriever {
|
public interface UserInfoRetriever {
|
||||||
|
|
||||||
<T> T retrieve(OAuth2ClientAuthenticationToken clientAuthentication, Class<T> responseType) throws OAuth2AuthenticationException;
|
<T> T retrieve(AuthorizedClient clientAuthentication, Class<T> responseType) throws OAuth2AuthenticationException;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -62,7 +62,7 @@ import java.util.Collection;
|
||||||
* @since 5.0
|
* @since 5.0
|
||||||
* @see AuthorizationCodeAuthenticationToken
|
* @see AuthorizationCodeAuthenticationToken
|
||||||
* @see SecurityTokenRepository
|
* @see SecurityTokenRepository
|
||||||
* @see OidcClientAuthenticationToken
|
* @see OidcAuthorizedClient
|
||||||
* @see OidcUserService
|
* @see OidcUserService
|
||||||
* @see OidcUser
|
* @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#CodeFlowAuth">Section 3.1 Authorization Code Grant Flow</a>
|
||||||
|
@ -142,28 +142,32 @@ public class OidcAuthorizationCodeAuthenticationProvider implements Authenticati
|
||||||
|
|
||||||
JwtDecoder jwtDecoder = this.jwtDecoderRegistry.getJwtDecoder(clientRegistration);
|
JwtDecoder jwtDecoder = this.jwtDecoderRegistry.getJwtDecoder(clientRegistration);
|
||||||
if (jwtDecoder == null) {
|
if (jwtDecoder == null) {
|
||||||
throw new IllegalArgumentException("Failed to find a registered JwtDecoder for Client Registration: '" + clientRegistration.getRegistrationId() +
|
throw new IllegalArgumentException("Failed to find a registered JwtDecoder for Client Registration: '" +
|
||||||
"'. Check to ensure you have configured the JwkSet URI.");
|
clientRegistration.getRegistrationId() + "'. Check to ensure you have configured the JwkSet URI.");
|
||||||
}
|
}
|
||||||
Jwt jwt = jwtDecoder.decode((String)tokenResponse.getAdditionalParameters().get(OidcParameter.ID_TOKEN));
|
Jwt jwt = jwtDecoder.decode((String)tokenResponse.getAdditionalParameters().get(OidcParameter.ID_TOKEN));
|
||||||
IdToken idToken = new IdToken(jwt.getTokenValue(), jwt.getIssuedAt(), jwt.getExpiresAt(), jwt.getClaims());
|
IdToken idToken = new IdToken(jwt.getTokenValue(), jwt.getIssuedAt(), jwt.getExpiresAt(), jwt.getClaims());
|
||||||
|
|
||||||
OidcClientAuthenticationToken clientAuthentication =
|
OidcAuthorizedClient authorizedClient = new OidcAuthorizedClient(
|
||||||
new OidcClientAuthenticationToken(clientRegistration, accessToken, idToken);
|
clientRegistration, idToken.getSubject(), accessToken, idToken);
|
||||||
clientAuthentication.setDetails(authorizationCodeAuthentication.getDetails());
|
|
||||||
|
|
||||||
this.accessTokenRepository.saveSecurityToken(
|
this.accessTokenRepository.saveSecurityToken(
|
||||||
clientAuthentication.getAccessToken(),
|
authorizedClient.getAccessToken(),
|
||||||
clientAuthentication.getClientRegistration());
|
authorizedClient.getClientRegistration());
|
||||||
|
|
||||||
OAuth2User oauth2User = this.userService.loadUser(clientAuthentication);
|
OAuth2User oauth2User = this.userService.loadUser(authorizedClient);
|
||||||
|
|
||||||
|
// Update AuthorizedClient as the 'principalName' may have changed
|
||||||
|
// (the default IdToken.subject) from the result of userService.loadUser()
|
||||||
|
authorizedClient = new OidcAuthorizedClient(
|
||||||
|
clientRegistration, oauth2User.getName(), accessToken, idToken);
|
||||||
|
|
||||||
Collection<? extends GrantedAuthority> mappedAuthorities =
|
Collection<? extends GrantedAuthority> mappedAuthorities =
|
||||||
this.authoritiesMapper.mapAuthorities(oauth2User.getAuthorities());
|
this.authoritiesMapper.mapAuthorities(oauth2User.getAuthorities());
|
||||||
|
|
||||||
OAuth2AuthenticationToken authenticationResult = new OAuth2AuthenticationToken(
|
OAuth2AuthenticationToken authenticationResult = new OAuth2AuthenticationToken(
|
||||||
oauth2User, mappedAuthorities, clientAuthentication);
|
oauth2User, mappedAuthorities, authorizedClient);
|
||||||
authenticationResult.setDetails(clientAuthentication.getDetails());
|
authenticationResult.setDetails(authorizationCodeAuthentication.getDetails());
|
||||||
|
|
||||||
return authenticationResult;
|
return authenticationResult;
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,37 +15,36 @@
|
||||||
*/
|
*/
|
||||||
package org.springframework.security.oauth2.oidc.client.authentication;
|
package org.springframework.security.oauth2.oidc.client.authentication;
|
||||||
|
|
||||||
import org.springframework.security.core.Authentication;
|
import org.springframework.security.oauth2.client.authentication.AuthorizedClient;
|
||||||
import org.springframework.security.oauth2.client.authentication.OAuth2ClientAuthenticationToken;
|
|
||||||
import org.springframework.security.oauth2.client.registration.ClientRegistration;
|
import org.springframework.security.oauth2.client.registration.ClientRegistration;
|
||||||
import org.springframework.security.oauth2.core.AccessToken;
|
import org.springframework.security.oauth2.core.AccessToken;
|
||||||
import org.springframework.security.oauth2.oidc.core.IdToken;
|
import org.springframework.security.oauth2.oidc.core.IdToken;
|
||||||
import org.springframework.util.Assert;
|
import org.springframework.util.Assert;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An {@link OAuth2ClientAuthenticationToken} that represents an
|
* A representation of an OpenID Connect 1.0 <i>"Authorized Client"</i>.
|
||||||
* <i>OpenID Connect 1.0 Client</i> {@link Authentication}.
|
|
||||||
*
|
|
||||||
* <p>
|
* <p>
|
||||||
* A client is considered <i>"authenticated"</i>,
|
* A client is considered <i>"authorized"</i>
|
||||||
* if it receives a successful response from the <i>Token Endpoint</i>.
|
* when it receives a successful response from the <i>Token Endpoint</i>.
|
||||||
* This {@link Authentication} associates the client identified in {@link #getClientRegistration()}
|
* <p>
|
||||||
* to the {@link #getAccessToken()} granted by the resource owner along with the {@link #getIdToken()}
|
* This class associates the {@link #getClientRegistration() Client}
|
||||||
* containing Claims about the authentication of the End-User.
|
* to the {@link #getAccessToken() Access Token}
|
||||||
|
* granted/authorized by the {@link #getPrincipalName() Resource Owner}, along with
|
||||||
|
* the {@link #getIdToken() ID Token} which contains Claims about the authentication of the End-User.
|
||||||
*
|
*
|
||||||
* @author Joe Grandja
|
* @author Joe Grandja
|
||||||
* @since 5.0
|
* @since 5.0
|
||||||
* @see IdToken
|
* @see IdToken
|
||||||
* @see OAuth2ClientAuthenticationToken
|
* @see AuthorizedClient
|
||||||
* @see <a target="_blank" href="http://openid.net/specs/openid-connect-core-1_0.html#TokenResponse">3.1.3.3 Successful Token Response</a>
|
* @see <a target="_blank" href="http://openid.net/specs/openid-connect-core-1_0.html#TokenResponse">3.1.3.3 Successful Token Response</a>
|
||||||
*/
|
*/
|
||||||
public class OidcClientAuthenticationToken extends OAuth2ClientAuthenticationToken {
|
public class OidcAuthorizedClient extends AuthorizedClient {
|
||||||
private final IdToken idToken;
|
private final IdToken idToken;
|
||||||
|
|
||||||
public OidcClientAuthenticationToken(ClientRegistration clientRegistration,
|
public OidcAuthorizedClient(ClientRegistration clientRegistration, String principalName,
|
||||||
AccessToken accessToken, IdToken idToken) {
|
AccessToken accessToken, IdToken idToken) {
|
||||||
|
|
||||||
super(clientRegistration, accessToken);
|
super(clientRegistration, principalName, accessToken);
|
||||||
Assert.notNull(idToken, "idToken cannot be null");
|
Assert.notNull(idToken, "idToken cannot be null");
|
||||||
this.idToken = idToken;
|
this.idToken = idToken;
|
||||||
}
|
}
|
|
@ -16,15 +16,15 @@
|
||||||
package org.springframework.security.oauth2.oidc.client.authentication.userinfo;
|
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.AuthorizedClient;
|
||||||
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.userinfo.NimbusUserInfoRetriever;
|
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.core.AuthorizationGrantType;
|
import org.springframework.security.oauth2.core.AuthorizationGrantType;
|
||||||
import org.springframework.security.oauth2.core.OAuth2Error;
|
import org.springframework.security.oauth2.core.OAuth2Error;
|
||||||
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.OidcAuthorizedClient;
|
||||||
import org.springframework.security.oauth2.oidc.core.OidcScope;
|
import org.springframework.security.oauth2.oidc.core.OidcScope;
|
||||||
import org.springframework.security.oauth2.oidc.core.UserInfo;
|
import org.springframework.security.oauth2.oidc.core.UserInfo;
|
||||||
import org.springframework.security.oauth2.oidc.core.user.DefaultOidcUser;
|
import org.springframework.security.oauth2.oidc.core.user.DefaultOidcUser;
|
||||||
|
@ -47,7 +47,7 @@ import java.util.Set;
|
||||||
* @author Joe Grandja
|
* @author Joe Grandja
|
||||||
* @since 5.0
|
* @since 5.0
|
||||||
* @see OAuth2UserService
|
* @see OAuth2UserService
|
||||||
* @see OidcClientAuthenticationToken
|
* @see OidcAuthorizedClient
|
||||||
* @see DefaultOidcUser
|
* @see DefaultOidcUser
|
||||||
* @see UserInfo
|
* @see UserInfo
|
||||||
* @see UserInfoRetriever
|
* @see UserInfoRetriever
|
||||||
|
@ -59,12 +59,12 @@ public class OidcUserService implements OAuth2UserService {
|
||||||
Arrays.asList(OidcScope.PROFILE, OidcScope.EMAIL, OidcScope.ADDRESS, OidcScope.PHONE));
|
Arrays.asList(OidcScope.PROFILE, OidcScope.EMAIL, OidcScope.ADDRESS, OidcScope.PHONE));
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public OAuth2User loadUser(OAuth2ClientAuthenticationToken clientAuthentication) throws OAuth2AuthenticationException {
|
public OAuth2User loadUser(AuthorizedClient authorizedClient) throws OAuth2AuthenticationException {
|
||||||
OidcClientAuthenticationToken oidcClientAuthentication = (OidcClientAuthenticationToken)clientAuthentication;
|
OidcAuthorizedClient oidcAuthorizedClient = (OidcAuthorizedClient)authorizedClient;
|
||||||
|
|
||||||
UserInfo userInfo = null;
|
UserInfo userInfo = null;
|
||||||
if (this.shouldRetrieveUserInfo(oidcClientAuthentication)) {
|
if (this.shouldRetrieveUserInfo(oidcAuthorizedClient)) {
|
||||||
Map<String, Object> userAttributes = this.userInfoRetriever.retrieve(oidcClientAuthentication, Map.class);
|
Map<String, Object> userAttributes = this.userInfoRetriever.retrieve(oidcAuthorizedClient, Map.class);
|
||||||
userInfo = new UserInfo(userAttributes);
|
userInfo = new UserInfo(userAttributes);
|
||||||
|
|
||||||
// http://openid.net/specs/openid-connect-core-1_0.html#UserInfoResponse
|
// http://openid.net/specs/openid-connect-core-1_0.html#UserInfoResponse
|
||||||
|
@ -74,17 +74,17 @@ public class OidcUserService implements OAuth2UserService {
|
||||||
// The sub Claim in the UserInfo Response MUST be verified to exactly match
|
// The sub Claim in the UserInfo Response MUST be verified to exactly match
|
||||||
// the sub Claim in the ID Token; if they do not match,
|
// the sub Claim in the ID Token; if they do not match,
|
||||||
// the UserInfo Response values MUST NOT be used.
|
// the UserInfo Response values MUST NOT be used.
|
||||||
if (!userInfo.getSubject().equals(oidcClientAuthentication.getIdToken().getSubject())) {
|
if (!userInfo.getSubject().equals(oidcAuthorizedClient.getIdToken().getSubject())) {
|
||||||
OAuth2Error oauth2Error = new OAuth2Error(INVALID_USER_INFO_RESPONSE_ERROR_CODE);
|
OAuth2Error oauth2Error = new OAuth2Error(INVALID_USER_INFO_RESPONSE_ERROR_CODE);
|
||||||
throw new OAuth2AuthenticationException(oauth2Error, oauth2Error.toString());
|
throw new OAuth2AuthenticationException(oauth2Error, oauth2Error.toString());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
GrantedAuthority authority = new OidcUserAuthority(oidcClientAuthentication.getIdToken(), userInfo);
|
GrantedAuthority authority = new OidcUserAuthority(oidcAuthorizedClient.getIdToken(), userInfo);
|
||||||
Set<GrantedAuthority> authorities = new HashSet<>();
|
Set<GrantedAuthority> authorities = new HashSet<>();
|
||||||
authorities.add(authority);
|
authorities.add(authority);
|
||||||
|
|
||||||
return new DefaultOidcUser(authorities, oidcClientAuthentication.getIdToken(), userInfo);
|
return new DefaultOidcUser(authorities, oidcAuthorizedClient.getIdToken(), userInfo);
|
||||||
}
|
}
|
||||||
|
|
||||||
public final void setUserInfoRetriever(UserInfoRetriever userInfoRetriever) {
|
public final void setUserInfoRetriever(UserInfoRetriever userInfoRetriever) {
|
||||||
|
@ -92,9 +92,9 @@ public class OidcUserService implements OAuth2UserService {
|
||||||
this.userInfoRetriever = userInfoRetriever;
|
this.userInfoRetriever = userInfoRetriever;
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean shouldRetrieveUserInfo(OidcClientAuthenticationToken oidcClientAuthentication) {
|
private boolean shouldRetrieveUserInfo(OidcAuthorizedClient oidcAuthorizedClient) {
|
||||||
// Auto-disabled if UserInfo Endpoint URI is not provided
|
// Auto-disabled if UserInfo Endpoint URI is not provided
|
||||||
if (StringUtils.isEmpty(oidcClientAuthentication.getClientRegistration().getProviderDetails()
|
if (StringUtils.isEmpty(oidcAuthorizedClient.getClientRegistration().getProviderDetails()
|
||||||
.getUserInfoEndpoint().getUri())) {
|
.getUserInfoEndpoint().getUri())) {
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
|
@ -107,10 +107,10 @@ public class OidcUserService implements OAuth2UserService {
|
||||||
// the resulting Claims are returned in the ID Token.
|
// the resulting Claims are returned in the ID Token.
|
||||||
// The Authorization Code Grant Flow, which is response_type=code, results in an Access Token being issued.
|
// The Authorization Code Grant Flow, which is response_type=code, results in an Access Token being issued.
|
||||||
if (AuthorizationGrantType.AUTHORIZATION_CODE.equals(
|
if (AuthorizationGrantType.AUTHORIZATION_CODE.equals(
|
||||||
oidcClientAuthentication.getClientRegistration().getAuthorizationGrantType())) {
|
oidcAuthorizedClient.getClientRegistration().getAuthorizationGrantType())) {
|
||||||
|
|
||||||
// Return true if there is at least one match between the authorized scope(s) and UserInfo scope(s)
|
// Return true if there is at least one match between the authorized scope(s) and UserInfo scope(s)
|
||||||
return oidcClientAuthentication.getAuthorizedScopes().stream().anyMatch(userInfoScopes::contains);
|
return oidcAuthorizedClient.getAuthorizedScopes().stream().anyMatch(userInfoScopes::contains);
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
|
|
|
@ -28,7 +28,7 @@ import org.springframework.security.core.AuthenticationException;
|
||||||
import org.springframework.security.core.authority.AuthorityUtils;
|
import org.springframework.security.core.authority.AuthorityUtils;
|
||||||
import org.springframework.security.core.context.SecurityContextHolder;
|
import org.springframework.security.core.context.SecurityContextHolder;
|
||||||
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.AuthorizedClient;
|
||||||
import org.springframework.security.oauth2.client.authentication.userinfo.OAuth2AuthenticationToken;
|
import org.springframework.security.oauth2.client.authentication.userinfo.OAuth2AuthenticationToken;
|
||||||
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;
|
||||||
|
@ -98,13 +98,13 @@ public class OAuth2LoginAuthenticationFilterTests {
|
||||||
@Test
|
@Test
|
||||||
public void doFilterWhenAuthorizationCodeSuccessResponseThenAuthenticationSuccessHandlerIsCalled() throws Exception {
|
public void doFilterWhenAuthorizationCodeSuccessResponseThenAuthenticationSuccessHandlerIsCalled() throws Exception {
|
||||||
ClientRegistration clientRegistration = TestUtil.githubClientRegistration();
|
ClientRegistration clientRegistration = TestUtil.githubClientRegistration();
|
||||||
OAuth2ClientAuthenticationToken clientAuthentication = new OAuth2ClientAuthenticationToken(
|
AuthorizedClient authorizedClient = new AuthorizedClient(
|
||||||
clientRegistration, mock(AccessToken.class));
|
clientRegistration, "principal", mock(AccessToken.class));
|
||||||
OAuth2AuthenticationToken userAuthentication = new OAuth2AuthenticationToken(
|
OAuth2AuthenticationToken userAuthentication = new OAuth2AuthenticationToken(
|
||||||
mock(OAuth2User.class), AuthorityUtils.createAuthorityList("ROLE_USER"), clientAuthentication);
|
mock(OAuth2User.class), AuthorityUtils.createAuthorityList("ROLE_USER"), authorizedClient);
|
||||||
SecurityContextHolder.getContext().setAuthentication(userAuthentication);
|
SecurityContextHolder.getContext().setAuthentication(userAuthentication);
|
||||||
AuthenticationManager authenticationManager = mock(AuthenticationManager.class);
|
AuthenticationManager authenticationManager = mock(AuthenticationManager.class);
|
||||||
Mockito.when(authenticationManager.authenticate(Matchers.any(Authentication.class))).thenReturn(clientAuthentication);
|
Mockito.when(authenticationManager.authenticate(Matchers.any(Authentication.class))).thenReturn(userAuthentication);
|
||||||
|
|
||||||
OAuth2LoginAuthenticationFilter filter = Mockito.spy(setupFilter(authenticationManager, clientRegistration));
|
OAuth2LoginAuthenticationFilter filter = Mockito.spy(setupFilter(authenticationManager, clientRegistration));
|
||||||
AuthenticationSuccessHandler successHandler = mock(AuthenticationSuccessHandler.class);
|
AuthenticationSuccessHandler successHandler = mock(AuthenticationSuccessHandler.class);
|
||||||
|
@ -128,7 +128,7 @@ public class OAuth2LoginAuthenticationFilterTests {
|
||||||
ArgumentCaptor<Authentication> authenticationArgCaptor = ArgumentCaptor.forClass(Authentication.class);
|
ArgumentCaptor<Authentication> authenticationArgCaptor = ArgumentCaptor.forClass(Authentication.class);
|
||||||
Mockito.verify(successHandler).onAuthenticationSuccess(Matchers.any(HttpServletRequest.class), Matchers.any(HttpServletResponse.class),
|
Mockito.verify(successHandler).onAuthenticationSuccess(Matchers.any(HttpServletRequest.class), Matchers.any(HttpServletResponse.class),
|
||||||
authenticationArgCaptor.capture());
|
authenticationArgCaptor.capture());
|
||||||
Assertions.assertThat(authenticationArgCaptor.getValue()).isEqualTo(clientAuthentication);
|
Assertions.assertThat(authenticationArgCaptor.getValue()).isEqualTo(userAuthentication);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|
|
@ -40,14 +40,14 @@ public class MainController {
|
||||||
@RequestMapping("/")
|
@RequestMapping("/")
|
||||||
public String index(Model model, @AuthenticationPrincipal OAuth2User user, OAuth2AuthenticationToken authentication) {
|
public String index(Model model, @AuthenticationPrincipal OAuth2User user, OAuth2AuthenticationToken authentication) {
|
||||||
model.addAttribute("userName", user.getName());
|
model.addAttribute("userName", user.getName());
|
||||||
model.addAttribute("clientName", authentication.getClientAuthentication().getClientRegistration().getClientName());
|
model.addAttribute("clientName", authentication.getAuthorizedClient().getClientRegistration().getClientName());
|
||||||
return "index";
|
return "index";
|
||||||
}
|
}
|
||||||
|
|
||||||
@RequestMapping("/userinfo")
|
@RequestMapping("/userinfo")
|
||||||
public String userinfo(Model model, OAuth2AuthenticationToken authentication) {
|
public String userinfo(Model model, OAuth2AuthenticationToken authentication) {
|
||||||
Map userAttributes = Collections.emptyMap();
|
Map userAttributes = Collections.emptyMap();
|
||||||
String userInfoEndpointUri = authentication.getClientAuthentication().getClientRegistration()
|
String userInfoEndpointUri = authentication.getAuthorizedClient().getClientRegistration()
|
||||||
.getProviderDetails().getUserInfoEndpoint().getUri();
|
.getProviderDetails().getUserInfoEndpoint().getUri();
|
||||||
if (!StringUtils.isEmpty(userInfoEndpointUri)) { // userInfoEndpointUri is optional for OIDC Clients
|
if (!StringUtils.isEmpty(userInfoEndpointUri)) { // userInfoEndpointUri is optional for OIDC Clients
|
||||||
userAttributes = WebClient.builder()
|
userAttributes = WebClient.builder()
|
||||||
|
@ -67,7 +67,7 @@ public class MainController {
|
||||||
return ExchangeFilterFunction.ofRequestProcessor(
|
return ExchangeFilterFunction.ofRequestProcessor(
|
||||||
clientRequest -> {
|
clientRequest -> {
|
||||||
ClientRequest authorizedRequest = ClientRequest.from(clientRequest)
|
ClientRequest authorizedRequest = ClientRequest.from(clientRequest)
|
||||||
.header(HttpHeaders.AUTHORIZATION, "Bearer " + authentication.getClientAuthentication().getAccessToken().getTokenValue())
|
.header(HttpHeaders.AUTHORIZATION, "Bearer " + authentication.getAuthorizedClient().getAccessToken().getTokenValue())
|
||||||
.build();
|
.build();
|
||||||
return Mono.just(authorizedRequest);
|
return Mono.just(authorizedRequest);
|
||||||
});
|
});
|
||||||
|
|
Loading…
Reference in New Issue