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 a620d67897..38c4eeb540 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,28 +20,31 @@ 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.AuthorizationCodeAuthenticationToken; import org.springframework.security.oauth2.client.authentication.AuthorizationGrantTokenExchanger; import org.springframework.security.oauth2.client.authentication.NimbusAuthorizationCodeTokenExchanger; 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.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.OAuth2UserService; +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.OidcUserService; import org.springframework.security.oauth2.client.registration.ClientRegistration; import org.springframework.security.oauth2.client.registration.ClientRegistrationRepository; import org.springframework.security.oauth2.client.registration.InMemoryClientRegistrationRepository; 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.OAuth2UserService; import org.springframework.security.oauth2.client.web.AuthorizationRequestRedirectFilter; import org.springframework.security.oauth2.client.web.AuthorizationRequestRepository; import org.springframework.security.oauth2.client.web.OAuth2LoginAuthenticationFilter; import org.springframework.security.oauth2.core.AccessToken; -import org.springframework.security.oauth2.client.endpoint.AuthorizationRequestUriBuilder; +import org.springframework.security.oauth2.core.oidc.user.OidcUser; import org.springframework.security.oauth2.core.user.OAuth2User; -import org.springframework.security.oauth2.client.oidc.authentication.OidcAuthorizationCodeAuthenticationProvider; -import org.springframework.security.oauth2.client.oidc.userinfo.OidcUserService; import org.springframework.security.web.authentication.ui.DefaultLoginPageGeneratingFilter; import org.springframework.security.web.util.matcher.AntPathRequestMatcher; import org.springframework.security.web.util.matcher.RequestMatcher; @@ -188,14 +191,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; @@ -229,13 +232,13 @@ 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); + oauth2UserService = new DelegatingOAuth2UserService<>(userServices); } else { oauth2UserService = new DefaultOAuth2UserService(); } @@ -254,11 +257,7 @@ public final class OAuth2LoginConfigurer> exten } http.authenticationProvider(this.postProcess(oauth2LoginAuthenticationProvider)); - OAuth2UserService oidcUserService = this.userInfoEndpointConfig.userService; - if (oidcUserService == null) { - 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/AuthorizedClient.java b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/OAuth2AuthorizedClient.java similarity index 86% rename from oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/AuthorizedClient.java rename to oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/OAuth2AuthorizedClient.java index 18d059da35..05edf0fc3f 100644 --- a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/AuthorizedClient.java +++ b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/OAuth2AuthorizedClient.java @@ -22,8 +22,8 @@ import org.springframework.util.Assert; /** * A representation of an OAuth 2.0 "Authorized Client". *

- * A client is considered "authorized" - * when it receives a successful response from the Token Endpoint. + * A client is considered "authorized" when the End-User (Resource Owner) + * grants authorization to the Client to access its protected resources. *

* This class associates the {@link #getClientRegistration() Client} * to the {@link #getAccessToken() Access Token} @@ -35,12 +35,12 @@ import org.springframework.util.Assert; * @see AccessToken * @see Section 5.1 Access Token Response */ -public class AuthorizedClient { +public class OAuth2AuthorizedClient { private final ClientRegistration clientRegistration; private final String principalName; private final AccessToken accessToken; - public AuthorizedClient(ClientRegistration clientRegistration, String principalName, AccessToken accessToken) { + public OAuth2AuthorizedClient(ClientRegistration clientRegistration, String principalName, AccessToken accessToken) { Assert.notNull(clientRegistration, "clientRegistration cannot be null"); Assert.hasText(principalName, "principalName cannot be empty"); Assert.notNull(accessToken, "accessToken cannot be null"); diff --git a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/authentication/OAuth2AuthenticationToken.java b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/authentication/OAuth2AuthenticationToken.java index d53c0dfb65..2c758101c7 100644 --- a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/authentication/OAuth2AuthenticationToken.java +++ b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/authentication/OAuth2AuthenticationToken.java @@ -19,7 +19,7 @@ import org.springframework.security.authentication.AbstractAuthenticationToken; import org.springframework.security.core.Authentication; import org.springframework.security.core.GrantedAuthority; import org.springframework.security.core.SpringSecurityCoreVersion; -import org.springframework.security.oauth2.client.AuthorizedClient; +import org.springframework.security.oauth2.client.OAuth2AuthorizedClient; import org.springframework.security.oauth2.core.user.OAuth2User; import org.springframework.util.Assert; @@ -29,21 +29,25 @@ import java.util.Collection; * An implementation of an {@link AbstractAuthenticationToken} * that represents an OAuth 2.0 {@link Authentication}. *

- * This {@link Authentication} associates an {@link OAuth2User} principal - * to an {@link AuthorizedClient}. + * This {@link Authentication} associates an {@link OAuth2User} Principal + * to an {@link OAuth2AuthorizedClient}, which the End-User (Principal) granted authorization to + * so that it can access its protected resource(s) at the UserInfo Endpoint. * * @author Joe Grandja * @since 5.0 + * @see AbstractAuthenticationToken + * @see OAuth2AuthorizedClient * @see OAuth2User - * @see AuthorizedClient + * + * @param The type of OAuth 2.0 User + * @param The type of Authorized Client */ -public class OAuth2AuthenticationToken extends AbstractAuthenticationToken { +public class OAuth2AuthenticationToken extends AbstractAuthenticationToken { private static final long serialVersionUID = SpringSecurityCoreVersion.SERIAL_VERSION_UID; - private final OAuth2User principal; - private final AuthorizedClient authorizedClient; + private final U principal; + private final C authorizedClient; - public OAuth2AuthenticationToken(OAuth2User principal, Collection authorities, - AuthorizedClient authorizedClient) { + public OAuth2AuthenticationToken(U principal, Collection authorities, C authorizedClient) { super(authorities); Assert.notNull(principal, "principal cannot be null"); Assert.notNull(authorizedClient, "authorizedClient cannot be null"); @@ -53,7 +57,7 @@ public class OAuth2AuthenticationToken extends AbstractAuthenticationToken { } @Override - public Object getPrincipal() { + public U getPrincipal() { return this.principal; } @@ -63,7 +67,7 @@ public class OAuth2AuthenticationToken extends AbstractAuthenticationToken { return ""; } - public AuthorizedClient getAuthorizedClient() { + public C getAuthorizedClient() { return this.authorizedClient; } } 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 5ab2e863c1..93df723ee6 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 @@ -20,7 +20,7 @@ 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.AuthorizedClient; +import org.springframework.security.oauth2.client.OAuth2AuthorizedClient; import org.springframework.security.oauth2.client.userinfo.OAuth2UserService; import org.springframework.security.oauth2.core.AccessToken; import org.springframework.security.oauth2.core.OAuth2AuthenticationException; @@ -41,7 +41,7 @@ import java.util.Collection; * an authorization code credential with the authorization server's Token Endpoint * and if valid, exchanging it for an access token credential. *

- * It will also obtain the user attributes of the End-User (resource owner) + * It will also obtain the user attributes of the End-User (Resource Owner) * from the UserInfo Endpoint using an {@link OAuth2UserService} * which will create a Principal in the form of an {@link OAuth2User}. * @@ -49,8 +49,8 @@ import java.util.Collection; * @since 5.0 * @see AuthorizationCodeAuthenticationToken * @see OAuth2AuthenticationToken - * @see AuthorizedClient * @see OAuth2UserService + * @see OAuth2AuthorizedClient * @see OAuth2User * @see Section 4.1 Authorization Code Grant Flow * @see Section 4.1.3 Access Token Request @@ -60,12 +60,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,20 +115,20 @@ public class OAuth2LoginAuthenticationProvider implements AuthenticationProvider tokenResponse.getTokenValue(), tokenResponse.getIssuedAt(), tokenResponse.getExpiresAt(), tokenResponse.getScopes()); - AuthorizedClient authorizedClient = new AuthorizedClient( + OAuth2AuthorizedClient oauth2AuthorizedClient = new OAuth2AuthorizedClient( authorizationCodeAuthentication.getClientRegistration(), "unknown", accessToken); - OAuth2User oauth2User = this.userService.loadUser(authorizedClient); + OAuth2User oauth2User = this.userService.loadUser(oauth2AuthorizedClient); - // Update AuthorizedClient now that we know the 'principalName' - authorizedClient = new AuthorizedClient( + // Update OAuth2AuthorizedClient now that we know the 'principalName' + oauth2AuthorizedClient = new OAuth2AuthorizedClient( authorizationCodeAuthentication.getClientRegistration(), oauth2User.getName(), accessToken); Collection mappedAuthorities = this.authoritiesMapper.mapAuthorities(oauth2User.getAuthorities()); - OAuth2AuthenticationToken authenticationResult = new OAuth2AuthenticationToken( - oauth2User, mappedAuthorities, authorizedClient); + OAuth2AuthenticationToken authenticationResult = + new OAuth2AuthenticationToken<>(oauth2User, mappedAuthorities, oauth2AuthorizedClient); authenticationResult.setDetails(authorizationCodeAuthentication.getDetails()); return authenticationResult; diff --git a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/oidc/OidcAuthorizedClient.java b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/oidc/OidcAuthorizedClient.java index 02bf4cb0c4..7299d25f58 100644 --- a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/oidc/OidcAuthorizedClient.java +++ b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/oidc/OidcAuthorizedClient.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2017 the original author or authors. + * 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. @@ -15,7 +15,7 @@ */ package org.springframework.security.oauth2.client.oidc; -import org.springframework.security.oauth2.client.AuthorizedClient; +import org.springframework.security.oauth2.client.OAuth2AuthorizedClient; import org.springframework.security.oauth2.client.registration.ClientRegistration; import org.springframework.security.oauth2.core.AccessToken; import org.springframework.security.oauth2.core.oidc.IdToken; @@ -24,8 +24,8 @@ import org.springframework.util.Assert; /** * A representation of an OpenID Connect 1.0 "Authorized Client". *

- * A client is considered "authorized" - * when it receives a successful response from the Token Endpoint. + * A client is considered "authorized" when the End-User (Resource Owner) + * grants authorization to the Client to access its protected resources. *

* This class associates the {@link #getClientRegistration() Client} * to the {@link #getAccessToken() Access Token} @@ -34,11 +34,11 @@ import org.springframework.util.Assert; * * @author Joe Grandja * @since 5.0 + * @see OAuth2AuthorizedClient * @see IdToken - * @see AuthorizedClient * @see 3.1.3.3 Successful Token Response */ -public class OidcAuthorizedClient extends AuthorizedClient { +public class OidcAuthorizedClient extends OAuth2AuthorizedClient { private final IdToken idToken; public OidcAuthorizedClient(ClientRegistration clientRegistration, String principalName, 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 de87b48314..6bf60a3f52 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 @@ -38,7 +38,6 @@ import org.springframework.security.oauth2.core.oidc.IdToken; import org.springframework.security.oauth2.core.oidc.OidcScope; import org.springframework.security.oauth2.core.oidc.endpoint.OidcParameter; import org.springframework.security.oauth2.core.oidc.user.OidcUser; -import org.springframework.security.oauth2.core.user.OAuth2User; import org.springframework.security.oauth2.jwt.Jwt; import org.springframework.security.oauth2.jwt.JwtDecoder; import org.springframework.util.Assert; @@ -65,8 +64,8 @@ import java.util.List; * @since 5.0 * @see AuthorizationCodeAuthenticationToken * @see OAuth2AuthenticationToken - * @see OidcAuthorizedClient * @see OidcUserService + * @see OidcAuthorizedClient * @see OidcUser * @see Section 3.1 Authorization Code Grant Flow * @see Section 3.1.3.1 Token Request @@ -77,13 +76,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"); @@ -153,21 +152,21 @@ public class OidcAuthorizationCodeAuthenticationProvider implements Authenticati this.validateIdToken(idToken, clientRegistration); - OidcAuthorizedClient authorizedClient = new OidcAuthorizedClient( + OidcAuthorizedClient oidcAuthorizedClient = new OidcAuthorizedClient( clientRegistration, idToken.getSubject(), accessToken, idToken); - OAuth2User oauth2User = this.userService.loadUser(authorizedClient); + OidcUser oidcUser = this.userService.loadUser(oidcAuthorizedClient); - // Update AuthorizedClient as the 'principalName' may have changed + // Update OidcAuthorizedClient as the 'principalName' may have changed // (the default IdToken.subject) from the result of userService.loadUser() - authorizedClient = new OidcAuthorizedClient( - clientRegistration, oauth2User.getName(), accessToken, idToken); + oidcAuthorizedClient = new OidcAuthorizedClient( + clientRegistration, oidcUser.getName(), accessToken, idToken); Collection mappedAuthorities = - this.authoritiesMapper.mapAuthorities(oauth2User.getAuthorities()); + this.authoritiesMapper.mapAuthorities(oidcUser.getAuthorities()); - OAuth2AuthenticationToken authenticationResult = new OAuth2AuthenticationToken( - oauth2User, mappedAuthorities, authorizedClient); + OAuth2AuthenticationToken authenticationResult = + new OAuth2AuthenticationToken<>(oidcUser, mappedAuthorities, oidcAuthorizedClient); authenticationResult.setDetails(authorizationCodeAuthentication.getDetails()); return authenticationResult; 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 663c01f01e..050c93fb2c 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.AuthorizedClient; import org.springframework.security.oauth2.client.oidc.OidcAuthorizedClient; import org.springframework.security.oauth2.client.userinfo.NimbusUserInfoRetriever; import org.springframework.security.oauth2.client.userinfo.OAuth2UserService; @@ -27,8 +26,8 @@ import org.springframework.security.oauth2.core.OAuth2Error; import org.springframework.security.oauth2.core.oidc.OidcScope; import org.springframework.security.oauth2.core.oidc.UserInfo; import org.springframework.security.oauth2.core.oidc.user.DefaultOidcUser; +import org.springframework.security.oauth2.core.oidc.user.OidcUser; import org.springframework.security.oauth2.core.oidc.user.OidcUserAuthority; -import org.springframework.security.oauth2.core.user.OAuth2User; import org.springframework.util.Assert; import org.springframework.util.StringUtils; @@ -48,23 +47,22 @@ import java.util.Set; * @since 5.0 * @see OAuth2UserService * @see OidcAuthorizedClient + * @see OidcUser * @see DefaultOidcUser * @see UserInfo * @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(OidcScope.PROFILE, OidcScope.EMAIL, OidcScope.ADDRESS, OidcScope.PHONE)); @Override - public OAuth2User loadUser(AuthorizedClient authorizedClient) throws OAuth2AuthenticationException { - OidcAuthorizedClient oidcAuthorizedClient = (OidcAuthorizedClient)authorizedClient; - + public OidcUser loadUser(OidcAuthorizedClient authorizedClient) throws OAuth2AuthenticationException { UserInfo userInfo = null; - if (this.shouldRetrieveUserInfo(oidcAuthorizedClient)) { - Map userAttributes = this.userInfoRetriever.retrieve(oidcAuthorizedClient, Map.class); + if (this.shouldRetrieveUserInfo(authorizedClient)) { + Map userAttributes = this.userInfoRetriever.retrieve(authorizedClient, Map.class); userInfo = new UserInfo(userAttributes); // http://openid.net/specs/openid-connect-core-1_0.html#UserInfoResponse @@ -74,17 +72,17 @@ public class OidcUserService implements OAuth2UserService { // 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 UserInfo Response values MUST NOT be used. - if (!userInfo.getSubject().equals(oidcAuthorizedClient.getIdToken().getSubject())) { + if (!userInfo.getSubject().equals(authorizedClient.getIdToken().getSubject())) { OAuth2Error oauth2Error = new OAuth2Error(INVALID_USER_INFO_RESPONSE_ERROR_CODE); throw new OAuth2AuthenticationException(oauth2Error, oauth2Error.toString()); } } - GrantedAuthority authority = new OidcUserAuthority(oidcAuthorizedClient.getIdToken(), userInfo); + GrantedAuthority authority = new OidcUserAuthority(authorizedClient.getIdToken(), userInfo); Set authorities = new HashSet<>(); authorities.add(authority); - return new DefaultOidcUser(authorities, oidcAuthorizedClient.getIdToken(), userInfo); + return new DefaultOidcUser(authorities, authorizedClient.getIdToken(), userInfo); } public final void setUserInfoRetriever(UserInfoRetriever userInfoRetriever) { @@ -92,9 +90,9 @@ public class OidcUserService implements OAuth2UserService { this.userInfoRetriever = userInfoRetriever; } - private boolean shouldRetrieveUserInfo(OidcAuthorizedClient oidcAuthorizedClient) { + private boolean shouldRetrieveUserInfo(OidcAuthorizedClient authorizedClient) { // Auto-disabled if UserInfo Endpoint URI is not provided - if (StringUtils.isEmpty(oidcAuthorizedClient.getClientRegistration().getProviderDetails() + if (StringUtils.isEmpty(authorizedClient.getClientRegistration().getProviderDetails() .getUserInfoEndpoint().getUri())) { return false; @@ -107,10 +105,10 @@ public class OidcUserService implements OAuth2UserService { // 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. if (AuthorizationGrantType.AUTHORIZATION_CODE.equals( - oidcAuthorizedClient.getClientRegistration().getAuthorizationGrantType())) { + authorizedClient.getClientRegistration().getAuthorizationGrantType())) { // Return true if there is at least one match between the authorized scope(s) and UserInfo scope(s) - return oidcAuthorizedClient.getAccessToken().getScopes().stream().anyMatch(userInfoScopes::contains); + return authorizedClient.getAccessToken().getScopes().stream().anyMatch(userInfoScopes::contains); } return false; diff --git a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/userinfo/CustomUserTypesOAuth2UserService.java b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/userinfo/CustomUserTypesOAuth2UserService.java index dba3f8308f..38851b8462 100644 --- a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/userinfo/CustomUserTypesOAuth2UserService.java +++ b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/userinfo/CustomUserTypesOAuth2UserService.java @@ -15,7 +15,7 @@ */ package org.springframework.security.oauth2.client.userinfo; -import org.springframework.security.oauth2.client.AuthorizedClient; +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; @@ -32,15 +32,16 @@ import java.util.Map; * representing the UserInfo Endpoint address. *

* This implementation uses a {@link UserInfoRetriever} to obtain the user attributes - * of the End-User (resource owner) from the UserInfo Endpoint. + * of the End-User (Resource Owner) from the UserInfo Endpoint. * * @author Joe Grandja * @since 5.0 * @see OAuth2UserService + * @see OAuth2AuthorizedClient * @see OAuth2User * @see UserInfoRetriever */ -public class CustomUserTypesOAuth2UserService implements OAuth2UserService { +public class CustomUserTypesOAuth2UserService implements OAuth2UserService { private final Map> customUserTypes; private UserInfoRetriever userInfoRetriever = new NimbusUserInfoRetriever(); @@ -50,7 +51,7 @@ public class CustomUserTypesOAuth2UserService implements OAuth2UserService { } @Override - public OAuth2User loadUser(AuthorizedClient authorizedClient) throws OAuth2AuthenticationException { + public OAuth2User loadUser(OAuth2AuthorizedClient authorizedClient) throws OAuth2AuthenticationException { String userInfoUri = authorizedClient.getClientRegistration().getProviderDetails().getUserInfoEndpoint().getUri(); Class customUserType; if ((customUserType = this.customUserTypes.get(userInfoUri)) == null) { 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 3905998ffc..4041005c16 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,9 +16,9 @@ package org.springframework.security.oauth2.client.userinfo; import org.springframework.security.core.GrantedAuthority; -import org.springframework.security.oauth2.core.OAuth2AuthenticationException; -import org.springframework.security.oauth2.client.AuthorizedClient; +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; import org.springframework.security.oauth2.core.user.OAuth2User; import org.springframework.security.oauth2.core.user.OAuth2UserAuthority; @@ -45,14 +45,16 @@ import java.util.Set; * @author Joe Grandja * @since 5.0 * @see OAuth2UserService + * @see OAuth2AuthorizedClient + * @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(AuthorizedClient authorizedClient) throws OAuth2AuthenticationException { + public OAuth2User loadUser(OAuth2AuthorizedClient authorizedClient) throws OAuth2AuthenticationException { String userNameAttributeName = authorizedClient.getClientRegistration().getProviderDetails().getUserInfoEndpoint().getUserNameAttributeName(); if (!StringUtils.hasText(userNameAttributeName)) { throw new IllegalArgumentException( 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 da0c07813f..e3d4f96faf 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,8 +15,8 @@ */ 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.client.AuthorizedClient; import org.springframework.security.oauth2.core.user.OAuth2User; import org.springframework.util.Assert; @@ -30,29 +30,32 @@ import java.util.Objects; * to it's internal List of {@link OAuth2UserService}'s. *

* Each {@link OAuth2UserService} is given a chance to - * {@link OAuth2UserService#loadUser(AuthorizedClient) load} an {@link OAuth2User} + * {@link OAuth2UserService#loadUser(OAuth2AuthorizedClient) load} an {@link OAuth2User} * with the first non-null {@link OAuth2User} being returned. * * @author Joe Grandja * @since 5.0 * @see OAuth2UserService + * @see OAuth2AuthorizedClient * @see OAuth2User + * + * @param The type of Authorized Client + * @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 OAuth2User loadUser(AuthorizedClient authorizedClient) throws OAuth2AuthenticationException { - OAuth2User oauth2User = this.userServices.stream() + public U loadUser(C authorizedClient) throws OAuth2AuthenticationException { + return this.userServices.stream() .map(userService -> userService.loadUser(authorizedClient)) .filter(Objects::nonNull) .findFirst() .orElse(null); - return oauth2User; } } 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 62c0df783e..39f3c8faf0 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,8 +27,8 @@ 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.client.AuthorizedClient; import org.springframework.security.oauth2.core.OAuth2Error; import org.springframework.util.Assert; @@ -51,7 +51,7 @@ public class NimbusUserInfoRetriever implements UserInfoRetriever { private final HttpMessageConverter jackson2HttpMessageConverter = new MappingJackson2HttpMessageConverter(); @Override - public T retrieve(AuthorizedClient authorizedClient, Class returnType) throws OAuth2AuthenticationException { + 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()); 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 d5078f0dfb..f2fdded12b 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,24 +16,28 @@ package org.springframework.security.oauth2.client.userinfo; import org.springframework.security.core.AuthenticatedPrincipal; -import org.springframework.security.oauth2.client.AuthorizedClient; +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 provided {@link AuthorizedClient#getAccessToken()} + * of the End-User (Resource Owner) from the UserInfo Endpoint + * using the {@link OAuth2AuthorizedClient#getAccessToken() Access Token} + * granted to the {@link OAuth2AuthorizedClient Authorized Client} * and returning an {@link AuthenticatedPrincipal} in the form of an {@link OAuth2User}. * * @author Joe Grandja * @since 5.0 - * @see AuthorizedClient - * @see AuthenticatedPrincipal + * @see OAuth2AuthorizedClient * @see OAuth2User + * @see AuthenticatedPrincipal + * + * @param The type of Authorized Client + * @param The type of OAuth 2.0 User */ -public interface OAuth2UserService { +public interface OAuth2UserService { - OAuth2User loadUser(AuthorizedClient authorizedClient) throws OAuth2AuthenticationException; + U loadUser(C authorizedClient) 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 5ba89bf09d..cdf858a06d 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,22 @@ */ 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.client.AuthorizedClient; /** * A strategy for retrieving the user attributes - * of the End-User (resource owner) from the UserInfo Endpoint - * using the provided {@link AuthorizedClient#getAccessToken()}. + * of the End-User (Resource Owner) from the UserInfo Endpoint + * using the provided {@link OAuth2AuthorizedClient#getAccessToken() Access Token}. * * @author Joe Grandja * @author Rob Winch * @since 5.0 - * @see AuthorizedClient + * @see OAuth2AuthorizedClient * @see OAuth2UserService */ public interface UserInfoRetriever { - T retrieve(AuthorizedClient authorizedClient, Class responseType) throws OAuth2AuthenticationException; + T retrieve(OAuth2AuthorizedClient authorizedClient, Class responseType) throws OAuth2AuthenticationException; } diff --git a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/web/OAuth2LoginAuthenticationFilter.java b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/web/OAuth2LoginAuthenticationFilter.java index bc434d2bf2..68f1008f0b 100644 --- a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/web/OAuth2LoginAuthenticationFilter.java +++ b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/web/OAuth2LoginAuthenticationFilter.java @@ -18,21 +18,23 @@ package org.springframework.security.oauth2.client.web; import org.springframework.security.authentication.AuthenticationManager; import org.springframework.security.core.Authentication; import org.springframework.security.core.AuthenticationException; +import org.springframework.security.oauth2.client.OAuth2AuthorizedClient; import org.springframework.security.oauth2.client.authentication.AuthorizationCodeAuthenticationToken; -import org.springframework.security.oauth2.core.OAuth2AuthenticationException; -import org.springframework.security.oauth2.client.authentication.OAuth2LoginAuthenticationProvider; import org.springframework.security.oauth2.client.authentication.OAuth2AuthenticationToken; +import org.springframework.security.oauth2.client.authentication.OAuth2LoginAuthenticationProvider; import org.springframework.security.oauth2.client.registration.ClientRegistration; import org.springframework.security.oauth2.client.registration.ClientRegistrationRepository; import org.springframework.security.oauth2.client.token.InMemoryAccessTokenRepository; import org.springframework.security.oauth2.client.token.OAuth2TokenRepository; import org.springframework.security.oauth2.core.AccessToken; +import org.springframework.security.oauth2.core.OAuth2AuthenticationException; import org.springframework.security.oauth2.core.OAuth2Error; import org.springframework.security.oauth2.core.OAuth2ErrorCode; import org.springframework.security.oauth2.core.endpoint.AuthorizationExchange; import org.springframework.security.oauth2.core.endpoint.AuthorizationRequest; import org.springframework.security.oauth2.core.endpoint.AuthorizationResponse; import org.springframework.security.oauth2.core.endpoint.OAuth2Parameter; +import org.springframework.security.oauth2.core.user.OAuth2User; import org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter; import org.springframework.util.Assert; import org.springframework.util.StringUtils; @@ -134,8 +136,8 @@ public class OAuth2LoginAuthenticationFilter extends AbstractAuthenticationProce clientRegistration, new AuthorizationExchange(authorizationRequest, authorizationResponse)); authorizationCodeAuthentication.setDetails(this.authenticationDetailsSource.buildDetails(request)); - OAuth2AuthenticationToken oauth2Authentication = - (OAuth2AuthenticationToken) this.getAuthenticationManager().authenticate(authorizationCodeAuthentication); + OAuth2AuthenticationToken oauth2Authentication = + (OAuth2AuthenticationToken) this.getAuthenticationManager().authenticate(authorizationCodeAuthentication); this.accessTokenRepository.saveToken( oauth2Authentication.getAuthorizedClient().getAccessToken(), diff --git a/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/web/OAuth2LoginAuthenticationFilterTests.java b/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/web/OAuth2LoginAuthenticationFilterTests.java index 2e759e7961..46e23903c0 100644 --- a/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/web/OAuth2LoginAuthenticationFilterTests.java +++ b/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/web/OAuth2LoginAuthenticationFilterTests.java @@ -27,12 +27,12 @@ import org.springframework.security.core.Authentication; import org.springframework.security.core.AuthenticationException; import org.springframework.security.core.authority.AuthorityUtils; import org.springframework.security.core.context.SecurityContextHolder; -import org.springframework.security.oauth2.core.OAuth2AuthenticationException; -import org.springframework.security.oauth2.client.AuthorizedClient; +import org.springframework.security.oauth2.client.OAuth2AuthorizedClient; import org.springframework.security.oauth2.client.authentication.OAuth2AuthenticationToken; import org.springframework.security.oauth2.client.registration.ClientRegistration; import org.springframework.security.oauth2.client.registration.ClientRegistrationRepository; import org.springframework.security.oauth2.core.AccessToken; +import org.springframework.security.oauth2.core.OAuth2AuthenticationException; import org.springframework.security.oauth2.core.OAuth2ErrorCode; import org.springframework.security.oauth2.core.endpoint.AuthorizationRequest; import org.springframework.security.oauth2.core.endpoint.OAuth2Parameter; @@ -98,7 +98,7 @@ public class OAuth2LoginAuthenticationFilterTests { @Test public void doFilterWhenAuthorizationCodeSuccessResponseThenAuthenticationSuccessHandlerIsCalled() throws Exception { ClientRegistration clientRegistration = TestUtil.githubClientRegistration(); - AuthorizedClient authorizedClient = new AuthorizedClient( + OAuth2AuthorizedClient authorizedClient = new OAuth2AuthorizedClient( clientRegistration, "principal", mock(AccessToken.class)); OAuth2AuthenticationToken userAuthentication = new OAuth2AuthenticationToken( mock(OAuth2User.class), AuthorityUtils.createAuthorityList("ROLE_USER"), authorizedClient);