|
@@ -18,6 +18,7 @@ package org.springframework.security.oauth2.client.oidc.userinfo;
|
|
|
import okhttp3.mockwebserver.MockResponse;
|
|
|
import okhttp3.mockwebserver.MockWebServer;
|
|
|
import okhttp3.mockwebserver.RecordedRequest;
|
|
|
+import org.junit.After;
|
|
|
import org.junit.Before;
|
|
|
import org.junit.Rule;
|
|
|
import org.junit.Test;
|
|
@@ -29,7 +30,6 @@ import org.powermock.modules.junit4.PowerMockRunner;
|
|
|
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.oauth2.client.registration.ClientRegistration;
|
|
|
import org.springframework.security.oauth2.client.userinfo.DefaultOAuth2UserService;
|
|
|
import org.springframework.security.oauth2.core.AuthenticationMethod;
|
|
@@ -71,12 +71,15 @@ public class OidcUserServiceTests {
|
|
|
private OAuth2AccessToken accessToken;
|
|
|
private OidcIdToken idToken;
|
|
|
private OidcUserService userService = new OidcUserService();
|
|
|
+ private MockWebServer server;
|
|
|
|
|
|
@Rule
|
|
|
public ExpectedException exception = ExpectedException.none();
|
|
|
|
|
|
@Before
|
|
|
- public void setUp() throws Exception {
|
|
|
+ public void setup() throws Exception {
|
|
|
+ this.server = new MockWebServer();
|
|
|
+ this.server.start();
|
|
|
this.clientRegistration = mock(ClientRegistration.class);
|
|
|
this.providerDetails = mock(ClientRegistration.ProviderDetails.class);
|
|
|
this.userInfoEndpoint = mock(ClientRegistration.ProviderDetails.UserInfoEndpoint.class);
|
|
@@ -101,6 +104,11 @@ public class OidcUserServiceTests {
|
|
|
this.userService.setOauth2UserService(new DefaultOAuth2UserService());
|
|
|
}
|
|
|
|
|
|
+ @After
|
|
|
+ public void cleanup() throws Exception {
|
|
|
+ this.server.shutdown();
|
|
|
+ }
|
|
|
+
|
|
|
@Test
|
|
|
public void setOauth2UserServiceWhenNullThenThrowIllegalArgumentException() {
|
|
|
assertThatThrownBy(() -> this.userService.setOauth2UserService(null))
|
|
@@ -135,9 +143,7 @@ public class OidcUserServiceTests {
|
|
|
}
|
|
|
|
|
|
@Test
|
|
|
- public void loadUserWhenUserInfoSuccessResponseThenReturnUser() throws Exception {
|
|
|
- MockWebServer server = new MockWebServer();
|
|
|
-
|
|
|
+ public void loadUserWhenUserInfoSuccessResponseThenReturnUser() {
|
|
|
String userInfoResponse = "{\n" +
|
|
|
" \"sub\": \"subject1\",\n" +
|
|
|
" \"name\": \"first last\",\n" +
|
|
@@ -146,13 +152,9 @@ public class OidcUserServiceTests {
|
|
|
" \"preferred_username\": \"user1\",\n" +
|
|
|
" \"email\": \"user1@example.com\"\n" +
|
|
|
"}\n";
|
|
|
- server.enqueue(new MockResponse()
|
|
|
- .setHeader(HttpHeaders.ACCEPT, MediaType.APPLICATION_JSON_VALUE)
|
|
|
- .setBody(userInfoResponse));
|
|
|
+ this.server.enqueue(jsonResponse(userInfoResponse));
|
|
|
|
|
|
- server.start();
|
|
|
-
|
|
|
- String userInfoUri = server.url("/user").toString();
|
|
|
+ String userInfoUri = this.server.url("/user").toString();
|
|
|
|
|
|
when(this.userInfoEndpoint.getUri()).thenReturn(userInfoUri);
|
|
|
when(this.accessToken.getTokenValue()).thenReturn("access-token");
|
|
@@ -160,8 +162,6 @@ public class OidcUserServiceTests {
|
|
|
OidcUser user = this.userService.loadUser(
|
|
|
new OidcUserRequest(this.clientRegistration, this.accessToken, this.idToken));
|
|
|
|
|
|
- server.shutdown();
|
|
|
-
|
|
|
assertThat(user.getIdToken()).isNotNull();
|
|
|
assertThat(user.getUserInfo()).isNotNull();
|
|
|
assertThat(user.getUserInfo().getClaims().size()).isEqualTo(6);
|
|
@@ -184,69 +184,47 @@ public class OidcUserServiceTests {
|
|
|
|
|
|
// gh-5447
|
|
|
@Test
|
|
|
- public void loadUserWhenUserInfoSuccessResponseAndUserInfoSubjectIsNullThenThrowOAuth2AuthenticationException() throws Exception {
|
|
|
+ public void loadUserWhenUserInfoSuccessResponseAndUserInfoSubjectIsNullThenThrowOAuth2AuthenticationException() {
|
|
|
this.exception.expect(OAuth2AuthenticationException.class);
|
|
|
this.exception.expectMessage(containsString("invalid_user_info_response"));
|
|
|
|
|
|
- MockWebServer server = new MockWebServer();
|
|
|
-
|
|
|
String userInfoResponse = "{\n" +
|
|
|
" \"email\": \"full_name@provider.com\",\n" +
|
|
|
" \"name\": \"full name\"\n" +
|
|
|
"}\n";
|
|
|
- server.enqueue(new MockResponse()
|
|
|
- .setHeader(HttpHeaders.ACCEPT, MediaType.APPLICATION_JSON_VALUE)
|
|
|
- .setBody(userInfoResponse));
|
|
|
+ this.server.enqueue(jsonResponse(userInfoResponse));
|
|
|
|
|
|
- server.start();
|
|
|
-
|
|
|
- String userInfoUri = server.url("/user").toString();
|
|
|
+ String userInfoUri = this.server.url("/user").toString();
|
|
|
|
|
|
when(this.userInfoEndpoint.getUri()).thenReturn(userInfoUri);
|
|
|
when(this.userInfoEndpoint.getUserNameAttributeName()).thenReturn(StandardClaimNames.EMAIL);
|
|
|
when(this.accessToken.getTokenValue()).thenReturn("access-token");
|
|
|
|
|
|
- try {
|
|
|
- this.userService.loadUser(new OidcUserRequest(this.clientRegistration, this.accessToken, this.idToken));
|
|
|
- } finally {
|
|
|
- server.shutdown();
|
|
|
- }
|
|
|
+ this.userService.loadUser(new OidcUserRequest(this.clientRegistration, this.accessToken, this.idToken));
|
|
|
}
|
|
|
|
|
|
@Test
|
|
|
- public void loadUserWhenUserInfoSuccessResponseAndUserInfoSubjectNotSameAsIdTokenSubjectThenThrowOAuth2AuthenticationException() throws Exception {
|
|
|
+ public void loadUserWhenUserInfoSuccessResponseAndUserInfoSubjectNotSameAsIdTokenSubjectThenThrowOAuth2AuthenticationException() {
|
|
|
this.exception.expect(OAuth2AuthenticationException.class);
|
|
|
this.exception.expectMessage(containsString("invalid_user_info_response"));
|
|
|
|
|
|
- MockWebServer server = new MockWebServer();
|
|
|
-
|
|
|
String userInfoResponse = "{\n" +
|
|
|
" \"sub\": \"other-subject\"\n" +
|
|
|
"}\n";
|
|
|
- server.enqueue(new MockResponse()
|
|
|
- .setHeader(HttpHeaders.ACCEPT, MediaType.APPLICATION_JSON_VALUE)
|
|
|
- .setBody(userInfoResponse));
|
|
|
-
|
|
|
- server.start();
|
|
|
+ this.server.enqueue(jsonResponse(userInfoResponse));
|
|
|
|
|
|
- String userInfoUri = server.url("/user").toString();
|
|
|
+ String userInfoUri = this.server.url("/user").toString();
|
|
|
|
|
|
when(this.userInfoEndpoint.getUri()).thenReturn(userInfoUri);
|
|
|
when(this.accessToken.getTokenValue()).thenReturn("access-token");
|
|
|
|
|
|
- try {
|
|
|
- this.userService.loadUser(new OidcUserRequest(this.clientRegistration, this.accessToken, this.idToken));
|
|
|
- } finally {
|
|
|
- server.shutdown();
|
|
|
- }
|
|
|
+ this.userService.loadUser(new OidcUserRequest(this.clientRegistration, this.accessToken, this.idToken));
|
|
|
}
|
|
|
|
|
|
@Test
|
|
|
- public void loadUserWhenUserInfoSuccessResponseInvalidThenThrowOAuth2AuthenticationException() throws Exception {
|
|
|
+ public void loadUserWhenUserInfoSuccessResponseInvalidThenThrowOAuth2AuthenticationException() {
|
|
|
this.exception.expect(OAuth2AuthenticationException.class);
|
|
|
- this.exception.expectMessage(containsString("invalid_user_info_response"));
|
|
|
-
|
|
|
- MockWebServer server = new MockWebServer();
|
|
|
+ this.exception.expectMessage(containsString("[invalid_user_info_response] An error occurred while attempting to retrieve the UserInfo Resource"));
|
|
|
|
|
|
String userInfoResponse = "{\n" +
|
|
|
" \"sub\": \"subject1\",\n" +
|
|
@@ -256,48 +234,35 @@ public class OidcUserServiceTests {
|
|
|
" \"preferred_username\": \"user1\",\n" +
|
|
|
" \"email\": \"user1@example.com\"\n";
|
|
|
// "}\n"; // Make the JSON invalid/malformed
|
|
|
- server.enqueue(new MockResponse()
|
|
|
- .setHeader(HttpHeaders.ACCEPT, MediaType.APPLICATION_JSON_VALUE)
|
|
|
- .setBody(userInfoResponse));
|
|
|
-
|
|
|
- server.start();
|
|
|
+ this.server.enqueue(jsonResponse(userInfoResponse));
|
|
|
|
|
|
- String userInfoUri = server.url("/user").toString();
|
|
|
+ String userInfoUri = this.server.url("/user").toString();
|
|
|
|
|
|
when(this.userInfoEndpoint.getUri()).thenReturn(userInfoUri);
|
|
|
when(this.accessToken.getTokenValue()).thenReturn("access-token");
|
|
|
|
|
|
- try {
|
|
|
- this.userService.loadUser(new OidcUserRequest(this.clientRegistration, this.accessToken, this.idToken));
|
|
|
- } finally {
|
|
|
- server.shutdown();
|
|
|
- }
|
|
|
+ this.userService.loadUser(new OidcUserRequest(this.clientRegistration, this.accessToken, this.idToken));
|
|
|
}
|
|
|
|
|
|
@Test
|
|
|
- public void loadUserWhenUserInfoErrorResponseThenThrowOAuth2AuthenticationException() throws Exception {
|
|
|
+ public void loadUserWhenServerErrorThenThrowOAuth2AuthenticationException() {
|
|
|
this.exception.expect(OAuth2AuthenticationException.class);
|
|
|
- this.exception.expectMessage(containsString("invalid_user_info_response"));
|
|
|
+ this.exception.expectMessage(containsString("[invalid_user_info_response] An error occurred while attempting to retrieve the UserInfo Resource: 500 Server Error"));
|
|
|
|
|
|
- MockWebServer server = new MockWebServer();
|
|
|
- server.enqueue(new MockResponse().setResponseCode(500));
|
|
|
- server.start();
|
|
|
+ this.server.enqueue(new MockResponse().setResponseCode(500));
|
|
|
|
|
|
String userInfoUri = server.url("/user").toString();
|
|
|
|
|
|
when(this.userInfoEndpoint.getUri()).thenReturn(userInfoUri);
|
|
|
when(this.accessToken.getTokenValue()).thenReturn("access-token");
|
|
|
|
|
|
- try {
|
|
|
- this.userService.loadUser(new OidcUserRequest(this.clientRegistration, this.accessToken, this.idToken));
|
|
|
- } finally {
|
|
|
- server.shutdown();
|
|
|
- }
|
|
|
+ this.userService.loadUser(new OidcUserRequest(this.clientRegistration, this.accessToken, this.idToken));
|
|
|
}
|
|
|
|
|
|
@Test
|
|
|
- public void loadUserWhenUserInfoUriInvalidThenThrowAuthenticationServiceException() throws Exception {
|
|
|
- this.exception.expect(AuthenticationServiceException.class);
|
|
|
+ public void loadUserWhenUserInfoUriInvalidThenThrowOAuth2AuthenticationException() {
|
|
|
+ this.exception.expect(OAuth2AuthenticationException.class);
|
|
|
+ this.exception.expectMessage(containsString("[invalid_user_info_response] An error occurred while attempting to retrieve the UserInfo Resource"));
|
|
|
|
|
|
String userInfoUri = "http://invalid-provider.com/user";
|
|
|
|
|
@@ -308,9 +273,7 @@ public class OidcUserServiceTests {
|
|
|
}
|
|
|
|
|
|
@Test
|
|
|
- public void loadUserWhenCustomUserNameAttributeNameThenGetNameReturnsCustomUserName() throws Exception {
|
|
|
- MockWebServer server = new MockWebServer();
|
|
|
-
|
|
|
+ public void loadUserWhenCustomUserNameAttributeNameThenGetNameReturnsCustomUserName() {
|
|
|
String userInfoResponse = "{\n" +
|
|
|
" \"sub\": \"subject1\",\n" +
|
|
|
" \"name\": \"first last\",\n" +
|
|
@@ -319,13 +282,9 @@ public class OidcUserServiceTests {
|
|
|
" \"preferred_username\": \"user1\",\n" +
|
|
|
" \"email\": \"user1@example.com\"\n" +
|
|
|
"}\n";
|
|
|
- server.enqueue(new MockResponse()
|
|
|
- .setHeader(HttpHeaders.ACCEPT, MediaType.APPLICATION_JSON_VALUE)
|
|
|
- .setBody(userInfoResponse));
|
|
|
+ this.server.enqueue(jsonResponse(userInfoResponse));
|
|
|
|
|
|
- server.start();
|
|
|
-
|
|
|
- String userInfoUri = server.url("/user").toString();
|
|
|
+ String userInfoUri = this.server.url("/user").toString();
|
|
|
|
|
|
when(this.userInfoEndpoint.getUri()).thenReturn(userInfoUri);
|
|
|
when(this.userInfoEndpoint.getUserNameAttributeName()).thenReturn(StandardClaimNames.EMAIL);
|
|
@@ -334,16 +293,12 @@ public class OidcUserServiceTests {
|
|
|
OidcUser user = this.userService.loadUser(
|
|
|
new OidcUserRequest(this.clientRegistration, this.accessToken, this.idToken));
|
|
|
|
|
|
- server.shutdown();
|
|
|
-
|
|
|
assertThat(user.getName()).isEqualTo("user1@example.com");
|
|
|
}
|
|
|
|
|
|
// gh-5294
|
|
|
@Test
|
|
|
public void loadUserWhenUserInfoSuccessResponseThenAcceptHeaderJson() throws Exception {
|
|
|
- MockWebServer server = new MockWebServer();
|
|
|
-
|
|
|
String userInfoResponse = "{\n" +
|
|
|
" \"sub\": \"subject1\",\n" +
|
|
|
" \"name\": \"first last\",\n" +
|
|
@@ -352,28 +307,21 @@ public class OidcUserServiceTests {
|
|
|
" \"preferred_username\": \"user1\",\n" +
|
|
|
" \"email\": \"user1@example.com\"\n" +
|
|
|
"}\n";
|
|
|
- server.enqueue(new MockResponse()
|
|
|
- .setHeader(HttpHeaders.ACCEPT, MediaType.APPLICATION_JSON_VALUE)
|
|
|
- .setBody(userInfoResponse));
|
|
|
-
|
|
|
- server.start();
|
|
|
+ this.server.enqueue(jsonResponse(userInfoResponse));
|
|
|
|
|
|
- String userInfoUri = server.url("/user").toString();
|
|
|
+ String userInfoUri = this.server.url("/user").toString();
|
|
|
|
|
|
when(this.userInfoEndpoint.getUri()).thenReturn(userInfoUri);
|
|
|
when(this.accessToken.getTokenValue()).thenReturn("access-token");
|
|
|
|
|
|
this.userService.loadUser(new OidcUserRequest(this.clientRegistration, this.accessToken, this.idToken));
|
|
|
- server.shutdown();
|
|
|
- assertThat(server.takeRequest(1, TimeUnit.SECONDS).getHeader(HttpHeaders.ACCEPT))
|
|
|
- .isEqualTo(MediaType.APPLICATION_JSON_VALUE);
|
|
|
+ assertThat(this.server.takeRequest(1, TimeUnit.SECONDS).getHeader(HttpHeaders.ACCEPT))
|
|
|
+ .isEqualTo(MediaType.APPLICATION_JSON_UTF8_VALUE);
|
|
|
}
|
|
|
|
|
|
// gh-5500
|
|
|
@Test
|
|
|
public void loadUserWhenAuthenticationMethodHeaderSuccessResponseThenHttpMethodGet() throws Exception {
|
|
|
- MockWebServer server = new MockWebServer();
|
|
|
-
|
|
|
String userInfoResponse = "{\n" +
|
|
|
" \"sub\": \"subject1\",\n" +
|
|
|
" \"name\": \"first last\",\n" +
|
|
@@ -382,31 +330,24 @@ public class OidcUserServiceTests {
|
|
|
" \"preferred_username\": \"user1\",\n" +
|
|
|
" \"email\": \"user1@example.com\"\n" +
|
|
|
"}\n";
|
|
|
- server.enqueue(new MockResponse()
|
|
|
- .setHeader(HttpHeaders.ACCEPT, MediaType.APPLICATION_JSON_VALUE)
|
|
|
- .setBody(userInfoResponse));
|
|
|
+ this.server.enqueue(jsonResponse(userInfoResponse));
|
|
|
|
|
|
- server.start();
|
|
|
-
|
|
|
- String userInfoUri = server.url("/user").toString();
|
|
|
+ String userInfoUri = this.server.url("/user").toString();
|
|
|
|
|
|
when(this.userInfoEndpoint.getUri()).thenReturn(userInfoUri);
|
|
|
when(this.userInfoEndpoint.getAuthenticationMethod()).thenReturn(AuthenticationMethod.HEADER);
|
|
|
when(this.accessToken.getTokenValue()).thenReturn("access-token");
|
|
|
|
|
|
this.userService.loadUser(new OidcUserRequest(this.clientRegistration, this.accessToken, this.idToken));
|
|
|
- server.shutdown();
|
|
|
- RecordedRequest request = server.takeRequest();
|
|
|
+ RecordedRequest request = this.server.takeRequest();
|
|
|
assertThat(request.getMethod()).isEqualTo(HttpMethod.GET.name());
|
|
|
- assertThat(request.getHeader(HttpHeaders.ACCEPT)).isEqualTo(MediaType.APPLICATION_JSON_VALUE);
|
|
|
+ assertThat(request.getHeader(HttpHeaders.ACCEPT)).isEqualTo(MediaType.APPLICATION_JSON_UTF8_VALUE);
|
|
|
assertThat(request.getHeader(HttpHeaders.AUTHORIZATION)).isEqualTo("Bearer " + this.accessToken.getTokenValue());
|
|
|
}
|
|
|
|
|
|
// gh-5500
|
|
|
@Test
|
|
|
public void loadUserWhenAuthenticationMethodFormSuccessResponseThenHttpMethodPost() throws Exception {
|
|
|
- MockWebServer server = new MockWebServer();
|
|
|
-
|
|
|
String userInfoResponse = "{\n" +
|
|
|
" \"sub\": \"subject1\",\n" +
|
|
|
" \"name\": \"first last\",\n" +
|
|
@@ -415,24 +356,25 @@ public class OidcUserServiceTests {
|
|
|
" \"preferred_username\": \"user1\",\n" +
|
|
|
" \"email\": \"user1@example.com\"\n" +
|
|
|
"}\n";
|
|
|
- server.enqueue(new MockResponse()
|
|
|
- .setHeader(HttpHeaders.ACCEPT, MediaType.APPLICATION_JSON_VALUE)
|
|
|
- .setBody(userInfoResponse));
|
|
|
+ this.server.enqueue(jsonResponse(userInfoResponse));
|
|
|
|
|
|
- server.start();
|
|
|
-
|
|
|
- String userInfoUri = server.url("/user").toString();
|
|
|
+ String userInfoUri = this.server.url("/user").toString();
|
|
|
|
|
|
when(this.userInfoEndpoint.getUri()).thenReturn(userInfoUri);
|
|
|
when(this.userInfoEndpoint.getAuthenticationMethod()).thenReturn(AuthenticationMethod.FORM);
|
|
|
when(this.accessToken.getTokenValue()).thenReturn("access-token");
|
|
|
|
|
|
this.userService.loadUser(new OidcUserRequest(this.clientRegistration, this.accessToken, this.idToken));
|
|
|
- server.shutdown();
|
|
|
- RecordedRequest request = server.takeRequest();
|
|
|
+ RecordedRequest request = this.server.takeRequest();
|
|
|
assertThat(request.getMethod()).isEqualTo(HttpMethod.POST.name());
|
|
|
- assertThat(request.getHeader(HttpHeaders.ACCEPT)).isEqualTo(MediaType.APPLICATION_JSON_VALUE);
|
|
|
+ assertThat(request.getHeader(HttpHeaders.ACCEPT)).isEqualTo(MediaType.APPLICATION_JSON_UTF8_VALUE);
|
|
|
assertThat(request.getHeader(HttpHeaders.CONTENT_TYPE)).contains(MediaType.APPLICATION_FORM_URLENCODED_VALUE);
|
|
|
assertThat(request.getBody().readUtf8()).isEqualTo("access_token=" + this.accessToken.getTokenValue());
|
|
|
}
|
|
|
+
|
|
|
+ private MockResponse jsonResponse(String json) {
|
|
|
+ return new MockResponse()
|
|
|
+ .setHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE)
|
|
|
+ .setBody(json);
|
|
|
+ }
|
|
|
}
|