diff --git a/config/src/main/java/org/springframework/security/config/annotation/web/configurers/oauth2/client/OAuth2LoginConfigurer.java b/config/src/main/java/org/springframework/security/config/annotation/web/configurers/oauth2/client/OAuth2LoginConfigurer.java index 35becbb24b..8a2f2ed5df 100644 --- a/config/src/main/java/org/springframework/security/config/annotation/web/configurers/oauth2/client/OAuth2LoginConfigurer.java +++ b/config/src/main/java/org/springframework/security/config/annotation/web/configurers/oauth2/client/OAuth2LoginConfigurer.java @@ -20,16 +20,15 @@ import org.springframework.core.ResolvableType; import org.springframework.security.config.annotation.web.HttpSecurityBuilder; import org.springframework.security.config.annotation.web.configurers.AbstractAuthenticationFilterConfigurer; import org.springframework.security.core.authority.mapping.GrantedAuthoritiesMapper; -import org.springframework.security.oauth2.client.OAuth2AuthorizedClient; -import org.springframework.security.oauth2.client.authentication.OAuth2AuthorizationCodeAuthenticationToken; import org.springframework.security.oauth2.client.authentication.AuthorizationGrantTokenExchanger; import org.springframework.security.oauth2.client.authentication.NimbusAuthorizationCodeTokenExchanger; +import org.springframework.security.oauth2.client.authentication.OAuth2AuthorizationCodeAuthenticationToken; import org.springframework.security.oauth2.client.authentication.OAuth2LoginAuthenticationProvider; import org.springframework.security.oauth2.client.endpoint.AuthorizationRequestUriBuilder; import org.springframework.security.oauth2.client.jwt.JwtDecoderRegistry; import org.springframework.security.oauth2.client.jwt.NimbusJwtDecoderRegistry; -import org.springframework.security.oauth2.client.oidc.OidcAuthorizedClient; import org.springframework.security.oauth2.client.oidc.authentication.OidcAuthorizationCodeAuthenticationProvider; +import org.springframework.security.oauth2.client.oidc.userinfo.OidcUserRequest; import org.springframework.security.oauth2.client.oidc.userinfo.OidcUserService; import org.springframework.security.oauth2.client.registration.ClientRegistration; import org.springframework.security.oauth2.client.registration.ClientRegistrationRepository; @@ -38,9 +37,10 @@ import org.springframework.security.oauth2.client.token.OAuth2TokenRepository; import org.springframework.security.oauth2.client.userinfo.CustomUserTypesOAuth2UserService; import org.springframework.security.oauth2.client.userinfo.DefaultOAuth2UserService; import org.springframework.security.oauth2.client.userinfo.DelegatingOAuth2UserService; +import org.springframework.security.oauth2.client.userinfo.OAuth2UserRequest; import org.springframework.security.oauth2.client.userinfo.OAuth2UserService; -import org.springframework.security.oauth2.client.web.OAuth2AuthorizationRequestRedirectFilter; import org.springframework.security.oauth2.client.web.AuthorizationRequestRepository; +import org.springframework.security.oauth2.client.web.OAuth2AuthorizationRequestRedirectFilter; import org.springframework.security.oauth2.client.web.OAuth2LoginAuthenticationFilter; import org.springframework.security.oauth2.core.OAuth2AccessToken; import org.springframework.security.oauth2.core.endpoint.OAuth2AuthorizationRequest; @@ -192,14 +192,14 @@ public final class OAuth2LoginConfigurer> exten } public class UserInfoEndpointConfig { - private OAuth2UserService userService; + private OAuth2UserService userService; private Map> customUserTypes = new HashMap<>(); private GrantedAuthoritiesMapper userAuthoritiesMapper; private UserInfoEndpointConfig() { } - public UserInfoEndpointConfig userService(OAuth2UserService userService) { + public UserInfoEndpointConfig userService(OAuth2UserService userService) { Assert.notNull(userService, "userService cannot be null"); this.userService = userService; return this; @@ -233,10 +233,10 @@ public final class OAuth2LoginConfigurer> exten authorizationCodeTokenExchanger = new NimbusAuthorizationCodeTokenExchanger(); } - OAuth2UserService oauth2UserService = this.userInfoEndpointConfig.userService; + OAuth2UserService oauth2UserService = this.userInfoEndpointConfig.userService; if (oauth2UserService == null) { if (!this.userInfoEndpointConfig.customUserTypes.isEmpty()) { - List> userServices = new ArrayList<>(); + List> userServices = new ArrayList<>(); userServices.add(new CustomUserTypesOAuth2UserService(this.userInfoEndpointConfig.customUserTypes)); userServices.add(new DefaultOAuth2UserService()); oauth2UserService = new DelegatingOAuth2UserService<>(userServices); @@ -258,7 +258,7 @@ public final class OAuth2LoginConfigurer> exten } http.authenticationProvider(this.postProcess(oauth2LoginAuthenticationProvider)); - OAuth2UserService oidcUserService = new OidcUserService(); + OAuth2UserService oidcUserService = new OidcUserService(); OidcAuthorizationCodeAuthenticationProvider oidcAuthorizationCodeAuthenticationProvider = new OidcAuthorizationCodeAuthenticationProvider( authorizationCodeTokenExchanger, oidcUserService, jwtDecoderRegistry); diff --git a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/authentication/OAuth2LoginAuthenticationProvider.java b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/authentication/OAuth2LoginAuthenticationProvider.java index 241e576fd3..3fea17a510 100644 --- a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/authentication/OAuth2LoginAuthenticationProvider.java +++ b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/authentication/OAuth2LoginAuthenticationProvider.java @@ -21,13 +21,14 @@ 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.OAuth2AuthorizedClient; +import org.springframework.security.oauth2.client.userinfo.OAuth2UserRequest; import org.springframework.security.oauth2.client.userinfo.OAuth2UserService; import org.springframework.security.oauth2.core.OAuth2AccessToken; import org.springframework.security.oauth2.core.OAuth2AuthenticationException; import org.springframework.security.oauth2.core.OAuth2Error; +import org.springframework.security.oauth2.core.endpoint.OAuth2AccessTokenResponse; import org.springframework.security.oauth2.core.endpoint.OAuth2AuthorizationRequest; import org.springframework.security.oauth2.core.endpoint.OAuth2AuthorizationResponse; -import org.springframework.security.oauth2.core.endpoint.OAuth2AccessTokenResponse; import org.springframework.security.oauth2.core.user.OAuth2User; import org.springframework.util.Assert; @@ -60,12 +61,12 @@ public class OAuth2LoginAuthenticationProvider implements AuthenticationProvider 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 authorizationCodeTokenExchanger; - private final OAuth2UserService userService; + private final OAuth2UserService userService; private GrantedAuthoritiesMapper authoritiesMapper = (authorities -> authorities); public OAuth2LoginAuthenticationProvider( AuthorizationGrantTokenExchanger authorizationCodeTokenExchanger, - OAuth2UserService userService) { + OAuth2UserService userService) { Assert.notNull(authorizationCodeTokenExchanger, "authorizationCodeTokenExchanger cannot be null"); Assert.notNull(userService, "userService cannot be null"); @@ -115,13 +116,10 @@ public class OAuth2LoginAuthenticationProvider implements AuthenticationProvider accessTokenResponse.getTokenValue(), accessTokenResponse.getIssuedAt(), accessTokenResponse.getExpiresAt(), accessTokenResponse.getScopes()); + OAuth2User oauth2User = this.userService.loadUser( + new OAuth2UserRequest(authorizationCodeAuthentication.getClientRegistration(), accessToken)); + OAuth2AuthorizedClient oauth2AuthorizedClient = new OAuth2AuthorizedClient( - authorizationCodeAuthentication.getClientRegistration(), "unknown", accessToken); - - OAuth2User oauth2User = this.userService.loadUser(oauth2AuthorizedClient); - - // Update OAuth2AuthorizedClient now that we know the 'principalName' - oauth2AuthorizedClient = new OAuth2AuthorizedClient( authorizationCodeAuthentication.getClientRegistration(), oauth2User.getName(), accessToken); Collection mappedAuthorities = diff --git a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/oidc/authentication/OidcAuthorizationCodeAuthenticationProvider.java b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/oidc/authentication/OidcAuthorizationCodeAuthenticationProvider.java index b2036b971d..01bc519feb 100644 --- a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/oidc/authentication/OidcAuthorizationCodeAuthenticationProvider.java +++ b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/oidc/authentication/OidcAuthorizationCodeAuthenticationProvider.java @@ -20,20 +20,21 @@ 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.OAuth2AuthorizationCodeAuthenticationToken; import org.springframework.security.oauth2.client.authentication.AuthorizationGrantTokenExchanger; import org.springframework.security.oauth2.client.authentication.OAuth2AuthenticationToken; +import org.springframework.security.oauth2.client.authentication.OAuth2AuthorizationCodeAuthenticationToken; import org.springframework.security.oauth2.client.jwt.JwtDecoderRegistry; import org.springframework.security.oauth2.client.oidc.OidcAuthorizedClient; +import org.springframework.security.oauth2.client.oidc.userinfo.OidcUserRequest; import org.springframework.security.oauth2.client.oidc.userinfo.OidcUserService; import org.springframework.security.oauth2.client.registration.ClientRegistration; import org.springframework.security.oauth2.client.userinfo.OAuth2UserService; import org.springframework.security.oauth2.core.OAuth2AccessToken; import org.springframework.security.oauth2.core.OAuth2AuthenticationException; import org.springframework.security.oauth2.core.OAuth2Error; +import org.springframework.security.oauth2.core.endpoint.OAuth2AccessTokenResponse; import org.springframework.security.oauth2.core.endpoint.OAuth2AuthorizationRequest; import org.springframework.security.oauth2.core.endpoint.OAuth2AuthorizationResponse; -import org.springframework.security.oauth2.core.endpoint.OAuth2AccessTokenResponse; import org.springframework.security.oauth2.core.oidc.OidcIdToken; import org.springframework.security.oauth2.core.oidc.OidcScopes; import org.springframework.security.oauth2.core.oidc.endpoint.OidcParameterNames; @@ -76,13 +77,13 @@ public class OidcAuthorizationCodeAuthenticationProvider implements Authenticati private static final String INVALID_REDIRECT_URI_PARAMETER_ERROR_CODE = "invalid_redirect_uri_parameter"; private static final String INVALID_ID_TOKEN_ERROR_CODE = "invalid_id_token"; private final AuthorizationGrantTokenExchanger authorizationCodeTokenExchanger; - private final OAuth2UserService userService; + private final OAuth2UserService userService; private final JwtDecoderRegistry jwtDecoderRegistry; private GrantedAuthoritiesMapper authoritiesMapper = (authorities -> authorities); public OidcAuthorizationCodeAuthenticationProvider( AuthorizationGrantTokenExchanger authorizationCodeTokenExchanger, - OAuth2UserService userService, + OAuth2UserService userService, JwtDecoderRegistry jwtDecoderRegistry) { Assert.notNull(authorizationCodeTokenExchanger, "authorizationCodeTokenExchanger cannot be null"); @@ -152,14 +153,10 @@ public class OidcAuthorizationCodeAuthenticationProvider implements Authenticati this.validateIdToken(idToken, clientRegistration); + OidcUser oidcUser = this.userService.loadUser( + new OidcUserRequest(clientRegistration, accessToken, idToken)); + OidcAuthorizedClient oidcAuthorizedClient = new OidcAuthorizedClient( - clientRegistration, idToken.getSubject(), accessToken, idToken); - - OidcUser oidcUser = this.userService.loadUser(oidcAuthorizedClient); - - // Update OidcAuthorizedClient as the 'principalName' may have changed - // (the default IdToken.subject) from the result of userService.loadUser() - oidcAuthorizedClient = new OidcAuthorizedClient( clientRegistration, oidcUser.getName(), accessToken, idToken); Collection mappedAuthorities = diff --git a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/oidc/userinfo/OidcUserRequest.java b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/oidc/userinfo/OidcUserRequest.java new file mode 100644 index 0000000000..992d0950aa --- /dev/null +++ b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/oidc/userinfo/OidcUserRequest.java @@ -0,0 +1,49 @@ +/* + * Copyright 2002-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.oidc.userinfo; + +import org.springframework.security.oauth2.client.registration.ClientRegistration; +import org.springframework.security.oauth2.client.userinfo.OAuth2UserRequest; +import org.springframework.security.oauth2.core.OAuth2AccessToken; +import org.springframework.security.oauth2.core.oidc.OidcIdToken; +import org.springframework.util.Assert; + +/** + * Represents a request the {@link OidcUserService} uses + * when initiating a HTTP request to the UserInfo Endpoint. + * + * @author Joe Grandja + * @since 5.0 + * @see ClientRegistration + * @see OAuth2AccessToken + * @see OidcIdToken + * @see OidcUserService + */ +public class OidcUserRequest extends OAuth2UserRequest { + private final OidcIdToken idToken; + + public OidcUserRequest(ClientRegistration clientRegistration, + OAuth2AccessToken accessToken, OidcIdToken idToken) { + + super(clientRegistration, accessToken); + Assert.notNull(idToken, "idToken cannot be null"); + this.idToken = idToken; + } + + public OidcIdToken getIdToken() { + return this.idToken; + } +} diff --git a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/oidc/userinfo/OidcUserService.java b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/oidc/userinfo/OidcUserService.java index 60fc91dce1..b99722da19 100644 --- a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/oidc/userinfo/OidcUserService.java +++ b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/oidc/userinfo/OidcUserService.java @@ -16,7 +16,6 @@ package org.springframework.security.oauth2.client.oidc.userinfo; import org.springframework.security.core.GrantedAuthority; -import org.springframework.security.oauth2.client.oidc.OidcAuthorizedClient; import org.springframework.security.oauth2.client.userinfo.NimbusUserInfoRetriever; import org.springframework.security.oauth2.client.userinfo.OAuth2UserService; import org.springframework.security.oauth2.client.userinfo.UserInfoRetriever; @@ -46,23 +45,23 @@ import java.util.Set; * @author Joe Grandja * @since 5.0 * @see OAuth2UserService - * @see OidcAuthorizedClient + * @see OidcUserRequest * @see OidcUser * @see DefaultOidcUser * @see OidcUserInfo * @see UserInfoRetriever */ -public class OidcUserService implements OAuth2UserService { +public class OidcUserService implements OAuth2UserService { private static final String INVALID_USER_INFO_RESPONSE_ERROR_CODE = "invalid_user_info_response"; private UserInfoRetriever userInfoRetriever = new NimbusUserInfoRetriever(); private final Set userInfoScopes = new HashSet<>( Arrays.asList(OidcScopes.PROFILE, OidcScopes.EMAIL, OidcScopes.ADDRESS, OidcScopes.PHONE)); @Override - public OidcUser loadUser(OidcAuthorizedClient authorizedClient) throws OAuth2AuthenticationException { + public OidcUser loadUser(OidcUserRequest userRequest) throws OAuth2AuthenticationException { OidcUserInfo userInfo = null; - if (this.shouldRetrieveUserInfo(authorizedClient)) { - Map userAttributes = this.userInfoRetriever.retrieve(authorizedClient, Map.class); + if (this.shouldRetrieveUserInfo(userRequest)) { + Map userAttributes = this.userInfoRetriever.retrieve(userRequest, Map.class); userInfo = new OidcUserInfo(userAttributes); // http://openid.net/specs/openid-connect-core-1_0.html#UserInfoResponse @@ -72,17 +71,17 @@ public class OidcUserService implements OAuth2UserService authorities = new HashSet<>(); authorities.add(authority); - return new DefaultOidcUser(authorities, authorizedClient.getIdToken(), userInfo); + return new DefaultOidcUser(authorities, userRequest.getIdToken(), userInfo); } public final void setUserInfoRetriever(UserInfoRetriever userInfoRetriever) { @@ -90,9 +89,9 @@ public class OidcUserService implements OAuth2UserService { +public class CustomUserTypesOAuth2UserService implements OAuth2UserService { private final Map> customUserTypes; private UserInfoRetriever userInfoRetriever = new NimbusUserInfoRetriever(); @@ -51,14 +50,14 @@ public class CustomUserTypesOAuth2UserService implements OAuth2UserService customUserType; if ((customUserType = this.customUserTypes.get(userInfoUri)) == null) { return null; } - return this.userInfoRetriever.retrieve(authorizedClient, customUserType); + return this.userInfoRetriever.retrieve(userRequest, customUserType); } public final void setUserInfoRetriever(UserInfoRetriever userInfoRetriever) { diff --git a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/userinfo/DefaultOAuth2UserService.java b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/userinfo/DefaultOAuth2UserService.java index 4041005c16..013bb0ede4 100644 --- a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/userinfo/DefaultOAuth2UserService.java +++ b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/userinfo/DefaultOAuth2UserService.java @@ -16,7 +16,6 @@ package org.springframework.security.oauth2.client.userinfo; import org.springframework.security.core.GrantedAuthority; -import org.springframework.security.oauth2.client.OAuth2AuthorizedClient; import org.springframework.security.oauth2.client.registration.ClientRegistration; import org.springframework.security.oauth2.core.OAuth2AuthenticationException; import org.springframework.security.oauth2.core.user.DefaultOAuth2User; @@ -45,24 +44,24 @@ import java.util.Set; * @author Joe Grandja * @since 5.0 * @see OAuth2UserService - * @see OAuth2AuthorizedClient + * @see OAuth2UserRequest * @see OAuth2User * @see DefaultOAuth2User * @see UserInfoRetriever */ -public class DefaultOAuth2UserService implements OAuth2UserService { +public class DefaultOAuth2UserService implements OAuth2UserService { private UserInfoRetriever userInfoRetriever = new NimbusUserInfoRetriever(); @Override - public OAuth2User loadUser(OAuth2AuthorizedClient authorizedClient) throws OAuth2AuthenticationException { - String userNameAttributeName = authorizedClient.getClientRegistration().getProviderDetails().getUserInfoEndpoint().getUserNameAttributeName(); + public OAuth2User loadUser(OAuth2UserRequest userRequest) throws OAuth2AuthenticationException { + String userNameAttributeName = userRequest.getClientRegistration().getProviderDetails().getUserInfoEndpoint().getUserNameAttributeName(); if (!StringUtils.hasText(userNameAttributeName)) { throw new IllegalArgumentException( "Missing required \"user name\" attribute name in UserInfoEndpoint for Client Registration: " + - authorizedClient.getClientRegistration().getRegistrationId()); + userRequest.getClientRegistration().getRegistrationId()); } - Map userAttributes = this.userInfoRetriever.retrieve(authorizedClient, Map.class); + Map userAttributes = this.userInfoRetriever.retrieve(userRequest, Map.class); GrantedAuthority authority = new OAuth2UserAuthority(userAttributes); Set authorities = new HashSet<>(); authorities.add(authority); diff --git a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/userinfo/DelegatingOAuth2UserService.java b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/userinfo/DelegatingOAuth2UserService.java index e3d4f96faf..3d4d75281f 100644 --- a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/userinfo/DelegatingOAuth2UserService.java +++ b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/userinfo/DelegatingOAuth2UserService.java @@ -15,7 +15,6 @@ */ package org.springframework.security.oauth2.client.userinfo; -import org.springframework.security.oauth2.client.OAuth2AuthorizedClient; import org.springframework.security.oauth2.core.OAuth2AuthenticationException; import org.springframework.security.oauth2.core.user.OAuth2User; import org.springframework.util.Assert; @@ -30,30 +29,30 @@ import java.util.Objects; * to it's internal List of {@link OAuth2UserService}'s. *

* Each {@link OAuth2UserService} is given a chance to - * {@link OAuth2UserService#loadUser(OAuth2AuthorizedClient) load} an {@link OAuth2User} + * {@link OAuth2UserService#loadUser(OAuth2UserRequest) load} an {@link OAuth2User} * with the first non-null {@link OAuth2User} being returned. * * @author Joe Grandja * @since 5.0 * @see OAuth2UserService - * @see OAuth2AuthorizedClient + * @see OAuth2UserRequest * @see OAuth2User * - * @param The type of Authorized Client + * @param The type of OAuth 2.0 User Request * @param The type of OAuth 2.0 User */ -public class DelegatingOAuth2UserService implements OAuth2UserService { - private final List> userServices; +public class DelegatingOAuth2UserService implements OAuth2UserService { + private final List> userServices; - public DelegatingOAuth2UserService(List> userServices) { + public DelegatingOAuth2UserService(List> userServices) { Assert.notEmpty(userServices, "userServices cannot be empty"); this.userServices = Collections.unmodifiableList(new ArrayList<>(userServices)); } @Override - public U loadUser(C authorizedClient) throws OAuth2AuthenticationException { + public U loadUser(R userRequest) throws OAuth2AuthenticationException { return this.userServices.stream() - .map(userService -> userService.loadUser(authorizedClient)) + .map(userService -> userService.loadUser(userRequest)) .filter(Objects::nonNull) .findFirst() .orElse(null); diff --git a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/userinfo/NimbusUserInfoRetriever.java b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/userinfo/NimbusUserInfoRetriever.java index 39f3c8faf0..f334b6d284 100644 --- a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/userinfo/NimbusUserInfoRetriever.java +++ b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/userinfo/NimbusUserInfoRetriever.java @@ -27,7 +27,6 @@ import org.springframework.http.client.AbstractClientHttpResponse; import org.springframework.http.converter.HttpMessageConverter; import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter; import org.springframework.security.authentication.AuthenticationServiceException; -import org.springframework.security.oauth2.client.OAuth2AuthorizedClient; import org.springframework.security.oauth2.core.OAuth2AuthenticationException; import org.springframework.security.oauth2.core.OAuth2Error; import org.springframework.util.Assert; @@ -51,9 +50,9 @@ public class NimbusUserInfoRetriever implements UserInfoRetriever { private final HttpMessageConverter jackson2HttpMessageConverter = new MappingJackson2HttpMessageConverter(); @Override - public T retrieve(OAuth2AuthorizedClient authorizedClient, Class returnType) throws OAuth2AuthenticationException { - URI userInfoUri = URI.create(authorizedClient.getClientRegistration().getProviderDetails().getUserInfoEndpoint().getUri()); - BearerAccessToken accessToken = new BearerAccessToken(authorizedClient.getAccessToken().getTokenValue()); + public T retrieve(OAuth2UserRequest userRequest, Class returnType) throws OAuth2AuthenticationException { + URI userInfoUri = URI.create(userRequest.getClientRegistration().getProviderDetails().getUserInfoEndpoint().getUri()); + BearerAccessToken accessToken = new BearerAccessToken(userRequest.getAccessToken().getTokenValue()); UserInfoRequest userInfoRequest = new UserInfoRequest(userInfoUri, accessToken); HTTPRequest httpRequest = userInfoRequest.toHTTPRequest(); diff --git a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/userinfo/OAuth2UserRequest.java b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/userinfo/OAuth2UserRequest.java new file mode 100644 index 0000000000..86389f1f4a --- /dev/null +++ b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/userinfo/OAuth2UserRequest.java @@ -0,0 +1,50 @@ +/* + * 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.userinfo; + +import org.springframework.security.oauth2.client.registration.ClientRegistration; +import org.springframework.security.oauth2.core.OAuth2AccessToken; +import org.springframework.util.Assert; + +/** + * Represents a request the {@link OAuth2UserService} uses + * when initiating a HTTP request to the UserInfo Endpoint. + * + * @author Joe Grandja + * @since 5.0 + * @see ClientRegistration + * @see OAuth2AccessToken + * @see OAuth2UserService + */ +public class OAuth2UserRequest { + private final ClientRegistration clientRegistration; + private final OAuth2AccessToken accessToken; + + public OAuth2UserRequest(ClientRegistration clientRegistration, OAuth2AccessToken accessToken) { + Assert.notNull(clientRegistration, "clientRegistration cannot be null"); + Assert.notNull(accessToken, "accessToken cannot be null"); + this.clientRegistration = clientRegistration; + this.accessToken = accessToken; + } + + public ClientRegistration getClientRegistration() { + return this.clientRegistration; + } + + public OAuth2AccessToken getAccessToken() { + return this.accessToken; + } +} diff --git a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/userinfo/OAuth2UserService.java b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/userinfo/OAuth2UserService.java index f2fdded12b..e71639d7b4 100644 --- a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/userinfo/OAuth2UserService.java +++ b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/userinfo/OAuth2UserService.java @@ -16,28 +16,27 @@ package org.springframework.security.oauth2.client.userinfo; import org.springframework.security.core.AuthenticatedPrincipal; -import org.springframework.security.oauth2.client.OAuth2AuthorizedClient; import org.springframework.security.oauth2.core.OAuth2AuthenticationException; import org.springframework.security.oauth2.core.user.OAuth2User; /** * Implementations of this interface are responsible for obtaining the user attributes * of the End-User (Resource Owner) from the UserInfo Endpoint - * using the {@link OAuth2AuthorizedClient#getAccessToken() Access Token} - * granted to the {@link OAuth2AuthorizedClient Authorized Client} + * using the {@link OAuth2UserRequest#getAccessToken() Access Token} + * granted to the {@link OAuth2UserRequest#getClientRegistration() Client} * and returning an {@link AuthenticatedPrincipal} in the form of an {@link OAuth2User}. * * @author Joe Grandja * @since 5.0 - * @see OAuth2AuthorizedClient + * @see OAuth2UserRequest * @see OAuth2User * @see AuthenticatedPrincipal * - * @param The type of Authorized Client + * @param The type of OAuth 2.0 User Request * @param The type of OAuth 2.0 User */ -public interface OAuth2UserService { +public interface OAuth2UserService { - U loadUser(C authorizedClient) throws OAuth2AuthenticationException; + U loadUser(R userRequest) throws OAuth2AuthenticationException; } diff --git a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/userinfo/UserInfoRetriever.java b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/userinfo/UserInfoRetriever.java index cdf858a06d..d0f4b75649 100644 --- a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/userinfo/UserInfoRetriever.java +++ b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/userinfo/UserInfoRetriever.java @@ -15,22 +15,21 @@ */ package org.springframework.security.oauth2.client.userinfo; -import org.springframework.security.oauth2.client.OAuth2AuthorizedClient; import org.springframework.security.oauth2.core.OAuth2AuthenticationException; /** * A strategy for retrieving the user attributes * of the End-User (Resource Owner) from the UserInfo Endpoint - * using the provided {@link OAuth2AuthorizedClient#getAccessToken() Access Token}. + * using the provided {@link OAuth2UserRequest#getAccessToken() Access Token}. * * @author Joe Grandja * @author Rob Winch * @since 5.0 - * @see OAuth2AuthorizedClient + * @see OAuth2UserRequest * @see OAuth2UserService */ public interface UserInfoRetriever { - T retrieve(OAuth2AuthorizedClient authorizedClient, Class responseType) throws OAuth2AuthenticationException; + T retrieve(OAuth2UserRequest userRequest, Class responseType) throws OAuth2AuthenticationException; }