Add XML namespace support for oauth2-login
Fixes gh-4557
This commit is contained in:
committed by
Joe Grandja
parent
40c0a452d7
commit
71a5c9521c
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2019 the original author or authors.
|
||||
* Copyright 2002-2020 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.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2019 the original author or authors.
|
||||
* Copyright 2002-2020 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.
|
||||
@@ -17,39 +17,622 @@ package org.springframework.security.config.http;
|
||||
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.mockito.ArgumentCaptor;
|
||||
import org.mockito.internal.util.MockUtil;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.ApplicationListener;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.security.authentication.event.AuthenticationSuccessEvent;
|
||||
import org.springframework.security.config.test.SpringTestRule;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.core.AuthenticationException;
|
||||
import org.springframework.security.core.GrantedAuthority;
|
||||
import org.springframework.security.core.authority.SimpleGrantedAuthority;
|
||||
import org.springframework.security.core.authority.mapping.GrantedAuthoritiesMapper;
|
||||
import org.springframework.security.oauth2.client.OAuth2AuthorizedClientService;
|
||||
import org.springframework.security.oauth2.client.endpoint.OAuth2AccessTokenResponseClient;
|
||||
import org.springframework.security.oauth2.client.endpoint.OAuth2AuthorizationCodeGrantRequest;
|
||||
import org.springframework.security.oauth2.client.registration.ClientRegistration;
|
||||
import org.springframework.security.oauth2.client.registration.ClientRegistrationRepository;
|
||||
import org.springframework.security.oauth2.client.registration.TestClientRegistrations;
|
||||
import org.springframework.security.oauth2.client.userinfo.OAuth2UserRequest;
|
||||
import org.springframework.security.oauth2.client.userinfo.OAuth2UserService;
|
||||
import org.springframework.security.oauth2.client.web.AuthenticatedPrincipalOAuth2AuthorizedClientRepository;
|
||||
import org.springframework.security.oauth2.client.web.AuthorizationRequestRepository;
|
||||
import org.springframework.security.oauth2.client.web.OAuth2AuthorizationRequestResolver;
|
||||
import org.springframework.security.oauth2.client.web.OAuth2AuthorizedClientRepository;
|
||||
import org.springframework.security.oauth2.client.web.OAuth2LoginAuthenticationFilter;
|
||||
import org.springframework.security.oauth2.core.OAuth2AuthenticationException;
|
||||
import org.springframework.security.oauth2.core.endpoint.OAuth2AccessTokenResponse;
|
||||
import org.springframework.security.oauth2.core.endpoint.OAuth2AuthorizationRequest;
|
||||
import org.springframework.security.oauth2.core.endpoint.OAuth2ParameterNames;
|
||||
import org.springframework.security.oauth2.core.endpoint.TestOAuth2AuthorizationRequests;
|
||||
import org.springframework.security.oauth2.core.oidc.endpoint.OidcParameterNames;
|
||||
import org.springframework.security.oauth2.core.user.OAuth2User;
|
||||
import org.springframework.security.oauth2.core.user.TestOAuth2Users;
|
||||
import org.springframework.security.oauth2.jwt.Jwt;
|
||||
import org.springframework.security.oauth2.jwt.JwtDecoderFactory;
|
||||
import org.springframework.security.oauth2.jwt.TestJwts;
|
||||
import org.springframework.security.web.authentication.AuthenticationFailureHandler;
|
||||
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
|
||||
import org.springframework.security.web.context.SecurityContextRepository;
|
||||
import org.springframework.test.web.servlet.MockMvc;
|
||||
import org.springframework.test.web.servlet.MvcResult;
|
||||
import org.springframework.util.LinkedMultiValueMap;
|
||||
import org.springframework.util.MultiValueMap;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.Mockito.times;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
import static org.springframework.security.oauth2.core.endpoint.TestOAuth2AccessTokenResponses.accessTokenResponse;
|
||||
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.redirectedUrlPattern;
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.redirectedUrl;
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
/**
|
||||
* Tests for {@link OAuth2LoginBeanDefinitionParser}.
|
||||
*
|
||||
* @author
|
||||
* @author Ruby Hartono
|
||||
*/
|
||||
public class OAuth2LoginBeanDefinitionParserTests {
|
||||
private static final String CONFIG_LOCATION_PREFIX =
|
||||
"classpath:org/springframework/security/config/http/OAuth2LoginBeanDefinitionParserTests";
|
||||
private static final String CONFIG_LOCATION_PREFIX = "classpath:org/springframework/security/config/http/OAuth2LoginBeanDefinitionParserTests";
|
||||
|
||||
@Rule
|
||||
public final SpringTestRule spring = new SpringTestRule();
|
||||
|
||||
@Autowired
|
||||
private ClientRegistrationRepository clientRegistrationRepository;
|
||||
|
||||
@Autowired
|
||||
private OAuth2LoginAuthenticationFilter oauth2LoginAuthenticationFilter;
|
||||
|
||||
@Autowired(required = false)
|
||||
private OAuth2AuthorizedClientRepository oauth2AuthorizedClientRepository;
|
||||
|
||||
@Autowired(required = false)
|
||||
private OAuth2AuthorizedClientService oauth2AuthorizedClientService;
|
||||
|
||||
@Autowired
|
||||
SecurityContextRepository securityContextRepository;
|
||||
|
||||
@Autowired(required = false)
|
||||
private ApplicationListener<AuthenticationSuccessEvent> authenticationSuccessListener;
|
||||
|
||||
@Autowired(required = false)
|
||||
private AuthorizationRequestRepository<OAuth2AuthorizationRequest> authorizationRequestRepository;
|
||||
|
||||
@Autowired(required = false)
|
||||
private OAuth2AccessTokenResponseClient<OAuth2AuthorizationCodeGrantRequest> accessTokenResponseClient;
|
||||
|
||||
@Autowired(required = false)
|
||||
private OAuth2UserService<OAuth2UserRequest, OAuth2User> oauth2UserService;
|
||||
|
||||
@Autowired(required = false)
|
||||
private JwtDecoderFactory<ClientRegistration> jwtDecoderFactory;
|
||||
|
||||
@Autowired(required = false)
|
||||
private OAuth2AuthorizationRequestResolver oauth2AuthorizationRequestResolver;
|
||||
|
||||
@Autowired(required = false)
|
||||
private GrantedAuthoritiesMapper grantedAuthoritiesMapper;
|
||||
|
||||
@Autowired(required = false)
|
||||
private AuthenticationFailureHandler authenticationFailureHandler;
|
||||
|
||||
@Autowired(required = false)
|
||||
private AuthenticationSuccessHandler authenticationSuccessHandler;
|
||||
|
||||
@Autowired
|
||||
private MockMvc mvc;
|
||||
|
||||
@Test
|
||||
public void requestLoginWhenMultiClientRegistrationThenReturnLoginPageWithOauth2Login() throws Exception {
|
||||
this.spring.configLocations(this.xml("MultiClientRegistration")).autowire();
|
||||
|
||||
MvcResult result = this.mvc.perform(get("/login")).andExpect(status().is2xxSuccessful()).andReturn();
|
||||
|
||||
assertThat(result.getResponse().getContentAsString())
|
||||
.contains("<a href=\"/oauth2/authorization/google-login\">Google</a>");
|
||||
assertThat(result.getResponse().getContentAsString())
|
||||
.contains("<a href=\"/oauth2/authorization/github-login\">Github</a>");
|
||||
}
|
||||
|
||||
// gh-5347
|
||||
@Test
|
||||
public void requestWhenSingleClientRegistrationThenAutoRedirect() throws Exception {
|
||||
this.spring.configLocations(this.xml("SingleClientRegistration-WithinSameFile")).autowire();
|
||||
|
||||
this.mvc.perform(get("/")).andExpect(status().is3xxRedirection())
|
||||
.andExpect(redirectedUrl("http://localhost/oauth2/authorization/google-login"));
|
||||
}
|
||||
|
||||
// gh-5347
|
||||
@Test
|
||||
public void requestWhenSingleClientRegistrationAndRequestFaviconNotAuthenticatedThenRedirectDefaultLoginPage()
|
||||
throws Exception {
|
||||
this.spring.configLocations(this.xml("SingleClientRegistration")).autowire();
|
||||
|
||||
this.mvc.perform(get("/"))
|
||||
.andExpect(status().is3xxRedirection())
|
||||
.andExpect(redirectedUrlPattern("/oauth2/authorization/google-login"));
|
||||
this.mvc.perform(get("/favicon.ico").accept(new MediaType("image", "*"))).andExpect(status().is3xxRedirection())
|
||||
.andExpect(redirectedUrl("http://localhost/login"));
|
||||
}
|
||||
|
||||
// gh-6812
|
||||
@Test
|
||||
public void requestWhenSingleClientRegistrationAndRequestXHRNotAuthenticatedThenDoesNotRedirectForAuthorization()
|
||||
throws Exception {
|
||||
this.spring.configLocations(this.xml("SingleClientRegistration")).autowire();
|
||||
|
||||
this.mvc.perform(get("/").header("X-Requested-With", "XMLHttpRequest")).andExpect(status().is3xxRedirection())
|
||||
.andExpect(redirectedUrl("http://localhost/login"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void requestWhenAuthorizationRequestNotFoundThenThrowAuthenticationException() throws Exception {
|
||||
this.spring.configLocations(this.xml("SingleClientRegistration-WithCustomAuthenticationFailureHandler"))
|
||||
.autowire();
|
||||
|
||||
MultiValueMap<String, String> params = new LinkedMultiValueMap<>();
|
||||
params.add("code", "code123");
|
||||
params.add("state", "state123");
|
||||
this.mvc.perform(get("/login/oauth2/code/google").params(params));
|
||||
|
||||
// assertions
|
||||
ArgumentCaptor<AuthenticationException> exceptionCaptor = ArgumentCaptor
|
||||
.forClass(AuthenticationException.class);
|
||||
verify(authenticationFailureHandler).onAuthenticationFailure(any(), any(), exceptionCaptor.capture());
|
||||
AuthenticationException excValue = exceptionCaptor.getValue();
|
||||
assertThat(excValue).isInstanceOf(OAuth2AuthenticationException.class);
|
||||
assertThat(((OAuth2AuthenticationException) excValue).getError().getErrorCode())
|
||||
.isEqualTo("authorization_request_not_found");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void requestWhenAuthorizationResponseValidThenAuthenticate() throws Exception {
|
||||
this.spring.configLocations(this.xml("SingleClientRegistration-WithTestConfiguration")).autowire();
|
||||
OAuth2AccessTokenResponse accessTokenResponse = accessTokenResponse().build();
|
||||
when(this.accessTokenResponseClient.getTokenResponse(any())).thenReturn(accessTokenResponse);
|
||||
|
||||
OAuth2User oauth2User = TestOAuth2Users.create();
|
||||
when(this.oauth2UserService.loadUser(any())).thenReturn(oauth2User);
|
||||
|
||||
Map<String, Object> attributes = new HashMap<>();
|
||||
attributes.put(OAuth2ParameterNames.REGISTRATION_ID, "google-login");
|
||||
OAuth2AuthorizationRequest authRequest = TestOAuth2AuthorizationRequests.request().attributes(attributes)
|
||||
.build();
|
||||
when(this.authorizationRequestRepository.removeAuthorizationRequest(any(), any())).thenReturn(authRequest);
|
||||
|
||||
MultiValueMap<String, String> params = new LinkedMultiValueMap<>();
|
||||
params.add("code", "code123");
|
||||
params.add("state", authRequest.getState());
|
||||
this.mvc.perform(get("/login/oauth2/code/google").params(params)).andExpect(status().is2xxSuccessful());
|
||||
|
||||
ArgumentCaptor<Authentication> authenticationCaptor = ArgumentCaptor.forClass(Authentication.class);
|
||||
verify(authenticationSuccessHandler).onAuthenticationSuccess(any(), any(), authenticationCaptor.capture());
|
||||
Authentication authenticationValue = authenticationCaptor.getValue();
|
||||
assertThat(authenticationValue.getAuthorities()).hasSize(1);
|
||||
assertThat(authenticationValue.getAuthorities()).first().isInstanceOf(SimpleGrantedAuthority.class)
|
||||
.hasToString("ROLE_USER");
|
||||
}
|
||||
|
||||
// gh-6009
|
||||
@Test
|
||||
public void requestWhenAuthorizationResponseValidThenAuthenticationSuccessEventPublished() throws Exception {
|
||||
this.spring.configLocations(this.xml("SingleClientRegistration-WithTestConfiguration")).autowire();
|
||||
OAuth2AccessTokenResponse accessTokenResponse = accessTokenResponse().build();
|
||||
when(this.accessTokenResponseClient.getTokenResponse(any())).thenReturn(accessTokenResponse);
|
||||
|
||||
OAuth2User oauth2User = TestOAuth2Users.create();
|
||||
when(this.oauth2UserService.loadUser(any())).thenReturn(oauth2User);
|
||||
|
||||
Map<String, Object> attributes = new HashMap<>();
|
||||
attributes.put(OAuth2ParameterNames.REGISTRATION_ID, "google-login");
|
||||
OAuth2AuthorizationRequest authRequest = TestOAuth2AuthorizationRequests.request().attributes(attributes)
|
||||
.build();
|
||||
when(this.authorizationRequestRepository.removeAuthorizationRequest(any(), any())).thenReturn(authRequest);
|
||||
|
||||
MultiValueMap<String, String> params = new LinkedMultiValueMap<>();
|
||||
params.add("code", "code123");
|
||||
params.add("state", authRequest.getState());
|
||||
this.mvc.perform(get("/login/oauth2/code/google").params(params));
|
||||
|
||||
// assertions
|
||||
verify(authenticationSuccessListener).onApplicationEvent(any(AuthenticationSuccessEvent.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void requestWhenOidcAuthenticationResponseValidThenJwtDecoderFactoryCalled() throws Exception {
|
||||
this.spring.configLocations(this.xml("SingleClientRegistration-WithJwtDecoderFactoryAndDefaultSuccessHandler"))
|
||||
.autowire();
|
||||
Map<String, Object> additionalParameters = new HashMap<>();
|
||||
additionalParameters.put(OidcParameterNames.ID_TOKEN, "token123");
|
||||
OAuth2AccessTokenResponse accessTokenResponse = accessTokenResponse().additionalParameters(additionalParameters)
|
||||
.build();
|
||||
when(this.accessTokenResponseClient.getTokenResponse(any())).thenReturn(accessTokenResponse);
|
||||
|
||||
Jwt jwt = TestJwts.user();
|
||||
when(this.jwtDecoderFactory.createDecoder(any())).thenReturn(token -> jwt);
|
||||
|
||||
Map<String, Object> attributes = new HashMap<>();
|
||||
attributes.put(OAuth2ParameterNames.REGISTRATION_ID, "google-login");
|
||||
OAuth2AuthorizationRequest authRequest = TestOAuth2AuthorizationRequests.request().attributes(attributes)
|
||||
.scope("openid").build();
|
||||
when(this.authorizationRequestRepository.removeAuthorizationRequest(any(), any())).thenReturn(authRequest);
|
||||
|
||||
MultiValueMap<String, String> params = new LinkedMultiValueMap<>();
|
||||
params.add("code", "code123");
|
||||
params.add("state", authRequest.getState());
|
||||
this.mvc.perform(get("/login/oauth2/code/google").params(params)).andExpect(status().is3xxRedirection())
|
||||
.andExpect(redirectedUrl("/"));
|
||||
}
|
||||
|
||||
@SuppressWarnings({ "unchecked", "rawtypes" })
|
||||
@Test
|
||||
public void requestWhenCustomGrantedAuthoritiesMapperThenCalled() throws Exception {
|
||||
this.spring.configLocations(this.xml("SingleClientRegistration-WithCustomGrantedAuthorities")).autowire();
|
||||
Map<String, Object> additionalParameters = new HashMap<>();
|
||||
additionalParameters.put(OidcParameterNames.ID_TOKEN, "token123");
|
||||
OAuth2AccessTokenResponse accessTokenResponse = accessTokenResponse().additionalParameters(additionalParameters)
|
||||
.build();
|
||||
when(this.accessTokenResponseClient.getTokenResponse(any())).thenReturn(accessTokenResponse);
|
||||
|
||||
OAuth2User oauth2User = TestOAuth2Users.create();
|
||||
when(this.oauth2UserService.loadUser(any())).thenReturn(oauth2User);
|
||||
|
||||
GrantedAuthority grantedAuthority = new SimpleGrantedAuthority("ROLE_OAUTH2_USER");
|
||||
when(this.grantedAuthoritiesMapper.mapAuthorities(any()))
|
||||
.thenReturn((Collection) Collections.singletonList(grantedAuthority));
|
||||
|
||||
Map<String, Object> attributes = new HashMap<>();
|
||||
attributes.put(OAuth2ParameterNames.REGISTRATION_ID, "google-login");
|
||||
OAuth2AuthorizationRequest authRequest = TestOAuth2AuthorizationRequests.request().attributes(attributes)
|
||||
.build();
|
||||
when(this.authorizationRequestRepository.removeAuthorizationRequest(any(), any())).thenReturn(authRequest);
|
||||
|
||||
MultiValueMap<String, String> params = new LinkedMultiValueMap<>();
|
||||
params.add("code", "code123");
|
||||
params.add("state", authRequest.getState());
|
||||
this.mvc.perform(get("/login/oauth2/code/google").params(params)).andExpect(status().is2xxSuccessful());
|
||||
|
||||
ArgumentCaptor<Authentication> authenticationCaptor = ArgumentCaptor.forClass(Authentication.class);
|
||||
verify(authenticationSuccessHandler).onAuthenticationSuccess(any(), any(), authenticationCaptor.capture());
|
||||
Authentication authenticationValue = authenticationCaptor.getValue();
|
||||
assertThat(authenticationValue.getAuthorities()).hasSize(1);
|
||||
assertThat(authenticationValue.getAuthorities()).first().isInstanceOf(SimpleGrantedAuthority.class)
|
||||
.hasToString("ROLE_OAUTH2_USER");
|
||||
|
||||
// re-setup for OIDC test
|
||||
Jwt jwt = TestJwts.user();
|
||||
when(this.jwtDecoderFactory.createDecoder(any())).thenReturn(token -> jwt);
|
||||
|
||||
grantedAuthority = new SimpleGrantedAuthority("ROLE_OIDC_USER");
|
||||
when(this.grantedAuthoritiesMapper.mapAuthorities(any()))
|
||||
.thenReturn((Collection) Collections.singletonList(grantedAuthority));
|
||||
|
||||
authRequest = TestOAuth2AuthorizationRequests.request().attributes(attributes).scope("openid").build();
|
||||
when(this.authorizationRequestRepository.removeAuthorizationRequest(any(), any())).thenReturn(authRequest);
|
||||
|
||||
this.mvc.perform(get("/login/oauth2/code/google").params(params)).andExpect(status().is2xxSuccessful());
|
||||
|
||||
authenticationCaptor = ArgumentCaptor.forClass(Authentication.class);
|
||||
verify(authenticationSuccessHandler, times(2)).onAuthenticationSuccess(any(), any(),
|
||||
authenticationCaptor.capture());
|
||||
authenticationValue = authenticationCaptor.getValue();
|
||||
assertThat(authenticationValue.getAuthorities()).hasSize(1);
|
||||
assertThat(authenticationValue.getAuthorities()).first().isInstanceOf(SimpleGrantedAuthority.class)
|
||||
.hasToString("ROLE_OIDC_USER");
|
||||
}
|
||||
|
||||
@SuppressWarnings({ "unchecked", "rawtypes" })
|
||||
@Test
|
||||
public void successOidcLoginWhenSingleClientRegistrationAndCustomAuthoritiesThenReturnSuccessWithCorrectAuthorities()
|
||||
throws Exception {
|
||||
this.spring.configLocations(this.xml("SingleClientRegistration-WithJwtDecoderFactory")).autowire();
|
||||
Map<String, Object> additionalParameters = new HashMap<>();
|
||||
additionalParameters.put(OidcParameterNames.ID_TOKEN, "token123");
|
||||
OAuth2AccessTokenResponse accessTokenResponse = accessTokenResponse().additionalParameters(additionalParameters)
|
||||
.build();
|
||||
when(this.accessTokenResponseClient.getTokenResponse(any())).thenReturn(accessTokenResponse);
|
||||
|
||||
Jwt jwt = TestJwts.user();
|
||||
when(this.jwtDecoderFactory.createDecoder(any())).thenReturn(token -> jwt);
|
||||
|
||||
GrantedAuthority grantedAuthority = new SimpleGrantedAuthority("ROLE_OIDC_USER");
|
||||
when(this.grantedAuthoritiesMapper.mapAuthorities(any()))
|
||||
.thenReturn((Collection) Collections.singletonList(grantedAuthority));
|
||||
|
||||
Map<String, Object> attributes = new HashMap<>();
|
||||
attributes.put(OAuth2ParameterNames.REGISTRATION_ID, "google-login");
|
||||
OAuth2AuthorizationRequest authRequest = TestOAuth2AuthorizationRequests.request().attributes(attributes)
|
||||
.scope("openid").build();
|
||||
when(this.authorizationRequestRepository.removeAuthorizationRequest(any(), any())).thenReturn(authRequest);
|
||||
|
||||
MultiValueMap<String, String> params = new LinkedMultiValueMap<>();
|
||||
params.add("code", "code123");
|
||||
params.add("state", authRequest.getState());
|
||||
this.mvc.perform(get("/login/oauth2/code/google").params(params)).andExpect(status().is2xxSuccessful());
|
||||
|
||||
ArgumentCaptor<Authentication> authenticationCaptor = ArgumentCaptor.forClass(Authentication.class);
|
||||
verify(authenticationSuccessHandler).onAuthenticationSuccess(any(), any(), authenticationCaptor.capture());
|
||||
Authentication authenticationValue = authenticationCaptor.getValue();
|
||||
assertThat(authenticationValue.getAuthorities()).hasSize(1);
|
||||
assertThat(authenticationValue.getAuthorities()).first().isInstanceOf(SimpleGrantedAuthority.class)
|
||||
.hasToString("ROLE_OIDC_USER");
|
||||
}
|
||||
|
||||
// gh-5488
|
||||
@Test
|
||||
public void requestWhenCustomLoginProcessingUrlThenProcessAuthentication() throws Exception {
|
||||
this.spring.configLocations(this.xml("SingleClientRegistration-WithCustomLoginProcessingUrl")).autowire();
|
||||
OAuth2AccessTokenResponse accessTokenResponse = accessTokenResponse().build();
|
||||
when(this.accessTokenResponseClient.getTokenResponse(any())).thenReturn(accessTokenResponse);
|
||||
|
||||
OAuth2User oauth2User = TestOAuth2Users.create();
|
||||
when(this.oauth2UserService.loadUser(any())).thenReturn(oauth2User);
|
||||
|
||||
Map<String, Object> attributes = new HashMap<>();
|
||||
attributes.put(OAuth2ParameterNames.REGISTRATION_ID, "google-login");
|
||||
OAuth2AuthorizationRequest authRequest = TestOAuth2AuthorizationRequests.request().attributes(attributes)
|
||||
.build();
|
||||
when(this.authorizationRequestRepository.removeAuthorizationRequest(any(), any())).thenReturn(authRequest);
|
||||
|
||||
MultiValueMap<String, String> params = new LinkedMultiValueMap<>();
|
||||
params.add("code", "code123");
|
||||
params.add("state", authRequest.getState());
|
||||
this.mvc.perform(get("/login/oauth2/google").params(params)).andExpect(status().is2xxSuccessful());
|
||||
|
||||
ArgumentCaptor<Authentication> authenticationCaptor = ArgumentCaptor.forClass(Authentication.class);
|
||||
verify(authenticationSuccessHandler).onAuthenticationSuccess(any(), any(), authenticationCaptor.capture());
|
||||
Authentication authenticationValue = authenticationCaptor.getValue();
|
||||
assertThat(authenticationValue.getAuthorities()).hasSize(1);
|
||||
assertThat(authenticationValue.getAuthorities()).first().isInstanceOf(SimpleGrantedAuthority.class)
|
||||
.hasToString("ROLE_USER");
|
||||
}
|
||||
|
||||
// gh-5521
|
||||
@Test
|
||||
public void requestWhenCustomAuthorizationRequestResolverThenCalled() throws Exception {
|
||||
this.spring.configLocations(this.xml("SingleClientRegistration-WithCustomAuthorizationRequestResolver"))
|
||||
.autowire();
|
||||
|
||||
this.mvc.perform(get("/oauth2/authorization/google")).andExpect(status().is3xxRedirection());
|
||||
|
||||
verify(oauth2AuthorizationRequestResolver).resolve(any());
|
||||
}
|
||||
|
||||
// gh-5347
|
||||
@Test
|
||||
public void requestWhenMultipleClientsConfiguredThenRedirectDefaultLoginPage() throws Exception {
|
||||
this.spring.configLocations(this.xml("MultiClientRegistration")).autowire();
|
||||
|
||||
this.mvc.perform(get("/")).andExpect(status().is3xxRedirection())
|
||||
.andExpect(redirectedUrl("http://localhost/login"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void requestWhenCustomLoginPageThenRedirectCustomLoginPage() throws Exception {
|
||||
this.spring.configLocations(this.xml("SingleClientRegistration-WithCustomLoginPage")).autowire();
|
||||
|
||||
this.mvc.perform(get("/")).andExpect(status().is3xxRedirection())
|
||||
.andExpect(redirectedUrl("http://localhost/custom-login"));
|
||||
}
|
||||
|
||||
// gh-6802
|
||||
@Test
|
||||
public void requestWhenSingleClientRegistrationAndFormLoginConfiguredThenRedirectDefaultLoginPage()
|
||||
throws Exception {
|
||||
this.spring.configLocations(this.xml("SingleClientRegistration-WithFormLogin")).autowire();
|
||||
|
||||
this.mvc.perform(get("/")).andExpect(status().is3xxRedirection())
|
||||
.andExpect(redirectedUrl("http://localhost/login"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void requestWhenCustomClientRegistrationRepositoryThenCalled() throws Exception {
|
||||
this.spring.configLocations(this.xml("WithCustomClientRegistrationRepository")).autowire();
|
||||
|
||||
OAuth2AccessTokenResponse accessTokenResponse = accessTokenResponse().build();
|
||||
when(this.accessTokenResponseClient.getTokenResponse(any())).thenReturn(accessTokenResponse);
|
||||
|
||||
OAuth2User oauth2User = TestOAuth2Users.create();
|
||||
when(this.oauth2UserService.loadUser(any())).thenReturn(oauth2User);
|
||||
|
||||
Map<String, Object> attributes = new HashMap<>();
|
||||
attributes.put(OAuth2ParameterNames.REGISTRATION_ID, "google-login");
|
||||
OAuth2AuthorizationRequest authRequest = TestOAuth2AuthorizationRequests.request().attributes(attributes)
|
||||
.build();
|
||||
when(this.authorizationRequestRepository.removeAuthorizationRequest(any(), any())).thenReturn(authRequest);
|
||||
|
||||
MultiValueMap<String, String> params = new LinkedMultiValueMap<>();
|
||||
params.add("code", "code123");
|
||||
params.add("state", authRequest.getState());
|
||||
this.mvc.perform(get("/login/oauth2/code/google").params(params));
|
||||
|
||||
assertThat(MockUtil.isMock(clientRegistrationRepository)).isTrue();
|
||||
verify(clientRegistrationRepository).findByRegistrationId("google-login");
|
||||
|
||||
Field field = oauth2LoginAuthenticationFilter.getClass().getDeclaredField("clientRegistrationRepository");
|
||||
field.setAccessible(true);
|
||||
Object fieldVal = field.get(oauth2LoginAuthenticationFilter);
|
||||
assertThat(MockUtil.isMock(fieldVal)).isTrue();
|
||||
assertThat(fieldVal).isSameAs(clientRegistrationRepository);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void requestWhenCustomAuthorizedClientRepositoryThenCalled() throws Exception {
|
||||
this.spring.configLocations(this.xml("WithCustomAuthorizedClientRepository")).autowire();
|
||||
|
||||
ClientRegistration clientReg = TestClientRegistrations.clientRegistration().build();
|
||||
when(this.clientRegistrationRepository.findByRegistrationId(any())).thenReturn(clientReg);
|
||||
|
||||
OAuth2AccessTokenResponse accessTokenResponse = accessTokenResponse().build();
|
||||
when(this.accessTokenResponseClient.getTokenResponse(any())).thenReturn(accessTokenResponse);
|
||||
|
||||
OAuth2User oauth2User = TestOAuth2Users.create();
|
||||
when(this.oauth2UserService.loadUser(any())).thenReturn(oauth2User);
|
||||
|
||||
Map<String, Object> attributes = new HashMap<>();
|
||||
attributes.put(OAuth2ParameterNames.REGISTRATION_ID, "google-login");
|
||||
OAuth2AuthorizationRequest authRequest = TestOAuth2AuthorizationRequests.request().attributes(attributes)
|
||||
.build();
|
||||
when(this.authorizationRequestRepository.removeAuthorizationRequest(any(), any())).thenReturn(authRequest);
|
||||
|
||||
MultiValueMap<String, String> params = new LinkedMultiValueMap<>();
|
||||
params.add("code", "code123");
|
||||
params.add("state", authRequest.getState());
|
||||
this.mvc.perform(get("/login/oauth2/code/registration-id").params(params));
|
||||
|
||||
assertThat(MockUtil.isMock(oauth2AuthorizedClientRepository)).isTrue();
|
||||
verify(oauth2AuthorizedClientRepository).saveAuthorizedClient(any(), any(), any(), any());
|
||||
|
||||
Field field = oauth2LoginAuthenticationFilter.getClass().getDeclaredField("authorizedClientRepository");
|
||||
field.setAccessible(true);
|
||||
Object fieldVal = field.get(oauth2LoginAuthenticationFilter);
|
||||
assertThat(MockUtil.isMock(fieldVal)).isTrue();
|
||||
assertThat(fieldVal).isSameAs(oauth2AuthorizedClientRepository);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void requestWhenCustomAuthorizedClientServiceThenCalled() throws Exception {
|
||||
this.spring.configLocations(this.xml("WithCustomAuthorizedClientService")).autowire();
|
||||
|
||||
ClientRegistration clientReg = TestClientRegistrations.clientRegistration().build();
|
||||
when(this.clientRegistrationRepository.findByRegistrationId(any())).thenReturn(clientReg);
|
||||
|
||||
OAuth2AccessTokenResponse accessTokenResponse = accessTokenResponse().build();
|
||||
when(this.accessTokenResponseClient.getTokenResponse(any())).thenReturn(accessTokenResponse);
|
||||
|
||||
OAuth2User oauth2User = TestOAuth2Users.create();
|
||||
when(this.oauth2UserService.loadUser(any())).thenReturn(oauth2User);
|
||||
|
||||
Map<String, Object> attributes = new HashMap<>();
|
||||
attributes.put(OAuth2ParameterNames.REGISTRATION_ID, "google-login");
|
||||
OAuth2AuthorizationRequest authRequest = TestOAuth2AuthorizationRequests.request().attributes(attributes)
|
||||
.build();
|
||||
when(this.authorizationRequestRepository.removeAuthorizationRequest(any(), any())).thenReturn(authRequest);
|
||||
|
||||
MultiValueMap<String, String> params = new LinkedMultiValueMap<>();
|
||||
params.add("code", "code123");
|
||||
params.add("state", authRequest.getState());
|
||||
this.mvc.perform(get("/login/oauth2/code/registration-id").params(params));
|
||||
|
||||
assertThat(MockUtil.isMock(oauth2AuthorizedClientService)).isTrue();
|
||||
verify(oauth2AuthorizedClientService).saveAuthorizedClient(any(), any());
|
||||
|
||||
Field authorizedClientRepositoryField = oauth2LoginAuthenticationFilter.getClass()
|
||||
.getDeclaredField("authorizedClientRepository");
|
||||
authorizedClientRepositoryField.setAccessible(true);
|
||||
Object authorizedClientRepositoryFieldVal = authorizedClientRepositoryField
|
||||
.get(oauth2LoginAuthenticationFilter);
|
||||
assertThat(authorizedClientRepositoryFieldVal)
|
||||
.isInstanceOf(AuthenticatedPrincipalOAuth2AuthorizedClientRepository.class);
|
||||
|
||||
Field authorizedClientServiceField = authorizedClientRepositoryFieldVal.getClass()
|
||||
.getDeclaredField("authorizedClientService");
|
||||
authorizedClientServiceField.setAccessible(true);
|
||||
Object authorizedClientServiceFieldVal = authorizedClientServiceField.get(authorizedClientRepositoryFieldVal);
|
||||
assertThat(MockUtil.isMock(authorizedClientServiceFieldVal)).isTrue();
|
||||
assertThat(authorizedClientServiceFieldVal).isSameAs(oauth2AuthorizedClientService);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void requestWhenCustomAuthorizationRequestRepositoryThenCalled() throws Exception {
|
||||
this.spring.configLocations(this.xml("WithCustomAuthorizationRequestRepository")).autowire();
|
||||
|
||||
ClientRegistration clientReg = TestClientRegistrations.clientRegistration().build();
|
||||
when(this.clientRegistrationRepository.findByRegistrationId(any())).thenReturn(clientReg);
|
||||
|
||||
OAuth2AccessTokenResponse accessTokenResponse = accessTokenResponse().build();
|
||||
when(this.accessTokenResponseClient.getTokenResponse(any())).thenReturn(accessTokenResponse);
|
||||
|
||||
OAuth2User oauth2User = TestOAuth2Users.create();
|
||||
when(this.oauth2UserService.loadUser(any())).thenReturn(oauth2User);
|
||||
|
||||
MultiValueMap<String, String> params = new LinkedMultiValueMap<>();
|
||||
params.add("code", "code123");
|
||||
params.add("state", "state");
|
||||
this.mvc.perform(get("/login/oauth2/code/registration-id").params(params));
|
||||
|
||||
assertThat(MockUtil.isMock(authorizationRequestRepository)).isTrue();
|
||||
verify(authorizationRequestRepository).removeAuthorizationRequest(any(), any());
|
||||
|
||||
Field authorizationRequestRepositoryField = oauth2LoginAuthenticationFilter.getClass()
|
||||
.getDeclaredField("authorizationRequestRepository");
|
||||
authorizationRequestRepositoryField.setAccessible(true);
|
||||
Object authorizationRequestRepositoryFieldVal = authorizationRequestRepositoryField
|
||||
.get(oauth2LoginAuthenticationFilter);
|
||||
assertThat(MockUtil.isMock(authorizationRequestRepositoryFieldVal)).isTrue();
|
||||
assertThat(authorizationRequestRepositoryFieldVal).isSameAs(authorizationRequestRepository);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void requestWhenCustomAuthenticationSuccessHandlerThenCalled() throws Exception {
|
||||
this.spring.configLocations(this.xml("SingleClientRegistration-WithCustomAuthenticationHandler")).autowire();
|
||||
OAuth2AccessTokenResponse accessTokenResponse = accessTokenResponse().build();
|
||||
when(this.accessTokenResponseClient.getTokenResponse(any())).thenReturn(accessTokenResponse);
|
||||
|
||||
OAuth2User oauth2User = TestOAuth2Users.create();
|
||||
when(this.oauth2UserService.loadUser(any())).thenReturn(oauth2User);
|
||||
|
||||
Map<String, Object> attributes = new HashMap<>();
|
||||
attributes.put(OAuth2ParameterNames.REGISTRATION_ID, "google-login");
|
||||
OAuth2AuthorizationRequest authRequest = TestOAuth2AuthorizationRequests.request().attributes(attributes)
|
||||
.build();
|
||||
when(this.authorizationRequestRepository.removeAuthorizationRequest(any(), any())).thenReturn(authRequest);
|
||||
|
||||
MultiValueMap<String, String> params = new LinkedMultiValueMap<>();
|
||||
params.add("code", "code123");
|
||||
params.add("state", authRequest.getState());
|
||||
this.mvc.perform(get("/login/oauth2/code/google").params(params)).andExpect(status().is2xxSuccessful());
|
||||
|
||||
ArgumentCaptor<Authentication> authenticationCaptor = ArgumentCaptor.forClass(Authentication.class);
|
||||
verify(authenticationSuccessHandler).onAuthenticationSuccess(any(), any(), authenticationCaptor.capture());
|
||||
Authentication authenticationValue = authenticationCaptor.getValue();
|
||||
assertThat(authenticationValue.getAuthorities()).hasSize(1);
|
||||
assertThat(authenticationValue.getAuthorities()).first().isInstanceOf(SimpleGrantedAuthority.class)
|
||||
.hasToString("ROLE_USER");
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void requestWhenCustomAuthenticationFailureHandlerThenCalled() throws Exception {
|
||||
this.spring.configLocations(this.xml("SingleClientRegistration-WithCustomAuthenticationHandler")).autowire();
|
||||
|
||||
MultiValueMap<String, String> params = new LinkedMultiValueMap<>();
|
||||
params.add("code", "code123");
|
||||
params.add("state", "state123");
|
||||
this.mvc.perform(get("/login/oauth2/code/google").params(params)).andExpect(status().isIAmATeapot());
|
||||
}
|
||||
|
||||
private String xml(String configName) {
|
||||
return CONFIG_LOCATION_PREFIX + "-" + configName + ".xml";
|
||||
}
|
||||
|
||||
public static class TeapotAuthenticationHandler
|
||||
implements AuthenticationSuccessHandler, AuthenticationFailureHandler {
|
||||
|
||||
@Override
|
||||
public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response,
|
||||
AuthenticationException exception) {
|
||||
response.setStatus(HttpStatus.I_AM_A_TEAPOT.value());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response,
|
||||
Authentication authentication) {
|
||||
response.setStatus(HttpStatus.I_AM_A_TEAPOT.value());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,242 @@
|
||||
/*
|
||||
* Copyright 2002-2020 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.security.config.oauth2.client;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
import java.util.Map;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.security.config.test.SpringTestRule;
|
||||
import org.springframework.security.oauth2.client.registration.ClientRegistration;
|
||||
import org.springframework.security.oauth2.client.registration.ClientRegistration.ProviderDetails;
|
||||
import org.springframework.security.oauth2.client.registration.ClientRegistrationRepository;
|
||||
import org.springframework.security.oauth2.client.registration.InMemoryClientRegistrationRepository;
|
||||
import org.springframework.security.oauth2.core.AuthenticationMethod;
|
||||
import org.springframework.security.oauth2.core.AuthorizationGrantType;
|
||||
import org.springframework.security.oauth2.core.ClientAuthenticationMethod;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
import com.fasterxml.jackson.core.type.TypeReference;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
|
||||
import okhttp3.mockwebserver.Dispatcher;
|
||||
import okhttp3.mockwebserver.MockResponse;
|
||||
import okhttp3.mockwebserver.MockWebServer;
|
||||
import okhttp3.mockwebserver.RecordedRequest;
|
||||
|
||||
/**
|
||||
* Tests for {@link ClientRegistrationsBeanDefinitionParser}.
|
||||
*
|
||||
* @author Ruby Hartono
|
||||
*/
|
||||
public class ClientRegistrationsBeanDefinitionParserTests {
|
||||
private static final String CONFIG_LOCATION_PREFIX = "classpath:org/springframework/security/config/oauth2/client/ClientRegistrationsBeanDefinitionParserTests";
|
||||
|
||||
@Rule
|
||||
public final SpringTestRule spring = new SpringTestRule();
|
||||
|
||||
@Autowired
|
||||
private ClientRegistrationRepository clientRegistrationRepository;
|
||||
|
||||
private static final String DEFAULT_RESPONSE =
|
||||
"{\n"
|
||||
+ " \"authorization_endpoint\": \"https://example.com/o/oauth2/v2/auth\", \n"
|
||||
+ " \"claims_supported\": [\n"
|
||||
+ " \"aud\", \n"
|
||||
+ " \"email\", \n"
|
||||
+ " \"email_verified\", \n"
|
||||
+ " \"exp\", \n"
|
||||
+ " \"family_name\", \n"
|
||||
+ " \"given_name\", \n"
|
||||
+ " \"iat\", \n"
|
||||
+ " \"iss\", \n"
|
||||
+ " \"locale\", \n"
|
||||
+ " \"name\", \n"
|
||||
+ " \"picture\", \n"
|
||||
+ " \"sub\"\n"
|
||||
+ " ], \n"
|
||||
+ " \"code_challenge_methods_supported\": [\n"
|
||||
+ " \"plain\", \n"
|
||||
+ " \"S256\"\n"
|
||||
+ " ], \n"
|
||||
+ " \"id_token_signing_alg_values_supported\": [\n"
|
||||
+ " \"RS256\"\n"
|
||||
+ " ], \n"
|
||||
+ " \"issuer\": \"http://localhost:49259\", \n"
|
||||
+ " \"jwks_uri\": \"https://example.com/oauth2/v3/certs\", \n"
|
||||
+ " \"response_types_supported\": [\n"
|
||||
+ " \"code\", \n"
|
||||
+ " \"token\", \n"
|
||||
+ " \"id_token\", \n"
|
||||
+ " \"code token\", \n"
|
||||
+ " \"code id_token\", \n"
|
||||
+ " \"token id_token\", \n"
|
||||
+ " \"code token id_token\", \n"
|
||||
+ " \"none\"\n"
|
||||
+ " ], \n"
|
||||
+ " \"revocation_endpoint\": \"https://example.com/o/oauth2/revoke\", \n"
|
||||
+ " \"scopes_supported\": [\n"
|
||||
+ " \"openid\", \n"
|
||||
+ " \"email\", \n"
|
||||
+ " \"profile\"\n"
|
||||
+ " ], \n"
|
||||
+ " \"subject_types_supported\": [\n"
|
||||
+ " \"public\"\n"
|
||||
+ " ], \n"
|
||||
+ " \"grant_types_supported\" : [\"authorization_code\"], \n"
|
||||
+ " \"token_endpoint\": \"https://example.com/oauth2/v4/token\", \n"
|
||||
+ " \"token_endpoint_auth_methods_supported\": [\n"
|
||||
+ " \"client_secret_post\", \n"
|
||||
+ " \"client_secret_basic\", \n"
|
||||
+ " \"none\"\n"
|
||||
+ " ], \n"
|
||||
+ " \"userinfo_endpoint\": \"https://example.com/oauth2/v3/userinfo\"\n"
|
||||
+ "}";
|
||||
|
||||
@Test
|
||||
public void parseWhenIssuerUriConfiguredThenRequestConfigFromIssuer() throws Exception {
|
||||
MockWebServer server = new MockWebServer();
|
||||
ObjectMapper mapper = new ObjectMapper();
|
||||
server.start(49259);
|
||||
Map<String, Object> response = mapper.readValue(DEFAULT_RESPONSE, new TypeReference<Map<String, Object>>() {
|
||||
});
|
||||
final String responseBody = mapper.writeValueAsString(response);
|
||||
|
||||
final Dispatcher oidcDispatcher = new Dispatcher() {
|
||||
@Override
|
||||
public MockResponse dispatch(RecordedRequest request) {
|
||||
switch (request.getPath()) {
|
||||
case "/issuer1/.well-known/openid-configuration":
|
||||
case "/.well-known/openid-configuration":
|
||||
return new MockResponse().setResponseCode(200).setBody(responseBody)
|
||||
.setHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE);
|
||||
}
|
||||
return new MockResponse().setResponseCode(404);
|
||||
}
|
||||
};
|
||||
|
||||
final Dispatcher oauthDispatcher = new Dispatcher() {
|
||||
@Override
|
||||
public MockResponse dispatch(RecordedRequest request) {
|
||||
switch (request.getPath()) {
|
||||
case "/.well-known/oauth-authorization-server/issuer1":
|
||||
case "/.well-known/oauth-authorization-server":
|
||||
return new MockResponse().setResponseCode(200).setBody(responseBody)
|
||||
.setHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE);
|
||||
}
|
||||
return new MockResponse().setResponseCode(404);
|
||||
}
|
||||
};
|
||||
|
||||
server.setDispatcher(oidcDispatcher);
|
||||
|
||||
this.spring.configLocations(this.xml("FromIssuerUri")).autowire();
|
||||
|
||||
assertThat(clientRegistrationRepository).isInstanceOf(InMemoryClientRegistrationRepository.class);
|
||||
|
||||
testIssuerUriResponse(clientRegistrationRepository);
|
||||
|
||||
// test oauth
|
||||
server.setDispatcher(oauthDispatcher);
|
||||
this.spring.configLocations(this.xml("FromIssuerUri")).autowire();
|
||||
testIssuerUriResponse(clientRegistrationRepository);
|
||||
|
||||
server.shutdown();
|
||||
server.close();
|
||||
}
|
||||
|
||||
private void testIssuerUriResponse(ClientRegistrationRepository clientRegistrationRepository) {
|
||||
ClientRegistration googleLogin = clientRegistrationRepository.findByRegistrationId("google-login");
|
||||
assertThat(googleLogin).isNotNull();
|
||||
assertThat(googleLogin.getRegistrationId()).isEqualTo("google-login");
|
||||
assertThat(googleLogin.getClientId()).isEqualTo("google-client-id");
|
||||
assertThat(googleLogin.getClientSecret()).isEqualTo("google-client-secret");
|
||||
assertThat(googleLogin.getClientAuthenticationMethod()).isEqualTo(ClientAuthenticationMethod.BASIC);
|
||||
assertThat(googleLogin.getAuthorizationGrantType()).isEqualTo(AuthorizationGrantType.AUTHORIZATION_CODE);
|
||||
assertThat(googleLogin.getRedirectUriTemplate()).isEqualTo("{baseUrl}/login/oauth2/code/{registrationId}");
|
||||
assertThat(googleLogin.getScopes()).isEqualTo(StringUtils.commaDelimitedListToSet("openid,profile,email"));
|
||||
assertThat(googleLogin.getClientName()).isEqualTo("Google");
|
||||
|
||||
ProviderDetails googleProviderDetails = googleLogin.getProviderDetails();
|
||||
assertThat(googleProviderDetails).isNotNull();
|
||||
assertThat(googleProviderDetails.getAuthorizationUri()).isEqualTo("https://example.com/o/oauth2/v2/auth");
|
||||
assertThat(googleProviderDetails.getTokenUri()).isEqualTo("https://example.com/oauth2/v4/token");
|
||||
assertThat(googleProviderDetails.getUserInfoEndpoint().getUri())
|
||||
.isEqualTo("https://example.com/oauth2/v3/userinfo");
|
||||
assertThat(googleProviderDetails.getUserInfoEndpoint().getAuthenticationMethod())
|
||||
.isEqualTo(AuthenticationMethod.HEADER);
|
||||
assertThat(googleProviderDetails.getUserInfoEndpoint().getUserNameAttributeName()).isEqualTo("sub");
|
||||
assertThat(googleProviderDetails.getJwkSetUri()).isEqualTo("https://example.com/oauth2/v3/certs");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void parseWhenMultipleClientsConfiguredThenAvailableInRepository() throws Exception {
|
||||
this.spring.configLocations(this.xml("MultiClientRegistration")).autowire();
|
||||
|
||||
assertThat(clientRegistrationRepository).isInstanceOf(InMemoryClientRegistrationRepository.class);
|
||||
|
||||
ClientRegistration googleLogin = clientRegistrationRepository.findByRegistrationId("google-login");
|
||||
assertThat(googleLogin).isNotNull();
|
||||
assertThat(googleLogin.getRegistrationId()).isEqualTo("google-login");
|
||||
assertThat(googleLogin.getClientId()).isEqualTo("google-client-id");
|
||||
assertThat(googleLogin.getClientSecret()).isEqualTo("google-client-secret");
|
||||
assertThat(googleLogin.getClientAuthenticationMethod()).isEqualTo(ClientAuthenticationMethod.BASIC);
|
||||
assertThat(googleLogin.getAuthorizationGrantType()).isEqualTo(AuthorizationGrantType.AUTHORIZATION_CODE);
|
||||
assertThat(googleLogin.getRedirectUriTemplate()).isEqualTo("{baseUrl}/login/oauth2/code/{registrationId}");
|
||||
assertThat(googleLogin.getScopes()).isEqualTo(StringUtils.commaDelimitedListToSet("openid,profile,email"));
|
||||
assertThat(googleLogin.getClientName()).isEqualTo("Google");
|
||||
|
||||
ProviderDetails googleProviderDetails = googleLogin.getProviderDetails();
|
||||
assertThat(googleProviderDetails).isNotNull();
|
||||
assertThat(googleProviderDetails.getAuthorizationUri())
|
||||
.isEqualTo("https://accounts.google.com/o/oauth2/v2/auth");
|
||||
assertThat(googleProviderDetails.getTokenUri()).isEqualTo("https://www.googleapis.com/oauth2/v4/token");
|
||||
assertThat(googleProviderDetails.getUserInfoEndpoint().getUri())
|
||||
.isEqualTo("https://www.googleapis.com/oauth2/v3/userinfo");
|
||||
assertThat(googleProviderDetails.getUserInfoEndpoint().getAuthenticationMethod())
|
||||
.isEqualTo(AuthenticationMethod.HEADER);
|
||||
assertThat(googleProviderDetails.getUserInfoEndpoint().getUserNameAttributeName()).isEqualTo("sub");
|
||||
assertThat(googleProviderDetails.getJwkSetUri()).isEqualTo("https://www.googleapis.com/oauth2/v3/certs");
|
||||
|
||||
ClientRegistration githubLogin = clientRegistrationRepository.findByRegistrationId("github-login");
|
||||
assertThat(githubLogin).isNotNull();
|
||||
assertThat(githubLogin.getRegistrationId()).isEqualTo("github-login");
|
||||
assertThat(githubLogin.getClientId()).isEqualTo("github-client-id");
|
||||
assertThat(githubLogin.getClientSecret()).isEqualTo("github-client-secret");
|
||||
assertThat(githubLogin.getClientAuthenticationMethod()).isEqualTo(ClientAuthenticationMethod.BASIC);
|
||||
assertThat(githubLogin.getAuthorizationGrantType()).isEqualTo(AuthorizationGrantType.AUTHORIZATION_CODE);
|
||||
assertThat(githubLogin.getRedirectUriTemplate()).isEqualTo("{baseUrl}/login/oauth2/code/{registrationId}");
|
||||
assertThat(googleLogin.getScopes()).isEqualTo(StringUtils.commaDelimitedListToSet("openid,profile,email"));
|
||||
assertThat(githubLogin.getClientName()).isEqualTo("Github");
|
||||
|
||||
ProviderDetails githubProviderDetails = githubLogin.getProviderDetails();
|
||||
assertThat(githubProviderDetails).isNotNull();
|
||||
assertThat(githubProviderDetails.getAuthorizationUri()).isEqualTo("https://github.com/login/oauth/authorize");
|
||||
assertThat(githubProviderDetails.getTokenUri()).isEqualTo("https://github.com/login/oauth/access_token");
|
||||
assertThat(githubProviderDetails.getUserInfoEndpoint().getUri()).isEqualTo("https://api.github.com/user");
|
||||
assertThat(githubProviderDetails.getUserInfoEndpoint().getAuthenticationMethod())
|
||||
.isEqualTo(AuthenticationMethod.HEADER);
|
||||
assertThat(githubProviderDetails.getUserInfoEndpoint().getUserNameAttributeName()).isEqualTo("id");
|
||||
}
|
||||
|
||||
private String xml(String configName) {
|
||||
return CONFIG_LOCATION_PREFIX + "-" + configName + ".xml";
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2009-2019 the original author or authors.
|
||||
* Copyright 2009-2020 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.
|
||||
|
||||
Reference in New Issue
Block a user