Add Authorities from Access Token
This commit is contained in:
parent
aa1c80c801
commit
833bfd0c22
|
@ -18,10 +18,12 @@ package org.springframework.security.oauth2.client.oidc.userinfo;
|
|||
import org.springframework.core.convert.TypeDescriptor;
|
||||
import org.springframework.core.convert.converter.Converter;
|
||||
import org.springframework.security.core.GrantedAuthority;
|
||||
import org.springframework.security.core.authority.SimpleGrantedAuthority;
|
||||
import org.springframework.security.oauth2.client.registration.ClientRegistration;
|
||||
import org.springframework.security.oauth2.client.userinfo.DefaultReactiveOAuth2UserService;
|
||||
import org.springframework.security.oauth2.client.userinfo.OAuth2UserRequest;
|
||||
import org.springframework.security.oauth2.client.userinfo.ReactiveOAuth2UserService;
|
||||
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.converter.ClaimConversionService;
|
||||
|
@ -99,6 +101,10 @@ public class OidcReactiveOAuth2UserService implements
|
|||
OidcUserInfo userInfo = authority.getUserInfo();
|
||||
Set<GrantedAuthority> authorities = new HashSet<>();
|
||||
authorities.add(authority);
|
||||
OAuth2AccessToken token = userRequest.getAccessToken();
|
||||
for (String scope : token.getScopes()) {
|
||||
authorities.add(new SimpleGrantedAuthority("SCOPE_" + scope));
|
||||
}
|
||||
String userNameAttributeName = userRequest.getClientRegistration()
|
||||
.getProviderDetails().getUserInfoEndpoint().getUserNameAttributeName();
|
||||
if (StringUtils.hasText(userNameAttributeName)) {
|
||||
|
|
|
@ -17,8 +17,6 @@ package org.springframework.security.oauth2.client.oidc.userinfo;
|
|||
|
||||
import java.time.Instant;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.LinkedHashSet;
|
||||
|
@ -29,11 +27,13 @@ import java.util.function.Function;
|
|||
import org.springframework.core.convert.TypeDescriptor;
|
||||
import org.springframework.core.convert.converter.Converter;
|
||||
import org.springframework.security.core.GrantedAuthority;
|
||||
import org.springframework.security.core.authority.SimpleGrantedAuthority;
|
||||
import org.springframework.security.oauth2.client.registration.ClientRegistration;
|
||||
import org.springframework.security.oauth2.client.userinfo.DefaultOAuth2UserService;
|
||||
import org.springframework.security.oauth2.client.userinfo.OAuth2UserRequest;
|
||||
import org.springframework.security.oauth2.client.userinfo.OAuth2UserService;
|
||||
import org.springframework.security.oauth2.core.AuthorizationGrantType;
|
||||
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.converter.ClaimConversionService;
|
||||
|
@ -96,7 +96,6 @@ public class OidcUserService implements OAuth2UserService<OidcUserRequest, OidcU
|
|||
public OidcUser loadUser(OidcUserRequest userRequest) throws OAuth2AuthenticationException {
|
||||
Assert.notNull(userRequest, "userRequest cannot be null");
|
||||
OidcUserInfo userInfo = null;
|
||||
Collection<? extends GrantedAuthority> oauth2UserAuthorities = Collections.emptyList();
|
||||
if (this.shouldRetrieveUserInfo(userRequest)) {
|
||||
OAuth2User oauth2User = this.oauth2UserService.loadUser(userRequest);
|
||||
|
||||
|
@ -109,7 +108,6 @@ public class OidcUserService implements OAuth2UserService<OidcUserRequest, OidcU
|
|||
claims = DEFAULT_CLAIM_TYPE_CONVERTER.convert(oauth2User.getAttributes());
|
||||
}
|
||||
userInfo = new OidcUserInfo(claims);
|
||||
oauth2UserAuthorities = oauth2User.getAuthorities();
|
||||
|
||||
// https://openid.net/specs/openid-connect-core-1_0.html#UserInfoResponse
|
||||
|
||||
|
@ -133,7 +131,10 @@ public class OidcUserService implements OAuth2UserService<OidcUserRequest, OidcU
|
|||
|
||||
Set<GrantedAuthority> authorities = new LinkedHashSet<>();
|
||||
authorities.add(new OidcUserAuthority(userRequest.getIdToken(), userInfo));
|
||||
authorities.addAll(oauth2UserAuthorities);
|
||||
OAuth2AccessToken token = userRequest.getAccessToken();
|
||||
for (String authority : token.getScopes()) {
|
||||
authorities.add(new SimpleGrantedAuthority("SCOPE_" + authority));
|
||||
}
|
||||
|
||||
OidcUser user;
|
||||
|
||||
|
|
|
@ -15,9 +15,6 @@
|
|||
*/
|
||||
package org.springframework.security.oauth2.client.userinfo;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
@ -30,7 +27,7 @@ import org.springframework.security.core.GrantedAuthority;
|
|||
import org.springframework.security.core.authority.SimpleGrantedAuthority;
|
||||
import org.springframework.security.oauth2.client.http.OAuth2ErrorResponseErrorHandler;
|
||||
import org.springframework.security.oauth2.client.registration.ClientRegistration;
|
||||
import org.springframework.security.oauth2.core.ClaimAccessor;
|
||||
import org.springframework.security.oauth2.core.OAuth2AccessToken;
|
||||
import org.springframework.security.oauth2.core.OAuth2AuthenticationException;
|
||||
import org.springframework.security.oauth2.core.OAuth2AuthorizationException;
|
||||
import org.springframework.security.oauth2.core.OAuth2Error;
|
||||
|
@ -71,9 +68,6 @@ public class DefaultOAuth2UserService implements OAuth2UserService<OAuth2UserReq
|
|||
private static final ParameterizedTypeReference<Map<String, Object>> PARAMETERIZED_RESPONSE_TYPE =
|
||||
new ParameterizedTypeReference<Map<String, Object>>() {};
|
||||
|
||||
private static final Collection<String> WELL_KNOWN_AUTHORITIES_CLAIM_NAMES =
|
||||
Arrays.asList("scope", "scp");
|
||||
|
||||
private Converter<OAuth2UserRequest, RequestEntity<?>> requestEntityConverter = new OAuth2UserRequestEntityConverter();
|
||||
|
||||
private RestOperations restOperations;
|
||||
|
@ -137,7 +131,8 @@ public class DefaultOAuth2UserService implements OAuth2UserService<OAuth2UserReq
|
|||
Map<String, Object> userAttributes = response.getBody();
|
||||
Set<GrantedAuthority> authorities = new LinkedHashSet<>();
|
||||
authorities.add(new OAuth2UserAuthority(userAttributes));
|
||||
for (String authority : getAuthorities(() -> userAttributes)) {
|
||||
OAuth2AccessToken token = userRequest.getAccessToken();
|
||||
for (String authority : token.getScopes()) {
|
||||
authorities.add(new SimpleGrantedAuthority("SCOPE_" + authority));
|
||||
}
|
||||
|
||||
|
@ -172,34 +167,4 @@ public class DefaultOAuth2UserService implements OAuth2UserService<OAuth2UserReq
|
|||
Assert.notNull(restOperations, "restOperations cannot be null");
|
||||
this.restOperations = restOperations;
|
||||
}
|
||||
|
||||
private String getAuthoritiesClaimName(ClaimAccessor claims) {
|
||||
for (String claimName : WELL_KNOWN_AUTHORITIES_CLAIM_NAMES) {
|
||||
if (claims.containsClaim(claimName)) {
|
||||
return claimName;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private Collection<String> getAuthorities(ClaimAccessor claims) {
|
||||
String claimName = getAuthoritiesClaimName(claims);
|
||||
|
||||
if (claimName == null) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
Object authorities = claims.getClaim(claimName);
|
||||
if (authorities instanceof String) {
|
||||
if (StringUtils.hasText((String) authorities)) {
|
||||
return Arrays.asList(((String) authorities).split(" "));
|
||||
} else {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
} else if (authorities instanceof Collection) {
|
||||
return (Collection<String>) authorities;
|
||||
}
|
||||
|
||||
return Collections.emptyList();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -28,7 +28,9 @@ import org.springframework.http.HttpStatus;
|
|||
import org.springframework.http.MediaType;
|
||||
import org.springframework.security.authentication.AuthenticationServiceException;
|
||||
import org.springframework.security.core.GrantedAuthority;
|
||||
import org.springframework.security.core.authority.SimpleGrantedAuthority;
|
||||
import org.springframework.security.oauth2.core.AuthenticationMethod;
|
||||
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.user.DefaultOAuth2User;
|
||||
|
@ -131,6 +133,10 @@ public class DefaultReactiveOAuth2UserService implements ReactiveOAuth2UserServi
|
|||
GrantedAuthority authority = new OAuth2UserAuthority(attrs);
|
||||
Set<GrantedAuthority> authorities = new HashSet<>();
|
||||
authorities.add(authority);
|
||||
OAuth2AccessToken token = userRequest.getAccessToken();
|
||||
for (String scope : token.getScopes()) {
|
||||
authorities.add(new SimpleGrantedAuthority("SCOPE_" + scope));
|
||||
}
|
||||
|
||||
return new DefaultOAuth2User(authorities, attrs, userNameAttributeName);
|
||||
})
|
||||
|
|
|
@ -16,13 +16,25 @@
|
|||
|
||||
package org.springframework.security.oauth2.client.oidc.userinfo;
|
||||
|
||||
import java.time.Duration;
|
||||
import java.time.Instant;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
import java.util.function.Function;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.junit.MockitoJUnitRunner;
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
import org.springframework.core.convert.converter.Converter;
|
||||
import org.springframework.security.core.GrantedAuthority;
|
||||
import org.springframework.security.core.authority.AuthorityUtils;
|
||||
import org.springframework.security.core.authority.SimpleGrantedAuthority;
|
||||
import org.springframework.security.oauth2.client.registration.ClientRegistration;
|
||||
import org.springframework.security.oauth2.client.registration.TestClientRegistrations;
|
||||
import org.springframework.security.oauth2.client.userinfo.OAuth2UserRequest;
|
||||
|
@ -36,17 +48,20 @@ import org.springframework.security.oauth2.core.oidc.StandardClaimNames;
|
|||
import org.springframework.security.oauth2.core.oidc.user.OidcUser;
|
||||
import org.springframework.security.oauth2.core.user.DefaultOAuth2User;
|
||||
import org.springframework.security.oauth2.core.user.OAuth2User;
|
||||
import reactor.core.publisher.Mono;
|
||||
import org.springframework.security.oauth2.core.user.OAuth2UserAuthority;
|
||||
|
||||
import java.time.Duration;
|
||||
import java.time.Instant;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.function.Function;
|
||||
|
||||
import static org.assertj.core.api.Assertions.*;
|
||||
import static org.mockito.Mockito.*;
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.Assertions.assertThatCode;
|
||||
import static org.assertj.core.api.Assertions.assertThatThrownBy;
|
||||
import static org.mockito.Mockito.any;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.same;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
import static org.springframework.security.oauth2.client.registration.TestClientRegistrations.clientRegistration;
|
||||
import static org.springframework.security.oauth2.core.TestOAuth2AccessTokens.noScopes;
|
||||
import static org.springframework.security.oauth2.core.TestOAuth2AccessTokens.scopes;
|
||||
import static org.springframework.security.oauth2.core.oidc.TestOidcIdTokens.idToken;
|
||||
|
||||
/**
|
||||
* @author Rob Winch
|
||||
|
@ -178,6 +193,38 @@ public class OidcReactiveOAuth2UserServiceTests {
|
|||
verify(customClaimTypeConverterFactory).apply(same(userRequest.getClientRegistration()));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void loadUserWhenTokenContainsScopesThenIndividualScopeAuthorities() {
|
||||
Map<String, Object> body = new HashMap<>();
|
||||
body.put("id", "id");
|
||||
body.put("sub", "test-subject");
|
||||
OidcReactiveOAuth2UserService userService = new OidcReactiveOAuth2UserService();
|
||||
OidcUserRequest request = new OidcUserRequest(
|
||||
clientRegistration().build(), scopes("message:read", "message:write"), idToken(body));
|
||||
OidcUser user = userService.loadUser(request).block();
|
||||
|
||||
assertThat(user.getAuthorities()).hasSize(3);
|
||||
Iterator<? extends GrantedAuthority> authorities = user.getAuthorities().iterator();
|
||||
assertThat(authorities.next()).isInstanceOf(OAuth2UserAuthority.class);
|
||||
assertThat(authorities.next()).isEqualTo(new SimpleGrantedAuthority("SCOPE_message:read"));
|
||||
assertThat(authorities.next()).isEqualTo(new SimpleGrantedAuthority("SCOPE_message:write"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void loadUserWhenTokenDoesNotContainScopesThenNoScopeAuthorities() {
|
||||
Map<String, Object> body = new HashMap<>();
|
||||
body.put("id", "id");
|
||||
body.put("sub", "test-subject");
|
||||
OidcReactiveOAuth2UserService userService = new OidcReactiveOAuth2UserService();
|
||||
OidcUserRequest request = new OidcUserRequest(
|
||||
clientRegistration().build(), noScopes(), idToken(body));
|
||||
OidcUser user = userService.loadUser(request).block();
|
||||
|
||||
assertThat(user.getAuthorities()).hasSize(1);
|
||||
Iterator<? extends GrantedAuthority> authorities = user.getAuthorities().iterator();
|
||||
assertThat(authorities.next()).isInstanceOf(OAuth2UserAuthority.class);
|
||||
}
|
||||
|
||||
private OidcUserRequest userRequest() {
|
||||
return new OidcUserRequest(this.registration.build(), this.accessToken, this.idToken);
|
||||
}
|
||||
|
|
|
@ -16,7 +16,6 @@
|
|||
package org.springframework.security.oauth2.client.oidc.userinfo;
|
||||
|
||||
import java.time.Instant;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
|
@ -33,19 +32,14 @@ import org.junit.Rule;
|
|||
import org.junit.Test;
|
||||
import org.junit.rules.ExpectedException;
|
||||
|
||||
import org.springframework.core.ParameterizedTypeReference;
|
||||
import org.springframework.core.convert.converter.Converter;
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.http.HttpMethod;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.http.RequestEntity;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.security.core.GrantedAuthority;
|
||||
import org.springframework.security.core.authority.SimpleGrantedAuthority;
|
||||
import org.springframework.security.oauth2.client.registration.ClientRegistration;
|
||||
import org.springframework.security.oauth2.client.userinfo.DefaultOAuth2UserService;
|
||||
import org.springframework.security.oauth2.client.userinfo.OAuth2UserRequest;
|
||||
import org.springframework.security.oauth2.core.AuthenticationMethod;
|
||||
import org.springframework.security.oauth2.core.OAuth2AccessToken;
|
||||
import org.springframework.security.oauth2.core.OAuth2AuthenticationException;
|
||||
|
@ -56,18 +50,16 @@ import org.springframework.security.oauth2.core.oidc.OidcScopes;
|
|||
import org.springframework.security.oauth2.core.oidc.StandardClaimNames;
|
||||
import org.springframework.security.oauth2.core.oidc.user.OidcUser;
|
||||
import org.springframework.security.oauth2.core.oidc.user.OidcUserAuthority;
|
||||
import org.springframework.web.client.RestOperations;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.Assertions.assertThatThrownBy;
|
||||
import static org.hamcrest.CoreMatchers.containsString;
|
||||
import static org.mockito.Mockito.any;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.nullable;
|
||||
import static org.mockito.Mockito.same;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
import static org.springframework.security.oauth2.client.registration.TestClientRegistrations.clientRegistration;
|
||||
import static org.springframework.security.oauth2.core.TestOAuth2AccessTokens.noScopes;
|
||||
import static org.springframework.security.oauth2.core.TestOAuth2AccessTokens.scopes;
|
||||
import static org.springframework.security.oauth2.core.oidc.TestOidcIdTokens.idToken;
|
||||
|
||||
|
@ -272,7 +264,7 @@ public class OidcUserServiceTests {
|
|||
assertThat(user.getUserInfo().getPreferredUsername()).isEqualTo("user1");
|
||||
assertThat(user.getUserInfo().getEmail()).isEqualTo("user1@example.com");
|
||||
|
||||
assertThat(user.getAuthorities().size()).isEqualTo(1);
|
||||
assertThat(user.getAuthorities().size()).isEqualTo(3);
|
||||
assertThat(user.getAuthorities().iterator().next()).isInstanceOf(OidcUserAuthority.class);
|
||||
OidcUserAuthority userAuthority = (OidcUserAuthority) user.getAuthorities().iterator().next();
|
||||
assertThat(userAuthority.getAuthority()).isEqualTo("ROLE_USER");
|
||||
|
@ -499,15 +491,13 @@ public class OidcUserServiceTests {
|
|||
}
|
||||
|
||||
@Test
|
||||
public void loadUserWhenAttributesContainScopeThenIndividualScopeAuthorities() {
|
||||
public void loadUserWhenTokenContainsScopesThenIndividualScopeAuthorities() {
|
||||
Map<String, Object> body = new HashMap<>();
|
||||
body.put("id", "id");
|
||||
body.put("sub", "test-subject");
|
||||
body.put("scope", "message:read message:write");
|
||||
OidcUserService userService = new OidcUserService();
|
||||
userService.setOauth2UserService(withMockResponse(body));
|
||||
OidcUserRequest request = new OidcUserRequest(clientRegistration().
|
||||
userInfoUri("uri").build(), scopes("profile"), idToken(body));
|
||||
OidcUserRequest request = new OidcUserRequest(clientRegistration().build(),
|
||||
scopes("message:read", "message:write"), idToken(body));
|
||||
OidcUser user = userService.loadUser(request);
|
||||
|
||||
assertThat(user.getAuthorities()).hasSize(3);
|
||||
|
@ -518,34 +508,13 @@ public class OidcUserServiceTests {
|
|||
}
|
||||
|
||||
@Test
|
||||
public void loadUserWhenAttributesContainScpThenIndividualScopeAuthorities() {
|
||||
public void loadUserWhenTokenDoesNotContainScopesThenNoScopeAuthorities() {
|
||||
Map<String, Object> body = new HashMap<>();
|
||||
body.put("id", "id");
|
||||
body.put("sub", "test-subject");
|
||||
body.put("scp", Arrays.asList("message:read", "message:write"));
|
||||
OidcUserService userService = new OidcUserService();
|
||||
userService.setOauth2UserService(withMockResponse(body));
|
||||
OidcUserRequest request = new OidcUserRequest(clientRegistration().
|
||||
userInfoUri("uri").build(), scopes("profile"), idToken(body));
|
||||
OidcUser user = userService.loadUser(request);
|
||||
|
||||
assertThat(user.getAuthorities()).hasSize(3);
|
||||
Iterator<? extends GrantedAuthority> authorities = user.getAuthorities().iterator();
|
||||
assertThat(authorities.next()).isInstanceOf(OidcUserAuthority.class);
|
||||
assertThat(authorities.next()).isEqualTo(new SimpleGrantedAuthority("SCOPE_message:read"));
|
||||
assertThat(authorities.next()).isEqualTo(new SimpleGrantedAuthority("SCOPE_message:write"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void loadUserWhenAttributesDoesNotContainScopesThenNoScopeAuthorities() {
|
||||
Map<String, Object> body = new HashMap<>();
|
||||
body.put("id", "id");
|
||||
body.put("sub", "test-subject");
|
||||
body.put("authorities", Arrays.asList("message:read", "message:write"));
|
||||
OidcUserService userService = new OidcUserService();
|
||||
userService.setOauth2UserService(withMockResponse(body));
|
||||
OidcUserRequest request = new OidcUserRequest(clientRegistration().
|
||||
userInfoUri("uri").build(), scopes("profile"), idToken(body));
|
||||
OidcUserRequest request = new OidcUserRequest(clientRegistration().build(),
|
||||
noScopes(), idToken(body));
|
||||
OidcUser user = userService.loadUser(request);
|
||||
|
||||
assertThat(user.getAuthorities()).hasSize(1);
|
||||
|
@ -553,18 +522,6 @@ public class OidcUserServiceTests {
|
|||
assertThat(authorities.next()).isInstanceOf(OidcUserAuthority.class);
|
||||
}
|
||||
|
||||
private DefaultOAuth2UserService withMockResponse(Map<String, Object> response) {
|
||||
ResponseEntity<Map<String, Object>> responseEntity = new ResponseEntity<>(response, HttpStatus.OK);
|
||||
Converter<OAuth2UserRequest, RequestEntity<?>> requestEntityConverter = mock(Converter.class);
|
||||
RestOperations rest = mock(RestOperations.class);
|
||||
when(rest.exchange(nullable(RequestEntity.class), any(ParameterizedTypeReference.class)))
|
||||
.thenReturn(responseEntity);
|
||||
DefaultOAuth2UserService userService = new DefaultOAuth2UserService();
|
||||
userService.setRequestEntityConverter(requestEntityConverter);
|
||||
userService.setRestOperations(rest);
|
||||
return userService;
|
||||
}
|
||||
|
||||
private MockResponse jsonResponse(String json) {
|
||||
return new MockResponse()
|
||||
.setHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE)
|
||||
|
|
|
@ -15,7 +15,6 @@
|
|||
*/
|
||||
package org.springframework.security.oauth2.client.userinfo;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
|
@ -56,6 +55,7 @@ import static org.mockito.Mockito.mock;
|
|||
import static org.mockito.Mockito.when;
|
||||
import static org.springframework.security.oauth2.client.registration.TestClientRegistrations.clientRegistration;
|
||||
import static org.springframework.security.oauth2.core.TestOAuth2AccessTokens.noScopes;
|
||||
import static org.springframework.security.oauth2.core.TestOAuth2AccessTokens.scopes;
|
||||
|
||||
/**
|
||||
* Tests for {@link DefaultOAuth2UserService}.
|
||||
|
@ -342,12 +342,12 @@ public class DefaultOAuth2UserServiceTests {
|
|||
}
|
||||
|
||||
@Test
|
||||
public void loadUserWhenAttributesContainScopeThenIndividualScopeAuthorities() {
|
||||
public void loadUserWhenTokenContainsScopesThenIndividualScopeAuthorities() {
|
||||
Map<String, Object> body = new HashMap<>();
|
||||
body.put("id", "id");
|
||||
body.put("scope", "message:read message:write");
|
||||
DefaultOAuth2UserService userService = withMockResponse(body);
|
||||
OAuth2UserRequest request = new OAuth2UserRequest(clientRegistration().build(), noScopes());
|
||||
OAuth2UserRequest request = new OAuth2UserRequest(
|
||||
clientRegistration().build(), scopes("message:read", "message:write"));
|
||||
OAuth2User user = userService.loadUser(request);
|
||||
|
||||
assertThat(user.getAuthorities()).hasSize(3);
|
||||
|
@ -358,28 +358,12 @@ public class DefaultOAuth2UserServiceTests {
|
|||
}
|
||||
|
||||
@Test
|
||||
public void loadUserWhenAttributesContainScpThenIndividualScopeAuthorities() {
|
||||
public void loadUserWhenTokenDoesNotContainScopesThenNoScopeAuthorities() {
|
||||
Map<String, Object> body = new HashMap<>();
|
||||
body.put("id", "id");
|
||||
body.put("scp", Arrays.asList("message:read", "message:write"));
|
||||
DefaultOAuth2UserService userService = withMockResponse(body);
|
||||
OAuth2UserRequest request = new OAuth2UserRequest(clientRegistration().build(), noScopes());
|
||||
OAuth2User user = userService.loadUser(request);
|
||||
|
||||
assertThat(user.getAuthorities()).hasSize(3);
|
||||
Iterator<? extends GrantedAuthority> authorities = user.getAuthorities().iterator();
|
||||
assertThat(authorities.next()).isInstanceOf(OAuth2UserAuthority.class);
|
||||
assertThat(authorities.next()).isEqualTo(new SimpleGrantedAuthority("SCOPE_message:read"));
|
||||
assertThat(authorities.next()).isEqualTo(new SimpleGrantedAuthority("SCOPE_message:write"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void loadUserWhenAttributesDoesNotContainScopesThenNoScopeAuthorities() {
|
||||
Map<String, Object> body = new HashMap<>();
|
||||
body.put("id", "id");
|
||||
body.put("authorities", Arrays.asList("message:read", "message:write"));
|
||||
DefaultOAuth2UserService userService = withMockResponse(body);
|
||||
OAuth2UserRequest request = new OAuth2UserRequest(clientRegistration().build(), noScopes());
|
||||
OAuth2UserRequest request = new OAuth2UserRequest(
|
||||
clientRegistration().build(), noScopes());
|
||||
OAuth2User user = userService.loadUser(request);
|
||||
|
||||
assertThat(user.getAuthorities()).hasSize(1);
|
||||
|
|
|
@ -16,15 +16,30 @@
|
|||
|
||||
package org.springframework.security.oauth2.client.userinfo;
|
||||
|
||||
import java.time.Duration;
|
||||
import java.time.Instant;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
import java.util.function.Function;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
import okhttp3.mockwebserver.MockResponse;
|
||||
import okhttp3.mockwebserver.MockWebServer;
|
||||
import okhttp3.mockwebserver.RecordedRequest;
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import reactor.core.publisher.Mono;
|
||||
import reactor.test.StepVerifier;
|
||||
|
||||
import org.springframework.core.ParameterizedTypeReference;
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.http.HttpMethod;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.security.authentication.AuthenticationServiceException;
|
||||
import org.springframework.security.core.GrantedAuthority;
|
||||
import org.springframework.security.core.authority.SimpleGrantedAuthority;
|
||||
import org.springframework.security.oauth2.client.registration.ClientRegistration;
|
||||
import org.springframework.security.oauth2.client.registration.TestClientRegistrations;
|
||||
import org.springframework.security.oauth2.core.AuthenticationMethod;
|
||||
|
@ -32,14 +47,17 @@ import org.springframework.security.oauth2.core.OAuth2AccessToken;
|
|||
import org.springframework.security.oauth2.core.OAuth2AuthenticationException;
|
||||
import org.springframework.security.oauth2.core.user.OAuth2User;
|
||||
import org.springframework.security.oauth2.core.user.OAuth2UserAuthority;
|
||||
import org.springframework.web.reactive.function.client.WebClient;
|
||||
|
||||
import okhttp3.mockwebserver.RecordedRequest;
|
||||
import reactor.test.StepVerifier;
|
||||
|
||||
import java.time.Duration;
|
||||
import java.time.Instant;
|
||||
|
||||
import static org.assertj.core.api.Assertions.*;
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.Assertions.assertThatThrownBy;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.spy;
|
||||
import static org.mockito.Mockito.when;
|
||||
import static org.springframework.security.oauth2.client.registration.TestClientRegistrations.clientRegistration;
|
||||
import static org.springframework.security.oauth2.core.TestOAuth2AccessTokens.noScopes;
|
||||
import static org.springframework.security.oauth2.core.TestOAuth2AccessTokens.scopes;
|
||||
|
||||
/**
|
||||
* @author Rob Winch
|
||||
|
@ -211,6 +229,53 @@ public class DefaultReactiveOAuth2UserServiceTests {
|
|||
.isInstanceOf(AuthenticationServiceException.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void loadUserWhenTokenContainsScopesThenIndividualScopeAuthorities() {
|
||||
Map<String, Object> body = new HashMap<>();
|
||||
body.put("id", "id");
|
||||
DefaultReactiveOAuth2UserService userService = withMockResponse(body);
|
||||
OAuth2UserRequest request = new OAuth2UserRequest(
|
||||
clientRegistration().build(), scopes("message:read", "message:write"));
|
||||
OAuth2User user = userService.loadUser(request).block();
|
||||
|
||||
assertThat(user.getAuthorities()).hasSize(3);
|
||||
Iterator<? extends GrantedAuthority> authorities = user.getAuthorities().iterator();
|
||||
assertThat(authorities.next()).isInstanceOf(OAuth2UserAuthority.class);
|
||||
assertThat(authorities.next()).isEqualTo(new SimpleGrantedAuthority("SCOPE_message:read"));
|
||||
assertThat(authorities.next()).isEqualTo(new SimpleGrantedAuthority("SCOPE_message:write"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void loadUserWhenTokenDoesNotContainScopesThenNoScopeAuthorities() {
|
||||
Map<String, Object> body = new HashMap<>();
|
||||
body.put("id", "id");
|
||||
DefaultReactiveOAuth2UserService userService = withMockResponse(body);
|
||||
OAuth2UserRequest request = new OAuth2UserRequest(
|
||||
clientRegistration().build(), noScopes());
|
||||
OAuth2User user = userService.loadUser(request).block();
|
||||
|
||||
assertThat(user.getAuthorities()).hasSize(1);
|
||||
Iterator<? extends GrantedAuthority> authorities = user.getAuthorities().iterator();
|
||||
assertThat(authorities.next()).isInstanceOf(OAuth2UserAuthority.class);
|
||||
}
|
||||
|
||||
private DefaultReactiveOAuth2UserService withMockResponse(Map<String, Object> body) {
|
||||
WebClient real = WebClient.builder().build();
|
||||
WebClient.RequestHeadersUriSpec spec = spy(real.post());
|
||||
WebClient rest = spy(WebClient.class);
|
||||
WebClient.ResponseSpec clientResponse = mock(WebClient.ResponseSpec.class);
|
||||
when(rest.get()).thenReturn(spec);
|
||||
when(spec.retrieve()).thenReturn(clientResponse);
|
||||
when(clientResponse.onStatus(any(Predicate.class), any(Function.class)))
|
||||
.thenReturn(clientResponse);
|
||||
when(clientResponse.bodyToMono(any(ParameterizedTypeReference.class)))
|
||||
.thenReturn(Mono.just(body));
|
||||
|
||||
DefaultReactiveOAuth2UserService userService = new DefaultReactiveOAuth2UserService();
|
||||
userService.setWebClient(rest);
|
||||
return userService;
|
||||
}
|
||||
|
||||
private OAuth2UserRequest oauth2UserRequest() {
|
||||
return new OAuth2UserRequest(this.clientRegistration.build(), this.accessToken);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue