parent
e3dd8d2530
commit
254f2e2aec
|
@ -29,6 +29,8 @@ import org.springframework.security.config.annotation.web.configuration.WebSecur
|
|||
import org.springframework.security.config.test.SpringTestRule;
|
||||
import org.springframework.security.core.authority.AuthorityUtils;
|
||||
import org.springframework.security.core.authority.SimpleGrantedAuthority;
|
||||
import org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestBuilders;
|
||||
import org.springframework.security.test.web.servlet.response.SecurityMockMvcResultMatchers;
|
||||
import org.springframework.test.web.servlet.MockMvc;
|
||||
|
||||
import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestBuilders.formLogin;
|
||||
|
@ -55,35 +57,39 @@ public class LdapAuthenticationProviderConfigurerTests {
|
|||
public void authenticationManagerSupportMultipleLdapContextWithDefaultRolePrefix() throws Exception {
|
||||
this.spring.register(MultiLdapAuthenticationProvidersConfig.class).autowire();
|
||||
|
||||
this.mockMvc.perform(formLogin().user("bob").password("bobspassword"))
|
||||
.andExpect(authenticated().withUsername("bob")
|
||||
.withAuthorities(Collections.singleton(new SimpleGrantedAuthority("ROLE_DEVELOPERS"))));
|
||||
SecurityMockMvcRequestBuilders.FormLoginRequestBuilder request = formLogin().user("bob").password("bobspassword");
|
||||
SecurityMockMvcResultMatchers.AuthenticatedMatcher expectedUser = authenticated().withUsername("bob")
|
||||
.withAuthorities(Collections.singleton(new SimpleGrantedAuthority("ROLE_DEVELOPERS")));
|
||||
this.mockMvc.perform(request).andExpect(expectedUser);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void authenticationManagerSupportMultipleLdapContextWithCustomRolePrefix() throws Exception {
|
||||
this.spring.register(MultiLdapWithCustomRolePrefixAuthenticationProvidersConfig.class).autowire();
|
||||
|
||||
this.mockMvc.perform(formLogin().user("bob").password("bobspassword"))
|
||||
.andExpect(authenticated().withUsername("bob")
|
||||
.withAuthorities(Collections.singleton(new SimpleGrantedAuthority("ROL_DEVELOPERS"))));
|
||||
SecurityMockMvcRequestBuilders.FormLoginRequestBuilder request = formLogin().user("bob").password("bobspassword");
|
||||
SecurityMockMvcResultMatchers.AuthenticatedMatcher expectedUser = authenticated().withUsername("bob")
|
||||
.withAuthorities(Collections.singleton(new SimpleGrantedAuthority("ROL_DEVELOPERS")));
|
||||
this.mockMvc.perform(request).andExpect(expectedUser);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void authenticationManagerWhenPortZeroThenAuthenticates() throws Exception {
|
||||
this.spring.register(LdapWithRandomPortConfig.class).autowire();
|
||||
|
||||
this.mockMvc.perform(formLogin().user("bob").password("bobspassword"))
|
||||
.andExpect(authenticated().withUsername("bob"));
|
||||
SecurityMockMvcRequestBuilders.FormLoginRequestBuilder request = formLogin().user("bob").password("bobspassword");
|
||||
SecurityMockMvcResultMatchers.AuthenticatedMatcher expectedUser = authenticated().withUsername("bob");
|
||||
this.mockMvc.perform(request).andExpect(expectedUser);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void authenticationManagerWhenSearchSubtreeThenNestedGroupFound() throws Exception {
|
||||
this.spring.register(GroupSubtreeSearchConfig.class).autowire();
|
||||
|
||||
this.mockMvc.perform(formLogin().user("ben").password("benspassword"))
|
||||
.andExpect(authenticated().withUsername("ben").withAuthorities(
|
||||
AuthorityUtils.createAuthorityList("ROLE_SUBMANAGERS", "ROLE_MANAGERS", "ROLE_DEVELOPERS")));
|
||||
SecurityMockMvcRequestBuilders.FormLoginRequestBuilder request = formLogin().user("ben").password("benspassword");
|
||||
SecurityMockMvcResultMatchers.AuthenticatedMatcher expectedUser = authenticated().withUsername("ben").withAuthorities(
|
||||
AuthorityUtils.createAuthorityList("ROLE_SUBMANAGERS", "ROLE_MANAGERS", "ROLE_DEVELOPERS"));
|
||||
this.mockMvc.perform(request).andExpect(expectedUser);
|
||||
}
|
||||
|
||||
@EnableWebSecurity
|
||||
|
|
|
@ -36,6 +36,8 @@ import org.springframework.security.core.authority.AuthorityUtils;
|
|||
import org.springframework.security.core.authority.SimpleGrantedAuthority;
|
||||
import org.springframework.security.ldap.DefaultSpringSecurityContextSource;
|
||||
import org.springframework.security.ldap.userdetails.DefaultLdapAuthoritiesPopulator;
|
||||
import org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestBuilders;
|
||||
import org.springframework.security.test.web.servlet.response.SecurityMockMvcResultMatchers;
|
||||
import org.springframework.security.web.FilterChainProxy;
|
||||
import org.springframework.test.web.servlet.MockMvc;
|
||||
|
||||
|
@ -57,16 +59,19 @@ public class NamespaceLdapAuthenticationProviderTests {
|
|||
public void ldapAuthenticationProvider() throws Exception {
|
||||
this.spring.register(LdapAuthenticationProviderConfig.class).autowire();
|
||||
|
||||
this.mockMvc.perform(formLogin().user("bob").password("bobspassword"))
|
||||
.andExpect(authenticated().withUsername("bob"));
|
||||
SecurityMockMvcRequestBuilders.FormLoginRequestBuilder request = formLogin().user("bob").password("bobspassword");
|
||||
SecurityMockMvcResultMatchers.AuthenticatedMatcher user = authenticated().withUsername("bob");
|
||||
this.mockMvc.perform(request).andExpect(user);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void ldapAuthenticationProviderCustom() throws Exception {
|
||||
this.spring.register(CustomLdapAuthenticationProviderConfig.class).autowire();
|
||||
|
||||
this.mockMvc.perform(formLogin().user("bob").password("bobspassword")).andExpect(authenticated()
|
||||
.withAuthorities(Collections.singleton(new SimpleGrantedAuthority("PREFIX_DEVELOPERS"))));
|
||||
SecurityMockMvcRequestBuilders.FormLoginRequestBuilder request = formLogin().user("bob").password("bobspassword");
|
||||
SecurityMockMvcResultMatchers.AuthenticatedMatcher user = authenticated()
|
||||
.withAuthorities(Collections.singleton(new SimpleGrantedAuthority("PREFIX_DEVELOPERS")));
|
||||
this.mockMvc.perform(request).andExpect(user);
|
||||
}
|
||||
|
||||
// SEC-2490
|
||||
|
@ -83,16 +88,18 @@ public class NamespaceLdapAuthenticationProviderTests {
|
|||
|
||||
this.spring.register(CustomAuthoritiesPopulatorConfig.class).autowire();
|
||||
|
||||
this.mockMvc.perform(formLogin().user("bob").password("bobspassword")).andExpect(
|
||||
authenticated().withAuthorities(Collections.singleton(new SimpleGrantedAuthority("ROLE_EXTRA"))));
|
||||
SecurityMockMvcRequestBuilders.FormLoginRequestBuilder request = formLogin().user("bob").password("bobspassword");
|
||||
SecurityMockMvcResultMatchers.AuthenticatedMatcher user = authenticated().withAuthorities(Collections.singleton(new SimpleGrantedAuthority("ROLE_EXTRA")));
|
||||
this.mockMvc.perform(request).andExpect(user);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void ldapAuthenticationProviderPasswordCompare() throws Exception {
|
||||
this.spring.register(PasswordCompareLdapConfig.class).autowire();
|
||||
|
||||
this.mockMvc.perform(formLogin().user("bcrypt").password("password"))
|
||||
.andExpect(authenticated().withUsername("bcrypt"));
|
||||
SecurityMockMvcRequestBuilders.FormLoginRequestBuilder request = formLogin().user("bcrypt").password("password");
|
||||
SecurityMockMvcResultMatchers.AuthenticatedMatcher user = authenticated().withUsername("bcrypt");
|
||||
this.mockMvc.perform(request).andExpect(user);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -71,9 +71,15 @@ public class HelloRSocketITests {
|
|||
|
||||
@Before
|
||||
public void setup() {
|
||||
this.server = RSocketFactory.receive().frameDecoder(PayloadDecoder.ZERO_COPY)
|
||||
.addSocketAcceptorPlugin(this.interceptor).acceptor(this.handler.responder())
|
||||
.transport(TcpServerTransport.create("localhost", 0)).start().block();
|
||||
// @formatter:off
|
||||
this.server = RSocketFactory.receive()
|
||||
.frameDecoder(PayloadDecoder.ZERO_COPY)
|
||||
.addSocketAcceptorPlugin(this.interceptor)
|
||||
.acceptor(this.handler.responder())
|
||||
.transport(TcpServerTransport.create("localhost", 0))
|
||||
.start()
|
||||
.block();
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@After
|
||||
|
@ -85,13 +91,23 @@ public class HelloRSocketITests {
|
|||
|
||||
@Test
|
||||
public void retrieveMonoWhenSecureThenDenied() throws Exception {
|
||||
this.requester = RSocketRequester.builder().rsocketStrategies(this.handler.getRSocketStrategies())
|
||||
.connectTcp("localhost", this.server.address().getPort()).block();
|
||||
// @formatter:off
|
||||
this.requester = RSocketRequester.builder()
|
||||
.rsocketStrategies(this.handler.getRSocketStrategies())
|
||||
.connectTcp("localhost", this.server.address().getPort())
|
||||
.block();
|
||||
// @formatter:on
|
||||
String data = "rob";
|
||||
// @formatter:off
|
||||
assertThatExceptionOfType(Exception.class).isThrownBy(
|
||||
() -> this.requester.route("secure.retrieve-mono").data(data).retrieveMono(String.class).block())
|
||||
() -> this.requester.route("secure.retrieve-mono")
|
||||
.data(data)
|
||||
.retrieveMono(String.class)
|
||||
.block()
|
||||
)
|
||||
.matches((ex) -> ex instanceof RejectedSetupException
|
||||
|| ex.getClass().toString().contains("ReactiveException"));
|
||||
// @formatter:on
|
||||
// FIXME: https://github.com/rsocket/rsocket-java/issues/686
|
||||
assertThat(this.controller.payloads).isEmpty();
|
||||
}
|
||||
|
@ -99,14 +115,21 @@ public class HelloRSocketITests {
|
|||
@Test
|
||||
public void retrieveMonoWhenAuthorizedThenGranted() throws Exception {
|
||||
UsernamePasswordMetadata credentials = new UsernamePasswordMetadata("rob", "password");
|
||||
// @formatter:off
|
||||
this.requester = RSocketRequester.builder()
|
||||
.setupMetadata(credentials, UsernamePasswordMetadata.BASIC_AUTHENTICATION_MIME_TYPE)
|
||||
.rsocketStrategies(this.handler.getRSocketStrategies())
|
||||
.connectTcp("localhost", this.server.address().getPort()).block();
|
||||
.setupMetadata(credentials, UsernamePasswordMetadata.BASIC_AUTHENTICATION_MIME_TYPE)
|
||||
.rsocketStrategies(this.handler.getRSocketStrategies())
|
||||
.connectTcp("localhost", this.server.address().getPort())
|
||||
.block();
|
||||
// @formatter:on
|
||||
String data = "rob";
|
||||
// @formatter:off
|
||||
String hiRob = this.requester.route("secure.retrieve-mono")
|
||||
.metadata(credentials, UsernamePasswordMetadata.BASIC_AUTHENTICATION_MIME_TYPE).data(data)
|
||||
.retrieveMono(String.class).block();
|
||||
.metadata(credentials, UsernamePasswordMetadata.BASIC_AUTHENTICATION_MIME_TYPE)
|
||||
.data(data)
|
||||
.retrieveMono(String.class)
|
||||
.block();
|
||||
// @formatter:on
|
||||
assertThat(hiRob).isEqualTo("Hi rob");
|
||||
assertThat(this.controller.payloads).containsOnly(data);
|
||||
}
|
||||
|
|
|
@ -99,10 +99,16 @@ public class JwtITests {
|
|||
public void routeWhenBearerThenAuthorized() {
|
||||
BearerTokenMetadata credentials = new BearerTokenMetadata("token");
|
||||
given(this.decoder.decode(any())).willReturn(Mono.just(jwt()));
|
||||
// @formatter:off
|
||||
this.requester = requester()
|
||||
.setupMetadata(credentials.getToken(), BearerTokenMetadata.BEARER_AUTHENTICATION_MIME_TYPE)
|
||||
.connectTcp(this.server.address().getHostName(), this.server.address().getPort()).block();
|
||||
String hiRob = this.requester.route("secure.retrieve-mono").data("rob").retrieveMono(String.class).block();
|
||||
.setupMetadata(credentials.getToken(), BearerTokenMetadata.BEARER_AUTHENTICATION_MIME_TYPE)
|
||||
.connectTcp(this.server.address().getHostName(), this.server.address().getPort())
|
||||
.block();
|
||||
String hiRob = this.requester.route("secure.retrieve-mono")
|
||||
.data("rob")
|
||||
.retrieveMono(String.class)
|
||||
.block();
|
||||
// @formatter:on
|
||||
assertThat(hiRob).isEqualTo("Hi rob");
|
||||
}
|
||||
|
||||
|
@ -112,9 +118,14 @@ public class JwtITests {
|
|||
.parseMimeType(WellKnownMimeType.MESSAGE_RSOCKET_AUTHENTICATION.getString());
|
||||
BearerTokenMetadata credentials = new BearerTokenMetadata("token");
|
||||
given(this.decoder.decode(any())).willReturn(Mono.just(jwt()));
|
||||
// @formatter:off
|
||||
this.requester = requester().setupMetadata(credentials, authenticationMimeType)
|
||||
.connectTcp(this.server.address().getHostName(), this.server.address().getPort()).block();
|
||||
String hiRob = this.requester.route("secure.retrieve-mono").data("rob").retrieveMono(String.class).block();
|
||||
.connectTcp(this.server.address().getHostName(), this.server.address().getPort())
|
||||
.block();
|
||||
String hiRob = this.requester.route("secure.retrieve-mono")
|
||||
.data("rob")
|
||||
.retrieveMono(String.class).block();
|
||||
// @formatter:on
|
||||
assertThat(hiRob).isEqualTo("Hi rob");
|
||||
}
|
||||
|
||||
|
|
|
@ -78,9 +78,15 @@ public class RSocketMessageHandlerConnectionITests {
|
|||
|
||||
@Before
|
||||
public void setup() {
|
||||
this.server = RSocketFactory.receive().frameDecoder(PayloadDecoder.ZERO_COPY)
|
||||
.addSocketAcceptorPlugin(this.interceptor).acceptor(this.handler.responder())
|
||||
.transport(TcpServerTransport.create("localhost", 0)).start().block();
|
||||
// @formatter:off
|
||||
this.server = RSocketFactory.receive()
|
||||
.frameDecoder(PayloadDecoder.ZERO_COPY)
|
||||
.addSocketAcceptorPlugin(this.interceptor)
|
||||
.acceptor(this.handler.responder())
|
||||
.transport(TcpServerTransport.create("localhost", 0))
|
||||
.start()
|
||||
.block();
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@After
|
||||
|
@ -93,94 +99,147 @@ public class RSocketMessageHandlerConnectionITests {
|
|||
@Test
|
||||
public void routeWhenAuthorized() {
|
||||
UsernamePasswordMetadata credentials = new UsernamePasswordMetadata("user", "password");
|
||||
// @formatter:off
|
||||
this.requester = requester().setupMetadata(credentials, UsernamePasswordMetadata.BASIC_AUTHENTICATION_MIME_TYPE)
|
||||
.connectTcp(this.server.address().getHostName(), this.server.address().getPort()).block();
|
||||
String hiRob = this.requester.route("secure.retrieve-mono").data("rob").retrieveMono(String.class).block();
|
||||
.connectTcp(this.server.address().getHostName(), this.server.address().getPort())
|
||||
.block();
|
||||
String hiRob = this.requester.route("secure.retrieve-mono")
|
||||
.data("rob")
|
||||
.retrieveMono(String.class)
|
||||
.block();
|
||||
// @formatter:on
|
||||
assertThat(hiRob).isEqualTo("Hi rob");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void routeWhenNotAuthorized() {
|
||||
UsernamePasswordMetadata credentials = new UsernamePasswordMetadata("user", "password");
|
||||
// @formatter:off
|
||||
this.requester = requester().setupMetadata(credentials, UsernamePasswordMetadata.BASIC_AUTHENTICATION_MIME_TYPE)
|
||||
.connectTcp(this.server.address().getHostName(), this.server.address().getPort()).block();
|
||||
.connectTcp(this.server.address().getHostName(), this.server.address().getPort())
|
||||
.block();
|
||||
assertThatExceptionOfType(ApplicationErrorException.class).isThrownBy(() -> this.requester
|
||||
.route("secure.admin.retrieve-mono").data("data").retrieveMono(String.class).block());
|
||||
.route("secure.admin.retrieve-mono")
|
||||
.data("data")
|
||||
.retrieveMono(String.class)
|
||||
.block()
|
||||
);
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
public void routeWhenStreamCredentialsAuthorized() {
|
||||
UsernamePasswordMetadata connectCredentials = new UsernamePasswordMetadata("user", "password");
|
||||
this.requester = requester()
|
||||
.setupMetadata(connectCredentials, UsernamePasswordMetadata.BASIC_AUTHENTICATION_MIME_TYPE)
|
||||
.connectTcp(this.server.address().getHostName(), this.server.address().getPort()).block();
|
||||
// @formatter:off
|
||||
this.requester = requester().setupMetadata(connectCredentials, UsernamePasswordMetadata.BASIC_AUTHENTICATION_MIME_TYPE)
|
||||
.connectTcp(this.server.address().getHostName(), this.server.address().getPort())
|
||||
.block();
|
||||
String hiRob = this.requester.route("secure.admin.retrieve-mono")
|
||||
.metadata(new UsernamePasswordMetadata("admin", "password"),
|
||||
UsernamePasswordMetadata.BASIC_AUTHENTICATION_MIME_TYPE)
|
||||
.data("rob").retrieveMono(String.class).block();
|
||||
.metadata(new UsernamePasswordMetadata("admin", "password"),
|
||||
UsernamePasswordMetadata.BASIC_AUTHENTICATION_MIME_TYPE)
|
||||
.data("rob")
|
||||
.retrieveMono(String.class)
|
||||
.block();
|
||||
// @formatter:on
|
||||
assertThat(hiRob).isEqualTo("Hi rob");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void routeWhenStreamCredentialsHaveAuthority() {
|
||||
UsernamePasswordMetadata connectCredentials = new UsernamePasswordMetadata("user", "password");
|
||||
this.requester = requester()
|
||||
.setupMetadata(connectCredentials, UsernamePasswordMetadata.BASIC_AUTHENTICATION_MIME_TYPE)
|
||||
.connectTcp(this.server.address().getHostName(), this.server.address().getPort()).block();
|
||||
// @formatter:off
|
||||
this.requester = requester().setupMetadata(connectCredentials, UsernamePasswordMetadata.BASIC_AUTHENTICATION_MIME_TYPE)
|
||||
.connectTcp(this.server.address().getHostName(), this.server.address().getPort())
|
||||
.block();
|
||||
String hiUser = this.requester.route("secure.authority.retrieve-mono")
|
||||
.metadata(new UsernamePasswordMetadata("admin", "password"),
|
||||
UsernamePasswordMetadata.BASIC_AUTHENTICATION_MIME_TYPE)
|
||||
.data("Felipe").retrieveMono(String.class).block();
|
||||
.metadata(new UsernamePasswordMetadata("admin", "password"),
|
||||
UsernamePasswordMetadata.BASIC_AUTHENTICATION_MIME_TYPE)
|
||||
.data("Felipe")
|
||||
.retrieveMono(String.class)
|
||||
.block();
|
||||
// @formatter:on
|
||||
assertThat(hiUser).isEqualTo("Hi Felipe");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void connectWhenNotAuthenticated() {
|
||||
// @formatter:off
|
||||
this.requester = requester().connectTcp(this.server.address().getHostName(), this.server.address().getPort())
|
||||
.block();
|
||||
assertThatExceptionOfType(Exception.class)
|
||||
.isThrownBy(() -> this.requester.route("retrieve-mono").data("data").retrieveMono(String.class).block())
|
||||
.isThrownBy(() -> this.requester.route("retrieve-mono")
|
||||
.data("data")
|
||||
.retrieveMono(String.class)
|
||||
.block()
|
||||
)
|
||||
.matches((ex) -> ex instanceof RejectedSetupException
|
||||
|| ex.getClass().toString().contains("ReactiveException"));
|
||||
// @formatter:on
|
||||
// FIXME: https://github.com/rsocket/rsocket-java/issues/686
|
||||
}
|
||||
|
||||
@Test
|
||||
public void connectWhenNotAuthorized() {
|
||||
UsernamePasswordMetadata credentials = new UsernamePasswordMetadata("evil", "password");
|
||||
// @formatter:off
|
||||
this.requester = requester().setupMetadata(credentials, UsernamePasswordMetadata.BASIC_AUTHENTICATION_MIME_TYPE)
|
||||
.connectTcp(this.server.address().getHostName(), this.server.address().getPort()).block();
|
||||
.connectTcp(this.server.address().getHostName(), this.server.address().getPort())
|
||||
.block();
|
||||
assertThatExceptionOfType(Exception.class)
|
||||
.isThrownBy(() -> this.requester.route("retrieve-mono").data("data").retrieveMono(String.class).block())
|
||||
.isThrownBy(() -> this.requester.route("retrieve-mono")
|
||||
.data("data")
|
||||
.retrieveMono(String.class)
|
||||
.block()
|
||||
)
|
||||
.matches((ex) -> ex instanceof RejectedSetupException
|
||||
|| ex.getClass().toString().contains("ReactiveException"));
|
||||
// @formatter:on
|
||||
// FIXME: https://github.com/rsocket/rsocket-java/issues/686
|
||||
}
|
||||
|
||||
@Test
|
||||
public void connectionDenied() {
|
||||
UsernamePasswordMetadata credentials = new UsernamePasswordMetadata("user", "password");
|
||||
// @formatter:off
|
||||
this.requester = requester().setupMetadata(credentials, UsernamePasswordMetadata.BASIC_AUTHENTICATION_MIME_TYPE)
|
||||
.connectTcp(this.server.address().getHostName(), this.server.address().getPort()).block();
|
||||
.connectTcp(this.server.address().getHostName(), this.server.address().getPort())
|
||||
.block();
|
||||
assertThatExceptionOfType(ApplicationErrorException.class)
|
||||
.isThrownBy(() -> this.requester.route("prohibit").data("data").retrieveMono(String.class).block());
|
||||
.isThrownBy(() -> this.requester.route("prohibit")
|
||||
.data("data")
|
||||
.retrieveMono(String.class)
|
||||
.block()
|
||||
);
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
public void connectWithAnyRole() {
|
||||
UsernamePasswordMetadata credentials = new UsernamePasswordMetadata("user", "password");
|
||||
// @formatter:off
|
||||
this.requester = requester().setupMetadata(credentials, UsernamePasswordMetadata.BASIC_AUTHENTICATION_MIME_TYPE)
|
||||
.connectTcp(this.server.address().getHostName(), this.server.address().getPort()).block();
|
||||
String hiRob = this.requester.route("anyroute").data("rob").retrieveMono(String.class).block();
|
||||
.connectTcp(this.server.address().getHostName(), this.server.address().getPort())
|
||||
.block();
|
||||
String hiRob = this.requester.route("anyroute")
|
||||
.data("rob")
|
||||
.retrieveMono(String.class)
|
||||
.block();
|
||||
// @formatter:on
|
||||
assertThat(hiRob).isEqualTo("Hi rob");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void connectWithAnyAuthority() {
|
||||
UsernamePasswordMetadata credentials = new UsernamePasswordMetadata("admin", "password");
|
||||
// @formatter:off
|
||||
this.requester = requester().setupMetadata(credentials, UsernamePasswordMetadata.BASIC_AUTHENTICATION_MIME_TYPE)
|
||||
.connectTcp(this.server.address().getHostName(), this.server.address().getPort()).block();
|
||||
String hiEbert = this.requester.route("management.users").data("admin").retrieveMono(String.class).block();
|
||||
.connectTcp(this.server.address().getHostName(), this.server.address().getPort())
|
||||
.block();
|
||||
String hiEbert = this.requester.route("management.users")
|
||||
.data("admin")
|
||||
.retrieveMono(String.class)
|
||||
.block();
|
||||
// @formatter:on
|
||||
assertThat(hiEbert).isEqualTo("Hi admin");
|
||||
}
|
||||
|
||||
|
@ -233,10 +292,18 @@ public class RSocketMessageHandlerConnectionITests {
|
|||
|
||||
@Bean
|
||||
PayloadSocketAcceptorInterceptor rsocketInterceptor(RSocketSecurity rsocket) {
|
||||
rsocket.authorizePayload((authorize) -> authorize.setup().hasRole("SETUP").route("secure.admin.*")
|
||||
.hasRole("ADMIN").route("secure.**").hasRole("USER").route("secure.authority.*")
|
||||
.hasAuthority("ROLE_USER").route("management.*").hasAnyAuthority("ROLE_ADMIN").route("prohibit")
|
||||
.denyAll().anyRequest().permitAll()).basicAuthentication(Customizer.withDefaults());
|
||||
// @formatter:off
|
||||
rsocket.authorizePayload((authorize) -> authorize
|
||||
.setup().hasRole("SETUP")
|
||||
.route("secure.admin.*").hasRole("ADMIN")
|
||||
.route("secure.**").hasRole("USER")
|
||||
.route("secure.authority.*").hasAuthority("ROLE_USER")
|
||||
.route("management.*").hasAnyAuthority("ROLE_ADMIN")
|
||||
.route("prohibit").denyAll()
|
||||
.anyRequest().permitAll()
|
||||
)
|
||||
.basicAuthentication(Customizer.withDefaults());
|
||||
// @formatter:on
|
||||
return rsocket.build();
|
||||
}
|
||||
|
||||
|
|
|
@ -76,14 +76,21 @@ public class RSocketMessageHandlerITests {
|
|||
|
||||
@Before
|
||||
public void setup() {
|
||||
this.server = RSocketFactory.receive().frameDecoder(PayloadDecoder.ZERO_COPY)
|
||||
.addSocketAcceptorPlugin(this.interceptor).acceptor(this.handler.responder())
|
||||
.transport(TcpServerTransport.create("localhost", 0)).start().block();
|
||||
// @formatter:off
|
||||
this.server = RSocketFactory.receive()
|
||||
.frameDecoder(PayloadDecoder.ZERO_COPY)
|
||||
.addSocketAcceptorPlugin(this.interceptor)
|
||||
.acceptor(this.handler.responder())
|
||||
.transport(TcpServerTransport.create("localhost", 0))
|
||||
.start()
|
||||
.block();
|
||||
this.requester = RSocketRequester.builder()
|
||||
// .rsocketFactory((factory) ->
|
||||
// factory.addRequesterPlugin(payloadInterceptor))
|
||||
.rsocketStrategies(this.handler.getRSocketStrategies())
|
||||
.connectTcp("localhost", this.server.address().getPort()).block();
|
||||
.connectTcp("localhost", this.server.address().getPort())
|
||||
.block();
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@After
|
||||
|
@ -96,9 +103,15 @@ public class RSocketMessageHandlerITests {
|
|||
@Test
|
||||
public void retrieveMonoWhenSecureThenDenied() throws Exception {
|
||||
String data = "rob";
|
||||
// @formatter:off
|
||||
assertThatExceptionOfType(ApplicationErrorException.class).isThrownBy(
|
||||
() -> this.requester.route("secure.retrieve-mono").data(data).retrieveMono(String.class).block())
|
||||
.withMessageContaining("Access Denied");
|
||||
() -> this.requester.route("secure.retrieve-mono")
|
||||
.data(data)
|
||||
.retrieveMono(String.class)
|
||||
.block()
|
||||
)
|
||||
.withMessageContaining("Access Denied");
|
||||
// @formatter:on
|
||||
assertThat(this.controller.payloads).isEmpty();
|
||||
}
|
||||
|
||||
|
@ -106,11 +119,15 @@ public class RSocketMessageHandlerITests {
|
|||
public void retrieveMonoWhenAuthenticationFailedThenException() throws Exception {
|
||||
String data = "rob";
|
||||
UsernamePasswordMetadata credentials = new UsernamePasswordMetadata("invalid", "password");
|
||||
// @formatter:off
|
||||
assertThatExceptionOfType(ApplicationErrorException.class)
|
||||
.isThrownBy(() -> this.requester.route("secure.retrieve-mono")
|
||||
.metadata(credentials, UsernamePasswordMetadata.BASIC_AUTHENTICATION_MIME_TYPE).data(data)
|
||||
.retrieveMono(String.class).block())
|
||||
.withMessageContaining("Invalid Credentials");
|
||||
.isThrownBy(() -> this.requester.route("secure.retrieve-mono")
|
||||
.metadata(credentials, UsernamePasswordMetadata.BASIC_AUTHENTICATION_MIME_TYPE).data(data)
|
||||
.retrieveMono(String.class)
|
||||
.block()
|
||||
)
|
||||
.withMessageContaining("Invalid Credentials");
|
||||
// @formatter:on
|
||||
assertThat(this.controller.payloads).isEmpty();
|
||||
}
|
||||
|
||||
|
@ -118,9 +135,13 @@ public class RSocketMessageHandlerITests {
|
|||
public void retrieveMonoWhenAuthorizedThenGranted() throws Exception {
|
||||
String data = "rob";
|
||||
UsernamePasswordMetadata credentials = new UsernamePasswordMetadata("rob", "password");
|
||||
// @formatter:off
|
||||
String hiRob = this.requester.route("secure.retrieve-mono")
|
||||
.metadata(credentials, UsernamePasswordMetadata.BASIC_AUTHENTICATION_MIME_TYPE).data(data)
|
||||
.retrieveMono(String.class).block();
|
||||
.metadata(credentials, UsernamePasswordMetadata.BASIC_AUTHENTICATION_MIME_TYPE)
|
||||
.data(data)
|
||||
.retrieveMono(String.class)
|
||||
.block();
|
||||
// @formatter:on
|
||||
assertThat(hiRob).isEqualTo("Hi rob");
|
||||
assertThat(this.controller.payloads).containsOnly(data);
|
||||
}
|
||||
|
@ -128,7 +149,12 @@ public class RSocketMessageHandlerITests {
|
|||
@Test
|
||||
public void retrieveMonoWhenPublicThenGranted() throws Exception {
|
||||
String data = "rob";
|
||||
String hiRob = this.requester.route("retrieve-mono").data(data).retrieveMono(String.class).block();
|
||||
// @formatter:off
|
||||
String hiRob = this.requester.route("retrieve-mono")
|
||||
.data(data)
|
||||
.retrieveMono(String.class)
|
||||
.block();
|
||||
// @formatter:on
|
||||
assertThat(hiRob).isEqualTo("Hi rob");
|
||||
assertThat(this.controller.payloads).containsOnly(data);
|
||||
}
|
||||
|
@ -136,18 +162,29 @@ public class RSocketMessageHandlerITests {
|
|||
@Test
|
||||
public void retrieveFluxWhenDataFluxAndSecureThenDenied() throws Exception {
|
||||
Flux<String> data = Flux.just("a", "b", "c");
|
||||
// @formatter:off
|
||||
assertThatExceptionOfType(ApplicationErrorException.class)
|
||||
.isThrownBy(() -> this.requester.route("secure.retrieve-flux").data(data, String.class)
|
||||
.retrieveFlux(String.class).collectList().block())
|
||||
.withMessageContaining("Access Denied");
|
||||
.isThrownBy(() -> this.requester.route("secure.retrieve-flux")
|
||||
.data(data, String.class)
|
||||
.retrieveFlux(String.class)
|
||||
.collectList()
|
||||
.block()
|
||||
)
|
||||
.withMessageContaining("Access Denied");
|
||||
// @formatter:on
|
||||
assertThat(this.controller.payloads).isEmpty();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void retrieveFluxWhenDataFluxAndPublicThenGranted() throws Exception {
|
||||
Flux<String> data = Flux.just("a", "b", "c");
|
||||
List<String> hi = this.requester.route("retrieve-flux").data(data, String.class).retrieveFlux(String.class)
|
||||
.collectList().block();
|
||||
// @formatter:off
|
||||
List<String> hi = this.requester.route("retrieve-flux")
|
||||
.data(data, String.class)
|
||||
.retrieveFlux(String.class)
|
||||
.collectList()
|
||||
.block();
|
||||
// @formatter:on
|
||||
assertThat(hi).containsOnly("hello a", "hello b", "hello c");
|
||||
assertThat(this.controller.payloads).containsOnlyElementsOf(data.collectList().block());
|
||||
}
|
||||
|
@ -164,14 +201,24 @@ public class RSocketMessageHandlerITests {
|
|||
@Test
|
||||
public void sendWhenSecureThenDenied() throws Exception {
|
||||
String data = "hi";
|
||||
this.requester.route("secure.send").data(data).send().block();
|
||||
// @formatter:off
|
||||
this.requester.route("secure.send")
|
||||
.data(data)
|
||||
.send()
|
||||
.block();
|
||||
// @formatter:on
|
||||
assertThat(this.controller.payloads).isEmpty();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void sendWhenPublicThenGranted() throws Exception {
|
||||
String data = "hi";
|
||||
this.requester.route("send").data(data).send().block();
|
||||
// @formatter:off
|
||||
this.requester.route("send")
|
||||
.data(data)
|
||||
.send()
|
||||
.block();
|
||||
// @formatter:on
|
||||
assertThat(this.controller.awaitPayloads()).containsOnly("hi");
|
||||
}
|
||||
|
||||
|
@ -215,9 +262,14 @@ public class RSocketMessageHandlerITests {
|
|||
|
||||
@Bean
|
||||
PayloadSocketAcceptorInterceptor rsocketInterceptor(RSocketSecurity rsocket) {
|
||||
// @formatter:off
|
||||
rsocket.authorizePayload(
|
||||
(authorize) -> authorize.route("secure.*").authenticated().anyExchange().permitAll())
|
||||
.basicAuthentication(Customizer.withDefaults());
|
||||
(authorize) -> authorize
|
||||
.route("secure.*").authenticated()
|
||||
.anyExchange().permitAll()
|
||||
)
|
||||
.basicAuthentication(Customizer.withDefaults());
|
||||
// @formatter:on
|
||||
return rsocket.build();
|
||||
}
|
||||
|
||||
|
|
|
@ -76,9 +76,15 @@ public class SimpleAuthenticationITests {
|
|||
|
||||
@Before
|
||||
public void setup() {
|
||||
this.server = RSocketFactory.receive().frameDecoder(PayloadDecoder.ZERO_COPY)
|
||||
.addSocketAcceptorPlugin(this.interceptor).acceptor(this.handler.responder())
|
||||
.transport(TcpServerTransport.create("localhost", 0)).start().block();
|
||||
// @formatter:off
|
||||
this.server = RSocketFactory.receive()
|
||||
.frameDecoder(PayloadDecoder.ZERO_COPY)
|
||||
.addSocketAcceptorPlugin(this.interceptor)
|
||||
.acceptor(this.handler.responder())
|
||||
.transport(TcpServerTransport.create("localhost", 0))
|
||||
.start()
|
||||
.block();
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@After
|
||||
|
@ -90,11 +96,20 @@ public class SimpleAuthenticationITests {
|
|||
|
||||
@Test
|
||||
public void retrieveMonoWhenSecureThenDenied() throws Exception {
|
||||
this.requester = RSocketRequester.builder().rsocketStrategies(this.handler.getRSocketStrategies())
|
||||
.connectTcp("localhost", this.server.address().getPort()).block();
|
||||
// @formatter:off
|
||||
this.requester = RSocketRequester.builder()
|
||||
.rsocketStrategies(this.handler.getRSocketStrategies())
|
||||
.connectTcp("localhost", this.server.address().getPort())
|
||||
.block();
|
||||
// @formatter:on
|
||||
String data = "rob";
|
||||
assertThatExceptionOfType(ApplicationErrorException.class).isThrownBy(
|
||||
() -> this.requester.route("secure.retrieve-mono").data(data).retrieveMono(String.class).block());
|
||||
// @formatter:off
|
||||
assertThatExceptionOfType(ApplicationErrorException.class)
|
||||
.isThrownBy(() -> this.requester.route("secure.retrieve-mono")
|
||||
.data(data).retrieveMono(String.class)
|
||||
.block()
|
||||
);
|
||||
// @formatter:on
|
||||
assertThat(this.controller.payloads).isEmpty();
|
||||
}
|
||||
|
||||
|
@ -103,12 +118,20 @@ public class SimpleAuthenticationITests {
|
|||
MimeType authenticationMimeType = MimeTypeUtils
|
||||
.parseMimeType(WellKnownMimeType.MESSAGE_RSOCKET_AUTHENTICATION.getString());
|
||||
UsernamePasswordMetadata credentials = new UsernamePasswordMetadata("rob", "password");
|
||||
this.requester = RSocketRequester.builder().setupMetadata(credentials, authenticationMimeType)
|
||||
.rsocketStrategies(this.handler.getRSocketStrategies())
|
||||
.connectTcp("localhost", this.server.address().getPort()).block();
|
||||
// @formatter:off
|
||||
this.requester = RSocketRequester.builder()
|
||||
.setupMetadata(credentials, authenticationMimeType)
|
||||
.rsocketStrategies(this.handler.getRSocketStrategies())
|
||||
.connectTcp("localhost", this.server.address().getPort())
|
||||
.block();
|
||||
// @formatter:on
|
||||
String data = "rob";
|
||||
String hiRob = this.requester.route("secure.retrieve-mono").metadata(credentials, authenticationMimeType)
|
||||
.data(data).retrieveMono(String.class).block();
|
||||
// @formatter:off
|
||||
String hiRob = this.requester.route("secure.retrieve-mono")
|
||||
.metadata(credentials, authenticationMimeType)
|
||||
.data(data).retrieveMono(String.class)
|
||||
.block();
|
||||
// @formatter:on
|
||||
assertThat(hiRob).isEqualTo("Hi rob");
|
||||
assertThat(this.controller.payloads).containsOnly(data);
|
||||
}
|
||||
|
|
|
@ -46,9 +46,15 @@ class SecuritySocketAcceptorInterceptorConfiguration {
|
|||
if (rsocket == null) {
|
||||
throw new NoSuchBeanDefinitionException("No RSocketSecurity defined");
|
||||
}
|
||||
rsocket.basicAuthentication(Customizer.withDefaults()).simpleAuthentication(Customizer.withDefaults())
|
||||
.authorizePayload((authz) -> authz.setup().authenticated().anyRequest().authenticated()
|
||||
.matcher((e) -> MatchResult.match()).permitAll());
|
||||
// @formatter:off
|
||||
rsocket.basicAuthentication(Customizer.withDefaults())
|
||||
.simpleAuthentication(Customizer.withDefaults())
|
||||
.authorizePayload((authz) -> authz
|
||||
.setup().authenticated()
|
||||
.anyRequest().authenticated()
|
||||
.matcher((e) -> MatchResult.match()).permitAll()
|
||||
);
|
||||
// @formatter:on
|
||||
return rsocket.build();
|
||||
}
|
||||
|
||||
|
|
|
@ -84,17 +84,20 @@ class HttpSecurityConfiguration {
|
|||
this.objectPostProcessor, passwordEncoder);
|
||||
authenticationBuilder.parentAuthenticationManager(authenticationManager());
|
||||
HttpSecurity http = new HttpSecurity(this.objectPostProcessor, authenticationBuilder, createSharedObjects());
|
||||
http.csrf(withDefaults());
|
||||
http.addFilter(new WebAsyncManagerIntegrationFilter());
|
||||
http.exceptionHandling(withDefaults());
|
||||
http.headers(withDefaults());
|
||||
http.sessionManagement(withDefaults());
|
||||
http.securityContext(withDefaults());
|
||||
http.requestCache(withDefaults());
|
||||
http.anonymous(withDefaults());
|
||||
http.servletApi(withDefaults());
|
||||
http.logout(withDefaults());
|
||||
http.apply(new DefaultLoginPageConfigurer<>());
|
||||
// @formatter:off
|
||||
http
|
||||
.csrf(withDefaults())
|
||||
.addFilter(new WebAsyncManagerIntegrationFilter())
|
||||
.exceptionHandling(withDefaults())
|
||||
.headers(withDefaults())
|
||||
.sessionManagement(withDefaults())
|
||||
.securityContext(withDefaults())
|
||||
.requestCache(withDefaults())
|
||||
.anonymous(withDefaults())
|
||||
.servletApi(withDefaults())
|
||||
.logout(withDefaults())
|
||||
.apply(new DefaultLoginPageConfigurer<>());
|
||||
// @formatter:on
|
||||
return http;
|
||||
}
|
||||
|
||||
|
|
|
@ -117,10 +117,15 @@ final class OAuth2ClientConfiguration {
|
|||
OAuth2AuthorizedClientManager authorizedClientManager = null;
|
||||
if (this.clientRegistrationRepository != null && this.authorizedClientRepository != null) {
|
||||
if (this.accessTokenResponseClient != null) {
|
||||
// @formatter:off
|
||||
OAuth2AuthorizedClientProvider authorizedClientProvider = OAuth2AuthorizedClientProviderBuilder
|
||||
.builder().authorizationCode().refreshToken().clientCredentials((configurer) -> configurer
|
||||
.accessTokenResponseClient(this.accessTokenResponseClient))
|
||||
.password().build();
|
||||
.builder()
|
||||
.authorizationCode()
|
||||
.refreshToken()
|
||||
.clientCredentials((configurer) -> configurer.accessTokenResponseClient(this.accessTokenResponseClient))
|
||||
.password()
|
||||
.build();
|
||||
// @formatter:on
|
||||
DefaultOAuth2AuthorizedClientManager defaultAuthorizedClientManager = new DefaultOAuth2AuthorizedClientManager(
|
||||
this.clientRegistrationRepository, this.authorizedClientRepository);
|
||||
defaultAuthorizedClientManager.setAuthorizedClientProvider(authorizedClientProvider);
|
||||
|
|
|
@ -125,7 +125,11 @@ class ServerHttpSecurityConfiguration {
|
|||
@Scope("prototype")
|
||||
ServerHttpSecurity httpSecurity() {
|
||||
ContextAwareServerHttpSecurity http = new ContextAwareServerHttpSecurity();
|
||||
return http.authenticationManager(authenticationManager()).headers().and().logout().and();
|
||||
// @formatter:off
|
||||
return http.authenticationManager(authenticationManager())
|
||||
.headers().and()
|
||||
.logout().and();
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
private ReactiveAuthenticationManager authenticationManager() {
|
||||
|
|
|
@ -18,12 +18,17 @@ package org.springframework.security.config;
|
|||
|
||||
public abstract class ConfigTestUtils {
|
||||
|
||||
// @formatter:off
|
||||
public static final String AUTH_PROVIDER_XML = "<authentication-manager alias='authManager'>"
|
||||
+ " <authentication-provider>" + " <user-service id='us'>"
|
||||
+ " <authentication-provider>"
|
||||
+ " <user-service id='us'>"
|
||||
+ " <user name='bob' password='{noop}bobspassword' authorities='ROLE_A,ROLE_B' />"
|
||||
+ " <user name='bill' password='{noop}billspassword' authorities='ROLE_A,ROLE_B,AUTH_OTHER' />"
|
||||
+ " <user name='admin' password='{noop}password' authorities='ROLE_ADMIN,ROLE_USER' />"
|
||||
+ " <user name='user' password='{noop}password' authorities='ROLE_USER' />"
|
||||
+ " </user-service>" + " </authentication-provider>" + "</authentication-manager>";
|
||||
+ " </user-service>"
|
||||
+ " </authentication-provider>"
|
||||
+ "</authentication-manager>";
|
||||
// @formatter:on
|
||||
|
||||
}
|
||||
|
|
|
@ -52,9 +52,15 @@ public class SecurityNamespaceHandlerTests {
|
|||
@Rule
|
||||
public ExpectedException thrown = ExpectedException.none();
|
||||
|
||||
private static final String XML_AUTHENTICATION_MANAGER = "<authentication-manager>" + " <authentication-provider>"
|
||||
+ " <user-service id='us'>" + " <user name='bob' password='bobspassword' authorities='ROLE_A' />"
|
||||
+ " </user-service>" + " </authentication-provider>" + "</authentication-manager>";
|
||||
// @formatter:off
|
||||
private static final String XML_AUTHENTICATION_MANAGER = "<authentication-manager>"
|
||||
+ " <authentication-provider>"
|
||||
+ " <user-service id='us'>"
|
||||
+ " <user name='bob' password='bobspassword' authorities='ROLE_A' />"
|
||||
+ " </user-service>"
|
||||
+ " </authentication-provider>"
|
||||
+ "</authentication-manager>";
|
||||
// @formatter:on
|
||||
|
||||
private static final String XML_HTTP_BLOCK = "<http auto-config='true'/>";
|
||||
|
||||
|
|
|
@ -50,6 +50,7 @@ import org.springframework.security.core.userdetails.UserDetailsService;
|
|||
import org.springframework.security.crypto.password.NoOpPasswordEncoder;
|
||||
import org.springframework.security.crypto.password.PasswordEncoder;
|
||||
import org.springframework.security.provisioning.InMemoryUserDetailsManager;
|
||||
import org.springframework.security.test.web.servlet.response.SecurityMockMvcResultMatchers;
|
||||
import org.springframework.test.web.servlet.MockMvc;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
@ -121,9 +122,10 @@ public class AuthenticationManagerBuilderTests {
|
|||
@Test
|
||||
public void authenticationManagerWhenMultipleProvidersThenWorks() throws Exception {
|
||||
this.spring.register(MultiAuthenticationProvidersConfig.class).autowire();
|
||||
this.mockMvc.perform(formLogin()).andExpect(authenticated().withUsername("user").withRoles("USER"));
|
||||
this.mockMvc.perform(formLogin().user("admin"))
|
||||
.andExpect(authenticated().withUsername("admin").withRoles("USER", "ADMIN"));
|
||||
SecurityMockMvcResultMatchers.AuthenticatedMatcher user = authenticated().withUsername("user").withRoles("USER");
|
||||
this.mockMvc.perform(formLogin()).andExpect(user);
|
||||
SecurityMockMvcResultMatchers.AuthenticatedMatcher admin = authenticated().withUsername("admin").withRoles("USER", "ADMIN");
|
||||
this.mockMvc.perform(formLogin().user("admin")).andExpect(admin);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -165,8 +167,14 @@ public class AuthenticationManagerBuilderTests {
|
|||
|
||||
@Override
|
||||
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
|
||||
auth.inMemoryAuthentication().withUser(PasswordEncodedUser.user()).and().inMemoryAuthentication()
|
||||
// @formatter:off
|
||||
auth
|
||||
.inMemoryAuthentication()
|
||||
.withUser(PasswordEncodedUser.user())
|
||||
.and()
|
||||
.inMemoryAuthentication()
|
||||
.withUser(PasswordEncodedUser.admin());
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -47,20 +47,18 @@ public class NamespaceAuthenticationManagerTests {
|
|||
@Test
|
||||
public void authenticationMangerWhenDefaultThenEraseCredentialsIsTrue() throws Exception {
|
||||
this.spring.register(EraseCredentialsTrueDefaultConfig.class).autowire();
|
||||
this.mockMvc.perform(formLogin())
|
||||
.andExpect(authenticated().withAuthentication((a) -> assertThat(a.getCredentials()).isNull()));
|
||||
this.mockMvc.perform(formLogin())
|
||||
.andExpect(authenticated().withAuthentication((a) -> assertThat(a.getCredentials()).isNull()));
|
||||
SecurityMockMvcResultMatchers.AuthenticatedMatcher nullCredentials = authenticated().withAuthentication((a) -> assertThat(a.getCredentials()).isNull());
|
||||
this.mockMvc.perform(formLogin()).andExpect(nullCredentials);
|
||||
this.mockMvc.perform(formLogin()).andExpect(nullCredentials);
|
||||
// no exception due to username being cleared out
|
||||
}
|
||||
|
||||
@Test
|
||||
public void authenticationMangerWhenEraseCredentialsIsFalseThenCredentialsNotNull() throws Exception {
|
||||
this.spring.register(EraseCredentialsFalseConfig.class).autowire();
|
||||
this.mockMvc.perform(formLogin())
|
||||
.andExpect(authenticated().withAuthentication((a) -> assertThat(a.getCredentials()).isNotNull()));
|
||||
this.mockMvc.perform(formLogin())
|
||||
.andExpect(authenticated().withAuthentication((a) -> assertThat(a.getCredentials()).isNotNull()));
|
||||
SecurityMockMvcResultMatchers.AuthenticatedMatcher notNullCredentials = authenticated().withAuthentication((a) -> assertThat(a.getCredentials()).isNotNull());
|
||||
this.mockMvc.perform(formLogin()).andExpect(notNullCredentials);
|
||||
this.mockMvc.perform(formLogin()).andExpect(notNullCredentials);
|
||||
// no exception due to username being cleared out
|
||||
}
|
||||
|
||||
|
@ -68,8 +66,8 @@ public class NamespaceAuthenticationManagerTests {
|
|||
// SEC-2533
|
||||
public void authenticationManagerWhenGlobalAndEraseCredentialsIsFalseThenCredentialsNotNull() throws Exception {
|
||||
this.spring.register(GlobalEraseCredentialsFalseConfig.class).autowire();
|
||||
this.mockMvc.perform(SecurityMockMvcRequestBuilders.formLogin()).andExpect(SecurityMockMvcResultMatchers
|
||||
.authenticated().withAuthentication((a) -> assertThat(a.getCredentials()).isNotNull()));
|
||||
SecurityMockMvcResultMatchers.AuthenticatedMatcher notNullCredentials = authenticated().withAuthentication((a) -> assertThat(a.getCredentials()).isNotNull());
|
||||
this.mockMvc.perform(formLogin()).andExpect(notNullCredentials);
|
||||
}
|
||||
|
||||
@EnableWebSecurity
|
||||
|
|
|
@ -34,6 +34,7 @@ import org.springframework.security.core.userdetails.PasswordEncodedUser;
|
|||
import org.springframework.security.core.userdetails.UserCache;
|
||||
import org.springframework.security.core.userdetails.UserDetails;
|
||||
import org.springframework.security.core.userdetails.jdbc.JdbcDaoImpl;
|
||||
import org.springframework.security.test.web.servlet.response.SecurityMockMvcResultMatchers;
|
||||
import org.springframework.test.web.servlet.MockMvc;
|
||||
|
||||
import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestBuilders.formLogin;
|
||||
|
@ -53,13 +54,15 @@ public class NamespaceJdbcUserServiceTests {
|
|||
@Test
|
||||
public void jdbcUserService() throws Exception {
|
||||
this.spring.register(DataSourceConfig.class, JdbcUserServiceConfig.class).autowire();
|
||||
this.mockMvc.perform(formLogin()).andExpect(authenticated().withUsername("user"));
|
||||
SecurityMockMvcResultMatchers.AuthenticatedMatcher user = authenticated().withUsername("user");
|
||||
this.mockMvc.perform(formLogin()).andExpect(user);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void jdbcUserServiceCustom() throws Exception {
|
||||
this.spring.register(CustomDataSourceConfig.class, CustomJdbcUserServiceSampleConfig.class).autowire();
|
||||
this.mockMvc.perform(formLogin()).andExpect(authenticated().withUsername("user").withRoles("DBA", "USER"));
|
||||
SecurityMockMvcResultMatchers.AuthenticatedMatcher dba = authenticated().withUsername("user").withRoles("DBA", "USER");
|
||||
this.mockMvc.perform(formLogin()).andExpect(dba);
|
||||
}
|
||||
|
||||
@EnableWebSecurity
|
||||
|
|
|
@ -43,9 +43,17 @@ public class UserDetailsManagerConfigurerTests {
|
|||
|
||||
@Test
|
||||
public void allAttributesSupported() {
|
||||
UserDetails userDetails = new UserDetailsManagerConfigurer<AuthenticationManagerBuilder, InMemoryUserDetailsManagerConfigurer<AuthenticationManagerBuilder>>(
|
||||
this.userDetailsManager).withUser("user").password("password").roles("USER").disabled(true)
|
||||
.accountExpired(true).accountLocked(true).credentialsExpired(true).build();
|
||||
// @formatter:off
|
||||
UserDetails userDetails = configurer()
|
||||
.withUser("user")
|
||||
.password("password")
|
||||
.roles("USER")
|
||||
.disabled(true)
|
||||
.accountExpired(true)
|
||||
.accountLocked(true)
|
||||
.credentialsExpired(true)
|
||||
.build();
|
||||
// @formatter:on
|
||||
assertThat(userDetails.getUsername()).isEqualTo("user");
|
||||
assertThat(userDetails.getPassword()).isEqualTo("password");
|
||||
assertThat(userDetails.getAuthorities().stream().findFirst().get().getAuthority()).isEqualTo("ROLE_USER");
|
||||
|
@ -58,26 +66,43 @@ public class UserDetailsManagerConfigurerTests {
|
|||
@Test
|
||||
public void authoritiesWithGrantedAuthorityWorks() {
|
||||
SimpleGrantedAuthority authority = new SimpleGrantedAuthority("ROLE_USER");
|
||||
UserDetails userDetails = new UserDetailsManagerConfigurer<AuthenticationManagerBuilder, InMemoryUserDetailsManagerConfigurer<AuthenticationManagerBuilder>>(
|
||||
this.userDetailsManager).withUser("user").password("password").authorities(authority).build();
|
||||
// @formatter:off
|
||||
UserDetails userDetails = configurer()
|
||||
.withUser("user")
|
||||
.password("password")
|
||||
.authorities(authority)
|
||||
.build();
|
||||
// @formatter:on
|
||||
assertThat(userDetails.getAuthorities().stream().findFirst().get()).isEqualTo(authority);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void authoritiesWithStringAuthorityWorks() {
|
||||
String authority = "ROLE_USER";
|
||||
UserDetails userDetails = new UserDetailsManagerConfigurer<AuthenticationManagerBuilder, InMemoryUserDetailsManagerConfigurer<AuthenticationManagerBuilder>>(
|
||||
this.userDetailsManager).withUser("user").password("password").authorities(authority).build();
|
||||
// @formatter:off
|
||||
UserDetails userDetails = configurer()
|
||||
.withUser("user")
|
||||
.password("password")
|
||||
.authorities(authority)
|
||||
.build();
|
||||
// @formatter:on
|
||||
assertThat(userDetails.getAuthorities().stream().findFirst().get().getAuthority()).isEqualTo(authority);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void authoritiesWithAListOfGrantedAuthorityWorks() {
|
||||
SimpleGrantedAuthority authority = new SimpleGrantedAuthority("ROLE_USER");
|
||||
UserDetails userDetails = new UserDetailsManagerConfigurer<AuthenticationManagerBuilder, InMemoryUserDetailsManagerConfigurer<AuthenticationManagerBuilder>>(
|
||||
this.userDetailsManager).withUser("user").password("password").authorities(Arrays.asList(authority))
|
||||
.build();
|
||||
// @formatter:off
|
||||
UserDetails userDetails = configurer()
|
||||
.withUser("user")
|
||||
.password("password")
|
||||
.authorities(Arrays.asList(authority))
|
||||
.build();
|
||||
// @formatter:on
|
||||
assertThat(userDetails.getAuthorities().stream().findFirst().get()).isEqualTo(authority);
|
||||
}
|
||||
|
||||
private UserDetailsManagerConfigurer<AuthenticationManagerBuilder, InMemoryUserDetailsManagerConfigurer<AuthenticationManagerBuilder>> configurer() {
|
||||
return new UserDetailsManagerConfigurer<AuthenticationManagerBuilder, InMemoryUserDetailsManagerConfigurer<AuthenticationManagerBuilder>>(this.userDetailsManager);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -68,18 +68,23 @@ public class HttpSecurityHeadersTests {
|
|||
// gh-3975
|
||||
@Test
|
||||
public void headerWhenSpringMvcResourceThenCacheRelatedHeadersReset() throws Exception {
|
||||
this.mockMvc.perform(get("/resources/file.js")).andExpect(status().isOk())
|
||||
// @formatter:off
|
||||
this.mockMvc.perform(get("/resources/file.js"))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(header().string(HttpHeaders.CACHE_CONTROL, "max-age=12345"))
|
||||
.andExpect(header().doesNotExist(HttpHeaders.PRAGMA))
|
||||
.andExpect(header().doesNotExist(HttpHeaders.EXPIRES));
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
public void headerWhenNotSpringResourceThenCacheRelatedHeadersSet() throws Exception {
|
||||
// @formatter:off
|
||||
this.mockMvc.perform(get("/notresource"))
|
||||
.andExpect(header().string(HttpHeaders.CACHE_CONTROL, "no-cache, no-store, max-age=0, must-revalidate"))
|
||||
.andExpect(header().string(HttpHeaders.PRAGMA, "no-cache"))
|
||||
.andExpect(header().string(HttpHeaders.EXPIRES, "0"));
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@EnableWebSecurity
|
||||
|
@ -97,8 +102,11 @@ public class HttpSecurityHeadersTests {
|
|||
|
||||
@Override
|
||||
public void addResourceHandlers(ResourceHandlerRegistry registry) {
|
||||
registry.addResourceHandler("/resources/**").addResourceLocations("classpath:/resources/")
|
||||
// @formatter:off
|
||||
registry.addResourceHandler("/resources/**")
|
||||
.addResourceLocations("classpath:/resources/")
|
||||
.setCachePeriod(12345);
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -51,6 +51,7 @@ import org.springframework.security.core.userdetails.UsernameNotFoundException;
|
|||
import org.springframework.security.provisioning.InMemoryUserDetailsManager;
|
||||
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
|
||||
import org.springframework.test.web.servlet.MockMvc;
|
||||
import org.springframework.test.web.servlet.request.MockHttpServletRequestBuilder;
|
||||
import org.springframework.web.accept.ContentNegotiationStrategy;
|
||||
import org.springframework.web.accept.HeaderContentNegotiationStrategy;
|
||||
import org.springframework.web.filter.OncePerRequestFilter;
|
||||
|
@ -83,12 +84,15 @@ public class WebSecurityConfigurerAdapterTests {
|
|||
@Test
|
||||
public void loadConfigWhenRequestSecureThenDefaultSecurityHeadersReturned() throws Exception {
|
||||
this.spring.register(HeadersArePopulatedByDefaultConfig.class).autowire();
|
||||
this.mockMvc.perform(get("/").secure(true)).andExpect(header().string("X-Content-Type-Options", "nosniff"))
|
||||
// @formatter:off
|
||||
this.mockMvc.perform(get("/").secure(true))
|
||||
.andExpect(header().string("X-Content-Type-Options", "nosniff"))
|
||||
.andExpect(header().string("X-Frame-Options", "DENY"))
|
||||
.andExpect(header().string("Strict-Transport-Security", "max-age=31536000 ; includeSubDomains"))
|
||||
.andExpect(header().string("Cache-Control", "no-cache, no-store, max-age=0, must-revalidate"))
|
||||
.andExpect(header().string("Pragma", "no-cache")).andExpect(header().string("Expires", "0"))
|
||||
.andExpect(header().string("X-XSS-Protection", "1; mode=block"));
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -188,10 +192,9 @@ public class WebSecurityConfigurerAdapterTests {
|
|||
public void performWhenUsingAuthenticationEventPublisherInDslThenUses() throws Exception {
|
||||
this.spring.register(CustomAuthenticationEventPublisherDsl.class).autowire();
|
||||
AuthenticationEventPublisher authenticationEventPublisher = CustomAuthenticationEventPublisherDsl.EVENT_PUBLISHER;
|
||||
this.mockMvc.perform(get("/").with(httpBasic("user", "password"))); // fails since
|
||||
// no
|
||||
// providers
|
||||
// configured
|
||||
MockHttpServletRequestBuilder userRequest = get("/").with(httpBasic("user", "password"));
|
||||
// fails since no providers configured
|
||||
this.mockMvc.perform(userRequest);
|
||||
verify(authenticationEventPublisher).publishAuthenticationFailure(any(AuthenticationException.class),
|
||||
any(Authentication.class));
|
||||
}
|
||||
|
|
|
@ -155,8 +155,11 @@ public class NamespaceHttpTests {
|
|||
public void configureWhenAuthenticationEntryPointSetAndRequestUnauthorizedThenRedirectedToAuthenticationEntryPoint()
|
||||
throws Exception {
|
||||
this.spring.register(EntryPointRefConfig.class).autowire();
|
||||
this.mockMvc.perform(get("/")).andExpect(status().is3xxRedirection())
|
||||
// @formatter:off
|
||||
this.mockMvc.perform(get("/"))
|
||||
.andExpect(status().is3xxRedirection())
|
||||
.andExpect(redirectedUrlPattern("**/entry-point"));
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test // http@jaas-api-provision
|
||||
|
@ -174,8 +177,11 @@ public class NamespaceHttpTests {
|
|||
@Test // http@realm
|
||||
public void configureWhenHttpBasicAndRequestUnauthorizedThenReturnWWWAuthenticateWithRealm() throws Exception {
|
||||
this.spring.register(RealmConfig.class).autowire();
|
||||
this.mockMvc.perform(get("/")).andExpect(status().isUnauthorized())
|
||||
// @formatter:off
|
||||
this.mockMvc.perform(get("/"))
|
||||
.andExpect(status().isUnauthorized())
|
||||
.andExpect(header().string("WWW-Authenticate", "Basic realm=\"RealmConfig\""));
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test // http@request-matcher-ref ant
|
||||
|
|
|
@ -68,7 +68,11 @@ public class AuthenticationPrincipalArgumentResolverTests {
|
|||
new UsernamePasswordAuthenticationToken(user, user.getPassword(), user.getAuthorities()));
|
||||
SecurityContextHolder.setContext(context);
|
||||
MockMvc mockMvc = MockMvcBuilders.webAppContextSetup(this.wac).build();
|
||||
mockMvc.perform(get("/users/self")).andExpect(status().isOk()).andExpect(content().string("extracted-user"));
|
||||
// @formatter:off
|
||||
mockMvc.perform(get("/users/self"))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(content().string("extracted-user"));
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@EnableWebSecurity
|
||||
|
|
|
@ -41,6 +41,7 @@ import org.springframework.security.web.SecurityFilterChain;
|
|||
import org.springframework.security.web.header.writers.frameoptions.XFrameOptionsHeaderWriter;
|
||||
import org.springframework.test.web.servlet.MockMvc;
|
||||
import org.springframework.test.web.servlet.MvcResult;
|
||||
import org.springframework.test.web.servlet.request.MockHttpServletRequestBuilder;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
|
@ -81,6 +82,7 @@ public class HttpSecurityConfigurationTests {
|
|||
@Test
|
||||
public void getWhenDefaultFilterChainBeanThenDefaultHeadersInResponse() throws Exception {
|
||||
this.spring.register(DefaultWithFilterChainConfig.class).autowire();
|
||||
// @formatter:off
|
||||
MvcResult mvcResult = this.mockMvc.perform(get("/").secure(true))
|
||||
.andExpect(header().string(HttpHeaders.X_CONTENT_TYPE_OPTIONS, "nosniff"))
|
||||
.andExpect(header().string(HttpHeaders.X_FRAME_OPTIONS,
|
||||
|
@ -90,7 +92,9 @@ public class HttpSecurityConfigurationTests {
|
|||
.andExpect(header().string(HttpHeaders.CACHE_CONTROL, "no-cache, no-store, max-age=0, must-revalidate"))
|
||||
.andExpect(header().string(HttpHeaders.EXPIRES, "0"))
|
||||
.andExpect(header().string(HttpHeaders.PRAGMA, "no-cache"))
|
||||
.andExpect(header().string(HttpHeaders.X_XSS_PROTECTION, "1; mode=block")).andReturn();
|
||||
.andExpect(header().string(HttpHeaders.X_XSS_PROTECTION, "1; mode=block"))
|
||||
.andReturn();
|
||||
// @formatter:on
|
||||
assertThat(mvcResult.getResponse().getHeaderNames()).containsExactlyInAnyOrder(
|
||||
HttpHeaders.X_CONTENT_TYPE_OPTIONS, HttpHeaders.X_FRAME_OPTIONS, HttpHeaders.STRICT_TRANSPORT_SECURITY,
|
||||
HttpHeaders.CACHE_CONTROL, HttpHeaders.EXPIRES, HttpHeaders.PRAGMA, HttpHeaders.X_XSS_PROTECTION);
|
||||
|
@ -99,21 +103,33 @@ public class HttpSecurityConfigurationTests {
|
|||
@Test
|
||||
public void logoutWhenDefaultFilterChainBeanThenCreatesDefaultLogoutEndpoint() throws Exception {
|
||||
this.spring.register(DefaultWithFilterChainConfig.class).autowire();
|
||||
this.mockMvc.perform(post("/logout").with(csrf())).andExpect(redirectedUrl("/login?logout"));
|
||||
// @formatter:off
|
||||
this.mockMvc.perform(post("/logout").with(csrf()))
|
||||
.andExpect(redirectedUrl("/login?logout"));
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
public void loadConfigWhenDefaultConfigThenWebAsyncManagerIntegrationFilterAdded() throws Exception {
|
||||
this.spring.register(DefaultWithFilterChainConfig.class, NameController.class).autowire();
|
||||
MvcResult mvcResult = this.mockMvc.perform(get("/name").with(user("Bob"))).andExpect(request().asyncStarted())
|
||||
// @formatter:off
|
||||
MockHttpServletRequestBuilder requestWithBob = get("/name").with(user("Bob"));
|
||||
MvcResult mvcResult = this.mockMvc.perform(requestWithBob)
|
||||
.andExpect(request().asyncStarted())
|
||||
.andReturn();
|
||||
this.mockMvc.perform(asyncDispatch(mvcResult)).andExpect(status().isOk()).andExpect(content().string("Bob"));
|
||||
this.mockMvc.perform(asyncDispatch(mvcResult))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(content().string("Bob"));
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getWhenDefaultFilterChainBeanThenAnonymousPermitted() throws Exception {
|
||||
this.spring.register(AuthorizeRequestsConfig.class, UserDetailsConfig.class, BaseController.class).autowire();
|
||||
this.mockMvc.perform(get("/")).andExpect(status().isOk());
|
||||
// @formatter:off
|
||||
this.mockMvc.perform(get("/"))
|
||||
.andExpect(status().isOk());
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -121,29 +137,48 @@ public class HttpSecurityConfigurationTests {
|
|||
this.spring.register(SecurityEnabledConfig.class, UserDetailsConfig.class).autowire();
|
||||
MockHttpSession session = new MockHttpSession();
|
||||
String sessionId = session.getId();
|
||||
MvcResult result = this.mockMvc.perform(
|
||||
post("/login").param("username", "user").param("password", "password").session(session).with(csrf()))
|
||||
.andReturn();
|
||||
// @formatter:off
|
||||
MockHttpServletRequestBuilder loginRequest = post("/login")
|
||||
.param("username", "user")
|
||||
.param("password", "password")
|
||||
.session(session)
|
||||
.with(csrf());
|
||||
// @formatter:on
|
||||
MvcResult result = this.mockMvc.perform(loginRequest).andReturn();
|
||||
assertThat(result.getRequest().getSession(false).getId()).isNotEqualTo(sessionId);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void authenticateWhenDefaultFilterChainBeanThenRedirectsToSavedRequest() throws Exception {
|
||||
this.spring.register(SecurityEnabledConfig.class, UserDetailsConfig.class).autowire();
|
||||
MockHttpSession session = (MockHttpSession) this.mockMvc.perform(get("/messages")).andReturn().getRequest()
|
||||
// @formatter:off
|
||||
MockHttpSession session = (MockHttpSession) this.mockMvc.perform(get("/messages"))
|
||||
.andReturn()
|
||||
.getRequest()
|
||||
.getSession();
|
||||
this.mockMvc.perform(
|
||||
post("/login").param("username", "user").param("password", "password").session(session).with(csrf()))
|
||||
// @formatter:on
|
||||
// @formatter:off
|
||||
MockHttpServletRequestBuilder loginRequest = post("/login")
|
||||
.param("username", "user")
|
||||
.param("password", "password")
|
||||
.session(session)
|
||||
.with(csrf());
|
||||
// @formatter:on
|
||||
// @formatter:off
|
||||
this.mockMvc.perform(loginRequest)
|
||||
.andExpect(redirectedUrl("http://localhost/messages"));
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
public void authenticateWhenDefaultFilterChainBeanThenRolePrefixIsSet() throws Exception {
|
||||
this.spring.register(SecurityEnabledConfig.class, UserDetailsConfig.class, UserController.class).autowire();
|
||||
TestingAuthenticationToken user = new TestingAuthenticationToken("user", "password", "ROLE_USER");
|
||||
// @formatter:off
|
||||
this.mockMvc
|
||||
.perform(get("/user")
|
||||
.with(authentication(new TestingAuthenticationToken("user", "password", "ROLE_USER"))))
|
||||
.perform(get("/user").with(authentication(user)))
|
||||
.andExpect(status().isOk());
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -177,7 +212,13 @@ public class HttpSecurityConfigurationTests {
|
|||
|
||||
@Bean
|
||||
SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
|
||||
return http.authorizeRequests((authorize) -> authorize.anyRequest().permitAll()).build();
|
||||
// @formatter:off
|
||||
return http
|
||||
.authorizeRequests((authorize) -> authorize
|
||||
.anyRequest().permitAll()
|
||||
)
|
||||
.build();
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -187,8 +228,14 @@ public class HttpSecurityConfigurationTests {
|
|||
|
||||
@Bean
|
||||
SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
|
||||
return http.authorizeRequests((authorize) -> authorize.anyRequest().authenticated())
|
||||
.formLogin(withDefaults()).build();
|
||||
// @formatter:off
|
||||
return http
|
||||
.authorizeRequests((authorize) -> authorize
|
||||
.anyRequest().authenticated()
|
||||
)
|
||||
.formLogin(withDefaults())
|
||||
.build();
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -198,8 +245,13 @@ public class HttpSecurityConfigurationTests {
|
|||
|
||||
@Bean
|
||||
UserDetailsService userDetailsService() {
|
||||
UserDetails user = User.withDefaultPasswordEncoder().username("user").password("password").roles("USER")
|
||||
// @formatter:off
|
||||
UserDetails user = User.withDefaultPasswordEncoder()
|
||||
.username("user")
|
||||
.password("password")
|
||||
.roles("USER")
|
||||
.build();
|
||||
// @formatter:on
|
||||
return new InMemoryUserDetailsManager(user);
|
||||
}
|
||||
|
||||
|
|
|
@ -43,6 +43,7 @@ import org.springframework.security.oauth2.core.TestOAuth2AccessTokens;
|
|||
import org.springframework.security.oauth2.core.endpoint.OAuth2AccessTokenResponse;
|
||||
import org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors;
|
||||
import org.springframework.test.web.servlet.MockMvc;
|
||||
import org.springframework.test.web.servlet.request.MockHttpServletRequestBuilder;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
|
||||
|
@ -56,6 +57,7 @@ import static org.mockito.Mockito.times;
|
|||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.verifyNoInteractions;
|
||||
import static org.mockito.Mockito.verifyZeroInteractions;
|
||||
import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.authentication;
|
||||
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
|
||||
|
@ -97,7 +99,7 @@ public class OAuth2ClientConfigurationTests {
|
|||
this.spring.register(OAuth2AuthorizedClientArgumentResolverConfig.class).autowire();
|
||||
this.mockMvc
|
||||
.perform(get("/authorized-client")
|
||||
.with(SecurityMockMvcRequestPostProcessors.authentication(authentication)))
|
||||
.with(authentication(authentication)))
|
||||
.andExpect(status().isOk()).andExpect(content().string("resolved"));
|
||||
verifyZeroInteractions(accessTokenResponseClient);
|
||||
}
|
||||
|
@ -114,18 +116,26 @@ public class OAuth2ClientConfigurationTests {
|
|||
ClientRegistration clientRegistration = TestClientRegistrations.clientCredentials()
|
||||
.registrationId(clientRegistrationId).build();
|
||||
given(clientRegistrationRepository.findByRegistrationId(clientRegistrationId)).willReturn(clientRegistration);
|
||||
OAuth2AccessTokenResponse accessTokenResponse = OAuth2AccessTokenResponse.withToken("access-token-1234")
|
||||
.tokenType(OAuth2AccessToken.TokenType.BEARER).expiresIn(300).build();
|
||||
// @formatter:off
|
||||
OAuth2AccessTokenResponse accessTokenResponse = OAuth2AccessTokenResponse
|
||||
.withToken("access-token-1234")
|
||||
.tokenType(OAuth2AccessToken.TokenType.BEARER)
|
||||
.expiresIn(300)
|
||||
.build();
|
||||
// @formatter:on
|
||||
given(accessTokenResponseClient.getTokenResponse(any(OAuth2ClientCredentialsGrantRequest.class)))
|
||||
.willReturn(accessTokenResponse);
|
||||
OAuth2AuthorizedClientArgumentResolverConfig.CLIENT_REGISTRATION_REPOSITORY = clientRegistrationRepository;
|
||||
OAuth2AuthorizedClientArgumentResolverConfig.AUTHORIZED_CLIENT_REPOSITORY = authorizedClientRepository;
|
||||
OAuth2AuthorizedClientArgumentResolverConfig.ACCESS_TOKEN_RESPONSE_CLIENT = accessTokenResponseClient;
|
||||
this.spring.register(OAuth2AuthorizedClientArgumentResolverConfig.class).autowire();
|
||||
this.mockMvc
|
||||
.perform(get("/authorized-client")
|
||||
.with(SecurityMockMvcRequestPostProcessors.authentication(authentication)))
|
||||
.andExpect(status().isOk()).andExpect(content().string("resolved"));
|
||||
MockHttpServletRequestBuilder authenticatedRequest = get("/authorized-client")
|
||||
.with(authentication(authentication));
|
||||
// @formatter:off
|
||||
this.mockMvc.perform(authenticatedRequest)
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(content().string("resolved"));
|
||||
// @formatter:on
|
||||
verify(accessTokenResponseClient, times(1)).getTokenResponse(any(OAuth2ClientCredentialsGrantRequest.class));
|
||||
}
|
||||
|
||||
|
@ -150,20 +160,25 @@ public class OAuth2ClientConfigurationTests {
|
|||
|
||||
@Test
|
||||
public void loadContextWhenClientRegistrationRepositoryRegisteredTwiceThenThrowNoUniqueBeanDefinitionException() {
|
||||
// @formatter:off
|
||||
assertThatExceptionOfType(Exception.class)
|
||||
.isThrownBy(
|
||||
() -> this.spring.register(ClientRegistrationRepositoryRegisteredTwiceConfig.class).autowire())
|
||||
.withMessageContaining(
|
||||
"expected single matching bean but found 2: clientRegistrationRepository1,clientRegistrationRepository2")
|
||||
.withRootCauseInstanceOf(NoUniqueBeanDefinitionException.class);
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
public void loadContextWhenAccessTokenResponseClientRegisteredTwiceThenThrowNoUniqueBeanDefinitionException() {
|
||||
// @formatter:off
|
||||
assertThatExceptionOfType(Exception.class)
|
||||
.isThrownBy(() -> this.spring.register(AccessTokenResponseClientRegisteredTwiceConfig.class).autowire())
|
||||
.withRootCauseInstanceOf(NoUniqueBeanDefinitionException.class).withMessageContaining(
|
||||
.withRootCauseInstanceOf(NoUniqueBeanDefinitionException.class)
|
||||
.withMessageContaining(
|
||||
"expected single matching bean but found 2: accessTokenResponseClient1,accessTokenResponseClient2");
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
// gh-8700
|
||||
|
@ -184,10 +199,14 @@ public class OAuth2ClientConfigurationTests {
|
|||
OAuth2AuthorizedClientManagerRegisteredConfig.AUTHORIZED_CLIENT_REPOSITORY = authorizedClientRepository;
|
||||
OAuth2AuthorizedClientManagerRegisteredConfig.AUTHORIZED_CLIENT_MANAGER = authorizedClientManager;
|
||||
this.spring.register(OAuth2AuthorizedClientManagerRegisteredConfig.class).autowire();
|
||||
MockHttpServletRequestBuilder authenticatedRequest = get("/authorized-client")
|
||||
.with(authentication(authentication));
|
||||
// @formatter:off
|
||||
this.mockMvc
|
||||
.perform(get("/authorized-client")
|
||||
.with(SecurityMockMvcRequestPostProcessors.authentication(authentication)))
|
||||
.andExpect(status().isOk()).andExpect(content().string("resolved"));
|
||||
.perform(authenticatedRequest)
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(content().string("resolved"));
|
||||
// @formatter:on
|
||||
verify(authorizedClientManager).authorize(any());
|
||||
verifyNoInteractions(clientRegistrationRepository);
|
||||
verifyNoInteractions(authorizedClientRepository);
|
||||
|
|
|
@ -36,10 +36,12 @@ import org.springframework.security.oauth2.server.resource.authentication.TestBe
|
|||
import org.springframework.security.oauth2.server.resource.web.reactive.function.client.ServletBearerExchangeFilterFunction;
|
||||
import org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors;
|
||||
import org.springframework.test.web.servlet.MockMvc;
|
||||
import org.springframework.test.web.servlet.request.MockHttpServletRequestBuilder;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
import org.springframework.web.reactive.function.client.WebClient;
|
||||
|
||||
import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.authentication;
|
||||
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
|
||||
|
@ -63,8 +65,12 @@ public class SecurityReactorContextConfigurationResourceServerTests {
|
|||
public void requestWhenUsingFilterThenBearerTokenPropagated() throws Exception {
|
||||
BearerTokenAuthentication authentication = TestBearerTokenAuthentications.bearer();
|
||||
this.spring.register(BearerFilterConfig.class, WebServerConfig.class, Controller.class).autowire();
|
||||
this.mockMvc.perform(get("/token").with(SecurityMockMvcRequestPostProcessors.authentication(authentication)))
|
||||
.andExpect(status().isOk()).andExpect(content().string("Bearer token"));
|
||||
MockHttpServletRequestBuilder authenticatedRequest = get("/token").with(authentication(authentication));
|
||||
// @formatter:off
|
||||
this.mockMvc.perform(authenticatedRequest)
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(content().string("Bearer token"));
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
// gh-7418
|
||||
|
@ -72,8 +78,12 @@ public class SecurityReactorContextConfigurationResourceServerTests {
|
|||
public void requestWhenNotUsingFilterThenBearerTokenNotPropagated() throws Exception {
|
||||
BearerTokenAuthentication authentication = TestBearerTokenAuthentications.bearer();
|
||||
this.spring.register(BearerFilterlessConfig.class, WebServerConfig.class, Controller.class).autowire();
|
||||
this.mockMvc.perform(get("/token").with(SecurityMockMvcRequestPostProcessors.authentication(authentication)))
|
||||
.andExpect(status().isOk()).andExpect(content().string(""));
|
||||
MockHttpServletRequestBuilder authenticatedRequest = get("/token").with(authentication(authentication));
|
||||
// @formatter:off
|
||||
this.mockMvc.perform(authenticatedRequest)
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(content().string(""));
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@EnableWebSecurity
|
||||
|
@ -120,8 +130,18 @@ public class SecurityReactorContextConfigurationResourceServerTests {
|
|||
|
||||
@GetMapping("/token")
|
||||
String token() {
|
||||
return this.rest.get().uri(this.uri).retrieve().bodyToMono(String.class)
|
||||
.flatMap((result) -> this.rest.get().uri(this.uri).retrieve().bodyToMono(String.class)).block();
|
||||
// @formatter:off
|
||||
return this.rest.get()
|
||||
.uri(this.uri)
|
||||
.retrieve()
|
||||
.bodyToMono(String.class)
|
||||
.flatMap((result) -> this.rest.get()
|
||||
.uri(this.uri)
|
||||
.retrieve()
|
||||
.bodyToMono(String.class)
|
||||
)
|
||||
.block();
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -198,9 +198,11 @@ public class SecurityReactorContextConfigurationTests {
|
|||
.setRequestAttributes(new ServletRequestAttributes(this.servletRequest, this.servletResponse));
|
||||
SecurityContextHolder.getContext().setAuthentication(this.authentication);
|
||||
ClientResponse clientResponseOk = ClientResponse.create(HttpStatus.OK).build();
|
||||
// @formatter:off
|
||||
ExchangeFilterFunction filter = (req, next) -> Mono.subscriberContext()
|
||||
.filter((ctx) -> ctx.hasKey(SecurityReactorContextSubscriber.SECURITY_CONTEXT_ATTRIBUTES))
|
||||
.map((ctx) -> ctx.get(SecurityReactorContextSubscriber.SECURITY_CONTEXT_ATTRIBUTES)).cast(Map.class)
|
||||
.map((ctx) -> ctx.get(SecurityReactorContextSubscriber.SECURITY_CONTEXT_ATTRIBUTES))
|
||||
.cast(Map.class)
|
||||
.map((attributes) -> {
|
||||
if (attributes.containsKey(HttpServletRequest.class)
|
||||
&& attributes.containsKey(HttpServletResponse.class)
|
||||
|
@ -211,6 +213,7 @@ public class SecurityReactorContextConfigurationTests {
|
|||
return ClientResponse.create(HttpStatus.NOT_FOUND).build();
|
||||
}
|
||||
});
|
||||
// @formatter:on
|
||||
ClientRequest clientRequest = ClientRequest.create(HttpMethod.GET, URI.create("https://example.com")).build();
|
||||
MockExchangeFunction exchange = new MockExchangeFunction();
|
||||
Map<Object, Object> expectedContextAttributes = new HashMap<>();
|
||||
|
@ -219,9 +222,14 @@ public class SecurityReactorContextConfigurationTests {
|
|||
expectedContextAttributes.put(Authentication.class, this.authentication);
|
||||
Mono<ClientResponse> clientResponseMono = filter.filter(clientRequest, exchange)
|
||||
.flatMap((response) -> filter.filter(clientRequest, exchange));
|
||||
StepVerifier.create(clientResponseMono).expectAccessibleContext()
|
||||
// @formatter:off
|
||||
StepVerifier.create(clientResponseMono)
|
||||
.expectAccessibleContext()
|
||||
.contains(SecurityReactorContextSubscriber.SECURITY_CONTEXT_ATTRIBUTES, expectedContextAttributes)
|
||||
.then().expectNext(clientResponseOk).verifyComplete();
|
||||
.then()
|
||||
.expectNext(clientResponseOk)
|
||||
.verifyComplete();
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@EnableWebSecurity
|
||||
|
|
|
@ -336,27 +336,51 @@ public class WebSecurityConfigurationTests {
|
|||
@Order(1)
|
||||
@Bean
|
||||
SecurityFilterChain filterChain1(HttpSecurity http) throws Exception {
|
||||
return http.antMatcher("/role1/**").authorizeRequests((authorize) -> authorize.anyRequest().hasRole("1"))
|
||||
// @formatter:off
|
||||
return http
|
||||
.antMatcher("/role1/**")
|
||||
.authorizeRequests((authorize) -> authorize
|
||||
.anyRequest().hasRole("1")
|
||||
)
|
||||
.build();
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Order(2)
|
||||
@Bean
|
||||
SecurityFilterChain filterChain2(HttpSecurity http) throws Exception {
|
||||
return http.antMatcher("/role2/**").authorizeRequests((authorize) -> authorize.anyRequest().hasRole("2"))
|
||||
// @formatter:off
|
||||
return http
|
||||
.antMatcher("/role2/**")
|
||||
.authorizeRequests((authorize) -> authorize
|
||||
.anyRequest().hasRole("2")
|
||||
)
|
||||
.build();
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Order(3)
|
||||
@Bean
|
||||
SecurityFilterChain filterChain3(HttpSecurity http) throws Exception {
|
||||
return http.antMatcher("/role3/**").authorizeRequests((authorize) -> authorize.anyRequest().hasRole("3"))
|
||||
// @formatter:off
|
||||
return http
|
||||
.antMatcher("/role3/**")
|
||||
.authorizeRequests((authorize) -> authorize
|
||||
.anyRequest().hasRole("3")
|
||||
)
|
||||
.build();
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Bean
|
||||
SecurityFilterChain filterChain4(HttpSecurity http) throws Exception {
|
||||
return http.authorizeRequests((authorize) -> authorize.anyRequest().hasRole("4")).build();
|
||||
// @formatter:off
|
||||
return http
|
||||
.authorizeRequests((authorize) -> authorize
|
||||
.anyRequest().hasRole("4")
|
||||
)
|
||||
.build();
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -509,7 +533,13 @@ public class WebSecurityConfigurationTests {
|
|||
|
||||
@Bean
|
||||
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
|
||||
return http.authorizeRequests((authorize) -> authorize.anyRequest().authenticated()).build();
|
||||
// @formatter:off
|
||||
return http
|
||||
.authorizeRequests((authorize) -> authorize
|
||||
.anyRequest().authenticated()
|
||||
)
|
||||
.build();
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -623,8 +653,14 @@ public class WebSecurityConfigurationTests {
|
|||
@Order(2)
|
||||
@Bean
|
||||
SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
|
||||
return http.antMatcher("/filter/**")
|
||||
.authorizeRequests((authorize) -> authorize.anyRequest().authenticated()).build();
|
||||
// @formatter:off
|
||||
return http
|
||||
.antMatcher("/filter/**")
|
||||
.authorizeRequests((authorize) -> authorize
|
||||
.anyRequest().authenticated()
|
||||
)
|
||||
.build();
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Order(1)
|
||||
|
@ -633,7 +669,13 @@ public class WebSecurityConfigurationTests {
|
|||
|
||||
@Override
|
||||
protected void configure(HttpSecurity http) throws Exception {
|
||||
http.antMatcher("/config/**").authorizeRequests((authorize) -> authorize.anyRequest().permitAll());
|
||||
// @formatter:off
|
||||
http
|
||||
.antMatcher("/config/**")
|
||||
.authorizeRequests((authorize) -> authorize
|
||||
.anyRequest().permitAll()
|
||||
);
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -46,6 +46,7 @@ import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
|
|||
import org.springframework.security.web.util.matcher.RequestMatcher;
|
||||
import org.springframework.test.web.servlet.MockMvc;
|
||||
import org.springframework.test.web.servlet.MvcResult;
|
||||
import org.springframework.test.web.servlet.request.MockHttpServletRequestBuilder;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
@ -288,8 +289,13 @@ public class CsrfConfigurerTests {
|
|||
given(CsrfTokenRepositoryConfig.REPO.loadToken(any())).willReturn(csrfToken);
|
||||
given(CsrfTokenRepositoryConfig.REPO.generateToken(any())).willReturn(csrfToken);
|
||||
this.spring.register(CsrfTokenRepositoryConfig.class, BasicController.class).autowire();
|
||||
this.mvc.perform(post("/login").with(csrf()).param("username", "user").param("password", "password"))
|
||||
.andExpect(redirectedUrl("/"));
|
||||
// @formatter:off
|
||||
MockHttpServletRequestBuilder loginRequest = post("/login")
|
||||
.with(csrf())
|
||||
.param("username", "user")
|
||||
.param("password", "password");
|
||||
// @formatter:on
|
||||
this.mvc.perform(loginRequest).andExpect(redirectedUrl("/"));
|
||||
verify(CsrfTokenRepositoryConfig.REPO).saveToken(isNull(), any(HttpServletRequest.class),
|
||||
any(HttpServletResponse.class));
|
||||
}
|
||||
|
@ -316,28 +322,40 @@ public class CsrfConfigurerTests {
|
|||
@Test
|
||||
public void loginWhenNoCsrfTokenThenRespondsWithForbidden() throws Exception {
|
||||
this.spring.register(FormLoginConfig.class).autowire();
|
||||
this.mvc.perform(post("/login").param("username", "user").param("password", "password"))
|
||||
.andExpect(status().isForbidden()).andExpect(unauthenticated());
|
||||
// @formatter:off
|
||||
MockHttpServletRequestBuilder loginRequest = post("/login")
|
||||
.param("username", "user")
|
||||
.param("password", "password");
|
||||
this.mvc.perform(loginRequest)
|
||||
.andExpect(status().isForbidden())
|
||||
.andExpect(unauthenticated());
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
public void logoutWhenNoCsrfTokenThenRespondsWithForbidden() throws Exception {
|
||||
this.spring.register(FormLoginConfig.class).autowire();
|
||||
this.mvc.perform(post("/logout").with(user("username"))).andExpect(status().isForbidden())
|
||||
MockHttpServletRequestBuilder logoutRequest = post("/logout").with(user("username"));
|
||||
// @formatter:off
|
||||
this.mvc.perform(logoutRequest)
|
||||
.andExpect(status().isForbidden())
|
||||
.andExpect(authenticated());
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
// SEC-2543
|
||||
@Test
|
||||
public void logoutWhenCsrfEnabledAndGetRequestThenDoesNotLogout() throws Exception {
|
||||
this.spring.register(FormLoginConfig.class).autowire();
|
||||
this.mvc.perform(get("/logout").with(user("username"))).andExpect(authenticated());
|
||||
MockHttpServletRequestBuilder logoutRequest = get("/logout").with(user("username"));
|
||||
this.mvc.perform(logoutRequest).andExpect(authenticated());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void logoutWhenGetRequestAndGetEnabledForLogoutThenLogsOut() throws Exception {
|
||||
this.spring.register(LogoutAllowsGetConfig.class).autowire();
|
||||
this.mvc.perform(get("/logout").with(user("username"))).andExpect(unauthenticated());
|
||||
MockHttpServletRequestBuilder logoutRequest = get("/logout").with(user("username"));
|
||||
this.mvc.perform(logoutRequest).andExpect(unauthenticated());
|
||||
}
|
||||
|
||||
// SEC-2749
|
||||
|
@ -366,8 +384,13 @@ public class CsrfConfigurerTests {
|
|||
public void csrfAuthenticationStrategyConfiguredThenStrategyUsed() throws Exception {
|
||||
CsrfAuthenticationStrategyConfig.STRATEGY = mock(SessionAuthenticationStrategy.class);
|
||||
this.spring.register(CsrfAuthenticationStrategyConfig.class).autowire();
|
||||
this.mvc.perform(post("/login").with(csrf()).param("username", "user").param("password", "password"))
|
||||
.andExpect(redirectedUrl("/"));
|
||||
// @formatter:off
|
||||
MockHttpServletRequestBuilder loginRequest = post("/login")
|
||||
.with(csrf())
|
||||
.param("username", "user")
|
||||
.param("password", "password");
|
||||
// @formatter:on
|
||||
this.mvc.perform(loginRequest).andExpect(redirectedUrl("/"));
|
||||
verify(CsrfAuthenticationStrategyConfig.STRATEGY, atLeastOnce()).onAuthentication(any(Authentication.class),
|
||||
any(HttpServletRequest.class), any(HttpServletResponse.class));
|
||||
}
|
||||
|
|
|
@ -40,6 +40,7 @@ import org.springframework.security.web.csrf.DefaultCsrfToken;
|
|||
import org.springframework.security.web.csrf.HttpSessionCsrfTokenRepository;
|
||||
import org.springframework.test.web.servlet.MockMvc;
|
||||
import org.springframework.test.web.servlet.MvcResult;
|
||||
import org.springframework.test.web.servlet.request.MockHttpServletRequestBuilder;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
|
@ -76,26 +77,37 @@ public class DefaultLoginPageConfigurerTests {
|
|||
this.spring.register(DefaultLoginPageConfig.class).autowire();
|
||||
CsrfToken csrfToken = new DefaultCsrfToken("X-CSRF-TOKEN", "_csrf", "BaseSpringSpec_CSRFTOKEN");
|
||||
String csrfAttributeName = HttpSessionCsrfTokenRepository.class.getName().concat(".CSRF_TOKEN");
|
||||
// @formatter:off
|
||||
this.mvc.perform(get("/login").sessionAttr(csrfAttributeName, csrfToken))
|
||||
.andExpect(content().string("<!DOCTYPE html>\n" + "<html lang=\"en\">\n" + " <head>\n"
|
||||
.andExpect(content().string("<!DOCTYPE html>\n"
|
||||
+ "<html lang=\"en\">\n"
|
||||
+ " <head>\n"
|
||||
+ " <meta charset=\"utf-8\">\n"
|
||||
+ " <meta name=\"viewport\" content=\"width=device-width, initial-scale=1, shrink-to-fit=no\">\n"
|
||||
+ " <meta name=\"description\" content=\"\">\n" + " <meta name=\"author\" content=\"\">\n"
|
||||
+ " <meta name=\"description\" content=\"\">\n"
|
||||
+ " <meta name=\"author\" content=\"\">\n"
|
||||
+ " <title>Please sign in</title>\n"
|
||||
+ " <link href=\"https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-beta/css/bootstrap.min.css\" rel=\"stylesheet\" integrity=\"sha384-/Y6pD6FV/Vv2HJnA6t+vslU6fwYXjCFtcEpHbNJ0lyAFsXTsjBbfaDjzALeQsN6M\" crossorigin=\"anonymous\">\n"
|
||||
+ " <link href=\"https://getbootstrap.com/docs/4.0/examples/signin/signin.css\" rel=\"stylesheet\" crossorigin=\"anonymous\"/>\n"
|
||||
+ " </head>\n" + " <body>\n" + " <div class=\"container\">\n"
|
||||
+ " </head>\n"
|
||||
+ " <body>\n"
|
||||
+ " <div class=\"container\">\n"
|
||||
+ " <form class=\"form-signin\" method=\"post\" action=\"/login\">\n"
|
||||
+ " <h2 class=\"form-signin-heading\">Please sign in</h2>\n" + " <p>\n"
|
||||
+ " <h2 class=\"form-signin-heading\">Please sign in</h2>\n"
|
||||
+ " <p>\n"
|
||||
+ " <label for=\"username\" class=\"sr-only\">Username</label>\n"
|
||||
+ " <input type=\"text\" id=\"username\" name=\"username\" class=\"form-control\" placeholder=\"Username\" required autofocus>\n"
|
||||
+ " </p>\n" + " <p>\n"
|
||||
+ " </p>\n"
|
||||
+ " <p>\n"
|
||||
+ " <label for=\"password\" class=\"sr-only\">Password</label>\n"
|
||||
+ " <input type=\"password\" id=\"password\" name=\"password\" class=\"form-control\" placeholder=\"Password\" required>\n"
|
||||
+ " </p>\n" + "<input name=\"" + csrfToken.getParameterName()
|
||||
+ "\" type=\"hidden\" value=\"" + csrfToken.getToken() + "\" />\n"
|
||||
+ " </p>\n"
|
||||
+ "<input name=\""+ csrfToken.getParameterName() + "\" type=\"hidden\" value=\"" + csrfToken.getToken() + "\" />\n"
|
||||
+ " <button class=\"btn btn-lg btn-primary btn-block\" type=\"submit\">Sign in</button>\n"
|
||||
+ " </form>\n" + "</div>\n" + "</body></html>"));
|
||||
+ " </form>\n"
|
||||
+ "</div>\n"
|
||||
+ "</body></html>"));
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -110,16 +122,22 @@ public class DefaultLoginPageConfigurerTests {
|
|||
CsrfToken csrfToken = new DefaultCsrfToken("X-CSRF-TOKEN", "_csrf", "BaseSpringSpec_CSRFTOKEN");
|
||||
String csrfAttributeName = HttpSessionCsrfTokenRepository.class.getName().concat(".CSRF_TOKEN");
|
||||
MvcResult mvcResult = this.mvc.perform(post("/login").with(csrf())).andReturn();
|
||||
// @formatter:off
|
||||
this.mvc.perform(get("/login?error").session((MockHttpSession) mvcResult.getRequest().getSession())
|
||||
.sessionAttr(csrfAttributeName, csrfToken))
|
||||
.andExpect(content().string("<!DOCTYPE html>\n" + "<html lang=\"en\">\n" + " <head>\n"
|
||||
.andExpect(content().string("<!DOCTYPE html>\n"
|
||||
+ "<html lang=\"en\">\n"
|
||||
+ " <head>\n"
|
||||
+ " <meta charset=\"utf-8\">\n"
|
||||
+ " <meta name=\"viewport\" content=\"width=device-width, initial-scale=1, shrink-to-fit=no\">\n"
|
||||
+ " <meta name=\"description\" content=\"\">\n" + " <meta name=\"author\" content=\"\">\n"
|
||||
+ " <meta name=\"description\" content=\"\">\n"
|
||||
+ " <meta name=\"author\" content=\"\">\n"
|
||||
+ " <title>Please sign in</title>\n"
|
||||
+ " <link href=\"https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-beta/css/bootstrap.min.css\" rel=\"stylesheet\" integrity=\"sha384-/Y6pD6FV/Vv2HJnA6t+vslU6fwYXjCFtcEpHbNJ0lyAFsXTsjBbfaDjzALeQsN6M\" crossorigin=\"anonymous\">\n"
|
||||
+ " <link href=\"https://getbootstrap.com/docs/4.0/examples/signin/signin.css\" rel=\"stylesheet\" crossorigin=\"anonymous\"/>\n"
|
||||
+ " </head>\n" + " <body>\n" + " <div class=\"container\">\n"
|
||||
+ " </head>\n"
|
||||
+ " <body>\n"
|
||||
+ " <div class=\"container\">\n"
|
||||
+ " <form class=\"form-signin\" method=\"post\" action=\"/login\">\n"
|
||||
+ " <h2 class=\"form-signin-heading\">Please sign in</h2>\n"
|
||||
+ "<div class=\"alert alert-danger\" role=\"alert\">Bad credentials</div> <p>\n"
|
||||
|
@ -128,17 +146,25 @@ public class DefaultLoginPageConfigurerTests {
|
|||
+ " </p>\n" + " <p>\n"
|
||||
+ " <label for=\"password\" class=\"sr-only\">Password</label>\n"
|
||||
+ " <input type=\"password\" id=\"password\" name=\"password\" class=\"form-control\" placeholder=\"Password\" required>\n"
|
||||
+ " </p>\n" + "<input name=\"" + csrfToken.getParameterName()
|
||||
+ "\" type=\"hidden\" value=\"" + csrfToken.getToken() + "\" />\n"
|
||||
+ " </p>\n"
|
||||
+ "<input name=\"" + csrfToken.getParameterName() + "\" type=\"hidden\" value=\"" + csrfToken.getToken() + "\" />\n"
|
||||
+ " <button class=\"btn btn-lg btn-primary btn-block\" type=\"submit\">Sign in</button>\n"
|
||||
+ " </form>\n" + "</div>\n" + "</body></html>"));
|
||||
+ " </form>\n"
|
||||
+ "</div>\n"
|
||||
+ "</body></html>"));
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
public void loginWhenValidCredentialsThenRedirectsToDefaultSuccessPage() throws Exception {
|
||||
this.spring.register(DefaultLoginPageConfig.class).autowire();
|
||||
this.mvc.perform(post("/login").with(csrf()).param("username", "user").param("password", "password"))
|
||||
.andExpect(redirectedUrl("/"));
|
||||
// @formatter:off
|
||||
MockHttpServletRequestBuilder loginRequest = post("/login")
|
||||
.with(csrf())
|
||||
.param("username", "user")
|
||||
.param("password", "password");
|
||||
// @formatter:on
|
||||
this.mvc.perform(loginRequest).andExpect(redirectedUrl("/"));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -146,27 +172,37 @@ public class DefaultLoginPageConfigurerTests {
|
|||
this.spring.register(DefaultLoginPageConfig.class).autowire();
|
||||
CsrfToken csrfToken = new DefaultCsrfToken("X-CSRF-TOKEN", "_csrf", "BaseSpringSpec_CSRFTOKEN");
|
||||
String csrfAttributeName = HttpSessionCsrfTokenRepository.class.getName().concat(".CSRF_TOKEN");
|
||||
// @formatter:off
|
||||
this.mvc.perform(get("/login?logout").sessionAttr(csrfAttributeName, csrfToken))
|
||||
.andExpect(content().string("<!DOCTYPE html>\n" + "<html lang=\"en\">\n" + " <head>\n"
|
||||
.andExpect(content().string("<!DOCTYPE html>\n"
|
||||
+ "<html lang=\"en\">\n"
|
||||
+ " <head>\n"
|
||||
+ " <meta charset=\"utf-8\">\n"
|
||||
+ " <meta name=\"viewport\" content=\"width=device-width, initial-scale=1, shrink-to-fit=no\">\n"
|
||||
+ " <meta name=\"description\" content=\"\">\n" + " <meta name=\"author\" content=\"\">\n"
|
||||
+ " <meta name=\"description\" content=\"\">\n"
|
||||
+ " <meta name=\"author\" content=\"\">\n"
|
||||
+ " <title>Please sign in</title>\n"
|
||||
+ " <link href=\"https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-beta/css/bootstrap.min.css\" rel=\"stylesheet\" integrity=\"sha384-/Y6pD6FV/Vv2HJnA6t+vslU6fwYXjCFtcEpHbNJ0lyAFsXTsjBbfaDjzALeQsN6M\" crossorigin=\"anonymous\">\n"
|
||||
+ " <link href=\"https://getbootstrap.com/docs/4.0/examples/signin/signin.css\" rel=\"stylesheet\" crossorigin=\"anonymous\"/>\n"
|
||||
+ " </head>\n" + " <body>\n" + " <div class=\"container\">\n"
|
||||
+ " </head>\n"
|
||||
+ " <body>\n"
|
||||
+ " <div class=\"container\">\n"
|
||||
+ " <form class=\"form-signin\" method=\"post\" action=\"/login\">\n"
|
||||
+ " <h2 class=\"form-signin-heading\">Please sign in</h2>\n"
|
||||
+ "<div class=\"alert alert-success\" role=\"alert\">You have been signed out</div> <p>\n"
|
||||
+ " <label for=\"username\" class=\"sr-only\">Username</label>\n"
|
||||
+ " <input type=\"text\" id=\"username\" name=\"username\" class=\"form-control\" placeholder=\"Username\" required autofocus>\n"
|
||||
+ " </p>\n" + " <p>\n"
|
||||
+ " </p>\n"
|
||||
+ " <p>\n"
|
||||
+ " <label for=\"password\" class=\"sr-only\">Password</label>\n"
|
||||
+ " <input type=\"password\" id=\"password\" name=\"password\" class=\"form-control\" placeholder=\"Password\" required>\n"
|
||||
+ " </p>\n" + "<input name=\"" + csrfToken.getParameterName()
|
||||
+ "\" type=\"hidden\" value=\"" + csrfToken.getToken() + "\" />\n"
|
||||
+ " </p>\n"
|
||||
+ "<input name=\"" + csrfToken.getParameterName() + "\" type=\"hidden\" value=\"" + csrfToken.getToken() + "\" />\n"
|
||||
+ " <button class=\"btn btn-lg btn-primary btn-block\" type=\"submit\">Sign in</button>\n"
|
||||
+ " </form>\n" + "</div>\n" + "</body></html>"));
|
||||
+ " </form>\n"
|
||||
+ "</div>\n"
|
||||
+ "</body></html>"));
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -186,28 +222,38 @@ public class DefaultLoginPageConfigurerTests {
|
|||
this.spring.register(DefaultLoginPageWithRememberMeConfig.class).autowire();
|
||||
CsrfToken csrfToken = new DefaultCsrfToken("X-CSRF-TOKEN", "_csrf", "BaseSpringSpec_CSRFTOKEN");
|
||||
String csrfAttributeName = HttpSessionCsrfTokenRepository.class.getName().concat(".CSRF_TOKEN");
|
||||
// @formatter:off
|
||||
this.mvc.perform(get("/login").sessionAttr(csrfAttributeName, csrfToken))
|
||||
.andExpect(content().string("<!DOCTYPE html>\n" + "<html lang=\"en\">\n" + " <head>\n"
|
||||
.andExpect(content().string("<!DOCTYPE html>\n"
|
||||
+ "<html lang=\"en\">\n"
|
||||
+ " <head>\n"
|
||||
+ " <meta charset=\"utf-8\">\n"
|
||||
+ " <meta name=\"viewport\" content=\"width=device-width, initial-scale=1, shrink-to-fit=no\">\n"
|
||||
+ " <meta name=\"description\" content=\"\">\n" + " <meta name=\"author\" content=\"\">\n"
|
||||
+ " <meta name=\"description\" content=\"\">\n"
|
||||
+ " <meta name=\"author\" content=\"\">\n"
|
||||
+ " <title>Please sign in</title>\n"
|
||||
+ " <link href=\"https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-beta/css/bootstrap.min.css\" rel=\"stylesheet\" integrity=\"sha384-/Y6pD6FV/Vv2HJnA6t+vslU6fwYXjCFtcEpHbNJ0lyAFsXTsjBbfaDjzALeQsN6M\" crossorigin=\"anonymous\">\n"
|
||||
+ " <link href=\"https://getbootstrap.com/docs/4.0/examples/signin/signin.css\" rel=\"stylesheet\" crossorigin=\"anonymous\"/>\n"
|
||||
+ " </head>\n" + " <body>\n" + " <div class=\"container\">\n"
|
||||
+ " </head>\n"
|
||||
+ " <body>\n"
|
||||
+ " <div class=\"container\">\n"
|
||||
+ " <form class=\"form-signin\" method=\"post\" action=\"/login\">\n"
|
||||
+ " <h2 class=\"form-signin-heading\">Please sign in</h2>\n" + " <p>\n"
|
||||
+ " <h2 class=\"form-signin-heading\">Please sign in</h2>\n"
|
||||
+ " <p>\n"
|
||||
+ " <label for=\"username\" class=\"sr-only\">Username</label>\n"
|
||||
+ " <input type=\"text\" id=\"username\" name=\"username\" class=\"form-control\" placeholder=\"Username\" required autofocus>\n"
|
||||
+ " </p>\n" + " <p>\n"
|
||||
+ " </p>\n"
|
||||
+ " <p>\n"
|
||||
+ " <label for=\"password\" class=\"sr-only\">Password</label>\n"
|
||||
+ " <input type=\"password\" id=\"password\" name=\"password\" class=\"form-control\" placeholder=\"Password\" required>\n"
|
||||
+ " </p>\n"
|
||||
+ "<p><input type='checkbox' name='remember-me'/> Remember me on this computer.</p>\n"
|
||||
+ "<input name=\"" + csrfToken.getParameterName() + "\" type=\"hidden\" value=\""
|
||||
+ csrfToken.getToken() + "\" />\n"
|
||||
+ "<input name=\"" + csrfToken.getParameterName() + "\" type=\"hidden\" value=\"" + csrfToken.getToken() + "\" />\n"
|
||||
+ " <button class=\"btn btn-lg btn-primary btn-block\" type=\"submit\">Sign in</button>\n"
|
||||
+ " </form>\n" + "</div>\n" + "</body></html>"));
|
||||
+ " </form>\n"
|
||||
+ "</div>\n"
|
||||
+ "</body></html>"));
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -215,23 +261,33 @@ public class DefaultLoginPageConfigurerTests {
|
|||
this.spring.register(DefaultLoginPageWithOpenIDConfig.class).autowire();
|
||||
CsrfToken csrfToken = new DefaultCsrfToken("X-CSRF-TOKEN", "_csrf", "BaseSpringSpec_CSRFTOKEN");
|
||||
String csrfAttributeName = HttpSessionCsrfTokenRepository.class.getName().concat(".CSRF_TOKEN");
|
||||
// @formatter:off
|
||||
this.mvc.perform(get("/login").sessionAttr(csrfAttributeName, csrfToken))
|
||||
.andExpect(content().string("<!DOCTYPE html>\n" + "<html lang=\"en\">\n" + " <head>\n"
|
||||
.andExpect(content().string("<!DOCTYPE html>\n"
|
||||
+ "<html lang=\"en\">\n"
|
||||
+ " <head>\n"
|
||||
+ " <meta charset=\"utf-8\">\n"
|
||||
+ " <meta name=\"viewport\" content=\"width=device-width, initial-scale=1, shrink-to-fit=no\">\n"
|
||||
+ " <meta name=\"description\" content=\"\">\n" + " <meta name=\"author\" content=\"\">\n"
|
||||
+ " <meta name=\"description\" content=\"\">\n"
|
||||
+ " <meta name=\"author\" content=\"\">\n"
|
||||
+ " <title>Please sign in</title>\n"
|
||||
+ " <link href=\"https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-beta/css/bootstrap.min.css\" rel=\"stylesheet\" integrity=\"sha384-/Y6pD6FV/Vv2HJnA6t+vslU6fwYXjCFtcEpHbNJ0lyAFsXTsjBbfaDjzALeQsN6M\" crossorigin=\"anonymous\">\n"
|
||||
+ " <link href=\"https://getbootstrap.com/docs/4.0/examples/signin/signin.css\" rel=\"stylesheet\" crossorigin=\"anonymous\"/>\n"
|
||||
+ " </head>\n" + " <body>\n" + " <div class=\"container\">\n"
|
||||
+ " </head>\n"
|
||||
+ " <body>\n"
|
||||
+ " <div class=\"container\">\n"
|
||||
+ " <form name=\"oidf\" class=\"form-signin\" method=\"post\" action=\"/login/openid\">\n"
|
||||
+ " <h2 class=\"form-signin-heading\">Login with OpenID Identity</h2>\n"
|
||||
+ " <p>\n" + " <label for=\"username\" class=\"sr-only\">Identity</label>\n"
|
||||
+ " <p>\n"
|
||||
+ " <label for=\"username\" class=\"sr-only\">Identity</label>\n"
|
||||
+ " <input type=\"text\" id=\"username\" name=\"openid_identifier\" class=\"form-control\" placeholder=\"Username\" required autofocus>\n"
|
||||
+ " </p>\n" + "<input name=\"" + csrfToken.getParameterName()
|
||||
+ "\" type=\"hidden\" value=\"" + csrfToken.getToken() + "\" />\n"
|
||||
+ " </p>\n"
|
||||
+ "<input name=\"" + csrfToken.getParameterName() + "\" type=\"hidden\" value=\"" + csrfToken.getToken() + "\" />\n"
|
||||
+ " <button class=\"btn btn-lg btn-primary btn-block\" type=\"submit\">Sign in</button>\n"
|
||||
+ " </form>\n" + "</div>\n" + "</body></html>"));
|
||||
+ " </form>\n"
|
||||
+ "</div>\n"
|
||||
+ "</body></html>"));
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -240,37 +296,45 @@ public class DefaultLoginPageConfigurerTests {
|
|||
CsrfToken csrfToken = new DefaultCsrfToken("X-CSRF-TOKEN", "_csrf", "BaseSpringSpec_CSRFTOKEN");
|
||||
String csrfAttributeName = HttpSessionCsrfTokenRepository.class.getName().concat(".CSRF_TOKEN");
|
||||
this.mvc.perform(get("/login").sessionAttr(csrfAttributeName, csrfToken))
|
||||
.andExpect(content().string("<!DOCTYPE html>\n" + "<html lang=\"en\">\n" + " <head>\n"
|
||||
.andExpect(content().string("<!DOCTYPE html>\n"
|
||||
+ "<html lang=\"en\">\n"
|
||||
+ " <head>\n"
|
||||
+ " <meta charset=\"utf-8\">\n"
|
||||
+ " <meta name=\"viewport\" content=\"width=device-width, initial-scale=1, shrink-to-fit=no\">\n"
|
||||
+ " <meta name=\"description\" content=\"\">\n" + " <meta name=\"author\" content=\"\">\n"
|
||||
+ " <meta name=\"description\" content=\"\">\n"
|
||||
+ " <meta name=\"author\" content=\"\">\n"
|
||||
+ " <title>Please sign in</title>\n"
|
||||
+ " <link href=\"https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-beta/css/bootstrap.min.css\" rel=\"stylesheet\" integrity=\"sha384-/Y6pD6FV/Vv2HJnA6t+vslU6fwYXjCFtcEpHbNJ0lyAFsXTsjBbfaDjzALeQsN6M\" crossorigin=\"anonymous\">\n"
|
||||
+ " <link href=\"https://getbootstrap.com/docs/4.0/examples/signin/signin.css\" rel=\"stylesheet\" crossorigin=\"anonymous\"/>\n"
|
||||
+ " </head>\n" + " <body>\n" + " <div class=\"container\">\n"
|
||||
+ " </head>\n"
|
||||
+ " <body>\n"
|
||||
+ " <div class=\"container\">\n"
|
||||
+ " <form class=\"form-signin\" method=\"post\" action=\"/login\">\n"
|
||||
+ " <h2 class=\"form-signin-heading\">Please sign in</h2>\n" + " <p>\n"
|
||||
+ " <h2 class=\"form-signin-heading\">Please sign in</h2>\n"
|
||||
+ " <p>\n"
|
||||
+ " <label for=\"username\" class=\"sr-only\">Username</label>\n"
|
||||
+ " <input type=\"text\" id=\"username\" name=\"username\" class=\"form-control\" placeholder=\"Username\" required autofocus>\n"
|
||||
+ " </p>\n" + " <p>\n"
|
||||
+ " </p>\n"
|
||||
+ " <p>\n"
|
||||
+ " <label for=\"password\" class=\"sr-only\">Password</label>\n"
|
||||
+ " <input type=\"password\" id=\"password\" name=\"password\" class=\"form-control\" placeholder=\"Password\" required>\n"
|
||||
+ " </p>\n"
|
||||
+ "<p><input type='checkbox' name='remember-me'/> Remember me on this computer.</p>\n"
|
||||
+ "<input name=\"" + csrfToken.getParameterName() + "\" type=\"hidden\" value=\""
|
||||
+ csrfToken.getToken() + "\" />\n"
|
||||
+ "<input name=\"" + csrfToken.getParameterName() + "\" type=\"hidden\" value=\"" + csrfToken.getToken() + "\" />\n"
|
||||
+ " <button class=\"btn btn-lg btn-primary btn-block\" type=\"submit\">Sign in</button>\n"
|
||||
+ " </form>\n"
|
||||
+ " <form name=\"oidf\" class=\"form-signin\" method=\"post\" action=\"/login/openid\">\n"
|
||||
+ " <h2 class=\"form-signin-heading\">Login with OpenID Identity</h2>\n"
|
||||
+ " <p>\n" + " <label for=\"username\" class=\"sr-only\">Identity</label>\n"
|
||||
+ " <p>\n"
|
||||
+ " <label for=\"username\" class=\"sr-only\">Identity</label>\n"
|
||||
+ " <input type=\"text\" id=\"username\" name=\"openid_identifier\" class=\"form-control\" placeholder=\"Username\" required autofocus>\n"
|
||||
+ " </p>\n"
|
||||
+ "<p><input type='checkbox' name='remember-me'/> Remember me on this computer.</p>\n"
|
||||
+ "<input name=\"" + csrfToken.getParameterName() + "\" type=\"hidden\" value=\""
|
||||
+ csrfToken.getToken() + "\" />\n"
|
||||
+ "<input name=\"" + csrfToken.getParameterName() + "\" type=\"hidden\" value=\"" + csrfToken.getToken() + "\" />\n"
|
||||
+ " <button class=\"btn btn-lg btn-primary btn-block\" type=\"submit\">Sign in</button>\n"
|
||||
+ " </form>\n" + "</div>\n" + "</body></html>"));
|
||||
+ " </form>\n"
|
||||
+ "</div>\n"
|
||||
+ "</body></html>"));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
|
@ -322,8 +322,14 @@ public class ExceptionHandlingConfigurerTests {
|
|||
@Override
|
||||
protected void configure(HttpSecurity http) throws Exception {
|
||||
// @formatter:on
|
||||
http.authorizeRequests().anyRequest().authenticated().and().exceptionHandling()
|
||||
.authenticationEntryPoint(AEP).and().exceptionHandling();
|
||||
http
|
||||
.authorizeRequests()
|
||||
.anyRequest().authenticated()
|
||||
.and()
|
||||
.exceptionHandling()
|
||||
.authenticationEntryPoint(AEP)
|
||||
.and()
|
||||
.exceptionHandling();
|
||||
// @formatter:off
|
||||
}
|
||||
}
|
||||
|
|
|
@ -51,6 +51,7 @@ import org.springframework.security.web.access.expression.WebExpressionVoter;
|
|||
import org.springframework.security.web.access.expression.WebSecurityExpressionRoot;
|
||||
import org.springframework.security.web.access.intercept.FilterSecurityInterceptor;
|
||||
import org.springframework.test.web.servlet.MockMvc;
|
||||
import org.springframework.test.web.servlet.request.MockHttpServletRequestBuilder;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
|
@ -113,16 +114,24 @@ public class ExpressionUrlAuthorizationConfigurerTests {
|
|||
@Test
|
||||
public void getWhenHasAnyAuthorityRoleUserConfiguredAndAuthorityIsRoleUserThenRespondsWithOk() throws Exception {
|
||||
this.spring.register(RoleUserAnyAuthorityConfig.class, BasicController.class).autowire();
|
||||
this.mvc.perform(get("/").with(user("user").authorities(new SimpleGrantedAuthority("ROLE_USER"))))
|
||||
.andExpect(status().isOk());
|
||||
// @formatter:off
|
||||
MockHttpServletRequestBuilder requestWithUser = get("/")
|
||||
.with(user("user")
|
||||
.authorities(new SimpleGrantedAuthority("ROLE_USER")));
|
||||
// @formatter:on
|
||||
this.mvc.perform(requestWithUser).andExpect(status().isOk());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getWhenHasAnyAuthorityRoleUserConfiguredAndAuthorityIsRoleAdminThenRespondsWithForbidden()
|
||||
throws Exception {
|
||||
this.spring.register(RoleUserAnyAuthorityConfig.class, BasicController.class).autowire();
|
||||
this.mvc.perform(get("/").with(user("user").authorities(new SimpleGrantedAuthority("ROLE_ADMIN"))))
|
||||
.andExpect(status().isForbidden());
|
||||
// @formatter:off
|
||||
MockHttpServletRequestBuilder requestWithAdmin = get("/")
|
||||
.with(user("user")
|
||||
.authorities(new SimpleGrantedAuthority("ROLE_ADMIN")));
|
||||
// @formatter:on
|
||||
this.mvc.perform(requestWithAdmin).andExpect(status().isForbidden());
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -134,16 +143,24 @@ public class ExpressionUrlAuthorizationConfigurerTests {
|
|||
@Test
|
||||
public void getWhenHasAuthorityRoleUserConfiguredAndAuthorityIsRoleUserThenRespondsWithOk() throws Exception {
|
||||
this.spring.register(RoleUserAuthorityConfig.class, BasicController.class).autowire();
|
||||
this.mvc.perform(get("/").with(user("user").authorities(new SimpleGrantedAuthority("ROLE_USER"))))
|
||||
.andExpect(status().isOk());
|
||||
// @formatter:off
|
||||
MockHttpServletRequestBuilder requestWithUser = get("/")
|
||||
.with(user("user")
|
||||
.authorities(new SimpleGrantedAuthority("ROLE_USER")));
|
||||
// @formatter:on
|
||||
this.mvc.perform(requestWithUser).andExpect(status().isOk());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getWhenHasAuthorityRoleUserConfiguredAndAuthorityIsRoleAdminThenRespondsWithForbidden()
|
||||
throws Exception {
|
||||
this.spring.register(RoleUserAuthorityConfig.class, BasicController.class).autowire();
|
||||
this.mvc.perform(get("/").with(user("user").authorities(new SimpleGrantedAuthority("ROLE_ADMIN"))))
|
||||
.andExpect(status().isForbidden());
|
||||
// @formatter:off
|
||||
MockHttpServletRequestBuilder requestWithAdmin = get("/")
|
||||
.with(user("user")
|
||||
.authorities(new SimpleGrantedAuthority("ROLE_ADMIN")));
|
||||
// @formatter:on
|
||||
this.mvc.perform(requestWithAdmin).andExpect(status().isForbidden());
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -155,22 +172,35 @@ public class ExpressionUrlAuthorizationConfigurerTests {
|
|||
@Test
|
||||
public void getWhenAuthorityRoleUserOrAdminRequiredAndAuthorityIsRoleUserThenRespondsWithOk() throws Exception {
|
||||
this.spring.register(RoleUserOrRoleAdminAuthorityConfig.class, BasicController.class).autowire();
|
||||
this.mvc.perform(get("/").with(user("user").authorities(new SimpleGrantedAuthority("ROLE_USER"))))
|
||||
.andExpect(status().isOk());
|
||||
// @formatter:off
|
||||
MockHttpServletRequestBuilder requestWithUser = get("/")
|
||||
.with(user("user")
|
||||
.authorities(new SimpleGrantedAuthority("ROLE_USER")));
|
||||
// @formatter:on
|
||||
this.mvc.perform(requestWithUser).andExpect(status().isOk());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getWhenAuthorityRoleUserOrAdminRequiredAndAuthorityIsRoleAdminThenRespondsWithOk() throws Exception {
|
||||
this.spring.register(RoleUserOrRoleAdminAuthorityConfig.class, BasicController.class).autowire();
|
||||
this.mvc.perform(get("/").with(user("user").authorities(new SimpleGrantedAuthority("ROLE_ADMIN"))))
|
||||
.andExpect(status().isOk());
|
||||
// @formatter:off
|
||||
MockHttpServletRequestBuilder requestWithUser = get("/")
|
||||
.with(user("user")
|
||||
.authorities(new SimpleGrantedAuthority("ROLE_ADMIN")));
|
||||
// @formatter:on
|
||||
this.mvc.perform(requestWithUser).andExpect(status().isOk());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getWhenAuthorityRoleUserOrAdminRequiredAndAuthorityIsRoleOtherThenRespondsWithForbidden()
|
||||
throws Exception {
|
||||
this.spring.register(RoleUserOrRoleAdminAuthorityConfig.class, BasicController.class).autowire();
|
||||
this.mvc.perform(get("/").with(user("user").authorities(new SimpleGrantedAuthority("ROLE_OTHER"))))
|
||||
// @formatter:off
|
||||
MockHttpServletRequestBuilder requestWithUser = get("/")
|
||||
.with(user("user")
|
||||
.authorities(new SimpleGrantedAuthority("ROLE_OTHER")));
|
||||
// @formatter:on
|
||||
this.mvc.perform(requestWithUser)
|
||||
.andExpect(status().isForbidden());
|
||||
}
|
||||
|
||||
|
@ -183,31 +213,56 @@ public class ExpressionUrlAuthorizationConfigurerTests {
|
|||
@Test
|
||||
public void getWhenHasAnyRoleUserConfiguredAndRoleIsUserThenRespondsWithOk() throws Exception {
|
||||
this.spring.register(RoleUserConfig.class, BasicController.class).autowire();
|
||||
this.mvc.perform(get("/").with(user("user").roles("USER"))).andExpect(status().isOk());
|
||||
// @formatter:off
|
||||
MockHttpServletRequestBuilder requestWithUser = get("/")
|
||||
.with(user("user")
|
||||
.roles("USER"));
|
||||
// @formatter:on
|
||||
this.mvc.perform(requestWithUser).andExpect(status().isOk());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getWhenHasAnyRoleUserConfiguredAndRoleIsAdminThenRespondsWithForbidden() throws Exception {
|
||||
this.spring.register(RoleUserConfig.class, BasicController.class).autowire();
|
||||
this.mvc.perform(get("/").with(user("user").roles("ADMIN"))).andExpect(status().isForbidden());
|
||||
// @formatter:off
|
||||
MockHttpServletRequestBuilder requestWithAdmin = get("/")
|
||||
.with(user("user")
|
||||
.roles("ADMIN"));
|
||||
// @formatter:on
|
||||
this.mvc.perform(requestWithAdmin).andExpect(status().isForbidden());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getWhenRoleUserOrAdminConfiguredAndRoleIsUserThenRespondsWithOk() throws Exception {
|
||||
this.spring.register(RoleUserOrAdminConfig.class, BasicController.class).autowire();
|
||||
this.mvc.perform(get("/").with(user("user").roles("USER"))).andExpect(status().isOk());
|
||||
// @formatter:off
|
||||
MockHttpServletRequestBuilder requestWithUser = get("/")
|
||||
.with(user("user")
|
||||
.roles("USER"));
|
||||
// @formatter:on
|
||||
this.mvc.perform(requestWithUser).andExpect(status().isOk());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getWhenRoleUserOrAdminConfiguredAndRoleIsAdminThenRespondsWithOk() throws Exception {
|
||||
this.spring.register(RoleUserOrAdminConfig.class, BasicController.class).autowire();
|
||||
this.mvc.perform(get("/").with(user("user").roles("ADMIN"))).andExpect(status().isOk());
|
||||
// @formatter:off
|
||||
MockHttpServletRequestBuilder requestWithAdmin = get("/")
|
||||
.with(user("user")
|
||||
.roles("ADMIN"));
|
||||
// @formatter:on
|
||||
this.mvc.perform(requestWithAdmin).andExpect(status().isOk());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getWhenRoleUserOrAdminConfiguredAndRoleIsOtherThenRespondsWithForbidden() throws Exception {
|
||||
this.spring.register(RoleUserOrAdminConfig.class, BasicController.class).autowire();
|
||||
this.mvc.perform(get("/").with(user("user").roles("OTHER"))).andExpect(status().isForbidden());
|
||||
//<editor-fold desc="Description">
|
||||
MockHttpServletRequestBuilder requestWithRoleOther = get("/")
|
||||
.with(user("user")
|
||||
.roles("OTHER"));
|
||||
//</editor-fold>
|
||||
this.mvc.perform(requestWithRoleOther).andExpect(status().isForbidden());
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -237,7 +292,8 @@ public class ExpressionUrlAuthorizationConfigurerTests {
|
|||
@Test
|
||||
public void getWhenAnonymousConfiguredAndLoggedInUserThenRespondsWithForbidden() throws Exception {
|
||||
this.spring.register(AnonymousConfig.class, BasicController.class).autowire();
|
||||
this.mvc.perform(get("/").with(user("user"))).andExpect(status().isForbidden());
|
||||
MockHttpServletRequestBuilder requestWithUser = get("/").with(user("user"));
|
||||
this.mvc.perform(requestWithUser).andExpect(status().isForbidden());
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -249,9 +305,9 @@ public class ExpressionUrlAuthorizationConfigurerTests {
|
|||
@Test
|
||||
public void getWhenRememberMeConfiguredAndRememberMeTokenThenRespondsWithOk() throws Exception {
|
||||
this.spring.register(RememberMeConfig.class, BasicController.class).autowire();
|
||||
this.mvc.perform(get("/").with(authentication(
|
||||
new RememberMeAuthenticationToken("key", "user", AuthorityUtils.createAuthorityList("ROLE_USER")))))
|
||||
.andExpect(status().isOk());
|
||||
RememberMeAuthenticationToken rememberme = new RememberMeAuthenticationToken("key", "user", AuthorityUtils.createAuthorityList("ROLE_USER"));
|
||||
MockHttpServletRequestBuilder requestWithRememberme = get("/").with(authentication(rememberme));
|
||||
this.mvc.perform(requestWithRememberme).andExpect(status().isOk());
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -263,7 +319,8 @@ public class ExpressionUrlAuthorizationConfigurerTests {
|
|||
@Test
|
||||
public void getWheDenyAllConfiguredAndUserLoggedInThenRespondsWithForbidden() throws Exception {
|
||||
this.spring.register(DenyAllConfig.class, BasicController.class).autowire();
|
||||
this.mvc.perform(get("/").with(user("user").roles("USER"))).andExpect(status().isForbidden());
|
||||
MockHttpServletRequestBuilder requestWithUser = get("/").with(user("user").roles("USER"));
|
||||
this.mvc.perform(requestWithUser).andExpect(status().isForbidden());
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -275,23 +332,24 @@ public class ExpressionUrlAuthorizationConfigurerTests {
|
|||
@Test
|
||||
public void getWhenNotDenyAllConfiguredAndRememberMeTokenThenRespondsWithOk() throws Exception {
|
||||
this.spring.register(NotDenyAllConfig.class, BasicController.class).autowire();
|
||||
this.mvc.perform(get("/").with(authentication(
|
||||
new RememberMeAuthenticationToken("key", "user", AuthorityUtils.createAuthorityList("ROLE_USER")))))
|
||||
.andExpect(status().isOk());
|
||||
RememberMeAuthenticationToken rememberme = new RememberMeAuthenticationToken("key", "user", AuthorityUtils.createAuthorityList("ROLE_USER"));
|
||||
MockHttpServletRequestBuilder requestWithRememberme = get("/").with(authentication(rememberme));
|
||||
this.mvc.perform(requestWithRememberme).andExpect(status().isOk());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getWhenFullyAuthenticatedConfiguredAndRememberMeTokenThenRespondsWithUnauthorized() throws Exception {
|
||||
this.spring.register(FullyAuthenticatedConfig.class, BasicController.class).autowire();
|
||||
this.mvc.perform(get("/").with(authentication(
|
||||
new RememberMeAuthenticationToken("key", "user", AuthorityUtils.createAuthorityList("ROLE_USER")))))
|
||||
.andExpect(status().isUnauthorized());
|
||||
RememberMeAuthenticationToken rememberme = new RememberMeAuthenticationToken("key", "user", AuthorityUtils.createAuthorityList("ROLE_USER"));
|
||||
MockHttpServletRequestBuilder requestWithRememberme = get("/").with(authentication(rememberme));
|
||||
this.mvc.perform(requestWithRememberme).andExpect(status().isUnauthorized());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getWhenFullyAuthenticatedConfiguredAndUserThenRespondsWithOk() throws Exception {
|
||||
this.spring.register(FullyAuthenticatedConfig.class, BasicController.class).autowire();
|
||||
this.mvc.perform(get("/").with(user("user").roles("USER"))).andExpect(status().isOk());
|
||||
MockHttpServletRequestBuilder requestWithUser = get("/").with(user("user").roles("USER"));
|
||||
this.mvc.perform(requestWithUser).andExpect(status().isOk());
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -303,19 +361,26 @@ public class ExpressionUrlAuthorizationConfigurerTests {
|
|||
@Test
|
||||
public void postWhenAccessRoleUserOrGetRequestConfiguredAndRoleUserThenRespondsWithOk() throws Exception {
|
||||
this.spring.register(AccessConfig.class, BasicController.class).autowire();
|
||||
this.mvc.perform(post("/").with(csrf()).with(user("user").roles("USER"))).andExpect(status().isOk());
|
||||
// @formatter:off
|
||||
MockHttpServletRequestBuilder requestWithUser = post("/")
|
||||
.with(csrf())
|
||||
.with(user("user").roles("USER"));
|
||||
// @formatter:on
|
||||
this.mvc.perform(requestWithUser).andExpect(status().isOk());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void postWhenAccessRoleUserOrGetRequestConfiguredThenRespondsWithUnauthorized() throws Exception {
|
||||
this.spring.register(AccessConfig.class, BasicController.class).autowire();
|
||||
this.mvc.perform(post("/").with(csrf())).andExpect(status().isUnauthorized());
|
||||
MockHttpServletRequestBuilder requestWithCsrf = post("/").with(csrf());
|
||||
this.mvc.perform(requestWithCsrf).andExpect(status().isUnauthorized());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void authorizeRequestsWhenInvokedTwiceThenUsesOriginalConfiguration() throws Exception {
|
||||
this.spring.register(InvokeTwiceDoesNotResetConfig.class, BasicController.class).autowire();
|
||||
this.mvc.perform(post("/").with(csrf())).andExpect(status().isUnauthorized());
|
||||
MockHttpServletRequestBuilder requestWithCsrf = post("/").with(csrf());
|
||||
this.mvc.perform(requestWithCsrf).andExpect(status().isUnauthorized());
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -334,50 +399,58 @@ public class ExpressionUrlAuthorizationConfigurerTests {
|
|||
@Test
|
||||
public void getWhenPermissionCheckAndRoleDoesNotMatchThenRespondsWithForbidden() throws Exception {
|
||||
this.spring.register(UseBeansInExpressions.class, WildcardController.class).autowire();
|
||||
this.mvc.perform(get("/admin").with(user("user").roles("USER"))).andExpect(status().isForbidden());
|
||||
MockHttpServletRequestBuilder requestWithUser = get("/admin").with(user("user").roles("USER"));
|
||||
this.mvc.perform(requestWithUser).andExpect(status().isForbidden());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getWhenPermissionCheckAndRoleMatchesThenRespondsWithOk() throws Exception {
|
||||
this.spring.register(UseBeansInExpressions.class, WildcardController.class).autowire();
|
||||
this.mvc.perform(get("/user").with(user("user").roles("USER"))).andExpect(status().isOk());
|
||||
MockHttpServletRequestBuilder requestWithUser = get("/user").with(user("user").roles("USER"));
|
||||
this.mvc.perform(requestWithUser).andExpect(status().isOk());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getWhenPermissionCheckAndAuthenticationNameMatchesThenRespondsWithOk() throws Exception {
|
||||
this.spring.register(UseBeansInExpressions.class, WildcardController.class).autowire();
|
||||
this.mvc.perform(get("/allow").with(user("user").roles("USER"))).andExpect(status().isOk());
|
||||
MockHttpServletRequestBuilder requestWithUser = get("/allow").with(user("user").roles("USER"));
|
||||
this.mvc.perform(requestWithUser).andExpect(status().isOk());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getWhenPermissionCheckAndAuthenticationNameDoesNotMatchThenRespondsWithForbidden() throws Exception {
|
||||
this.spring.register(UseBeansInExpressions.class, WildcardController.class).autowire();
|
||||
this.mvc.perform(get("/deny").with(user("user").roles("USER"))).andExpect(status().isForbidden());
|
||||
MockHttpServletRequestBuilder requestWithUser = get("/deny").with(user("user").roles("USER"));
|
||||
this.mvc.perform(requestWithUser).andExpect(status().isForbidden());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getWhenCustomExpressionHandlerAndRoleDoesNotMatchThenRespondsWithForbidden() throws Exception {
|
||||
this.spring.register(CustomExpressionRootConfig.class, WildcardController.class).autowire();
|
||||
this.mvc.perform(get("/admin").with(user("user").roles("USER"))).andExpect(status().isForbidden());
|
||||
MockHttpServletRequestBuilder requestWithUser = get("/admin").with(user("user").roles("USER"));
|
||||
this.mvc.perform(requestWithUser).andExpect(status().isForbidden());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getWhenCustomExpressionHandlerAndRoleMatchesThenRespondsWithOk() throws Exception {
|
||||
this.spring.register(CustomExpressionRootConfig.class, WildcardController.class).autowire();
|
||||
this.mvc.perform(get("/user").with(user("user").roles("USER"))).andExpect(status().isOk());
|
||||
MockHttpServletRequestBuilder requestWithUser = get("/user").with(user("user").roles("USER"));
|
||||
this.mvc.perform(requestWithUser).andExpect(status().isOk());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getWhenCustomExpressionHandlerAndAuthenticationNameMatchesThenRespondsWithOk() throws Exception {
|
||||
this.spring.register(CustomExpressionRootConfig.class, WildcardController.class).autowire();
|
||||
this.mvc.perform(get("/allow").with(user("user").roles("USER"))).andExpect(status().isOk());
|
||||
MockHttpServletRequestBuilder requestWithUser = get("/allow").with(user("user").roles("USER"));
|
||||
this.mvc.perform(requestWithUser).andExpect(status().isOk());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getWhenCustomExpressionHandlerAndAuthenticationNameDoesNotMatchThenRespondsWithForbidden()
|
||||
throws Exception {
|
||||
this.spring.register(CustomExpressionRootConfig.class, WildcardController.class).autowire();
|
||||
this.mvc.perform(get("/deny").with(user("user").roles("USER"))).andExpect(status().isForbidden());
|
||||
MockHttpServletRequestBuilder requestWithUser = get("/deny").with(user("user").roles("USER"));
|
||||
this.mvc.perform(requestWithUser).andExpect(status().isForbidden());
|
||||
}
|
||||
|
||||
// SEC-3011
|
||||
|
@ -418,13 +491,15 @@ public class ExpressionUrlAuthorizationConfigurerTests {
|
|||
@Test
|
||||
public void getWhenRegisteringRoleHierarchyAndRelatedRoleAllowedThenRespondsWithOk() throws Exception {
|
||||
this.spring.register(RoleHierarchyConfig.class, WildcardController.class).autowire();
|
||||
this.mvc.perform(get("/allow").with(user("user").roles("USER"))).andExpect(status().isOk());
|
||||
MockHttpServletRequestBuilder requestWithUser = get("/allow").with(user("user").roles("USER"));
|
||||
this.mvc.perform(requestWithUser).andExpect(status().isOk());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getWhenRegisteringRoleHierarchyAndNoRelatedRolesAllowedThenRespondsWithForbidden() throws Exception {
|
||||
this.spring.register(RoleHierarchyConfig.class, WildcardController.class).autowire();
|
||||
this.mvc.perform(get("/deny").with(user("user").roles("USER"))).andExpect(status().isForbidden());
|
||||
MockHttpServletRequestBuilder requestWithUser = get("/deny").with(user("user").roles("USER"));
|
||||
this.mvc.perform(requestWithUser).andExpect(status().isForbidden());
|
||||
}
|
||||
|
||||
@EnableWebSecurity
|
||||
|
|
|
@ -30,6 +30,7 @@ import org.springframework.security.config.annotation.web.configuration.WebSecur
|
|||
import org.springframework.security.config.test.SpringTestRule;
|
||||
import org.springframework.security.config.users.AuthenticationTestConfiguration;
|
||||
import org.springframework.security.core.userdetails.PasswordEncodedUser;
|
||||
import org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestBuilders;
|
||||
import org.springframework.security.web.PortMapper;
|
||||
import org.springframework.security.web.access.ExceptionTranslationFilter;
|
||||
import org.springframework.security.web.authentication.AuthenticationFailureHandler;
|
||||
|
@ -85,21 +86,34 @@ public class FormLoginConfigurerTests {
|
|||
@Test
|
||||
public void loginWhenFormLoginConfiguredThenHasDefaultUsernameAndPasswordParameterNames() throws Exception {
|
||||
this.spring.register(FormLoginConfig.class).autowire();
|
||||
this.mockMvc.perform(formLogin().user("username", "user").password("password", "password"))
|
||||
.andExpect(status().isFound()).andExpect(redirectedUrl("/"));
|
||||
// @formatter:off
|
||||
SecurityMockMvcRequestBuilders.FormLoginRequestBuilder loginRequest = formLogin()
|
||||
.user("username", "user")
|
||||
.password("password", "password");
|
||||
this.mockMvc.perform(loginRequest)
|
||||
.andExpect(status().isFound())
|
||||
.andExpect(redirectedUrl("/"));
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
public void loginWhenFormLoginConfiguredThenHasDefaultFailureUrl() throws Exception {
|
||||
this.spring.register(FormLoginConfig.class).autowire();
|
||||
this.mockMvc.perform(formLogin().user("invalid")).andExpect(status().isFound())
|
||||
// @formatter:off
|
||||
this.mockMvc.perform(formLogin().user("invalid"))
|
||||
.andExpect(status().isFound())
|
||||
.andExpect(redirectedUrl("/login?error"));
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
public void loginWhenFormLoginConfiguredThenHasDefaultSuccessUrl() throws Exception {
|
||||
this.spring.register(FormLoginConfig.class).autowire();
|
||||
this.mockMvc.perform(formLogin()).andExpect(status().isFound()).andExpect(redirectedUrl("/"));
|
||||
// @formatter:off
|
||||
this.mockMvc.perform(formLogin())
|
||||
.andExpect(status().isFound())
|
||||
.andExpect(redirectedUrl("/"));
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -117,28 +131,44 @@ public class FormLoginConfigurerTests {
|
|||
@Test
|
||||
public void requestProtectedWhenFormLoginConfiguredThenRedirectsToLogin() throws Exception {
|
||||
this.spring.register(FormLoginConfig.class).autowire();
|
||||
this.mockMvc.perform(get("/private")).andExpect(status().isFound())
|
||||
// @formatter:off
|
||||
this.mockMvc.perform(get("/private"))
|
||||
.andExpect(status().isFound())
|
||||
.andExpect(redirectedUrl("http://localhost/login"));
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
public void loginWhenFormLoginDefaultsInLambdaThenHasDefaultUsernameAndPasswordParameterNames() throws Exception {
|
||||
this.spring.register(FormLoginInLambdaConfig.class).autowire();
|
||||
this.mockMvc.perform(formLogin().user("username", "user").password("password", "password"))
|
||||
.andExpect(status().isFound()).andExpect(redirectedUrl("/"));
|
||||
// @formatter:off
|
||||
SecurityMockMvcRequestBuilders.FormLoginRequestBuilder loginRequest = formLogin()
|
||||
.user("username", "user")
|
||||
.password("password", "password");
|
||||
this.mockMvc.perform(loginRequest)
|
||||
.andExpect(status().isFound())
|
||||
.andExpect(redirectedUrl("/"));
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
public void loginWhenFormLoginDefaultsInLambdaThenHasDefaultFailureUrl() throws Exception {
|
||||
this.spring.register(FormLoginInLambdaConfig.class).autowire();
|
||||
this.mockMvc.perform(formLogin().user("invalid")).andExpect(status().isFound())
|
||||
// @formatter:off
|
||||
this.mockMvc.perform(formLogin().user("invalid"))
|
||||
.andExpect(status().isFound())
|
||||
.andExpect(redirectedUrl("/login?error"));
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
public void loginWhenFormLoginDefaultsInLambdaThenHasDefaultSuccessUrl() throws Exception {
|
||||
this.spring.register(FormLoginInLambdaConfig.class).autowire();
|
||||
this.mockMvc.perform(formLogin()).andExpect(status().isFound()).andExpect(redirectedUrl("/"));
|
||||
// @formatter:off
|
||||
this.mockMvc.perform(formLogin())
|
||||
.andExpect(status().isFound())
|
||||
.andExpect(redirectedUrl("/"));
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -156,27 +186,41 @@ public class FormLoginConfigurerTests {
|
|||
@Test
|
||||
public void requestProtectedWhenFormLoginDefaultsInLambdaThenRedirectsToLogin() throws Exception {
|
||||
this.spring.register(FormLoginInLambdaConfig.class).autowire();
|
||||
this.mockMvc.perform(get("/private")).andExpect(status().isFound())
|
||||
// @formatter:off
|
||||
this.mockMvc.perform(get("/private"))
|
||||
.andExpect(status().isFound())
|
||||
.andExpect(redirectedUrl("http://localhost/login"));
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getLoginPageWhenFormLoginPermitAllThenPermittedAndNoRedirect() throws Exception {
|
||||
this.spring.register(FormLoginConfigPermitAll.class).autowire();
|
||||
this.mockMvc.perform(get("/login")).andExpect(status().isOk()).andExpect(redirectedUrl(null));
|
||||
// @formatter:off
|
||||
this.mockMvc.perform(get("/login"))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(redirectedUrl(null));
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getLoginPageWithErrorQueryWhenFormLoginPermitAllThenPermittedAndNoRedirect() throws Exception {
|
||||
this.spring.register(FormLoginConfigPermitAll.class).autowire();
|
||||
this.mockMvc.perform(get("/login?error")).andExpect(status().isOk()).andExpect(redirectedUrl(null));
|
||||
// @formatter:off
|
||||
this.mockMvc.perform(get("/login?error"))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(redirectedUrl(null));
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
public void loginWhenFormLoginPermitAllAndInvalidUserThenRedirectsToLoginPageWithError() throws Exception {
|
||||
this.spring.register(FormLoginConfigPermitAll.class).autowire();
|
||||
this.mockMvc.perform(formLogin().user("invalid")).andExpect(status().isFound())
|
||||
// @formatter:off
|
||||
this.mockMvc.perform(formLogin().user("invalid"))
|
||||
.andExpect(status().isFound())
|
||||
.andExpect(redirectedUrl("/login?error"));
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -194,8 +238,12 @@ public class FormLoginConfigurerTests {
|
|||
@Test
|
||||
public void loginWhenCustomLoginPageAndInvalidUserThenRedirectsToCustomLoginPageWithError() throws Exception {
|
||||
this.spring.register(FormLoginDefaultsConfig.class).autowire();
|
||||
this.mockMvc.perform(formLogin("/authenticate").user("invalid")).andExpect(status().isFound())
|
||||
SecurityMockMvcRequestBuilders.FormLoginRequestBuilder request = formLogin("/authenticate").user("invalid");
|
||||
// @formatter:off
|
||||
this.mockMvc.perform(request)
|
||||
.andExpect(status().isFound())
|
||||
.andExpect(redirectedUrl("/authenticate?error"));
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -219,13 +267,21 @@ public class FormLoginConfigurerTests {
|
|||
@Test
|
||||
public void loginWhenCustomLoginProcessingUrlThenRedirectsToHome() throws Exception {
|
||||
this.spring.register(FormLoginLoginProcessingUrlConfig.class).autowire();
|
||||
this.mockMvc.perform(formLogin("/loginCheck")).andExpect(status().isFound()).andExpect(redirectedUrl("/"));
|
||||
// @formatter:off
|
||||
this.mockMvc.perform(formLogin("/loginCheck"))
|
||||
.andExpect(status().isFound())
|
||||
.andExpect(redirectedUrl("/"));
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
public void loginWhenCustomLoginProcessingUrlInLambdaThenRedirectsToHome() throws Exception {
|
||||
this.spring.register(FormLoginLoginProcessingUrlInLambdaConfig.class).autowire();
|
||||
this.mockMvc.perform(formLogin("/loginCheck")).andExpect(status().isFound()).andExpect(redirectedUrl("/"));
|
||||
// @formatter:off
|
||||
this.mockMvc.perform(formLogin("/loginCheck"))
|
||||
.andExpect(status().isFound())
|
||||
.andExpect(redirectedUrl("/"));
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -233,28 +289,36 @@ public class FormLoginConfigurerTests {
|
|||
FormLoginUsesPortMapperConfig.PORT_MAPPER = mock(PortMapper.class);
|
||||
given(FormLoginUsesPortMapperConfig.PORT_MAPPER.lookupHttpsPort(any())).willReturn(9443);
|
||||
this.spring.register(FormLoginUsesPortMapperConfig.class).autowire();
|
||||
this.mockMvc.perform(get("http://localhost:9090")).andExpect(status().isFound())
|
||||
// @formatter:off
|
||||
this.mockMvc.perform(get("http://localhost:9090"))
|
||||
.andExpect(status().isFound())
|
||||
.andExpect(redirectedUrl("https://localhost:9443/login"));
|
||||
// @formatter:on
|
||||
verify(FormLoginUsesPortMapperConfig.PORT_MAPPER).lookupHttpsPort(any());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void failureUrlWhenPermitAllAndFailureHandlerThenSecured() throws Exception {
|
||||
this.spring.register(PermitAllIgnoresFailureHandlerConfig.class).autowire();
|
||||
this.mockMvc.perform(get("/login?error")).andExpect(status().isFound())
|
||||
// @formatter:off
|
||||
this.mockMvc.perform(get("/login?error"))
|
||||
.andExpect(status().isFound())
|
||||
.andExpect(redirectedUrl("http://localhost/login"));
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
public void formLoginWhenInvokedTwiceThenUsesOriginalUsernameParameter() throws Exception {
|
||||
this.spring.register(DuplicateInvocationsDoesNotOverrideConfig.class).autowire();
|
||||
this.mockMvc.perform(formLogin().user("custom-username", "user")).andExpect(authenticated());
|
||||
SecurityMockMvcRequestBuilders.FormLoginRequestBuilder loginRequest = formLogin().user("custom-username", "user");
|
||||
this.mockMvc.perform(loginRequest).andExpect(authenticated());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void loginWhenInvalidLoginAndFailureForwardUrlThenForwardsToFailureForwardUrl() throws Exception {
|
||||
this.spring.register(FormLoginUserForwardAuthenticationSuccessAndFailureConfig.class).autowire();
|
||||
this.mockMvc.perform(formLogin().user("invalid")).andExpect(forwardedUrl("/failure_forward_url"));
|
||||
SecurityMockMvcRequestBuilders.FormLoginRequestBuilder loginRequest = formLogin().user("invalid");
|
||||
this.mockMvc.perform(loginRequest).andExpect(forwardedUrl("/failure_forward_url"));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
|
@ -62,15 +62,17 @@ public class HeadersConfigurerEagerHeadersTests {
|
|||
|
||||
@Override
|
||||
protected void configure(HttpSecurity http) throws Exception {
|
||||
// @ formatter:off
|
||||
http.headers().addObjectPostProcessor(new ObjectPostProcessor<HeaderWriterFilter>() {
|
||||
@Override
|
||||
public HeaderWriterFilter postProcess(HeaderWriterFilter filter) {
|
||||
filter.setShouldWriteHeadersEagerly(true);
|
||||
return filter;
|
||||
}
|
||||
});
|
||||
// @ formatter:on
|
||||
// @formatter:off
|
||||
http
|
||||
.headers()
|
||||
.addObjectPostProcessor(new ObjectPostProcessor<HeaderWriterFilter>() {
|
||||
@Override
|
||||
public HeaderWriterFilter postProcess(HeaderWriterFilter filter) {
|
||||
filter.setShouldWriteHeadersEagerly(true);
|
||||
return filter;
|
||||
}
|
||||
});
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -34,6 +34,7 @@ import org.springframework.security.web.header.writers.ReferrerPolicyHeaderWrite
|
|||
import org.springframework.security.web.header.writers.frameoptions.XFrameOptionsHeaderWriter.XFrameOptionsMode;
|
||||
import org.springframework.test.web.servlet.MockMvc;
|
||||
import org.springframework.test.web.servlet.MvcResult;
|
||||
import org.springframework.test.web.servlet.ResultMatcher;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
|
||||
|
@ -198,10 +199,13 @@ public class HeadersConfigurerTests {
|
|||
@Test
|
||||
public void getWhenSecureRequestAndHpkpWithPinThenPublicKeyPinsReportOnlyHeaderInResponse() throws Exception {
|
||||
this.spring.register(HpkpConfig.class).autowire();
|
||||
ResultMatcher pinsReportOnly = header().string(HttpHeaders.PUBLIC_KEY_PINS_REPORT_ONLY,
|
||||
"max-age=5184000 ; pin-sha256=\"d6qzRu9zOECb90Uez27xWltNsj0e1Md7GkYYkVoZWmM=\"");
|
||||
// @formatter:off
|
||||
MvcResult mvcResult = this.mvc.perform(get("/").secure(true))
|
||||
.andExpect(header().string(HttpHeaders.PUBLIC_KEY_PINS_REPORT_ONLY,
|
||||
"max-age=5184000 ; pin-sha256=\"d6qzRu9zOECb90Uez27xWltNsj0e1Md7GkYYkVoZWmM=\""))
|
||||
.andExpect(pinsReportOnly)
|
||||
.andReturn();
|
||||
// @formatter:on
|
||||
assertThat(mvcResult.getResponse().getHeaderNames()).containsExactly(HttpHeaders.PUBLIC_KEY_PINS_REPORT_ONLY);
|
||||
}
|
||||
|
||||
|
@ -216,30 +220,40 @@ public class HeadersConfigurerTests {
|
|||
public void getWhenHpkpWithMultiplePinsThenPublicKeyPinsReportOnlyHeaderWithMultiplePinsInResponse()
|
||||
throws Exception {
|
||||
this.spring.register(HpkpConfigWithPins.class).autowire();
|
||||
MvcResult mvcResult = this.mvc.perform(get("/").secure(true)).andExpect(header().string(
|
||||
ResultMatcher pinsReportOnly = header().string(
|
||||
HttpHeaders.PUBLIC_KEY_PINS_REPORT_ONLY,
|
||||
"max-age=5184000 ; pin-sha256=\"d6qzRu9zOECb90Uez27xWltNsj0e1Md7GkYYkVoZWmM=\" ; pin-sha256=\"E9CZ9INDbd+2eRQozYqqbQ2yXLVKB9+xcprMF+44U1g=\""))
|
||||
"max-age=5184000 ; pin-sha256=\"d6qzRu9zOECb90Uez27xWltNsj0e1Md7GkYYkVoZWmM=\" ; pin-sha256=\"E9CZ9INDbd+2eRQozYqqbQ2yXLVKB9+xcprMF+44U1g=\"");
|
||||
// @formatter:off
|
||||
MvcResult mvcResult = this.mvc.perform(get("/").secure(true))
|
||||
.andExpect(pinsReportOnly)
|
||||
.andReturn();
|
||||
// @formatter:on
|
||||
assertThat(mvcResult.getResponse().getHeaderNames()).containsExactly(HttpHeaders.PUBLIC_KEY_PINS_REPORT_ONLY);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getWhenHpkpWithCustomAgeThenPublicKeyPinsReportOnlyHeaderWithCustomAgeInResponse() throws Exception {
|
||||
this.spring.register(HpkpConfigCustomAge.class).autowire();
|
||||
ResultMatcher pinsReportOnly = header().string(HttpHeaders.PUBLIC_KEY_PINS_REPORT_ONLY,
|
||||
"max-age=604800 ; pin-sha256=\"d6qzRu9zOECb90Uez27xWltNsj0e1Md7GkYYkVoZWmM=\"");
|
||||
// @formatter:off
|
||||
MvcResult mvcResult = this.mvc.perform(get("/").secure(true))
|
||||
.andExpect(header().string(HttpHeaders.PUBLIC_KEY_PINS_REPORT_ONLY,
|
||||
"max-age=604800 ; pin-sha256=\"d6qzRu9zOECb90Uez27xWltNsj0e1Md7GkYYkVoZWmM=\""))
|
||||
.andExpect(pinsReportOnly)
|
||||
.andReturn();
|
||||
// @formatter:on
|
||||
assertThat(mvcResult.getResponse().getHeaderNames()).containsExactly(HttpHeaders.PUBLIC_KEY_PINS_REPORT_ONLY);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getWhenHpkpWithReportOnlyFalseThenPublicKeyPinsHeaderInResponse() throws Exception {
|
||||
this.spring.register(HpkpConfigTerminateConnection.class).autowire();
|
||||
ResultMatcher pins = header().string(HttpHeaders.PUBLIC_KEY_PINS,
|
||||
"max-age=5184000 ; pin-sha256=\"d6qzRu9zOECb90Uez27xWltNsj0e1Md7GkYYkVoZWmM=\"");
|
||||
// @formatter:off
|
||||
MvcResult mvcResult = this.mvc.perform(get("/").secure(true))
|
||||
.andExpect(header().string(HttpHeaders.PUBLIC_KEY_PINS,
|
||||
"max-age=5184000 ; pin-sha256=\"d6qzRu9zOECb90Uez27xWltNsj0e1Md7GkYYkVoZWmM=\""))
|
||||
.andExpect(pins)
|
||||
.andReturn();
|
||||
// @formatter:on
|
||||
assertThat(mvcResult.getResponse().getHeaderNames()).containsExactly(HttpHeaders.PUBLIC_KEY_PINS);
|
||||
}
|
||||
|
||||
|
@ -247,20 +261,28 @@ public class HeadersConfigurerTests {
|
|||
public void getWhenHpkpIncludeSubdomainThenPublicKeyPinsReportOnlyHeaderWithIncludeSubDomainsInResponse()
|
||||
throws Exception {
|
||||
this.spring.register(HpkpConfigIncludeSubDomains.class).autowire();
|
||||
MvcResult mvcResult = this.mvc.perform(get("/").secure(true)).andExpect(header().string(
|
||||
ResultMatcher pinsReportOnly = header().string(
|
||||
HttpHeaders.PUBLIC_KEY_PINS_REPORT_ONLY,
|
||||
"max-age=5184000 ; pin-sha256=\"d6qzRu9zOECb90Uez27xWltNsj0e1Md7GkYYkVoZWmM=\" ; includeSubDomains"))
|
||||
"max-age=5184000 ; pin-sha256=\"d6qzRu9zOECb90Uez27xWltNsj0e1Md7GkYYkVoZWmM=\" ; includeSubDomains");
|
||||
// @formatter:off
|
||||
MvcResult mvcResult = this.mvc.perform(get("/").secure(true))
|
||||
.andExpect(pinsReportOnly)
|
||||
.andReturn();
|
||||
// @formatter:on
|
||||
assertThat(mvcResult.getResponse().getHeaderNames()).containsExactly(HttpHeaders.PUBLIC_KEY_PINS_REPORT_ONLY);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getWhenHpkpWithReportUriThenPublicKeyPinsReportOnlyHeaderWithReportUriInResponse() throws Exception {
|
||||
this.spring.register(HpkpConfigWithReportURI.class).autowire();
|
||||
MvcResult mvcResult = this.mvc.perform(get("/").secure(true)).andExpect(header().string(
|
||||
ResultMatcher pinsReportOnly = header().string(
|
||||
HttpHeaders.PUBLIC_KEY_PINS_REPORT_ONLY,
|
||||
"max-age=5184000 ; pin-sha256=\"d6qzRu9zOECb90Uez27xWltNsj0e1Md7GkYYkVoZWmM=\" ; report-uri=\"https://example.net/pkp-report\""))
|
||||
"max-age=5184000 ; pin-sha256=\"d6qzRu9zOECb90Uez27xWltNsj0e1Md7GkYYkVoZWmM=\" ; report-uri=\"https://example.net/pkp-report\"");
|
||||
// @formatter:off
|
||||
MvcResult mvcResult = this.mvc.perform(get("/").secure(true))
|
||||
.andExpect(pinsReportOnly)
|
||||
.andReturn();
|
||||
// @formatter:on
|
||||
assertThat(mvcResult.getResponse().getHeaderNames()).containsExactly(HttpHeaders.PUBLIC_KEY_PINS_REPORT_ONLY);
|
||||
}
|
||||
|
||||
|
@ -268,10 +290,14 @@ public class HeadersConfigurerTests {
|
|||
public void getWhenHpkpWithReportUriAsStringThenPublicKeyPinsReportOnlyHeaderWithReportUriInResponse()
|
||||
throws Exception {
|
||||
this.spring.register(HpkpConfigWithReportURIAsString.class).autowire();
|
||||
MvcResult mvcResult = this.mvc.perform(get("/").secure(true)).andExpect(header().string(
|
||||
ResultMatcher pinsReportOnly = header().string(
|
||||
HttpHeaders.PUBLIC_KEY_PINS_REPORT_ONLY,
|
||||
"max-age=5184000 ; pin-sha256=\"d6qzRu9zOECb90Uez27xWltNsj0e1Md7GkYYkVoZWmM=\" ; report-uri=\"https://example.net/pkp-report\""))
|
||||
"max-age=5184000 ; pin-sha256=\"d6qzRu9zOECb90Uez27xWltNsj0e1Md7GkYYkVoZWmM=\" ; report-uri=\"https://example.net/pkp-report\"");
|
||||
// @formatter:off
|
||||
MvcResult mvcResult = this.mvc.perform(get("/").secure(true))
|
||||
.andExpect(pinsReportOnly)
|
||||
.andReturn();
|
||||
// @formatter:on
|
||||
assertThat(mvcResult.getResponse().getHeaderNames()).containsExactly(HttpHeaders.PUBLIC_KEY_PINS_REPORT_ONLY);
|
||||
}
|
||||
|
||||
|
@ -279,18 +305,26 @@ public class HeadersConfigurerTests {
|
|||
public void getWhenHpkpWithReportUriInLambdaThenPublicKeyPinsReportOnlyHeaderWithReportUriInResponse()
|
||||
throws Exception {
|
||||
this.spring.register(HpkpWithReportUriInLambdaConfig.class).autowire();
|
||||
MvcResult mvcResult = this.mvc.perform(get("/").secure(true)).andExpect(header().string(
|
||||
ResultMatcher pinsReportOnly = header().string(
|
||||
HttpHeaders.PUBLIC_KEY_PINS_REPORT_ONLY,
|
||||
"max-age=5184000 ; pin-sha256=\"d6qzRu9zOECb90Uez27xWltNsj0e1Md7GkYYkVoZWmM=\" ; report-uri=\"https://example.net/pkp-report\""))
|
||||
"max-age=5184000 ; pin-sha256=\"d6qzRu9zOECb90Uez27xWltNsj0e1Md7GkYYkVoZWmM=\" ; report-uri=\"https://example.net/pkp-report\"");
|
||||
// @formatter:off
|
||||
MvcResult mvcResult = this.mvc.perform(get("/").secure(true))
|
||||
.andExpect(pinsReportOnly)
|
||||
.andReturn();
|
||||
// @formatter:on
|
||||
assertThat(mvcResult.getResponse().getHeaderNames()).containsExactly(HttpHeaders.PUBLIC_KEY_PINS_REPORT_ONLY);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getWhenContentSecurityPolicyConfiguredThenContentSecurityPolicyHeaderInResponse() throws Exception {
|
||||
this.spring.register(ContentSecurityPolicyDefaultConfig.class).autowire();
|
||||
ResultMatcher csp = header().string(HttpHeaders.CONTENT_SECURITY_POLICY, "default-src 'self'");
|
||||
// @formatter:off
|
||||
MvcResult mvcResult = this.mvc.perform(get("/").secure(true))
|
||||
.andExpect(header().string(HttpHeaders.CONTENT_SECURITY_POLICY, "default-src 'self'")).andReturn();
|
||||
.andExpect(csp)
|
||||
.andReturn();
|
||||
// @formatter:on
|
||||
assertThat(mvcResult.getResponse().getHeaderNames()).containsExactly(HttpHeaders.CONTENT_SECURITY_POLICY);
|
||||
}
|
||||
|
||||
|
@ -298,10 +332,13 @@ public class HeadersConfigurerTests {
|
|||
public void getWhenContentSecurityPolicyWithReportOnlyThenContentSecurityPolicyReportOnlyHeaderInResponse()
|
||||
throws Exception {
|
||||
this.spring.register(ContentSecurityPolicyReportOnlyConfig.class).autowire();
|
||||
ResultMatcher cspReportOnly = header().string(HttpHeaders.CONTENT_SECURITY_POLICY_REPORT_ONLY,
|
||||
"default-src 'self'; script-src trustedscripts.example.com");
|
||||
// @formatter:off
|
||||
MvcResult mvcResult = this.mvc.perform(get("/").secure(true))
|
||||
.andExpect(header().string(HttpHeaders.CONTENT_SECURITY_POLICY_REPORT_ONLY,
|
||||
"default-src 'self'; script-src trustedscripts.example.com"))
|
||||
.andExpect(cspReportOnly)
|
||||
.andReturn();
|
||||
// @formatter:on
|
||||
assertThat(mvcResult.getResponse().getHeaderNames())
|
||||
.containsExactly(HttpHeaders.CONTENT_SECURITY_POLICY_REPORT_ONLY);
|
||||
}
|
||||
|
@ -310,10 +347,13 @@ public class HeadersConfigurerTests {
|
|||
public void getWhenContentSecurityPolicyWithReportOnlyInLambdaThenContentSecurityPolicyReportOnlyHeaderInResponse()
|
||||
throws Exception {
|
||||
this.spring.register(ContentSecurityPolicyReportOnlyInLambdaConfig.class).autowire();
|
||||
ResultMatcher csp = header().string(HttpHeaders.CONTENT_SECURITY_POLICY_REPORT_ONLY,
|
||||
"default-src 'self'; script-src trustedscripts.example.com");
|
||||
// @formatter:off
|
||||
MvcResult mvcResult = this.mvc.perform(get("/").secure(true))
|
||||
.andExpect(header().string(HttpHeaders.CONTENT_SECURITY_POLICY_REPORT_ONLY,
|
||||
"default-src 'self'; script-src trustedscripts.example.com"))
|
||||
.andExpect(csp)
|
||||
.andReturn();
|
||||
// @formatter:on
|
||||
assertThat(mvcResult.getResponse().getHeaderNames())
|
||||
.containsExactly(HttpHeaders.CONTENT_SECURITY_POLICY_REPORT_ONLY);
|
||||
}
|
||||
|
@ -335,24 +375,36 @@ public class HeadersConfigurerTests {
|
|||
@Test
|
||||
public void configureWhenContentSecurityPolicyNoPolicyDirectivesInLambdaThenDefaultHeaderValue() throws Exception {
|
||||
this.spring.register(ContentSecurityPolicyNoDirectivesInLambdaConfig.class).autowire();
|
||||
ResultMatcher csp = header().string(HttpHeaders.CONTENT_SECURITY_POLICY, "default-src 'self'");
|
||||
// @formatter:off
|
||||
MvcResult mvcResult = this.mvc.perform(get("/").secure(true))
|
||||
.andExpect(header().string(HttpHeaders.CONTENT_SECURITY_POLICY, "default-src 'self'")).andReturn();
|
||||
.andExpect(csp)
|
||||
.andReturn();
|
||||
// @formatter:on
|
||||
assertThat(mvcResult.getResponse().getHeaderNames()).containsExactly(HttpHeaders.CONTENT_SECURITY_POLICY);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getWhenReferrerPolicyConfiguredThenReferrerPolicyHeaderInResponse() throws Exception {
|
||||
this.spring.register(ReferrerPolicyDefaultConfig.class).autowire();
|
||||
ResultMatcher referrerPolicy = header().string("Referrer-Policy", ReferrerPolicy.NO_REFERRER.getPolicy());
|
||||
// @formatter:off
|
||||
MvcResult mvcResult = this.mvc.perform(get("/").secure(true))
|
||||
.andExpect(header().string("Referrer-Policy", ReferrerPolicy.NO_REFERRER.getPolicy())).andReturn();
|
||||
.andExpect(referrerPolicy)
|
||||
.andReturn();
|
||||
// @formatter:on
|
||||
assertThat(mvcResult.getResponse().getHeaderNames()).containsExactly("Referrer-Policy");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getWhenReferrerPolicyInLambdaThenReferrerPolicyHeaderInResponse() throws Exception {
|
||||
this.spring.register(ReferrerPolicyDefaultInLambdaConfig.class).autowire();
|
||||
ResultMatcher referrerPolicy = header().string("Referrer-Policy", ReferrerPolicy.NO_REFERRER.getPolicy());
|
||||
// @formatter:off
|
||||
MvcResult mvcResult = this.mvc.perform(get("/").secure(true))
|
||||
.andExpect(header().string("Referrer-Policy", ReferrerPolicy.NO_REFERRER.getPolicy())).andReturn();
|
||||
.andExpect(referrerPolicy)
|
||||
.andReturn();
|
||||
// @formatter:on
|
||||
assertThat(mvcResult.getResponse().getHeaderNames()).containsExactly("Referrer-Policy");
|
||||
}
|
||||
|
||||
|
@ -360,24 +412,36 @@ public class HeadersConfigurerTests {
|
|||
public void getWhenReferrerPolicyConfiguredWithCustomValueThenReferrerPolicyHeaderWithCustomValueInResponse()
|
||||
throws Exception {
|
||||
this.spring.register(ReferrerPolicyCustomConfig.class).autowire();
|
||||
ResultMatcher referrerPolicy = header().string("Referrer-Policy", ReferrerPolicy.SAME_ORIGIN.getPolicy());
|
||||
// @formatter:off
|
||||
MvcResult mvcResult = this.mvc.perform(get("/").secure(true))
|
||||
.andExpect(header().string("Referrer-Policy", ReferrerPolicy.SAME_ORIGIN.getPolicy())).andReturn();
|
||||
.andExpect(referrerPolicy)
|
||||
.andReturn();
|
||||
// @formatter:on
|
||||
assertThat(mvcResult.getResponse().getHeaderNames()).containsExactly("Referrer-Policy");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getWhenReferrerPolicyConfiguredWithCustomValueInLambdaThenCustomValueInResponse() throws Exception {
|
||||
this.spring.register(ReferrerPolicyCustomInLambdaConfig.class).autowire();
|
||||
ResultMatcher referrerPolicy = header().string("Referrer-Policy", ReferrerPolicy.SAME_ORIGIN.getPolicy());
|
||||
// @formatter:off
|
||||
MvcResult mvcResult = this.mvc.perform(get("/").secure(true))
|
||||
.andExpect(header().string("Referrer-Policy", ReferrerPolicy.SAME_ORIGIN.getPolicy())).andReturn();
|
||||
.andExpect(referrerPolicy)
|
||||
.andReturn();
|
||||
// @formatter:on
|
||||
assertThat(mvcResult.getResponse().getHeaderNames()).containsExactly("Referrer-Policy");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getWhenFeaturePolicyConfiguredThenFeaturePolicyHeaderInResponse() throws Exception {
|
||||
this.spring.register(FeaturePolicyConfig.class).autowire();
|
||||
ResultMatcher featurePolicy = header().string("Feature-Policy", "geolocation 'self'");
|
||||
// @formatter:off
|
||||
MvcResult mvcResult = this.mvc.perform(get("/").secure(true))
|
||||
.andExpect(header().string("Feature-Policy", "geolocation 'self'")).andReturn();
|
||||
.andExpect(featurePolicy)
|
||||
.andReturn();
|
||||
// @formatter:on
|
||||
assertThat(mvcResult.getResponse().getHeaderNames()).containsExactly("Feature-Policy");
|
||||
}
|
||||
|
||||
|
@ -392,9 +456,13 @@ public class HeadersConfigurerTests {
|
|||
public void getWhenHstsConfiguredWithPreloadThenStrictTransportSecurityHeaderWithPreloadInResponse()
|
||||
throws Exception {
|
||||
this.spring.register(HstsWithPreloadConfig.class).autowire();
|
||||
MvcResult mvcResult = this.mvc.perform(get("/").secure(true)).andExpect(header()
|
||||
.string(HttpHeaders.STRICT_TRANSPORT_SECURITY, "max-age=31536000 ; includeSubDomains ; preload"))
|
||||
ResultMatcher hsts = header()
|
||||
.string(HttpHeaders.STRICT_TRANSPORT_SECURITY, "max-age=31536000 ; includeSubDomains ; preload");
|
||||
// @formatter:off
|
||||
MvcResult mvcResult = this.mvc.perform(get("/").secure(true))
|
||||
.andExpect(hsts)
|
||||
.andReturn();
|
||||
// @formatter:on
|
||||
assertThat(mvcResult.getResponse().getHeaderNames()).containsExactly(HttpHeaders.STRICT_TRANSPORT_SECURITY);
|
||||
}
|
||||
|
||||
|
@ -402,9 +470,13 @@ public class HeadersConfigurerTests {
|
|||
public void getWhenHstsConfiguredWithPreloadInLambdaThenStrictTransportSecurityHeaderWithPreloadInResponse()
|
||||
throws Exception {
|
||||
this.spring.register(HstsWithPreloadInLambdaConfig.class).autowire();
|
||||
MvcResult mvcResult = this.mvc.perform(get("/").secure(true)).andExpect(header()
|
||||
.string(HttpHeaders.STRICT_TRANSPORT_SECURITY, "max-age=31536000 ; includeSubDomains ; preload"))
|
||||
ResultMatcher hsts = header()
|
||||
.string(HttpHeaders.STRICT_TRANSPORT_SECURITY, "max-age=31536000 ; includeSubDomains ; preload");
|
||||
// @formatter:off
|
||||
MvcResult mvcResult = this.mvc.perform(get("/").secure(true))
|
||||
.andExpect(hsts)
|
||||
.andReturn();
|
||||
// @formatter:on
|
||||
assertThat(mvcResult.getResponse().getHeaderNames()).containsExactly(HttpHeaders.STRICT_TRANSPORT_SECURITY);
|
||||
}
|
||||
|
||||
|
|
|
@ -38,6 +38,7 @@ import org.springframework.security.provisioning.InMemoryUserDetailsManager;
|
|||
import org.springframework.security.web.AuthenticationEntryPoint;
|
||||
import org.springframework.security.web.authentication.www.BasicAuthenticationFilter;
|
||||
import org.springframework.test.web.servlet.MockMvc;
|
||||
import org.springframework.test.web.servlet.request.MockHttpServletRequestBuilder;
|
||||
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.Mockito.mock;
|
||||
|
@ -73,16 +74,22 @@ public class HttpBasicConfigurerTests {
|
|||
@Test
|
||||
public void httpBasicWhenUsingDefaultsInLambdaThenResponseIncludesBasicChallenge() throws Exception {
|
||||
this.spring.register(DefaultsLambdaEntryPointConfig.class).autowire();
|
||||
this.mvc.perform(get("/")).andExpect(status().isUnauthorized())
|
||||
// @formatter:off
|
||||
this.mvc.perform(get("/"))
|
||||
.andExpect(status().isUnauthorized())
|
||||
.andExpect(header().string("WWW-Authenticate", "Basic realm=\"Realm\""));
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
// SEC-2198
|
||||
@Test
|
||||
public void httpBasicWhenUsingDefaultsThenResponseIncludesBasicChallenge() throws Exception {
|
||||
this.spring.register(DefaultsEntryPointConfig.class).autowire();
|
||||
this.mvc.perform(get("/")).andExpect(status().isUnauthorized())
|
||||
// @formatter:off
|
||||
this.mvc.perform(get("/"))
|
||||
.andExpect(status().isUnauthorized())
|
||||
.andExpect(header().string("WWW-Authenticate", "Basic realm=\"Realm\""));
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -105,8 +112,8 @@ public class HttpBasicConfigurerTests {
|
|||
@Test
|
||||
public void httpBasicWhenRememberMeConfiguredThenSetsRememberMeCookie() throws Exception {
|
||||
this.spring.register(BasicUsesRememberMeConfig.class).autowire();
|
||||
this.mvc.perform(get("/").with(httpBasic("user", "password")).param("remember-me", "true"))
|
||||
.andExpect(cookie().exists("remember-me"));
|
||||
MockHttpServletRequestBuilder rememberMeRequest = get("/").with(httpBasic("user", "password")).param("remember-me", "true");
|
||||
this.mvc.perform(rememberMeRequest).andExpect(cookie().exists("remember-me"));
|
||||
}
|
||||
|
||||
@EnableWebSecurity
|
||||
|
|
|
@ -31,9 +31,11 @@ import org.springframework.security.config.test.SpringTestRule;
|
|||
import org.springframework.security.core.authority.AuthorityUtils;
|
||||
import org.springframework.security.core.userdetails.AuthenticationUserDetailsService;
|
||||
import org.springframework.security.core.userdetails.User;
|
||||
import org.springframework.security.test.web.servlet.response.SecurityMockMvcResultMatchers;
|
||||
import org.springframework.security.web.authentication.preauth.j2ee.J2eeBasedPreAuthenticatedWebAuthenticationDetailsSource;
|
||||
import org.springframework.security.web.authentication.preauth.j2ee.J2eePreAuthenticatedProcessingFilter;
|
||||
import org.springframework.test.web.servlet.MockMvc;
|
||||
import org.springframework.test.web.servlet.request.MockHttpServletRequestBuilder;
|
||||
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.BDDMockito.given;
|
||||
|
@ -78,11 +80,16 @@ public class JeeConfigurerTests {
|
|||
this.spring.register(InvokeTwiceDoesNotOverride.class).autowire();
|
||||
Principal user = mock(Principal.class);
|
||||
given(user.getName()).willReturn("user");
|
||||
this.mvc.perform(get("/").principal(user).with((request) -> {
|
||||
request.addUserRole("ROLE_ADMIN");
|
||||
request.addUserRole("ROLE_USER");
|
||||
return request;
|
||||
})).andExpect(authenticated().withRoles("USER"));
|
||||
// @formatter:off
|
||||
MockHttpServletRequestBuilder request = get("/")
|
||||
.principal(user)
|
||||
.with((request) -> {
|
||||
request.addUserRole("ROLE_ADMIN");
|
||||
request.addUserRole("ROLE_USER");
|
||||
return request;
|
||||
});
|
||||
// @formatter:on
|
||||
this.mvc.perform(request).andExpect(authenticated().withRoles("USER"));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -90,11 +97,16 @@ public class JeeConfigurerTests {
|
|||
this.spring.register(JeeMappableRolesConfig.class).autowire();
|
||||
Principal user = mock(Principal.class);
|
||||
given(user.getName()).willReturn("user");
|
||||
this.mvc.perform(get("/").principal(user).with((request) -> {
|
||||
request.addUserRole("ROLE_ADMIN");
|
||||
request.addUserRole("ROLE_USER");
|
||||
return request;
|
||||
})).andExpect(authenticated().withRoles("USER"));
|
||||
// @formatter:off
|
||||
MockHttpServletRequestBuilder request = get("/")
|
||||
.principal(user)
|
||||
.with((request) -> {
|
||||
request.addUserRole("ROLE_ADMIN");
|
||||
request.addUserRole("ROLE_USER");
|
||||
return request;
|
||||
});
|
||||
// @formatter:on
|
||||
this.mvc.perform(request).andExpect(authenticated().withRoles("USER"));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -102,11 +114,17 @@ public class JeeConfigurerTests {
|
|||
this.spring.register(JeeMappableAuthoritiesConfig.class).autowire();
|
||||
Principal user = mock(Principal.class);
|
||||
given(user.getName()).willReturn("user");
|
||||
this.mvc.perform(get("/").principal(user).with((request) -> {
|
||||
request.addUserRole("ROLE_ADMIN");
|
||||
request.addUserRole("ROLE_USER");
|
||||
return request;
|
||||
})).andExpect(authenticated().withAuthorities(AuthorityUtils.createAuthorityList("ROLE_USER")));
|
||||
// @formatter:off
|
||||
MockHttpServletRequestBuilder request = get("/")
|
||||
.principal(user)
|
||||
.with((request) -> {
|
||||
request.addUserRole("ROLE_ADMIN");
|
||||
request.addUserRole("ROLE_USER");
|
||||
return request;
|
||||
});
|
||||
// @formatter:on
|
||||
SecurityMockMvcResultMatchers.AuthenticatedMatcher authenticatedAsUser = authenticated().withAuthorities(AuthorityUtils.createAuthorityList("ROLE_USER"));
|
||||
this.mvc.perform(request).andExpect(authenticatedAsUser);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -119,11 +137,16 @@ public class JeeConfigurerTests {
|
|||
given(user.getName()).willReturn("user");
|
||||
given(JeeCustomAuthenticatedUserDetailsServiceConfig.authenticationUserDetailsService.loadUserDetails(any()))
|
||||
.willReturn(userDetails);
|
||||
this.mvc.perform(get("/").principal(user).with((request) -> {
|
||||
request.addUserRole("ROLE_ADMIN");
|
||||
request.addUserRole("ROLE_USER");
|
||||
return request;
|
||||
})).andExpect(authenticated().withRoles("USER"));
|
||||
// @formatter:off
|
||||
MockHttpServletRequestBuilder request = get("/")
|
||||
.principal(user)
|
||||
.with((request) -> {
|
||||
request.addUserRole("ROLE_ADMIN");
|
||||
request.addUserRole("ROLE_USER");
|
||||
return request;
|
||||
});
|
||||
// @formatter:on
|
||||
this.mvc.perform(request).andExpect(authenticated().withRoles("USER"));
|
||||
}
|
||||
|
||||
@EnableWebSecurity
|
||||
|
|
|
@ -27,13 +27,14 @@ import org.springframework.security.config.annotation.web.configuration.WebSecur
|
|||
import org.springframework.security.config.test.SpringTestRule;
|
||||
import org.springframework.security.test.context.annotation.SecurityTestExecutionListeners;
|
||||
import org.springframework.security.test.context.support.WithMockUser;
|
||||
import org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors;
|
||||
import org.springframework.security.web.authentication.logout.HeaderWriterLogoutHandler;
|
||||
import org.springframework.security.web.header.writers.ClearSiteDataHeaderWriter;
|
||||
import org.springframework.security.web.header.writers.ClearSiteDataHeaderWriter.Directive;
|
||||
import org.springframework.test.context.junit4.SpringRunner;
|
||||
import org.springframework.test.web.servlet.MockMvc;
|
||||
import org.springframework.test.web.servlet.request.MockHttpServletRequestBuilder;
|
||||
|
||||
import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.csrf;
|
||||
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
|
||||
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.header;
|
||||
|
@ -67,24 +68,24 @@ public class LogoutConfigurerClearSiteDataTests {
|
|||
@WithMockUser
|
||||
public void logoutWhenRequestTypeGetThenHeaderNotPresentt() throws Exception {
|
||||
this.spring.register(HttpLogoutConfig.class).autowire();
|
||||
this.mvc.perform(get("/logout").secure(true).with(SecurityMockMvcRequestPostProcessors.csrf()))
|
||||
.andExpect(header().doesNotExist(CLEAR_SITE_DATA_HEADER));
|
||||
MockHttpServletRequestBuilder logoutRequest = get("/logout").secure(true).with(csrf());
|
||||
this.mvc.perform(logoutRequest).andExpect(header().doesNotExist(CLEAR_SITE_DATA_HEADER));
|
||||
}
|
||||
|
||||
@Test
|
||||
@WithMockUser
|
||||
public void logoutWhenRequestTypePostAndNotSecureThenHeaderNotPresent() throws Exception {
|
||||
this.spring.register(HttpLogoutConfig.class).autowire();
|
||||
this.mvc.perform(post("/logout").with(SecurityMockMvcRequestPostProcessors.csrf()))
|
||||
.andExpect(header().doesNotExist(CLEAR_SITE_DATA_HEADER));
|
||||
MockHttpServletRequestBuilder logoutRequest = post("/logout").with(csrf());
|
||||
this.mvc.perform(logoutRequest).andExpect(header().doesNotExist(CLEAR_SITE_DATA_HEADER));
|
||||
}
|
||||
|
||||
@Test
|
||||
@WithMockUser
|
||||
public void logoutWhenRequestTypePostAndSecureThenHeaderIsPresent() throws Exception {
|
||||
this.spring.register(HttpLogoutConfig.class).autowire();
|
||||
this.mvc.perform(post("/logout").secure(true).with(SecurityMockMvcRequestPostProcessors.csrf()))
|
||||
.andExpect(header().stringValues(CLEAR_SITE_DATA_HEADER, HEADER_VALUE));
|
||||
MockHttpServletRequestBuilder logoutRequest = post("/logout").secure(true).with(csrf());
|
||||
this.mvc.perform(logoutRequest).andExpect(header().stringValues(CLEAR_SITE_DATA_HEADER, HEADER_VALUE));
|
||||
}
|
||||
|
||||
@EnableWebSecurity
|
||||
|
|
|
@ -35,6 +35,7 @@ import org.springframework.security.web.authentication.logout.LogoutFilter;
|
|||
import org.springframework.security.web.authentication.logout.LogoutSuccessHandler;
|
||||
import org.springframework.security.web.util.matcher.RequestMatcher;
|
||||
import org.springframework.test.web.servlet.MockMvc;
|
||||
import org.springframework.test.web.servlet.request.MockHttpServletRequestBuilder;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
|
@ -101,65 +102,103 @@ public class LogoutConfigurerTests {
|
|||
@Test
|
||||
public void logoutWhenInvokedTwiceThenUsesOriginalLogoutUrl() throws Exception {
|
||||
this.spring.register(DuplicateDoesNotOverrideConfig.class).autowire();
|
||||
this.mvc.perform(post("/custom/logout").with(csrf())).andExpect(status().isFound())
|
||||
MockHttpServletRequestBuilder logoutRequest = post("/custom/logout").with(csrf());
|
||||
// @formatter:off
|
||||
this.mvc.perform(logoutRequest)
|
||||
.andExpect(status().isFound())
|
||||
.andExpect(redirectedUrl("/login?logout"));
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
// SEC-2311
|
||||
@Test
|
||||
public void logoutWhenGetRequestAndCsrfDisabledThenRedirectsToLogin() throws Exception {
|
||||
this.spring.register(CsrfDisabledConfig.class).autowire();
|
||||
this.mvc.perform(get("/logout")).andExpect(status().isFound()).andExpect(redirectedUrl("/login?logout"));
|
||||
// @formatter:off
|
||||
this.mvc.perform(get("/logout"))
|
||||
.andExpect(status().isFound())
|
||||
.andExpect(redirectedUrl("/login?logout"));
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
public void logoutWhenPostRequestAndCsrfDisabledThenRedirectsToLogin() throws Exception {
|
||||
this.spring.register(CsrfDisabledConfig.class).autowire();
|
||||
this.mvc.perform(post("/logout")).andExpect(status().isFound()).andExpect(redirectedUrl("/login?logout"));
|
||||
// @formatter:off
|
||||
this.mvc.perform(post("/logout"))
|
||||
.andExpect(status().isFound())
|
||||
.andExpect(redirectedUrl("/login?logout"));
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
public void logoutWhenPutRequestAndCsrfDisabledThenRedirectsToLogin() throws Exception {
|
||||
this.spring.register(CsrfDisabledConfig.class).autowire();
|
||||
this.mvc.perform(put("/logout")).andExpect(status().isFound()).andExpect(redirectedUrl("/login?logout"));
|
||||
// @formatter:off
|
||||
this.mvc.perform(put("/logout"))
|
||||
.andExpect(status().isFound())
|
||||
.andExpect(redirectedUrl("/login?logout"));
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
public void logoutWhenDeleteRequestAndCsrfDisabledThenRedirectsToLogin() throws Exception {
|
||||
this.spring.register(CsrfDisabledConfig.class).autowire();
|
||||
this.mvc.perform(delete("/logout")).andExpect(status().isFound()).andExpect(redirectedUrl("/login?logout"));
|
||||
// @formatter:off
|
||||
this.mvc.perform(delete("/logout"))
|
||||
.andExpect(status().isFound())
|
||||
.andExpect(redirectedUrl("/login?logout"));
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
public void logoutWhenGetRequestAndCsrfDisabledAndCustomLogoutUrlThenRedirectsToLogin() throws Exception {
|
||||
this.spring.register(CsrfDisabledAndCustomLogoutConfig.class).autowire();
|
||||
this.mvc.perform(get("/custom/logout")).andExpect(status().isFound()).andExpect(redirectedUrl("/login?logout"));
|
||||
// @formatter:off
|
||||
this.mvc.perform(get("/custom/logout"))
|
||||
.andExpect(status().isFound())
|
||||
.andExpect(redirectedUrl("/login?logout"));
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
public void logoutWhenPostRequestAndCsrfDisabledAndCustomLogoutUrlThenRedirectsToLogin() throws Exception {
|
||||
this.spring.register(CsrfDisabledAndCustomLogoutConfig.class).autowire();
|
||||
this.mvc.perform(post("/custom/logout")).andExpect(status().isFound())
|
||||
// @formatter:off
|
||||
this.mvc.perform(post("/custom/logout"))
|
||||
.andExpect(status().isFound())
|
||||
.andExpect(redirectedUrl("/login?logout"));
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
public void logoutWhenPutRequestAndCsrfDisabledAndCustomLogoutUrlThenRedirectsToLogin() throws Exception {
|
||||
this.spring.register(CsrfDisabledAndCustomLogoutConfig.class).autowire();
|
||||
this.mvc.perform(put("/custom/logout")).andExpect(status().isFound()).andExpect(redirectedUrl("/login?logout"));
|
||||
// @formatter:off
|
||||
this.mvc.perform(put("/custom/logout"))
|
||||
.andExpect(status().isFound())
|
||||
.andExpect(redirectedUrl("/login?logout"));
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
public void logoutWhenDeleteRequestAndCsrfDisabledAndCustomLogoutUrlThenRedirectsToLogin() throws Exception {
|
||||
this.spring.register(CsrfDisabledAndCustomLogoutConfig.class).autowire();
|
||||
this.mvc.perform(delete("/custom/logout")).andExpect(status().isFound())
|
||||
// @formatter:off
|
||||
this.mvc.perform(delete("/custom/logout"))
|
||||
.andExpect(status().isFound())
|
||||
.andExpect(redirectedUrl("/login?logout"));
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
public void logoutWhenCustomLogoutUrlInLambdaThenRedirectsToLogin() throws Exception {
|
||||
this.spring.register(CsrfDisabledAndCustomLogoutInLambdaConfig.class).autowire();
|
||||
this.mvc.perform(get("/custom/logout")).andExpect(status().isFound()).andExpect(redirectedUrl("/login?logout"));
|
||||
// @formatter:off
|
||||
this.mvc.perform(get("/custom/logout"))
|
||||
.andExpect(status().isFound())
|
||||
.andExpect(redirectedUrl("/login?logout"));
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
// SEC-3170
|
||||
|
@ -188,44 +227,70 @@ public class LogoutConfigurerTests {
|
|||
@Test
|
||||
public void logoutWhenAcceptTextHtmlThenRedirectsToLogin() throws Exception {
|
||||
this.spring.register(BasicSecurityConfig.class).autowire();
|
||||
this.mvc.perform(
|
||||
post("/logout").with(csrf()).with(user("user")).header(HttpHeaders.ACCEPT, MediaType.TEXT_HTML_VALUE))
|
||||
.andExpect(status().isFound()).andExpect(redirectedUrl("/login?logout"));
|
||||
// @formatter:off
|
||||
MockHttpServletRequestBuilder logoutRequest = post("/logout")
|
||||
.with(csrf())
|
||||
.with(user("user"))
|
||||
.header(HttpHeaders.ACCEPT, MediaType.TEXT_HTML_VALUE);
|
||||
this.mvc.perform(logoutRequest)
|
||||
.andExpect(status().isFound())
|
||||
.andExpect(redirectedUrl("/login?logout"));
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
// gh-3282
|
||||
@Test
|
||||
public void logoutWhenAcceptApplicationJsonThenReturnsStatusNoContent() throws Exception {
|
||||
this.spring.register(BasicSecurityConfig.class).autowire();
|
||||
this.mvc.perform(post("/logout").with(csrf()).with(user("user")).header(HttpHeaders.ACCEPT,
|
||||
MediaType.APPLICATION_JSON_VALUE)).andExpect(status().isNoContent());
|
||||
// @formatter:off
|
||||
MockHttpServletRequestBuilder request = post("/logout")
|
||||
.with(csrf())
|
||||
.with(user("user"))
|
||||
.header(HttpHeaders.ACCEPT, MediaType.APPLICATION_JSON_VALUE);
|
||||
// @formatter:on
|
||||
this.mvc.perform(request).andExpect(status().isNoContent());
|
||||
}
|
||||
|
||||
// gh-4831
|
||||
@Test
|
||||
public void logoutWhenAcceptAllThenReturnsStatusNoContent() throws Exception {
|
||||
this.spring.register(BasicSecurityConfig.class).autowire();
|
||||
this.mvc.perform(
|
||||
post("/logout").with(csrf()).with(user("user")).header(HttpHeaders.ACCEPT, MediaType.ALL_VALUE))
|
||||
.andExpect(status().isNoContent());
|
||||
// @formatter:off
|
||||
MockHttpServletRequestBuilder logoutRequest = post("/logout")
|
||||
.with(csrf())
|
||||
.with(user("user"))
|
||||
.header(HttpHeaders.ACCEPT, MediaType.ALL_VALUE);
|
||||
// @formatter:on
|
||||
this.mvc.perform(logoutRequest).andExpect(status().isNoContent());
|
||||
}
|
||||
|
||||
// gh-3902
|
||||
@Test
|
||||
public void logoutWhenAcceptFromChromeThenRedirectsToLogin() throws Exception {
|
||||
this.spring.register(BasicSecurityConfig.class).autowire();
|
||||
this.mvc.perform(post("/logout").with(csrf()).with(user("user")).header(HttpHeaders.ACCEPT,
|
||||
"text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8"))
|
||||
.andExpect(status().isFound()).andExpect(redirectedUrl("/login?logout"));
|
||||
// @formatter:off
|
||||
MockHttpServletRequestBuilder request = post("/logout")
|
||||
.with(csrf())
|
||||
.with(user("user"))
|
||||
.header(HttpHeaders.ACCEPT, "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8");
|
||||
this.mvc.perform(request)
|
||||
.andExpect(status().isFound())
|
||||
.andExpect(redirectedUrl("/login?logout"));
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
// gh-3997
|
||||
@Test
|
||||
public void logoutWhenXMLHttpRequestThenReturnsStatusNoContent() throws Exception {
|
||||
this.spring.register(BasicSecurityConfig.class).autowire();
|
||||
this.mvc.perform(post("/logout").with(csrf()).with(user("user"))
|
||||
.header(HttpHeaders.ACCEPT, "text/html,application/json").header("X-Requested-With", "XMLHttpRequest"))
|
||||
.andExpect(status().isNoContent());
|
||||
// @formatter:off
|
||||
MockHttpServletRequestBuilder request = post("/logout")
|
||||
.with(csrf())
|
||||
.with(user("user"))
|
||||
.header(HttpHeaders.ACCEPT, "text/html,application/json")
|
||||
.header("X-Requested-With", "XMLHttpRequest");
|
||||
// @formatter:on
|
||||
this.mvc.perform(request).andExpect(status().isNoContent());
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
|
@ -35,6 +35,7 @@ import org.springframework.security.core.userdetails.UserDetailsService;
|
|||
import org.springframework.security.provisioning.InMemoryUserDetailsManager;
|
||||
import org.springframework.security.web.AuthenticationEntryPoint;
|
||||
import org.springframework.test.web.servlet.MockMvc;
|
||||
import org.springframework.test.web.servlet.request.MockHttpServletRequestBuilder;
|
||||
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.Mockito.mock;
|
||||
|
@ -66,18 +67,28 @@ public class NamespaceHttpBasicTests {
|
|||
public void basicAuthenticationWhenUsingDefaultsThenMatchesNamespace() throws Exception {
|
||||
this.spring.register(HttpBasicConfig.class, UserConfig.class).autowire();
|
||||
this.mvc.perform(get("/")).andExpect(status().isUnauthorized());
|
||||
this.mvc.perform(get("/").with(httpBasic("user", "invalid"))).andExpect(status().isUnauthorized())
|
||||
MockHttpServletRequestBuilder requestWithInvalidPassword = get("/").with(httpBasic("user", "invalid"));
|
||||
// @formatter:off
|
||||
this.mvc.perform(requestWithInvalidPassword)
|
||||
.andExpect(status().isUnauthorized())
|
||||
.andExpect(header().string(HttpHeaders.WWW_AUTHENTICATE, "Basic realm=\"Realm\""));
|
||||
this.mvc.perform(get("/").with(httpBasic("user", "password"))).andExpect(status().isNotFound());
|
||||
// @formatter:on
|
||||
MockHttpServletRequestBuilder requestWithValidPassword = get("/").with(httpBasic("user", "password"));
|
||||
this.mvc.perform(requestWithValidPassword).andExpect(status().isNotFound());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void basicAuthenticationWhenUsingDefaultsInLambdaThenMatchesNamespace() throws Exception {
|
||||
this.spring.register(HttpBasicLambdaConfig.class, UserConfig.class).autowire();
|
||||
this.mvc.perform(get("/")).andExpect(status().isUnauthorized());
|
||||
this.mvc.perform(get("/").with(httpBasic("user", "invalid"))).andExpect(status().isUnauthorized())
|
||||
MockHttpServletRequestBuilder requestWithInvalidPassword = get("/").with(httpBasic("user", "invalid"));
|
||||
// @formatter:off
|
||||
this.mvc.perform(requestWithInvalidPassword)
|
||||
.andExpect(status().isUnauthorized())
|
||||
.andExpect(header().string(HttpHeaders.WWW_AUTHENTICATE, "Basic realm=\"Realm\""));
|
||||
this.mvc.perform(get("/").with(httpBasic("user", "password"))).andExpect(status().isNotFound());
|
||||
// @formatter:on
|
||||
MockHttpServletRequestBuilder requestWithValidPassword = get("/").with(httpBasic("user", "password"));
|
||||
this.mvc.perform(requestWithValidPassword).andExpect(status().isNotFound());
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -86,15 +97,23 @@ public class NamespaceHttpBasicTests {
|
|||
@Test
|
||||
public void basicAuthenticationWhenUsingCustomRealmThenMatchesNamespace() throws Exception {
|
||||
this.spring.register(CustomHttpBasicConfig.class, UserConfig.class).autowire();
|
||||
this.mvc.perform(get("/").with(httpBasic("user", "invalid"))).andExpect(status().isUnauthorized())
|
||||
MockHttpServletRequestBuilder requestWithInvalidPassword = get("/").with(httpBasic("user", "invalid"));
|
||||
// @formatter:off
|
||||
this.mvc.perform(requestWithInvalidPassword)
|
||||
.andExpect(status().isUnauthorized())
|
||||
.andExpect(header().string(HttpHeaders.WWW_AUTHENTICATE, "Basic realm=\"Custom Realm\""));
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
public void basicAuthenticationWhenUsingCustomRealmInLambdaThenMatchesNamespace() throws Exception {
|
||||
this.spring.register(CustomHttpBasicLambdaConfig.class, UserConfig.class).autowire();
|
||||
this.mvc.perform(get("/").with(httpBasic("user", "invalid"))).andExpect(status().isUnauthorized())
|
||||
MockHttpServletRequestBuilder requestWithInvalidPassword = get("/").with(httpBasic("user", "invalid"));
|
||||
// @formatter:off
|
||||
this.mvc.perform(requestWithInvalidPassword)
|
||||
.andExpect(status().isUnauthorized())
|
||||
.andExpect(header().string(HttpHeaders.WWW_AUTHENTICATE, "Basic realm=\"Custom Realm\""));
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -39,6 +39,7 @@ import org.springframework.security.config.test.SpringTestRule;
|
|||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.core.AuthenticationException;
|
||||
import org.springframework.security.core.userdetails.User;
|
||||
import org.springframework.security.core.userdetails.UserDetails;
|
||||
import org.springframework.security.core.userdetails.UserDetailsService;
|
||||
import org.springframework.security.provisioning.InMemoryUserDetailsManager;
|
||||
import org.springframework.security.web.FilterChainProxy;
|
||||
|
@ -193,8 +194,14 @@ public class NamespaceHttpCustomFilterTests {
|
|||
|
||||
@Bean
|
||||
UserDetailsService userDetailsService() {
|
||||
return new InMemoryUserDetailsManager(
|
||||
User.withDefaultPasswordEncoder().username("user").password("password").roles("USER").build());
|
||||
// @formatter:off
|
||||
UserDetails user = User.withDefaultPasswordEncoder()
|
||||
.username("user")
|
||||
.password("password")
|
||||
.roles("USER")
|
||||
.build();
|
||||
// @formatter:on
|
||||
return new InMemoryUserDetailsManager(user);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -36,6 +36,7 @@ import org.springframework.security.web.authentication.SavedRequestAwareAuthenti
|
|||
import org.springframework.security.web.authentication.SimpleUrlAuthenticationFailureHandler;
|
||||
import org.springframework.security.web.authentication.WebAuthenticationDetailsSource;
|
||||
import org.springframework.test.web.servlet.MockMvc;
|
||||
import org.springframework.test.web.servlet.request.MockHttpServletRequestBuilder;
|
||||
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.Mockito.spy;
|
||||
|
@ -65,8 +66,13 @@ public class NamespaceHttpFormLoginTests {
|
|||
this.spring.register(FormLoginConfig.class, UserDetailsServiceConfig.class).autowire();
|
||||
this.mvc.perform(get("/")).andExpect(redirectedUrl("http://localhost/login"));
|
||||
this.mvc.perform(post("/login").with(csrf())).andExpect(redirectedUrl("/login?error"));
|
||||
this.mvc.perform(post("/login").param("username", "user").param("password", "password").with(csrf()))
|
||||
.andExpect(redirectedUrl("/"));
|
||||
// @formatter:off
|
||||
MockHttpServletRequestBuilder loginRequest = post("/login")
|
||||
.param("username", "user")
|
||||
.param("password", "password")
|
||||
.with(csrf());
|
||||
// @formatter:on
|
||||
this.mvc.perform(loginRequest).andExpect(redirectedUrl("/"));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -75,8 +81,13 @@ public class NamespaceHttpFormLoginTests {
|
|||
this.mvc.perform(get("/")).andExpect(redirectedUrl("http://localhost/authentication/login"));
|
||||
this.mvc.perform(post("/authentication/login/process").with(csrf()))
|
||||
.andExpect(redirectedUrl("/authentication/login?failed"));
|
||||
this.mvc.perform(post("/authentication/login/process").param("username", "user").param("password", "password")
|
||||
.with(csrf())).andExpect(redirectedUrl("/default"));
|
||||
// @formatter:off
|
||||
MockHttpServletRequestBuilder request = post("/authentication/login/process")
|
||||
.param("username", "user")
|
||||
.param("password", "password")
|
||||
.with(csrf());
|
||||
// @formatter:on
|
||||
this.mvc.perform(request).andExpect(redirectedUrl("/default"));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -85,8 +96,13 @@ public class NamespaceHttpFormLoginTests {
|
|||
this.mvc.perform(get("/")).andExpect(redirectedUrl("http://localhost/login"));
|
||||
this.mvc.perform(post("/login").with(csrf())).andExpect(redirectedUrl("/custom/failure"));
|
||||
verifyBean(WebAuthenticationDetailsSource.class).buildDetails(any(HttpServletRequest.class));
|
||||
this.mvc.perform(post("/login").param("username", "user").param("password", "password").with(csrf()))
|
||||
.andExpect(redirectedUrl("/custom/targetUrl"));
|
||||
// @formatter:off
|
||||
MockHttpServletRequestBuilder loginRequest = post("/login")
|
||||
.param("username", "user")
|
||||
.param("password", "password")
|
||||
.with(csrf());
|
||||
// @formatter:on
|
||||
this.mvc.perform(loginRequest).andExpect(redirectedUrl("/custom/targetUrl"));
|
||||
}
|
||||
|
||||
private <T> T verifyBean(Class<T> beanClass) {
|
||||
|
|
|
@ -30,6 +30,7 @@ import org.springframework.security.config.test.SpringTestRule;
|
|||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.core.authority.AuthorityUtils;
|
||||
import org.springframework.test.web.servlet.MockMvc;
|
||||
import org.springframework.test.web.servlet.request.MockHttpServletRequestBuilder;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
@ -66,22 +67,26 @@ public class NamespaceHttpInterceptUrlTests {
|
|||
@Test
|
||||
public void authenticatedRequestWhenUrlRequiresElevatedPrivilegesThenBehaviorMatchesNamespace() throws Exception {
|
||||
this.spring.register(HttpInterceptUrlConfig.class).autowire();
|
||||
this.mvc.perform(get("/users").with(authentication(user("ROLE_USER")))).andExpect(status().isForbidden());
|
||||
MockHttpServletRequestBuilder requestWithUser = get("/users").with(authentication(user("ROLE_USER")));
|
||||
this.mvc.perform(requestWithUser).andExpect(status().isForbidden());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void authenticatedRequestWhenAuthorizedThenBehaviorMatchesNamespace() throws Exception {
|
||||
this.spring.register(HttpInterceptUrlConfig.class, BaseController.class).autowire();
|
||||
this.mvc.perform(get("/users").with(authentication(user("ROLE_ADMIN")))).andExpect(status().isOk()).andReturn();
|
||||
MockHttpServletRequestBuilder requestWithAdmin = get("/users").with(authentication(user("ROLE_ADMIN")));
|
||||
this.mvc.perform(requestWithAdmin).andExpect(status().isOk()).andReturn();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void requestWhenMappedByPostInterceptUrlThenBehaviorMatchesNamespace() throws Exception {
|
||||
this.spring.register(HttpInterceptUrlConfig.class, BaseController.class).autowire();
|
||||
this.mvc.perform(get("/admin/post").with(authentication(user("ROLE_USER")))).andExpect(status().isOk());
|
||||
this.mvc.perform(post("/admin/post").with(authentication(user("ROLE_USER")))).andExpect(status().isForbidden());
|
||||
this.mvc.perform(post("/admin/post").with(csrf()).with(authentication(user("ROLE_ADMIN"))))
|
||||
.andExpect(status().isOk());
|
||||
MockHttpServletRequestBuilder getWithUser = get("/admin/post").with(authentication(user("ROLE_USER")));
|
||||
this.mvc.perform(getWithUser).andExpect(status().isOk());
|
||||
MockHttpServletRequestBuilder postWithUser = post("/admin/post").with(authentication(user("ROLE_USER")));
|
||||
this.mvc.perform(postWithUser).andExpect(status().isForbidden());
|
||||
MockHttpServletRequestBuilder requestWithAdmin = post("/admin/post").with(csrf()).with(authentication(user("ROLE_ADMIN")));
|
||||
this.mvc.perform(requestWithAdmin).andExpect(status().isOk());
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
|
@ -40,6 +40,7 @@ import org.springframework.security.web.authentication.logout.SimpleUrlLogoutSuc
|
|||
import org.springframework.test.context.junit4.SpringRunner;
|
||||
import org.springframework.test.web.servlet.MockMvc;
|
||||
import org.springframework.test.web.servlet.ResultMatcher;
|
||||
import org.springframework.test.web.servlet.request.MockHttpServletRequestBuilder;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.csrf;
|
||||
|
@ -72,15 +73,21 @@ public class NamespaceHttpLogoutTests {
|
|||
@WithMockUser
|
||||
public void logoutWhenUsingDefaultsThenMatchesNamespace() throws Exception {
|
||||
this.spring.register(HttpLogoutConfig.class).autowire();
|
||||
this.mvc.perform(post("/logout").with(csrf())).andExpect(authenticated(false))
|
||||
.andExpect(redirectedUrl("/login?logout")).andExpect(noCookies()).andExpect(session(Objects::isNull));
|
||||
// @formatter:off
|
||||
this.mvc.perform(post("/logout").with(csrf()))
|
||||
.andExpect(authenticated(false))
|
||||
.andExpect(redirectedUrl("/login?logout"))
|
||||
.andExpect(noCookies())
|
||||
.andExpect(session(Objects::isNull));
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
@WithMockUser
|
||||
public void logoutWhenDisabledInLambdaThenRespondsWithNotFound() throws Exception {
|
||||
this.spring.register(HttpLogoutDisabledInLambdaConfig.class).autowire();
|
||||
this.mvc.perform(post("/logout").with(csrf()).with(user("user"))).andExpect(status().isNotFound());
|
||||
MockHttpServletRequestBuilder logoutRequest = post("/logout").with(csrf()).with(user("user"));
|
||||
this.mvc.perform(logoutRequest).andExpect(status().isNotFound());
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -90,20 +97,28 @@ public class NamespaceHttpLogoutTests {
|
|||
@WithMockUser
|
||||
public void logoutWhenUsingVariousCustomizationsMatchesNamespace() throws Exception {
|
||||
this.spring.register(CustomHttpLogoutConfig.class).autowire();
|
||||
this.mvc.perform(post("/custom-logout").with(csrf())).andExpect(authenticated(false))
|
||||
// @formatter:off
|
||||
this.mvc.perform(post("/custom-logout").with(csrf()))
|
||||
.andExpect(authenticated(false))
|
||||
.andExpect(redirectedUrl("/logout-success"))
|
||||
.andExpect((result) -> assertThat(result.getResponse().getCookies()).hasSize(1))
|
||||
.andExpect(cookie().maxAge("remove", 0)).andExpect(session(Objects::nonNull));
|
||||
.andExpect(cookie().maxAge("remove", 0))
|
||||
.andExpect(session(Objects::nonNull));
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
@WithMockUser
|
||||
public void logoutWhenUsingVariousCustomizationsInLambdaThenMatchesNamespace() throws Exception {
|
||||
this.spring.register(CustomHttpLogoutInLambdaConfig.class).autowire();
|
||||
this.mvc.perform(post("/custom-logout").with(csrf())).andExpect(authenticated(false))
|
||||
// @formatter:off
|
||||
this.mvc.perform(post("/custom-logout").with(csrf()))
|
||||
.andExpect(authenticated(false))
|
||||
.andExpect(redirectedUrl("/logout-success"))
|
||||
.andExpect((result) -> assertThat(result.getResponse().getCookies()).hasSize(1))
|
||||
.andExpect(cookie().maxAge("remove", 0)).andExpect(session(Objects::nonNull));
|
||||
.andExpect(cookie().maxAge("remove", 0))
|
||||
.andExpect(session(Objects::nonNull));
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -113,18 +128,26 @@ public class NamespaceHttpLogoutTests {
|
|||
@WithMockUser
|
||||
public void logoutWhenUsingSuccessHandlerRefThenMatchesNamespace() throws Exception {
|
||||
this.spring.register(SuccessHandlerRefHttpLogoutConfig.class).autowire();
|
||||
this.mvc.perform(post("/logout").with(csrf())).andExpect(authenticated(false))
|
||||
.andExpect(redirectedUrl("/SuccessHandlerRefHttpLogoutConfig")).andExpect(noCookies())
|
||||
// @formatter:off
|
||||
this.mvc.perform(post("/logout").with(csrf()))
|
||||
.andExpect(authenticated(false))
|
||||
.andExpect(redirectedUrl("/SuccessHandlerRefHttpLogoutConfig"))
|
||||
.andExpect(noCookies())
|
||||
.andExpect(session(Objects::isNull));
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
@WithMockUser
|
||||
public void logoutWhenUsingSuccessHandlerRefInLambdaThenMatchesNamespace() throws Exception {
|
||||
this.spring.register(SuccessHandlerRefHttpLogoutInLambdaConfig.class).autowire();
|
||||
this.mvc.perform(post("/logout").with(csrf())).andExpect(authenticated(false))
|
||||
.andExpect(redirectedUrl("/SuccessHandlerRefHttpLogoutConfig")).andExpect(noCookies())
|
||||
// @formatter:off
|
||||
this.mvc.perform(post("/logout").with(csrf()))
|
||||
.andExpect(authenticated(false))
|
||||
.andExpect(redirectedUrl("/SuccessHandlerRefHttpLogoutConfig"))
|
||||
.andExpect(noCookies())
|
||||
.andExpect(session(Objects::isNull));
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
ResultMatcher authenticated(boolean authenticated) {
|
||||
|
|
|
@ -56,6 +56,7 @@ import org.springframework.security.web.authentication.SimpleUrlAuthenticationFa
|
|||
import org.springframework.security.web.authentication.WebAuthenticationDetailsSource;
|
||||
import org.springframework.test.web.servlet.MockMvc;
|
||||
import org.springframework.test.web.servlet.MvcResult;
|
||||
import org.springframework.test.web.servlet.request.MockHttpServletRequestBuilder;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
|
@ -141,19 +142,22 @@ public class NamespaceHttpOpenIDLoginTests {
|
|||
OpenIDAuthenticationToken token = new OpenIDAuthenticationToken(OpenIDAuthenticationStatus.SUCCESS,
|
||||
"identityUrl", "message", Arrays.asList(new OpenIDAttribute("name", "type")));
|
||||
OpenIDLoginCustomRefsConfig.AUDS = mock(AuthenticationUserDetailsService.class);
|
||||
given(OpenIDLoginCustomRefsConfig.AUDS.loadUserDetails(any(Authentication.class)))
|
||||
.willReturn(new User("user", "password", AuthorityUtils.createAuthorityList("ROLE_USER")));
|
||||
User user = new User("user", "password", AuthorityUtils.createAuthorityList("ROLE_USER"));
|
||||
given(OpenIDLoginCustomRefsConfig.AUDS.loadUserDetails(any(Authentication.class))).willReturn(user);
|
||||
OpenIDLoginCustomRefsConfig.ADS = spy(new WebAuthenticationDetailsSource());
|
||||
OpenIDLoginCustomRefsConfig.CONSUMER = mock(OpenIDConsumer.class);
|
||||
this.spring.register(OpenIDLoginCustomRefsConfig.class, UserDetailsServiceConfig.class).autowire();
|
||||
given(OpenIDLoginCustomRefsConfig.CONSUMER.endConsumption(any(HttpServletRequest.class)))
|
||||
.willThrow(new AuthenticationServiceException("boom"));
|
||||
this.mvc.perform(post("/login/openid").with(csrf()).param("openid.identity", "identity"))
|
||||
.andExpect(redirectedUrl("/custom/failure"));
|
||||
// @formatter:off
|
||||
MockHttpServletRequestBuilder login = post("/login/openid")
|
||||
.with(csrf())
|
||||
.param("openid.identity", "identity");
|
||||
// @formatter:on
|
||||
this.mvc.perform(login).andExpect(redirectedUrl("/custom/failure"));
|
||||
reset(OpenIDLoginCustomRefsConfig.CONSUMER);
|
||||
given(OpenIDLoginCustomRefsConfig.CONSUMER.endConsumption(any(HttpServletRequest.class))).willReturn(token);
|
||||
this.mvc.perform(post("/login/openid").with(csrf()).param("openid.identity", "identity"))
|
||||
.andExpect(redirectedUrl("/custom/targetUrl"));
|
||||
this.mvc.perform(login).andExpect(redirectedUrl("/custom/targetUrl"));
|
||||
verify(OpenIDLoginCustomRefsConfig.AUDS).loadUserDetails(any(Authentication.class));
|
||||
verify(OpenIDLoginCustomRefsConfig.ADS).buildDetails(any(Object.class));
|
||||
}
|
||||
|
|
|
@ -62,15 +62,21 @@ public class NamespaceHttpServerAccessDeniedHandlerTests {
|
|||
@Test
|
||||
public void requestWhenCustomAccessDeniedPageThenBehaviorMatchesNamespace() throws Exception {
|
||||
this.spring.register(AccessDeniedPageConfig.class).autowire();
|
||||
this.mvc.perform(get("/").with(authentication(user()))).andExpect(status().isForbidden())
|
||||
// @formatter:off
|
||||
this.mvc.perform(get("/").with(authentication(user())))
|
||||
.andExpect(status().isForbidden())
|
||||
.andExpect(forwardedUrl("/AccessDeniedPageConfig"));
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
public void requestWhenCustomAccessDeniedPageInLambdaThenForwardedToCustomPage() throws Exception {
|
||||
this.spring.register(AccessDeniedPageInLambdaConfig.class).autowire();
|
||||
this.mvc.perform(get("/").with(authentication(user()))).andExpect(status().isForbidden())
|
||||
// @formatter:off
|
||||
this.mvc.perform(get("/").with(authentication(user())))
|
||||
.andExpect(status().isForbidden())
|
||||
.andExpect(forwardedUrl("/AccessDeniedPageConfig"));
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
|
@ -282,7 +282,11 @@ public class NamespaceHttpX509Tests {
|
|||
|
||||
@Override
|
||||
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
|
||||
auth.inMemoryAuthentication().withUser("rod").password("password").roles("USER", "ADMIN");
|
||||
// @formatter:off
|
||||
auth
|
||||
.inMemoryAuthentication()
|
||||
.withUser("rod").password("password").roles("USER", "ADMIN");
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -46,6 +46,7 @@ import org.springframework.security.web.authentication.rememberme.PersistentReme
|
|||
import org.springframework.security.web.authentication.rememberme.PersistentTokenRepository;
|
||||
import org.springframework.test.web.servlet.MockMvc;
|
||||
import org.springframework.test.web.servlet.MvcResult;
|
||||
import org.springframework.test.web.servlet.request.MockHttpServletRequestBuilder;
|
||||
import org.springframework.test.web.servlet.request.RequestPostProcessor;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
@ -87,12 +88,25 @@ public class NamespaceRememberMeTests {
|
|||
assertThat(rememberMe).isNotNull();
|
||||
this.mvc.perform(get("/authentication-class").cookie(rememberMe))
|
||||
.andExpect(content().string(RememberMeAuthenticationToken.class.getName()));
|
||||
result = this.mvc.perform(post("/logout").with(csrf()).session(session).cookie(rememberMe))
|
||||
.andExpect(redirectedUrl("/login?logout")).andReturn();
|
||||
// @formatter:off
|
||||
MockHttpServletRequestBuilder logoutRequest = post("/logout")
|
||||
.with(csrf())
|
||||
.session(session)
|
||||
.cookie(rememberMe);
|
||||
result = this.mvc.perform(logoutRequest)
|
||||
.andExpect(redirectedUrl("/login?logout"))
|
||||
.andReturn();
|
||||
// @formatter:on
|
||||
rememberMe = result.getResponse().getCookie("remember-me");
|
||||
assertThat(rememberMe).isNotNull().extracting(Cookie::getMaxAge).isEqualTo(0);
|
||||
this.mvc.perform(post("/authentication-class").with(csrf()).cookie(rememberMe))
|
||||
.andExpect(redirectedUrl("http://localhost/login")).andReturn();
|
||||
// @formatter:off
|
||||
MockHttpServletRequestBuilder authenticationClassRequest = post("/authentication-class")
|
||||
.with(csrf())
|
||||
.cookie(rememberMe);
|
||||
this.mvc.perform(authenticationClassRequest)
|
||||
.andExpect(redirectedUrl("http://localhost/login"))
|
||||
.andReturn();
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
// SEC-3170 - RememberMeService implementations should not have to also implement
|
||||
|
@ -125,13 +139,27 @@ public class NamespaceRememberMeTests {
|
|||
@Test
|
||||
public void rememberMeLoginWhenKeyDeclaredThenMatchesNamespace() throws Exception {
|
||||
this.spring.register(WithoutKeyConfig.class, KeyConfig.class, SecurityController.class).autowire();
|
||||
Cookie withoutKey = this.mvc.perform(post("/without-key/login").with(rememberMeLogin()))
|
||||
.andExpect(redirectedUrl("/")).andReturn().getResponse().getCookie("remember-me");
|
||||
this.mvc.perform(get("/somewhere").cookie(withoutKey)).andExpect(status().isFound())
|
||||
.andExpect(redirectedUrl("http://localhost/login"));
|
||||
Cookie withKey = this.mvc.perform(post("/login").with(rememberMeLogin())).andReturn().getResponse()
|
||||
MockHttpServletRequestBuilder requestWithRememberme = post("/without-key/login").with(rememberMeLogin());
|
||||
// @formatter:off
|
||||
Cookie withoutKey = this.mvc.perform(requestWithRememberme)
|
||||
.andExpect(redirectedUrl("/"))
|
||||
.andReturn()
|
||||
.getResponse()
|
||||
.getCookie("remember-me");
|
||||
this.mvc.perform(get("/somewhere").cookie(withKey)).andExpect(status().isNotFound());
|
||||
// @formatter:on
|
||||
MockHttpServletRequestBuilder somewhereRequest = get("/somewhere").cookie(withoutKey);
|
||||
// @formatter:off
|
||||
this.mvc.perform(somewhereRequest)
|
||||
.andExpect(status().isFound())
|
||||
.andExpect(redirectedUrl("http://localhost/login"));
|
||||
MockHttpServletRequestBuilder loginWithRememberme = post("/login").with(rememberMeLogin());
|
||||
Cookie withKey = this.mvc.perform(loginWithRememberme)
|
||||
.andReturn()
|
||||
.getResponse()
|
||||
.getCookie("remember-me");
|
||||
this.mvc.perform(get("/somewhere").cookie(withKey))
|
||||
.andExpect(status().isNotFound());
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
// http/remember-me@services-alias is not supported use standard aliasing instead
|
||||
|
@ -149,40 +177,61 @@ public class NamespaceRememberMeTests {
|
|||
@Test
|
||||
public void rememberMeLoginWhenTokenValidityDeclaredThenMatchesNamespace() throws Exception {
|
||||
this.spring.register(TokenValiditySecondsConfig.class).autowire();
|
||||
Cookie expiredRememberMe = this.mvc.perform(post("/login").with(rememberMeLogin())).andReturn().getResponse()
|
||||
// @formatter:off
|
||||
Cookie expiredRememberMe = this.mvc.perform(post("/login").with(rememberMeLogin()))
|
||||
.andReturn()
|
||||
.getResponse()
|
||||
.getCookie("remember-me");
|
||||
// @formatter:on
|
||||
assertThat(expiredRememberMe).extracting(Cookie::getMaxAge).isEqualTo(314);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void rememberMeLoginWhenUsingDefaultsThenCookieMaxAgeMatchesNamespace() throws Exception {
|
||||
this.spring.register(RememberMeConfig.class).autowire();
|
||||
Cookie expiredRememberMe = this.mvc.perform(post("/login").with(rememberMeLogin())).andReturn().getResponse()
|
||||
// @formatter:off
|
||||
Cookie expiredRememberMe = this.mvc.perform(post("/login").with(rememberMeLogin()))
|
||||
.andReturn()
|
||||
.getResponse()
|
||||
.getCookie("remember-me");
|
||||
// @formatter:on
|
||||
assertThat(expiredRememberMe).extracting(Cookie::getMaxAge).isEqualTo(AbstractRememberMeServices.TWO_WEEKS_S);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void rememberMeLoginWhenUsingSecureCookieThenMatchesNamespace() throws Exception {
|
||||
this.spring.register(UseSecureCookieConfig.class).autowire();
|
||||
Cookie secureCookie = this.mvc.perform(post("/login").with(rememberMeLogin())).andReturn().getResponse()
|
||||
// @formatter:off
|
||||
Cookie secureCookie = this.mvc.perform(post("/login").with(rememberMeLogin()))
|
||||
.andReturn()
|
||||
.getResponse()
|
||||
.getCookie("remember-me");
|
||||
// @formatter:on
|
||||
assertThat(secureCookie).extracting(Cookie::getSecure).isEqualTo(true);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void rememberMeLoginWhenUsingDefaultsThenCookieSecurityMatchesNamespace() throws Exception {
|
||||
this.spring.register(RememberMeConfig.class).autowire();
|
||||
Cookie secureCookie = this.mvc.perform(post("/login").with(rememberMeLogin()).secure(true)).andReturn()
|
||||
.getResponse().getCookie("remember-me");
|
||||
// @formatter:off
|
||||
Cookie secureCookie = this.mvc.perform(post("/login").with(rememberMeLogin()).secure(true))
|
||||
.andReturn()
|
||||
.getResponse()
|
||||
.getCookie("remember-me");
|
||||
// @formatter:on
|
||||
assertThat(secureCookie).extracting(Cookie::getSecure).isEqualTo(true);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void rememberMeLoginWhenParameterSpecifiedThenMatchesNamespace() throws Exception {
|
||||
this.spring.register(RememberMeParameterConfig.class).autowire();
|
||||
Cookie rememberMe = this.mvc.perform(post("/login").with(rememberMeLogin("rememberMe", true))).andReturn()
|
||||
.getResponse().getCookie("remember-me");
|
||||
MockHttpServletRequestBuilder loginWithRememberme = post("/login").with(rememberMeLogin("rememberMe", true));
|
||||
// @formatter:off
|
||||
Cookie rememberMe = this.mvc.perform(loginWithRememberme)
|
||||
.andReturn()
|
||||
.getResponse()
|
||||
.getCookie("remember-me");
|
||||
// @formatter:on
|
||||
assertThat(rememberMe).isNotNull();
|
||||
}
|
||||
|
||||
|
@ -190,8 +239,12 @@ public class NamespaceRememberMeTests {
|
|||
@Test
|
||||
public void rememberMeLoginWhenCookieNameDeclaredThenMatchesNamespace() throws Exception {
|
||||
this.spring.register(RememberMeCookieNameConfig.class).autowire();
|
||||
Cookie rememberMe = this.mvc.perform(post("/login").with(rememberMeLogin())).andReturn().getResponse()
|
||||
// @formatter:off
|
||||
Cookie rememberMe = this.mvc.perform(post("/login").with(rememberMeLogin()))
|
||||
.andReturn()
|
||||
.getResponse()
|
||||
.getCookie("rememberMe");
|
||||
// @formatter:on
|
||||
assertThat(rememberMe).isNotNull();
|
||||
}
|
||||
|
||||
|
@ -207,8 +260,8 @@ public class NamespaceRememberMeTests {
|
|||
public void rememberMeLoginWhenUserDetailsServiceDeclaredThenMatchesNamespace() throws Exception {
|
||||
UserServiceRefConfig.USERDETAILS_SERVICE = mock(UserDetailsService.class);
|
||||
this.spring.register(UserServiceRefConfig.class).autowire();
|
||||
given(UserServiceRefConfig.USERDETAILS_SERVICE.loadUserByUsername("user"))
|
||||
.willReturn(new User("user", "password", AuthorityUtils.createAuthorityList("ROLE_USER")));
|
||||
User user = new User("user", "password", AuthorityUtils.createAuthorityList("ROLE_USER"));
|
||||
given(UserServiceRefConfig.USERDETAILS_SERVICE.loadUserByUsername("user")).willReturn(user);
|
||||
this.mvc.perform(post("/login").with(rememberMeLogin()));
|
||||
verify(UserServiceRefConfig.USERDETAILS_SERVICE).loadUserByUsername("user");
|
||||
}
|
||||
|
@ -470,7 +523,7 @@ public class NamespaceRememberMeTests {
|
|||
@Bean
|
||||
public UserDetailsService userDetailsService() {
|
||||
return new InMemoryUserDetailsManager(
|
||||
// @formatter:off
|
||||
// @formatter:off
|
||||
User.withDefaultPasswordEncoder()
|
||||
.username("user")
|
||||
.password("password")
|
||||
|
|
|
@ -52,6 +52,7 @@ import org.springframework.security.web.session.InvalidSessionStrategy;
|
|||
import org.springframework.test.web.servlet.MockMvc;
|
||||
import org.springframework.test.web.servlet.MvcResult;
|
||||
import org.springframework.test.web.servlet.ResultMatcher;
|
||||
import org.springframework.test.web.servlet.request.MockHttpServletRequestBuilder;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
|
@ -84,19 +85,24 @@ public class NamespaceSessionManagementTests {
|
|||
.autowire();
|
||||
MockHttpSession session = new MockHttpSession();
|
||||
String sessionId = session.getId();
|
||||
MvcResult result = this.mvc.perform(get("/auth").session(session).with(httpBasic("user", "password")))
|
||||
.andExpect(session()).andReturn();
|
||||
MockHttpServletRequestBuilder request = get("/auth").session(session).with(httpBasic("user", "password"));
|
||||
// @formatter:off
|
||||
MvcResult result = this.mvc.perform(request)
|
||||
.andExpect(session())
|
||||
.andReturn();
|
||||
// @formatter:on
|
||||
assertThat(result.getRequest().getSession(false).getId()).isNotEqualTo(sessionId);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void authenticateWhenUsingInvalidSessionUrlThenMatchesNamespace() throws Exception {
|
||||
this.spring.register(CustomSessionManagementConfig.class).autowire();
|
||||
this.mvc.perform(get("/auth").with((request) -> {
|
||||
MockHttpServletRequestBuilder request = get("/auth").with((request) -> {
|
||||
request.setRequestedSessionIdValid(false);
|
||||
request.setRequestedSessionId("id");
|
||||
return request;
|
||||
})).andExpect(redirectedUrl("/invalid-session"));
|
||||
});
|
||||
this.mvc.perform(request).andExpect(redirectedUrl("/invalid-session"));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -127,8 +133,12 @@ public class NamespaceSessionManagementTests {
|
|||
mock.setSession(new MockHttpSession());
|
||||
given(mock.changeSessionId()).willThrow(SessionAuthenticationException.class);
|
||||
mock.setMethod("GET");
|
||||
this.mvc.perform(get("/auth").with((request) -> mock).with(httpBasic("user", "password")))
|
||||
.andExpect(redirectedUrl("/session-auth-error"));
|
||||
// @formatter:off
|
||||
MockHttpServletRequestBuilder request = get("/auth")
|
||||
.with((request) -> mock)
|
||||
.with(httpBasic("user", "password"));
|
||||
// @formatter:on
|
||||
this.mvc.perform(request).andExpect(redirectedUrl("/session-auth-error"));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -136,7 +146,8 @@ public class NamespaceSessionManagementTests {
|
|||
this.spring.register(CustomSessionManagementConfig.class, BasicController.class, UserDetailsServiceConfig.class)
|
||||
.autowire();
|
||||
SessionRegistry sessionRegistry = this.spring.getContext().getBean(SessionRegistry.class);
|
||||
this.mvc.perform(get("/auth").with(httpBasic("user", "password"))).andExpect(status().isOk());
|
||||
MockHttpServletRequestBuilder request = get("/auth").with(httpBasic("user", "password"));
|
||||
this.mvc.perform(request).andExpect(status().isOk());
|
||||
verify(sessionRegistry).registerNewSession(any(String.class), any(Object.class));
|
||||
}
|
||||
|
||||
|
@ -144,11 +155,12 @@ public class NamespaceSessionManagementTests {
|
|||
@Test
|
||||
public void authenticateWhenUsingCustomInvalidSessionStrategyThenMatchesNamespace() throws Exception {
|
||||
this.spring.register(InvalidSessionStrategyConfig.class).autowire();
|
||||
this.mvc.perform(get("/auth").with((request) -> {
|
||||
MockHttpServletRequestBuilder request = get("/auth").with((request) -> {
|
||||
request.setRequestedSessionIdValid(false);
|
||||
request.setRequestedSessionId("id");
|
||||
return request;
|
||||
})).andExpect(status().isOk());
|
||||
});
|
||||
this.mvc.perform(request).andExpect(status().isOk());
|
||||
verifyBean(InvalidSessionStrategy.class).onInvalidSessionDetected(any(HttpServletRequest.class),
|
||||
any(HttpServletResponse.class));
|
||||
}
|
||||
|
@ -157,7 +169,8 @@ public class NamespaceSessionManagementTests {
|
|||
public void authenticateWhenUsingCustomSessionAuthenticationStrategyThenMatchesNamespace() throws Exception {
|
||||
this.spring.register(RefsSessionManagementConfig.class, BasicController.class, UserDetailsServiceConfig.class)
|
||||
.autowire();
|
||||
this.mvc.perform(get("/auth").with(httpBasic("user", "password"))).andExpect(status().isOk());
|
||||
MockHttpServletRequestBuilder request = get("/auth").with(httpBasic("user", "password"));
|
||||
this.mvc.perform(request).andExpect(status().isOk());
|
||||
verifyBean(SessionAuthenticationStrategy.class).onAuthentication(any(Authentication.class),
|
||||
any(HttpServletRequest.class), any(HttpServletResponse.class));
|
||||
}
|
||||
|
@ -169,9 +182,16 @@ public class NamespaceSessionManagementTests {
|
|||
.autowire();
|
||||
MockHttpSession givenSession = new MockHttpSession();
|
||||
String givenSessionId = givenSession.getId();
|
||||
MockHttpSession resultingSession = (MockHttpSession) this.mvc
|
||||
.perform(get("/auth").session(givenSession).with(httpBasic("user", "password")))
|
||||
.andExpect(status().isOk()).andReturn().getRequest().getSession(false);
|
||||
// @formatter:off
|
||||
MockHttpServletRequestBuilder request = get("/auth")
|
||||
.session(givenSession)
|
||||
.with(httpBasic("user", "password"));
|
||||
MockHttpSession resultingSession = (MockHttpSession) this.mvc.perform(request)
|
||||
.andExpect(status().isOk())
|
||||
.andReturn()
|
||||
.getRequest()
|
||||
.getSession(false);
|
||||
// @formatter:on
|
||||
assertThat(givenSessionId).isEqualTo(resultingSession.getId());
|
||||
}
|
||||
|
||||
|
@ -182,9 +202,15 @@ public class NamespaceSessionManagementTests {
|
|||
MockHttpSession givenSession = new MockHttpSession();
|
||||
String givenSessionId = givenSession.getId();
|
||||
givenSession.setAttribute("name", "value");
|
||||
MockHttpSession resultingSession = (MockHttpSession) this.mvc
|
||||
.perform(get("/auth").session(givenSession).with(httpBasic("user", "password")))
|
||||
.andExpect(status().isOk()).andReturn().getRequest().getSession(false);
|
||||
// @formatter:off
|
||||
MockHttpSession resultingSession = (MockHttpSession) this.mvc.perform(get("/auth")
|
||||
.session(givenSession)
|
||||
.with(httpBasic("user", "password")))
|
||||
.andExpect(status().isOk())
|
||||
.andReturn()
|
||||
.getRequest()
|
||||
.getSession(false);
|
||||
// @formatter:on
|
||||
assertThat(givenSessionId).isNotEqualTo(resultingSession.getId());
|
||||
assertThat(resultingSession.getAttribute("name")).isEqualTo("value");
|
||||
}
|
||||
|
@ -193,8 +219,12 @@ public class NamespaceSessionManagementTests {
|
|||
@Test
|
||||
public void authenticateWhenUsingSessionFixationProtectionThenUsesNonNullEventPublisher() throws Exception {
|
||||
this.spring.register(SFPPostProcessedConfig.class, UserDetailsServiceConfig.class).autowire();
|
||||
this.mvc.perform(get("/auth").session(new MockHttpSession()).with(httpBasic("user", "password")))
|
||||
.andExpect(status().isNotFound());
|
||||
// @formatter:off
|
||||
MockHttpServletRequestBuilder request = get("/auth")
|
||||
.session(new MockHttpSession())
|
||||
.with(httpBasic("user", "password"));
|
||||
// @formatter:on
|
||||
this.mvc.perform(request).andExpect(status().isNotFound());
|
||||
verifyBean(MockEventListener.class).onApplicationEvent(any(SessionFixationProtectionEvent.class));
|
||||
}
|
||||
|
||||
|
@ -204,9 +234,15 @@ public class NamespaceSessionManagementTests {
|
|||
MockHttpSession givenSession = new MockHttpSession();
|
||||
String givenSessionId = givenSession.getId();
|
||||
givenSession.setAttribute("name", "value");
|
||||
MockHttpSession resultingSession = (MockHttpSession) this.mvc
|
||||
.perform(get("/auth").session(givenSession).with(httpBasic("user", "password")))
|
||||
.andExpect(status().isNotFound()).andReturn().getRequest().getSession(false);
|
||||
MockHttpServletRequestBuilder request = get("/auth").session(givenSession)
|
||||
.with(httpBasic("user", "password"));
|
||||
// @formatter:off
|
||||
MockHttpSession resultingSession = (MockHttpSession) this.mvc.perform(request)
|
||||
.andExpect(status().isNotFound())
|
||||
.andReturn()
|
||||
.getRequest()
|
||||
.getSession(false);
|
||||
// @formatter:on
|
||||
assertThat(givenSessionId).isNotEqualTo(resultingSession.getId());
|
||||
assertThat(resultingSession.getAttribute("name")).isNull();
|
||||
}
|
||||
|
|
|
@ -26,6 +26,7 @@ import org.springframework.security.config.annotation.web.configuration.EnableWe
|
|||
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
|
||||
import org.springframework.security.config.test.SpringTestRule;
|
||||
import org.springframework.test.web.servlet.MockMvc;
|
||||
import org.springframework.test.web.servlet.request.MockHttpServletRequestBuilder;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
|
||||
import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.csrf;
|
||||
|
@ -49,10 +50,14 @@ public class PermitAllSupportTests {
|
|||
@Test
|
||||
public void performWhenUsingPermitAllExactUrlRequestMatcherThenMatchesExactUrl() throws Exception {
|
||||
this.spring.register(PermitAllConfig.class).autowire();
|
||||
this.mvc.perform(get("/app/xyz").contextPath("/app")).andExpect(status().isNotFound());
|
||||
this.mvc.perform(get("/app/xyz?def").contextPath("/app")).andExpect(status().isFound());
|
||||
this.mvc.perform(post("/app/abc?def").with(csrf()).contextPath("/app")).andExpect(status().isNotFound());
|
||||
this.mvc.perform(get("/app/abc").with(csrf()).contextPath("/app")).andExpect(status().isFound());
|
||||
MockHttpServletRequestBuilder request = get("/app/xyz").contextPath("/app");
|
||||
this.mvc.perform(request).andExpect(status().isNotFound());
|
||||
MockHttpServletRequestBuilder getWithQuery = get("/app/xyz?def").contextPath("/app");
|
||||
this.mvc.perform(getWithQuery).andExpect(status().isFound());
|
||||
MockHttpServletRequestBuilder postWithQueryAndCsrf = post("/app/abc?def").with(csrf()).contextPath("/app");
|
||||
this.mvc.perform(postWithQueryAndCsrf).andExpect(status().isNotFound());
|
||||
MockHttpServletRequestBuilder getWithCsrf = get("/app/abc").with(csrf()).contextPath("/app");
|
||||
this.mvc.perform(getWithCsrf).andExpect(status().isFound());
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
|
@ -40,11 +40,13 @@ import org.springframework.security.core.userdetails.PasswordEncodedUser;
|
|||
import org.springframework.security.core.userdetails.User;
|
||||
import org.springframework.security.core.userdetails.UserDetailsService;
|
||||
import org.springframework.security.provisioning.InMemoryUserDetailsManager;
|
||||
import org.springframework.security.test.web.servlet.response.SecurityMockMvcResultMatchers;
|
||||
import org.springframework.security.web.authentication.RememberMeServices;
|
||||
import org.springframework.security.web.authentication.rememberme.RememberMeAuthenticationFilter;
|
||||
import org.springframework.security.web.authentication.rememberme.TokenBasedRememberMeServices;
|
||||
import org.springframework.test.web.servlet.MockMvc;
|
||||
import org.springframework.test.web.servlet.MvcResult;
|
||||
import org.springframework.test.web.servlet.request.MockHttpServletRequestBuilder;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
|
||||
|
@ -83,8 +85,16 @@ public class RememberMeConfigurerTests {
|
|||
public void postWhenNoUserDetailsServiceThenException() {
|
||||
this.spring.register(NullUserDetailsConfig.class).autowire();
|
||||
assertThatIllegalStateException()
|
||||
.isThrownBy(() -> this.mvc.perform(post("/login").param("username", "user")
|
||||
.param("password", "password").param("remember-me", "true").with(csrf())))
|
||||
.isThrownBy(() -> {
|
||||
// @formatter:off
|
||||
MockHttpServletRequestBuilder request = post("/login")
|
||||
.param("username", "user")
|
||||
.param("password", "password")
|
||||
.param("remember-me", "true")
|
||||
.with(csrf());
|
||||
// @formatter:on
|
||||
this.mvc.perform(request);
|
||||
})
|
||||
.withMessageContaining("UserDetailsService is required");
|
||||
}
|
||||
|
||||
|
@ -99,15 +109,26 @@ public class RememberMeConfigurerTests {
|
|||
given(DuplicateDoesNotOverrideConfig.userDetailsService.loadUserByUsername(anyString()))
|
||||
.willReturn(new User("user", "password", Collections.emptyList()));
|
||||
this.spring.register(DuplicateDoesNotOverrideConfig.class).autowire();
|
||||
this.mvc.perform(get("/").with(httpBasic("user", "password")).param("remember-me", "true"));
|
||||
// @formatter:off
|
||||
MockHttpServletRequestBuilder request = get("/")
|
||||
.with(httpBasic("user", "password"))
|
||||
.param("remember-me", "true");
|
||||
// @formatter:on
|
||||
this.mvc.perform(request);
|
||||
verify(DuplicateDoesNotOverrideConfig.userDetailsService).loadUserByUsername("user");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void loginWhenRememberMeTrueThenRespondsWithRememberMeCookie() throws Exception {
|
||||
this.spring.register(RememberMeConfig.class).autowire();
|
||||
this.mvc.perform(post("/login").with(csrf()).param("username", "user").param("password", "password")
|
||||
.param("remember-me", "true")).andExpect(cookie().exists("remember-me"));
|
||||
// @formatter:off
|
||||
MockHttpServletRequestBuilder request = post("/login")
|
||||
.with(csrf())
|
||||
.param("username", "user")
|
||||
.param("password", "password")
|
||||
.param("remember-me", "true");
|
||||
// @formatter:on
|
||||
this.mvc.perform(request).andExpect(cookie().exists("remember-me"));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -116,57 +137,108 @@ public class RememberMeConfigurerTests {
|
|||
MvcResult mvcResult = this.mvc.perform(post("/login").with(csrf()).param("username", "user")
|
||||
.param("password", "password").param("remember-me", "true")).andReturn();
|
||||
Cookie rememberMeCookie = mvcResult.getResponse().getCookie("remember-me");
|
||||
this.mvc.perform(get("/abc").cookie(rememberMeCookie)).andExpect(authenticated()
|
||||
.withAuthentication((auth) -> assertThat(auth).isInstanceOf(RememberMeAuthenticationToken.class)));
|
||||
// @formatter:off
|
||||
MockHttpServletRequestBuilder request = get("/abc").cookie(rememberMeCookie);
|
||||
SecurityMockMvcResultMatchers.AuthenticatedMatcher remembermeAuthentication = authenticated()
|
||||
.withAuthentication((auth) -> assertThat(auth).isInstanceOf(RememberMeAuthenticationToken.class));
|
||||
// @formatter:on
|
||||
this.mvc.perform(request).andExpect(remembermeAuthentication);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void logoutWhenRememberMeCookieThenAuthenticationIsRememberMeCookieExpired() throws Exception {
|
||||
this.spring.register(RememberMeConfig.class).autowire();
|
||||
MvcResult mvcResult = this.mvc.perform(post("/login").with(csrf()).param("username", "user")
|
||||
.param("password", "password").param("remember-me", "true")).andReturn();
|
||||
// @formatter:off
|
||||
MockHttpServletRequestBuilder loginRequest = post("/login")
|
||||
.with(csrf())
|
||||
.param("username", "user")
|
||||
.param("password", "password")
|
||||
.param("remember-me", "true");
|
||||
// @formatter:on
|
||||
MvcResult mvcResult = this.mvc.perform(loginRequest).andReturn();
|
||||
Cookie rememberMeCookie = mvcResult.getResponse().getCookie("remember-me");
|
||||
HttpSession session = mvcResult.getRequest().getSession();
|
||||
this.mvc.perform(post("/logout").with(csrf()).cookie(rememberMeCookie).session((MockHttpSession) session))
|
||||
.andExpect(redirectedUrl("/login?logout")).andExpect(cookie().maxAge("remember-me", 0));
|
||||
// @formatter:off
|
||||
MockHttpServletRequestBuilder logoutRequest = post("/logout")
|
||||
.with(csrf())
|
||||
.cookie(rememberMeCookie)
|
||||
.session((MockHttpSession) session);
|
||||
this.mvc.perform(logoutRequest)
|
||||
.andExpect(redirectedUrl("/login?logout"))
|
||||
.andExpect(cookie().maxAge("remember-me", 0));
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getWhenRememberMeCookieAndLoggedOutThenRedirectsToLogin() throws Exception {
|
||||
this.spring.register(RememberMeConfig.class).autowire();
|
||||
MvcResult loginMvcResult = this.mvc.perform(post("/login").with(csrf()).param("username", "user")
|
||||
.param("password", "password").param("remember-me", "true")).andReturn();
|
||||
// @formatter:off
|
||||
MockHttpServletRequestBuilder loginRequest = post("/login")
|
||||
.with(csrf())
|
||||
.param("username", "user")
|
||||
.param("password", "password")
|
||||
.param("remember-me", "true");
|
||||
// @formatter:on
|
||||
MvcResult loginMvcResult = this.mvc.perform(loginRequest).andReturn();
|
||||
Cookie rememberMeCookie = loginMvcResult.getResponse().getCookie("remember-me");
|
||||
HttpSession session = loginMvcResult.getRequest().getSession();
|
||||
MvcResult logoutMvcResult = this.mvc
|
||||
.perform(post("/logout").with(csrf()).cookie(rememberMeCookie).session((MockHttpSession) session))
|
||||
.andReturn();
|
||||
// @formatter:off
|
||||
MockHttpServletRequestBuilder logoutRequest = post("/logout")
|
||||
.with(csrf())
|
||||
.cookie(rememberMeCookie)
|
||||
.session((MockHttpSession) session);
|
||||
// @formatter:on
|
||||
MvcResult logoutMvcResult = this.mvc.perform(logoutRequest).andReturn();
|
||||
Cookie expiredRememberMeCookie = logoutMvcResult.getResponse().getCookie("remember-me");
|
||||
this.mvc.perform(get("/abc").with(csrf()).cookie(expiredRememberMeCookie))
|
||||
.andExpect(redirectedUrl("http://localhost/login"));
|
||||
// @formatter:off
|
||||
MockHttpServletRequestBuilder expiredRequest = get("/abc")
|
||||
.with(csrf())
|
||||
.cookie(expiredRememberMeCookie);
|
||||
// @formatter:on
|
||||
this.mvc.perform(expiredRequest).andExpect(redirectedUrl("http://localhost/login"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void loginWhenRememberMeConfiguredInLambdaThenRespondsWithRememberMeCookie() throws Exception {
|
||||
this.spring.register(RememberMeInLambdaConfig.class).autowire();
|
||||
this.mvc.perform(post("/login").with(csrf()).param("username", "user").param("password", "password")
|
||||
.param("remember-me", "true")).andExpect(cookie().exists("remember-me"));
|
||||
// @formatter:off
|
||||
MockHttpServletRequestBuilder request = post("/login")
|
||||
.with(csrf())
|
||||
.param("username", "user")
|
||||
.param("password", "password")
|
||||
.param("remember-me", "true");
|
||||
// @formatter:on
|
||||
this.mvc.perform(request).andExpect(cookie().exists("remember-me"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void loginWhenRememberMeTrueAndCookieDomainThenRememberMeCookieHasDomain() throws Exception {
|
||||
this.spring.register(RememberMeCookieDomainConfig.class).autowire();
|
||||
this.mvc.perform(post("/login").with(csrf()).param("username", "user").param("password", "password")
|
||||
.param("remember-me", "true")).andExpect(cookie().exists("remember-me"))
|
||||
// @formatter:off
|
||||
MockHttpServletRequestBuilder request = post("/login")
|
||||
.with(csrf())
|
||||
.param("username", "user")
|
||||
.param("password", "password")
|
||||
.param("remember-me", "true");
|
||||
this.mvc.perform(request).
|
||||
andExpect(cookie().exists("remember-me"))
|
||||
.andExpect(cookie().domain("remember-me", "spring.io"));
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
public void loginWhenRememberMeTrueAndCookieDomainInLambdaThenRememberMeCookieHasDomain() throws Exception {
|
||||
this.spring.register(RememberMeCookieDomainInLambdaConfig.class).autowire();
|
||||
this.mvc.perform(post("/login").with(csrf()).param("username", "user").param("password", "password")
|
||||
.param("remember-me", "true")).andExpect(cookie().exists("remember-me"))
|
||||
// @formatter:off
|
||||
MockHttpServletRequestBuilder loginRequest = post("/login")
|
||||
.with(csrf())
|
||||
.param("username", "user")
|
||||
.param("password", "password")
|
||||
.param("remember-me", "true");
|
||||
this.mvc.perform(loginRequest)
|
||||
.andExpect(cookie().exists("remember-me"))
|
||||
.andExpect(cookie().domain("remember-me", "spring.io"));
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -181,11 +253,21 @@ public class RememberMeConfigurerTests {
|
|||
@Test
|
||||
public void getWhenRememberMeCookieAndNoKeyConfiguredThenKeyFromRememberMeServicesIsUsed() throws Exception {
|
||||
this.spring.register(FallbackRememberMeKeyConfig.class).autowire();
|
||||
MvcResult mvcResult = this.mvc.perform(post("/login").with(csrf()).param("username", "user")
|
||||
.param("password", "password").param("remember-me", "true")).andReturn();
|
||||
// @formatter:off
|
||||
MockHttpServletRequestBuilder loginRequest = post("/login")
|
||||
.with(csrf())
|
||||
.param("username", "user")
|
||||
.param("password", "password")
|
||||
.param("remember-me", "true");
|
||||
// @formatter:on
|
||||
MvcResult mvcResult = this.mvc.perform(loginRequest).andReturn();
|
||||
Cookie rememberMeCookie = mvcResult.getResponse().getCookie("remember-me");
|
||||
this.mvc.perform(get("/abc").cookie(rememberMeCookie)).andExpect(authenticated()
|
||||
.withAuthentication((auth) -> assertThat(auth).isInstanceOf(RememberMeAuthenticationToken.class)));
|
||||
MockHttpServletRequestBuilder requestWithRememberme = get("/abc").cookie(rememberMeCookie);
|
||||
// @formatter:off
|
||||
SecurityMockMvcResultMatchers.AuthenticatedMatcher remembermeAuthentication = authenticated()
|
||||
.withAuthentication((auth) -> assertThat(auth).isInstanceOf(RememberMeAuthenticationToken.class));
|
||||
// @formatter:on
|
||||
this.mvc.perform(requestWithRememberme).andExpect(remembermeAuthentication);
|
||||
}
|
||||
|
||||
@EnableWebSecurity
|
||||
|
|
|
@ -40,6 +40,8 @@ import org.springframework.security.web.savedrequest.RequestCache;
|
|||
import org.springframework.security.web.savedrequest.RequestCacheAwareFilter;
|
||||
import org.springframework.test.web.servlet.MockMvc;
|
||||
import org.springframework.test.web.servlet.RequestBuilder;
|
||||
import org.springframework.test.web.servlet.request.MockHttpServletRequestBuilder;
|
||||
import org.springframework.test.web.servlet.request.MockMultipartHttpServletRequestBuilder;
|
||||
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.Mockito.mock;
|
||||
|
@ -83,41 +85,63 @@ public class RequestCacheConfigurerTests {
|
|||
@Test
|
||||
public void getWhenBookmarkedUrlIsFaviconIcoThenPostAuthenticationRedirectsToRoot() throws Exception {
|
||||
this.spring.register(RequestCacheDefaultsConfig.class, DefaultSecurityConfig.class).autowire();
|
||||
// @formatter:off
|
||||
MockHttpSession session = (MockHttpSession) this.mvc.perform(get("/favicon.ico"))
|
||||
.andExpect(redirectedUrl("http://localhost/login")).andReturn().getRequest().getSession();
|
||||
this.mvc.perform(formLogin(session)).andExpect(redirectedUrl("/")); // ignores
|
||||
// favicon.ico
|
||||
.andExpect(redirectedUrl("http://localhost/login"))
|
||||
.andReturn()
|
||||
.getRequest()
|
||||
.getSession();
|
||||
// @formatter:on
|
||||
// ignores favicon.ico
|
||||
this.mvc.perform(formLogin(session)).andExpect(redirectedUrl("/"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getWhenBookmarkedUrlIsFaviconPngThenPostAuthenticationRedirectsToRoot() throws Exception {
|
||||
this.spring.register(RequestCacheDefaultsConfig.class, DefaultSecurityConfig.class).autowire();
|
||||
// @formatter:off
|
||||
MockHttpSession session = (MockHttpSession) this.mvc.perform(get("/favicon.png"))
|
||||
.andExpect(redirectedUrl("http://localhost/login")).andReturn().getRequest().getSession();
|
||||
this.mvc.perform(formLogin(session)).andExpect(redirectedUrl("/")); // ignores
|
||||
// favicon.png
|
||||
.andExpect(redirectedUrl("http://localhost/login"))
|
||||
.andReturn()
|
||||
.getRequest()
|
||||
.getSession();
|
||||
// @formatter:on
|
||||
// ignores favicon.png
|
||||
this.mvc.perform(formLogin(session)).andExpect(redirectedUrl("/"));
|
||||
}
|
||||
|
||||
// SEC-2321
|
||||
@Test
|
||||
public void getWhenBookmarkedRequestIsApplicationJsonThenPostAuthenticationRedirectsToRoot() throws Exception {
|
||||
this.spring.register(RequestCacheDefaultsConfig.class, DefaultSecurityConfig.class).autowire();
|
||||
MockHttpSession session = (MockHttpSession) this.mvc
|
||||
.perform(get("/messages").header(HttpHeaders.ACCEPT, MediaType.APPLICATION_JSON))
|
||||
.andExpect(redirectedUrl("http://localhost/login")).andReturn().getRequest().getSession();
|
||||
this.mvc.perform(formLogin(session)).andExpect(redirectedUrl("/")); // ignores
|
||||
// application/json
|
||||
MockHttpServletRequestBuilder request = get("/messages").header(HttpHeaders.ACCEPT, MediaType.APPLICATION_JSON);
|
||||
// @formatter:off
|
||||
MockHttpSession session = (MockHttpSession) this.mvc.perform(request)
|
||||
.andExpect(redirectedUrl("http://localhost/login"))
|
||||
.andReturn()
|
||||
.getRequest()
|
||||
.getSession();
|
||||
// @formatter:on
|
||||
// ignores application/json
|
||||
// This is desirable since JSON requests are typically not invoked directly from
|
||||
// the browser and we don't want the browser to replay them
|
||||
this.mvc.perform(formLogin(session)).andExpect(redirectedUrl("/"));
|
||||
}
|
||||
|
||||
// SEC-2321
|
||||
@Test
|
||||
public void getWhenBookmarkedRequestIsXRequestedWithThenPostAuthenticationRedirectsToRoot() throws Exception {
|
||||
this.spring.register(RequestCacheDefaultsConfig.class, DefaultSecurityConfig.class).autowire();
|
||||
// @formatter:off
|
||||
MockHttpServletRequestBuilder xRequestedWith = get("/messages")
|
||||
.header("X-Requested-With", "XMLHttpRequest");
|
||||
MockHttpSession session = (MockHttpSession) this.mvc
|
||||
.perform(get("/messages").header("X-Requested-With", "XMLHttpRequest"))
|
||||
.andExpect(redirectedUrl("http://localhost/login")).andReturn().getRequest().getSession();
|
||||
.perform(xRequestedWith)
|
||||
.andExpect(redirectedUrl("http://localhost/login"))
|
||||
.andReturn()
|
||||
.getRequest()
|
||||
.getSession();
|
||||
// @formatter:on
|
||||
this.mvc.perform(formLogin(session)).andExpect(redirectedUrl("/"));
|
||||
// This is desirable since XHR requests are typically not invoked directly from
|
||||
// the browser and we don't want the browser to replay them
|
||||
|
@ -126,49 +150,75 @@ public class RequestCacheConfigurerTests {
|
|||
@Test
|
||||
public void getWhenBookmarkedRequestIsTextEventStreamThenPostAuthenticationRedirectsToRoot() throws Exception {
|
||||
this.spring.register(RequestCacheDefaultsConfig.class, DefaultSecurityConfig.class).autowire();
|
||||
MockHttpSession session = (MockHttpSession) this.mvc
|
||||
.perform(get("/messages").header(HttpHeaders.ACCEPT, MediaType.TEXT_EVENT_STREAM))
|
||||
.andExpect(redirectedUrl("http://localhost/login")).andReturn().getRequest().getSession();
|
||||
this.mvc.perform(formLogin(session)).andExpect(redirectedUrl("/")); // ignores
|
||||
// text/event-stream
|
||||
MockHttpServletRequestBuilder request = get("/messages").header(HttpHeaders.ACCEPT, MediaType.TEXT_EVENT_STREAM);
|
||||
// @formatter:off
|
||||
MockHttpSession session = (MockHttpSession) this.mvc.perform(request)
|
||||
.andExpect(redirectedUrl("http://localhost/login"))
|
||||
.andReturn()
|
||||
.getRequest()
|
||||
.getSession();
|
||||
// @formatter:on
|
||||
// ignores text/event-stream
|
||||
// This is desirable since event-stream requests are typically not invoked
|
||||
// directly from the browser and we don't want the browser to replay them
|
||||
this.mvc.perform(formLogin(session)).andExpect(redirectedUrl("/"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getWhenBookmarkedRequestIsAllMediaTypeThenPostAuthenticationRemembers() throws Exception {
|
||||
this.spring.register(RequestCacheDefaultsConfig.class, DefaultSecurityConfig.class).autowire();
|
||||
MockHttpSession session = (MockHttpSession) this.mvc
|
||||
.perform(get("/messages").header(HttpHeaders.ACCEPT, MediaType.ALL))
|
||||
.andExpect(redirectedUrl("http://localhost/login")).andReturn().getRequest().getSession();
|
||||
MockHttpServletRequestBuilder request = get("/messages").header(HttpHeaders.ACCEPT, MediaType.ALL);
|
||||
// @formatter:off
|
||||
MockHttpSession session = (MockHttpSession) this.mvc.perform(request)
|
||||
.andExpect(redirectedUrl("http://localhost/login"))
|
||||
.andReturn()
|
||||
.getRequest()
|
||||
.getSession();
|
||||
// @formatter:on
|
||||
this.mvc.perform(formLogin(session)).andExpect(redirectedUrl("http://localhost/messages"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getWhenBookmarkedRequestIsTextHtmlThenPostAuthenticationRemembers() throws Exception {
|
||||
this.spring.register(RequestCacheDefaultsConfig.class, DefaultSecurityConfig.class).autowire();
|
||||
MockHttpSession session = (MockHttpSession) this.mvc
|
||||
.perform(get("/messages").header(HttpHeaders.ACCEPT, MediaType.TEXT_HTML))
|
||||
.andExpect(redirectedUrl("http://localhost/login")).andReturn().getRequest().getSession();
|
||||
MockHttpServletRequestBuilder request = get("/messages").header(HttpHeaders.ACCEPT, MediaType.TEXT_HTML);
|
||||
// @formatter:off
|
||||
MockHttpSession session = (MockHttpSession) this.mvc.perform(request)
|
||||
.andExpect(redirectedUrl("http://localhost/login"))
|
||||
.andReturn()
|
||||
.getRequest()
|
||||
.getSession();
|
||||
// @formatter:on
|
||||
this.mvc.perform(formLogin(session)).andExpect(redirectedUrl("http://localhost/messages"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getWhenBookmarkedRequestIsChromeThenPostAuthenticationRemembers() throws Exception {
|
||||
this.spring.register(RequestCacheDefaultsConfig.class, DefaultSecurityConfig.class).autowire();
|
||||
MockHttpSession session = (MockHttpSession) this.mvc
|
||||
.perform(get("/messages").header(HttpHeaders.ACCEPT,
|
||||
"text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8"))
|
||||
.andExpect(redirectedUrl("http://localhost/login")).andReturn().getRequest().getSession();
|
||||
// @formatter:off
|
||||
MockHttpServletRequestBuilder request = get("/messages")
|
||||
.header(HttpHeaders.ACCEPT, "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8");
|
||||
MockHttpSession session = (MockHttpSession) this.mvc.perform(request)
|
||||
.andExpect(redirectedUrl("http://localhost/login"))
|
||||
.andReturn()
|
||||
.getRequest()
|
||||
.getSession();
|
||||
// @formatter:on
|
||||
this.mvc.perform(formLogin(session)).andExpect(redirectedUrl("http://localhost/messages"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getWhenBookmarkedRequestIsRequestedWithAndroidThenPostAuthenticationRemembers() throws Exception {
|
||||
this.spring.register(RequestCacheDefaultsConfig.class, DefaultSecurityConfig.class).autowire();
|
||||
MockHttpSession session = (MockHttpSession) this.mvc
|
||||
.perform(get("/messages").header("X-Requested-With", "com.android"))
|
||||
.andExpect(redirectedUrl("http://localhost/login")).andReturn().getRequest().getSession();
|
||||
// @formatter:off
|
||||
MockHttpServletRequestBuilder request = get("/messages")
|
||||
.header("X-Requested-With", "com.android");
|
||||
MockHttpSession session = (MockHttpSession) this.mvc.perform(request)
|
||||
.andExpect(redirectedUrl("http://localhost/login"))
|
||||
.andReturn()
|
||||
.getRequest()
|
||||
.getSession();
|
||||
// @formatter:on
|
||||
this.mvc.perform(formLogin(session)).andExpect(redirectedUrl("http://localhost/messages"));
|
||||
}
|
||||
|
||||
|
@ -177,7 +227,12 @@ public class RequestCacheConfigurerTests {
|
|||
public void getWhenRequestCacheIsDisabledThenExceptionTranslationFilterDoesNotStoreRequest() throws Exception {
|
||||
this.spring.register(RequestCacheDisabledConfig.class,
|
||||
ExceptionHandlingConfigurerTests.DefaultSecurityConfig.class).autowire();
|
||||
MockHttpSession session = (MockHttpSession) this.mvc.perform(get("/bob")).andReturn().getRequest().getSession();
|
||||
// @formatter:off
|
||||
MockHttpSession session = (MockHttpSession) this.mvc.perform(get("/bob"))
|
||||
.andReturn()
|
||||
.getRequest()
|
||||
.getSession();
|
||||
// @formatter:on
|
||||
this.mvc.perform(formLogin(session)).andExpect(redirectedUrl("/"));
|
||||
}
|
||||
|
||||
|
@ -186,8 +241,13 @@ public class RequestCacheConfigurerTests {
|
|||
public void postWhenRequestIsMultipartThenPostAuthenticationRedirectsToRoot() throws Exception {
|
||||
this.spring.register(RequestCacheDefaultsConfig.class, DefaultSecurityConfig.class).autowire();
|
||||
MockMultipartFile aFile = new MockMultipartFile("aFile", "A_FILE".getBytes());
|
||||
MockHttpSession session = (MockHttpSession) this.mvc.perform(multipart("/upload").file(aFile)).andReturn()
|
||||
.getRequest().getSession();
|
||||
MockMultipartHttpServletRequestBuilder request = multipart("/upload").file(aFile);
|
||||
// @formatter:off
|
||||
MockHttpSession session = (MockHttpSession) this.mvc.perform(request)
|
||||
.andReturn()
|
||||
.getRequest()
|
||||
.getSession();
|
||||
// @formatter:on
|
||||
this.mvc.perform(formLogin(session)).andExpect(redirectedUrl("/"));
|
||||
}
|
||||
|
||||
|
@ -195,26 +255,47 @@ public class RequestCacheConfigurerTests {
|
|||
public void getWhenRequestCacheIsDisabledInLambdaThenExceptionTranslationFilterDoesNotStoreRequest()
|
||||
throws Exception {
|
||||
this.spring.register(RequestCacheDisabledInLambdaConfig.class, DefaultSecurityConfig.class).autowire();
|
||||
MockHttpSession session = (MockHttpSession) this.mvc.perform(get("/bob")).andReturn().getRequest().getSession();
|
||||
// @formatter:off
|
||||
MockHttpSession session = (MockHttpSession) this.mvc.perform(get("/bob"))
|
||||
.andReturn()
|
||||
.getRequest()
|
||||
.getSession();
|
||||
// @formatter:on
|
||||
this.mvc.perform(formLogin(session)).andExpect(redirectedUrl("/"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getWhenRequestCacheInLambdaThenRedirectedToCachedPage() throws Exception {
|
||||
this.spring.register(RequestCacheInLambdaConfig.class, DefaultSecurityConfig.class).autowire();
|
||||
MockHttpSession session = (MockHttpSession) this.mvc.perform(get("/bob")).andReturn().getRequest().getSession();
|
||||
// @formatter:off
|
||||
MockHttpSession session = (MockHttpSession) this.mvc.perform(get("/bob"))
|
||||
.andReturn()
|
||||
.getRequest()
|
||||
.getSession();
|
||||
// @formatter:on
|
||||
this.mvc.perform(formLogin(session)).andExpect(redirectedUrl("http://localhost/bob"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getWhenCustomRequestCacheInLambdaThenCustomRequestCacheUsed() throws Exception {
|
||||
this.spring.register(CustomRequestCacheInLambdaConfig.class, DefaultSecurityConfig.class).autowire();
|
||||
MockHttpSession session = (MockHttpSession) this.mvc.perform(get("/bob")).andReturn().getRequest().getSession();
|
||||
// @formatter:off
|
||||
MockHttpSession session = (MockHttpSession) this.mvc.perform(get("/bob"))
|
||||
.andReturn()
|
||||
.getRequest()
|
||||
.getSession();
|
||||
// @formatter:on
|
||||
this.mvc.perform(formLogin(session)).andExpect(redirectedUrl("/"));
|
||||
}
|
||||
|
||||
private static RequestBuilder formLogin(MockHttpSession session) {
|
||||
return post("/login").param("username", "user").param("password", "password").session(session).with(csrf());
|
||||
// @formatter:off
|
||||
return post("/login")
|
||||
.param("username", "user")
|
||||
.param("password", "password")
|
||||
.session(session)
|
||||
.with(csrf());
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@EnableWebSecurity
|
||||
|
|
|
@ -47,15 +47,23 @@ public class RequestMatcherConfigurerTests {
|
|||
@Test
|
||||
public void authorizeRequestsWhenInvokedMultipleTimesThenChainsPaths() throws Exception {
|
||||
this.spring.register(Sec2908Config.class).autowire();
|
||||
this.mvc.perform(get("/oauth/abc")).andExpect(status().isForbidden());
|
||||
this.mvc.perform(get("/api/abc")).andExpect(status().isForbidden());
|
||||
// @formatter:off
|
||||
this.mvc.perform(get("/oauth/abc"))
|
||||
.andExpect(status().isForbidden());
|
||||
this.mvc.perform(get("/api/abc"))
|
||||
.andExpect(status().isForbidden());
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
public void authorizeRequestsWhenInvokedMultipleTimesInLambdaThenChainsPaths() throws Exception {
|
||||
this.spring.register(AuthorizeRequestInLambdaConfig.class).autowire();
|
||||
this.mvc.perform(get("/oauth/abc")).andExpect(status().isForbidden());
|
||||
this.mvc.perform(get("/api/abc")).andExpect(status().isForbidden());
|
||||
// @formatter:off
|
||||
this.mvc.perform(get("/oauth/abc"))
|
||||
.andExpect(status().isForbidden());
|
||||
this.mvc.perform(get("/api/abc"))
|
||||
.andExpect(status().isForbidden());
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@EnableWebSecurity
|
||||
|
|
|
@ -42,6 +42,7 @@ import org.springframework.security.config.test.SpringTestRule;
|
|||
import org.springframework.security.core.AuthenticationException;
|
||||
import org.springframework.security.core.authority.AuthorityUtils;
|
||||
import org.springframework.security.core.userdetails.PasswordEncodedUser;
|
||||
import org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors;
|
||||
import org.springframework.security.util.FieldUtils;
|
||||
import org.springframework.security.web.AuthenticationEntryPoint;
|
||||
import org.springframework.security.web.FilterChainProxy;
|
||||
|
@ -52,6 +53,7 @@ import org.springframework.security.web.authentication.logout.LogoutSuccessEvent
|
|||
import org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter;
|
||||
import org.springframework.test.web.servlet.MockMvc;
|
||||
import org.springframework.test.web.servlet.MvcResult;
|
||||
import org.springframework.test.web.servlet.request.MockHttpServletRequestBuilder;
|
||||
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
@ -109,9 +111,9 @@ public class ServletApiConfigurerTests {
|
|||
@Test
|
||||
public void configureWhenUsingDefaultsThenRolePrefixIsSet() throws Exception {
|
||||
this.spring.register(ServletApiConfig.class, AdminController.class).autowire();
|
||||
this.mvc.perform(
|
||||
get("/admin").with(authentication(new TestingAuthenticationToken("user", "pass", "ROLE_ADMIN"))))
|
||||
.andExpect(status().isOk());
|
||||
TestingAuthenticationToken user = new TestingAuthenticationToken("user", "pass", "ROLE_ADMIN");
|
||||
MockHttpServletRequestBuilder request = get("/admin").with(authentication(user));
|
||||
this.mvc.perform(request).andExpect(status().isOk());
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -125,11 +127,18 @@ public class ServletApiConfigurerTests {
|
|||
@Test
|
||||
public void servletApiWhenInvokedTwiceThenUsesOriginalRole() throws Exception {
|
||||
this.spring.register(DuplicateInvocationsDoesNotOverrideConfig.class, AdminController.class).autowire();
|
||||
this.mvc.perform(
|
||||
get("/admin").with(user("user").authorities(AuthorityUtils.createAuthorityList("PERMISSION_ADMIN"))))
|
||||
// @formatter:off
|
||||
MockHttpServletRequestBuilder request = get("/admin")
|
||||
.with(user("user").authorities(AuthorityUtils.createAuthorityList("PERMISSION_ADMIN")));
|
||||
this.mvc.perform(request)
|
||||
.andExpect(status().isOk());
|
||||
this.mvc.perform(get("/admin").with(user("user").authorities(AuthorityUtils.createAuthorityList("ROLE_ADMIN"))))
|
||||
SecurityMockMvcRequestPostProcessors.UserRequestPostProcessor userWithRoleAdmin = user("user")
|
||||
.authorities(AuthorityUtils.createAuthorityList("ROLE_ADMIN"));
|
||||
MockHttpServletRequestBuilder requestWithRoleAdmin = get("/admin")
|
||||
.with(userWithRoleAdmin);
|
||||
this.mvc.perform(requestWithRoleAdmin)
|
||||
.andExpect(status().isForbidden());
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -142,18 +151,25 @@ public class ServletApiConfigurerTests {
|
|||
@Test
|
||||
public void requestWhenServletApiWithDefaultsInLambdaThenUsesDefaultRolePrefix() throws Exception {
|
||||
this.spring.register(ServletApiWithDefaultsInLambdaConfig.class, AdminController.class).autowire();
|
||||
this.mvc.perform(get("/admin").with(user("user").authorities(AuthorityUtils.createAuthorityList("ROLE_ADMIN"))))
|
||||
MockHttpServletRequestBuilder request = get("/admin")
|
||||
.with(user("user").authorities(AuthorityUtils.createAuthorityList("ROLE_ADMIN")));
|
||||
this.mvc.perform(request)
|
||||
.andExpect(status().isOk());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void requestWhenRolePrefixInLambdaThenUsesCustomRolePrefix() throws Exception {
|
||||
this.spring.register(RolePrefixInLambdaConfig.class, AdminController.class).autowire();
|
||||
this.mvc.perform(
|
||||
get("/admin").with(user("user").authorities(AuthorityUtils.createAuthorityList("PERMISSION_ADMIN"))))
|
||||
// @formatter:off
|
||||
MockHttpServletRequestBuilder requestWithAdminPermission = get("/admin")
|
||||
.with(user("user").authorities(AuthorityUtils.createAuthorityList("PERMISSION_ADMIN")));
|
||||
this.mvc.perform(requestWithAdminPermission)
|
||||
.andExpect(status().isOk());
|
||||
this.mvc.perform(get("/admin").with(user("user").authorities(AuthorityUtils.createAuthorityList("ROLE_ADMIN"))))
|
||||
MockHttpServletRequestBuilder requestWithAdminRole = get("/admin")
|
||||
.with(user("user").authorities(AuthorityUtils.createAuthorityList("ROLE_ADMIN")));
|
||||
this.mvc.perform(requestWithAdminRole)
|
||||
.andExpect(status().isForbidden());
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
|
@ -62,7 +62,11 @@ public class SessionManagementConfigurerSessionCreationPolicyTests {
|
|||
@Test
|
||||
public void getWhenDefaultsThenLoginChallengeCreatesSession() throws Exception {
|
||||
this.spring.register(DefaultConfig.class, BasicController.class).autowire();
|
||||
MvcResult result = this.mvc.perform(get("/")).andExpect(status().isUnauthorized()).andReturn();
|
||||
// @formatter:off
|
||||
MvcResult result = this.mvc.perform(get("/"))
|
||||
.andExpect(status().isUnauthorized())
|
||||
.andReturn();
|
||||
// @formatter:on
|
||||
assertThat(result.getRequest().getSession(false)).isNotNull();
|
||||
}
|
||||
|
||||
|
|
|
@ -49,6 +49,7 @@ import org.springframework.security.web.session.HttpSessionDestroyedEvent;
|
|||
import org.springframework.security.web.session.SessionManagementFilter;
|
||||
import org.springframework.test.web.servlet.MockMvc;
|
||||
import org.springframework.test.web.servlet.MvcResult;
|
||||
import org.springframework.test.web.servlet.request.MockHttpServletRequestBuilder;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
|
@ -114,8 +115,14 @@ public class SessionManagementConfigurerTests {
|
|||
this.spring.register(DisableSessionFixationEnableConcurrencyControlConfig.class).autowire();
|
||||
MockHttpSession session = new MockHttpSession();
|
||||
String sessionId = session.getId();
|
||||
MvcResult mvcResult = this.mvc.perform(get("/").with(httpBasic("user", "password")).session(session))
|
||||
.andExpect(status().isNotFound()).andReturn();
|
||||
// @formatter:off
|
||||
MockHttpServletRequestBuilder request = get("/")
|
||||
.with(httpBasic("user", "password"))
|
||||
.session(session);
|
||||
MvcResult mvcResult = this.mvc.perform(request)
|
||||
.andExpect(status().isNotFound())
|
||||
.andReturn();
|
||||
// @formatter:on
|
||||
assertThat(mvcResult.getRequest().getSession().getId()).isEqualTo(sessionId);
|
||||
}
|
||||
|
||||
|
@ -125,9 +132,16 @@ public class SessionManagementConfigurerTests {
|
|||
MockHttpSession givenSession = new MockHttpSession();
|
||||
String givenSessionId = givenSession.getId();
|
||||
givenSession.setAttribute("name", "value");
|
||||
MockHttpSession resultingSession = (MockHttpSession) this.mvc
|
||||
.perform(get("/auth").session(givenSession).with(httpBasic("user", "password")))
|
||||
.andExpect(status().isNotFound()).andReturn().getRequest().getSession(false);
|
||||
// @formatter:off
|
||||
MockHttpServletRequestBuilder request = get("/auth")
|
||||
.session(givenSession)
|
||||
.with(httpBasic("user", "password"));
|
||||
MockHttpSession resultingSession = (MockHttpSession) this.mvc.perform(request)
|
||||
.andExpect(status().isNotFound())
|
||||
.andReturn()
|
||||
.getRequest()
|
||||
.getSession(false);
|
||||
// @formatter:on
|
||||
assertThat(givenSessionId).isNotEqualTo(resultingSession.getId());
|
||||
assertThat(resultingSession.getAttribute("name")).isNull();
|
||||
}
|
||||
|
@ -135,29 +149,65 @@ public class SessionManagementConfigurerTests {
|
|||
@Test
|
||||
public void loginWhenUserLoggedInAndMaxSessionsIsOneThenLoginPrevented() throws Exception {
|
||||
this.spring.register(ConcurrencyControlConfig.class).autowire();
|
||||
this.mvc.perform(post("/login").with(csrf()).param("username", "user").param("password", "password"));
|
||||
this.mvc.perform(post("/login").with(csrf()).param("username", "user").param("password", "password"))
|
||||
.andExpect(status().isFound()).andExpect(redirectedUrl("/login?error"));
|
||||
// @formatter:off
|
||||
MockHttpServletRequestBuilder firstRequest = post("/login")
|
||||
.with(csrf())
|
||||
.param("username", "user")
|
||||
.param("password", "password");
|
||||
this.mvc.perform(firstRequest);
|
||||
MockHttpServletRequestBuilder secondRequest = post("/login")
|
||||
.with(csrf())
|
||||
.param("username", "user")
|
||||
.param("password", "password");
|
||||
this.mvc.perform(secondRequest)
|
||||
.andExpect(status().isFound())
|
||||
.andExpect(redirectedUrl("/login?error"));
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
public void loginWhenUserSessionExpiredAndMaxSessionsIsOneThenLoggedIn() throws Exception {
|
||||
this.spring.register(ConcurrencyControlConfig.class).autowire();
|
||||
MvcResult mvcResult = this.mvc
|
||||
.perform(post("/login").with(csrf()).param("username", "user").param("password", "password"))
|
||||
// @formatter:off
|
||||
MockHttpServletRequestBuilder firstRequest = post("/login")
|
||||
.with(csrf())
|
||||
.param("username", "user")
|
||||
.param("password", "password");
|
||||
MvcResult mvcResult = this.mvc.perform(firstRequest)
|
||||
.andReturn();
|
||||
// @formatter:on
|
||||
HttpSession authenticatedSession = mvcResult.getRequest().getSession();
|
||||
this.spring.getContext().publishEvent(new HttpSessionDestroyedEvent(authenticatedSession));
|
||||
this.mvc.perform(post("/login").with(csrf()).param("username", "user").param("password", "password"))
|
||||
.andExpect(status().isFound()).andExpect(redirectedUrl("/"));
|
||||
// @formatter:off
|
||||
MockHttpServletRequestBuilder secondRequest = post("/login")
|
||||
.with(csrf())
|
||||
.param("username", "user")
|
||||
.param("password", "password");
|
||||
this.mvc.perform(secondRequest)
|
||||
.andExpect(status().isFound())
|
||||
.andExpect(redirectedUrl("/"));
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
public void loginWhenUserLoggedInAndMaxSessionsOneInLambdaThenLoginPrevented() throws Exception {
|
||||
this.spring.register(ConcurrencyControlInLambdaConfig.class).autowire();
|
||||
this.mvc.perform(post("/login").with(csrf()).param("username", "user").param("password", "password"));
|
||||
this.mvc.perform(post("/login").with(csrf()).param("username", "user").param("password", "password"))
|
||||
.andExpect(status().isFound()).andExpect(redirectedUrl("/login?error"));
|
||||
// @formatter:off
|
||||
MockHttpServletRequestBuilder firstRequest = post("/login")
|
||||
.with(csrf())
|
||||
.param("username", "user")
|
||||
.param("password", "password");
|
||||
// @formatter:on
|
||||
this.mvc.perform(firstRequest);
|
||||
// @formatter:off
|
||||
MockHttpServletRequestBuilder secondRequest = post("/login")
|
||||
.with(csrf())
|
||||
.param("username", "user")
|
||||
.param("password", "password");
|
||||
this.mvc.perform(secondRequest)
|
||||
.andExpect(status().isFound())
|
||||
.andExpect(redirectedUrl("/login?error"));
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
|
@ -61,42 +61,60 @@ public class UrlAuthorizationsTests {
|
|||
@WithMockUser(authorities = "ROLE_USER")
|
||||
public void hasAnyAuthorityWhenAuthoritySpecifiedThenMatchesAuthority() throws Exception {
|
||||
this.spring.register(RoleConfig.class).autowire();
|
||||
this.mvc.perform(get("/role-user-authority")).andExpect(status().isNotFound());
|
||||
this.mvc.perform(get("/role-user")).andExpect(status().isNotFound());
|
||||
this.mvc.perform(get("/role-admin-authority")).andExpect(status().isForbidden());
|
||||
// @formatter:off
|
||||
this.mvc.perform(get("/role-user-authority"))
|
||||
.andExpect(status().isNotFound());
|
||||
this.mvc.perform(get("/role-user"))
|
||||
.andExpect(status().isNotFound());
|
||||
this.mvc.perform(get("/role-admin-authority"))
|
||||
.andExpect(status().isForbidden());
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
@WithMockUser(authorities = "ROLE_ADMIN")
|
||||
public void hasAnyAuthorityWhenAuthoritiesSpecifiedThenMatchesAuthority() throws Exception {
|
||||
this.spring.register(RoleConfig.class).autowire();
|
||||
this.mvc.perform(get("/role-user-admin-authority")).andExpect(status().isNotFound());
|
||||
this.mvc.perform(get("/role-user-admin")).andExpect(status().isNotFound());
|
||||
this.mvc.perform(get("/role-user-authority")).andExpect(status().isForbidden());
|
||||
this.mvc.perform(get("/role-user-admin-authority"))
|
||||
.andExpect(status().isNotFound());
|
||||
this.mvc.perform(get("/role-user-admin"))
|
||||
.andExpect(status().isNotFound());
|
||||
this.mvc.perform(get("/role-user-authority"))
|
||||
.andExpect(status().isForbidden());
|
||||
}
|
||||
|
||||
@Test
|
||||
@WithMockUser(roles = "USER")
|
||||
public void hasAnyRoleWhenRoleSpecifiedThenMatchesRole() throws Exception {
|
||||
this.spring.register(RoleConfig.class).autowire();
|
||||
this.mvc.perform(get("/role-user")).andExpect(status().isNotFound());
|
||||
this.mvc.perform(get("/role-admin")).andExpect(status().isForbidden());
|
||||
// @formatter:off
|
||||
this.mvc.perform(get("/role-user"))
|
||||
.andExpect(status().isNotFound());
|
||||
this.mvc.perform(get("/role-admin"))
|
||||
.andExpect(status().isForbidden());
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
@WithMockUser(roles = "ADMIN")
|
||||
public void hasAnyRoleWhenRolesSpecifiedThenMatchesRole() throws Exception {
|
||||
this.spring.register(RoleConfig.class).autowire();
|
||||
this.mvc.perform(get("/role-admin-user")).andExpect(status().isNotFound());
|
||||
this.mvc.perform(get("/role-user")).andExpect(status().isForbidden());
|
||||
this.mvc.perform(get("/role-admin-user"))
|
||||
.andExpect(status().isNotFound());
|
||||
this.mvc.perform(get("/role-user"))
|
||||
.andExpect(status().isForbidden());
|
||||
}
|
||||
|
||||
@Test
|
||||
@WithMockUser(authorities = "USER")
|
||||
public void hasAnyRoleWhenRoleSpecifiedThenDoesNotMatchAuthority() throws Exception {
|
||||
this.spring.register(RoleConfig.class).autowire();
|
||||
this.mvc.perform(get("/role-user")).andExpect(status().isForbidden());
|
||||
this.mvc.perform(get("/role-admin")).andExpect(status().isForbidden());
|
||||
// @formatter:off
|
||||
this.mvc.perform(get("/role-user"))
|
||||
.andExpect(status().isForbidden());
|
||||
this.mvc.perform(get("/role-admin"))
|
||||
.andExpect(status().isForbidden());
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -145,7 +163,11 @@ public class UrlAuthorizationsTests {
|
|||
ApplicationContext context = getApplicationContext();
|
||||
UrlAuthorizationConfigurer<HttpSecurity>.StandardInterceptUrlRegistry registry = http
|
||||
.apply(new UrlAuthorizationConfigurer(context)).getRegistry();
|
||||
registry.antMatchers("/a").hasRole("ADMIN").anyRequest().hasRole("USER");
|
||||
// @formatter:off
|
||||
registry
|
||||
.antMatchers("/a").hasRole("ADMIN")
|
||||
.anyRequest().hasRole("USER");
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -68,21 +68,30 @@ public class X509ConfigurerTests {
|
|||
public void x509WhenInvokedTwiceThenUsesOriginalSubjectPrincipalRegex() throws Exception {
|
||||
this.spring.register(DuplicateDoesNotOverrideConfig.class).autowire();
|
||||
X509Certificate certificate = loadCert("rodatexampledotcom.cer");
|
||||
this.mvc.perform(get("/").with(x509(certificate))).andExpect(authenticated().withUsername("rod"));
|
||||
// @formatter:off
|
||||
this.mvc.perform(get("/").with(x509(certificate)))
|
||||
.andExpect(authenticated().withUsername("rod"));
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
public void x509WhenConfiguredInLambdaThenUsesDefaults() throws Exception {
|
||||
this.spring.register(DefaultsInLambdaConfig.class).autowire();
|
||||
X509Certificate certificate = loadCert("rod.cer");
|
||||
this.mvc.perform(get("/").with(x509(certificate))).andExpect(authenticated().withUsername("rod"));
|
||||
// @formatter:off
|
||||
this.mvc.perform(get("/").with(x509(certificate)))
|
||||
.andExpect(authenticated().withUsername("rod"));
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
public void x509WhenSubjectPrincipalRegexInLambdaThenUsesRegexToExtractPrincipal() throws Exception {
|
||||
this.spring.register(SubjectPrincipalRegexInLambdaConfig.class).autowire();
|
||||
X509Certificate certificate = loadCert("rodatexampledotcom.cer");
|
||||
this.mvc.perform(get("/").with(x509(certificate))).andExpect(authenticated().withUsername("rod"));
|
||||
// @formatter:off
|
||||
this.mvc.perform(get("/").with(x509(certificate)))
|
||||
.andExpect(authenticated().withUsername("rod"));
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
private <T extends Certificate> T loadCert(String location) {
|
||||
|
|
|
@ -61,6 +61,7 @@ import org.springframework.security.oauth2.core.endpoint.OAuth2ParameterNames;
|
|||
import org.springframework.security.web.savedrequest.RequestCache;
|
||||
import org.springframework.test.web.servlet.MockMvc;
|
||||
import org.springframework.test.web.servlet.MvcResult;
|
||||
import org.springframework.test.web.servlet.request.MockHttpServletRequestBuilder;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
|
||||
|
@ -107,13 +108,22 @@ public class OAuth2ClientConfigurerTests {
|
|||
|
||||
@Before
|
||||
public void setup() {
|
||||
this.registration1 = TestClientRegistrations.clientRegistration().registrationId("registration-1")
|
||||
.clientId("client-1").clientSecret("secret")
|
||||
// @formatter:off
|
||||
this.registration1 = TestClientRegistrations.clientRegistration()
|
||||
.registrationId("registration-1")
|
||||
.clientId("client-1")
|
||||
.clientSecret("secret")
|
||||
.clientAuthenticationMethod(ClientAuthenticationMethod.BASIC)
|
||||
.authorizationGrantType(AuthorizationGrantType.AUTHORIZATION_CODE).redirectUri("{baseUrl}/client-1")
|
||||
.scope("user").authorizationUri("https://provider.com/oauth2/authorize")
|
||||
.tokenUri("https://provider.com/oauth2/token").userInfoUri("https://provider.com/oauth2/user")
|
||||
.userNameAttributeName("id").clientName("client-1").build();
|
||||
.authorizationGrantType(AuthorizationGrantType.AUTHORIZATION_CODE)
|
||||
.redirectUri("{baseUrl}/client-1")
|
||||
.scope("user")
|
||||
.authorizationUri("https://provider.com/oauth2/authorize")
|
||||
.tokenUri("https://provider.com/oauth2/token")
|
||||
.userInfoUri("https://provider.com/oauth2/user")
|
||||
.userNameAttributeName("id")
|
||||
.clientName("client-1")
|
||||
.build();
|
||||
// @formatter:on
|
||||
clientRegistrationRepository = new InMemoryClientRegistrationRepository(this.registration1);
|
||||
authorizedClientService = new InMemoryOAuth2AuthorizedClientService(clientRegistrationRepository);
|
||||
authorizedClientRepository = new AuthenticatedPrincipalOAuth2AuthorizedClientRepository(
|
||||
|
@ -131,11 +141,13 @@ public class OAuth2ClientConfigurerTests {
|
|||
@Test
|
||||
public void configureWhenAuthorizationCodeRequestThenRedirectForAuthorization() throws Exception {
|
||||
this.spring.register(OAuth2ClientConfig.class).autowire();
|
||||
// @formatter:off
|
||||
MvcResult mvcResult = this.mockMvc.perform(get("/oauth2/authorization/registration-1"))
|
||||
.andExpect(status().is3xxRedirection()).andReturn();
|
||||
assertThat(mvcResult.getResponse().getRedirectedUrl())
|
||||
.matches("https://provider.com/oauth2/authorize\\?" + "response_type=code&client_id=client-1&"
|
||||
+ "scope=user&state=.{15,}&" + "redirect_uri=http://localhost/client-1");
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -154,10 +166,15 @@ public class OAuth2ClientConfigurerTests {
|
|||
// Setup the Authorization Request in the session
|
||||
Map<String, Object> attributes = new HashMap<>();
|
||||
attributes.put(OAuth2ParameterNames.REGISTRATION_ID, this.registration1.getRegistrationId());
|
||||
// @formatter:off
|
||||
OAuth2AuthorizationRequest authorizationRequest = OAuth2AuthorizationRequest.authorizationCode()
|
||||
.authorizationUri(this.registration1.getProviderDetails().getAuthorizationUri())
|
||||
.clientId(this.registration1.getClientId()).redirectUri("http://localhost/client-1").state("state")
|
||||
.attributes(attributes).build();
|
||||
.clientId(this.registration1.getClientId())
|
||||
.redirectUri("http://localhost/client-1")
|
||||
.state("state")
|
||||
.attributes(attributes)
|
||||
.build();
|
||||
// @formatter:on
|
||||
AuthorizationRequestRepository<OAuth2AuthorizationRequest> authorizationRequestRepository = new HttpSessionOAuth2AuthorizationRequestRepository();
|
||||
MockHttpServletRequest request = new MockHttpServletRequest("GET", "");
|
||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
|
@ -165,9 +182,16 @@ public class OAuth2ClientConfigurerTests {
|
|||
MockHttpSession session = (MockHttpSession) request.getSession();
|
||||
String principalName = "user1";
|
||||
TestingAuthenticationToken authentication = new TestingAuthenticationToken(principalName, "password");
|
||||
this.mockMvc.perform(get("/client-1").param(OAuth2ParameterNames.CODE, "code")
|
||||
.param(OAuth2ParameterNames.STATE, "state").with(authentication(authentication)).session(session))
|
||||
.andExpect(status().is3xxRedirection()).andExpect(redirectedUrl("http://localhost/client-1"));
|
||||
// @formatter:off
|
||||
MockHttpServletRequestBuilder clientRequest = get("/client-1")
|
||||
.param(OAuth2ParameterNames.CODE, "code")
|
||||
.param(OAuth2ParameterNames.STATE, "state")
|
||||
.with(authentication(authentication))
|
||||
.session(session);
|
||||
this.mockMvc.perform(clientRequest)
|
||||
.andExpect(status().is3xxRedirection())
|
||||
.andExpect(redirectedUrl("http://localhost/client-1"));
|
||||
// @formatter:on
|
||||
OAuth2AuthorizedClient authorizedClient = authorizedClientRepository
|
||||
.loadAuthorizedClient(this.registration1.getRegistrationId(), authentication, request);
|
||||
assertThat(authorizedClient).isNotNull();
|
||||
|
@ -191,10 +215,14 @@ public class OAuth2ClientConfigurerTests {
|
|||
// Setup the Authorization Request in the session
|
||||
Map<String, Object> attributes = new HashMap<>();
|
||||
attributes.put(OAuth2ParameterNames.REGISTRATION_ID, this.registration1.getRegistrationId());
|
||||
// @formatter:off
|
||||
OAuth2AuthorizationRequest authorizationRequest = OAuth2AuthorizationRequest.authorizationCode()
|
||||
.authorizationUri(this.registration1.getProviderDetails().getAuthorizationUri())
|
||||
.clientId(this.registration1.getClientId()).redirectUri("http://localhost/client-1").state("state")
|
||||
.attributes(attributes).build();
|
||||
.clientId(this.registration1.getClientId()).redirectUri("http://localhost/client-1")
|
||||
.state("state")
|
||||
.attributes(attributes)
|
||||
.build();
|
||||
// @formatter:on
|
||||
AuthorizationRequestRepository<OAuth2AuthorizationRequest> authorizationRequestRepository = new HttpSessionOAuth2AuthorizationRequestRepository();
|
||||
MockHttpServletRequest request = new MockHttpServletRequest("GET", "");
|
||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
|
@ -202,9 +230,16 @@ public class OAuth2ClientConfigurerTests {
|
|||
MockHttpSession session = (MockHttpSession) request.getSession();
|
||||
String principalName = "user1";
|
||||
TestingAuthenticationToken authentication = new TestingAuthenticationToken(principalName, "password");
|
||||
this.mockMvc.perform(get("/client-1").param(OAuth2ParameterNames.CODE, "code")
|
||||
.param(OAuth2ParameterNames.STATE, "state").with(authentication(authentication)).session(session))
|
||||
.andExpect(status().is3xxRedirection()).andExpect(redirectedUrl("http://localhost/client-1"));
|
||||
// @formatter:off
|
||||
MockHttpServletRequestBuilder clientRequest = get("/client-1")
|
||||
.param(OAuth2ParameterNames.CODE, "code")
|
||||
.param(OAuth2ParameterNames.STATE, "state")
|
||||
.with(authentication(authentication))
|
||||
.session(session);
|
||||
this.mockMvc.perform(clientRequest)
|
||||
.andExpect(status().is3xxRedirection())
|
||||
.andExpect(redirectedUrl("http://localhost/client-1"));
|
||||
// @formatter:on
|
||||
verify(requestCache).getRequest(any(HttpServletRequest.class), any(HttpServletResponse.class));
|
||||
}
|
||||
|
||||
|
@ -218,8 +253,11 @@ public class OAuth2ClientConfigurerTests {
|
|||
given(authorizationRequestResolver.resolve(any()))
|
||||
.willAnswer((invocation) -> defaultAuthorizationRequestResolver.resolve(invocation.getArgument(0)));
|
||||
this.spring.register(OAuth2ClientConfig.class).autowire();
|
||||
this.mockMvc.perform(get("/oauth2/authorization/registration-1")).andExpect(status().is3xxRedirection())
|
||||
// @formatter:off
|
||||
this.mockMvc.perform(get("/oauth2/authorization/registration-1"))
|
||||
.andExpect(status().is3xxRedirection())
|
||||
.andReturn();
|
||||
// @formatter:on
|
||||
verify(authorizationRequestResolver).resolve(any());
|
||||
}
|
||||
|
||||
|
|
|
@ -110,11 +110,21 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.
|
|||
*/
|
||||
public class OAuth2LoginConfigurerTests {
|
||||
|
||||
// @formatter:off
|
||||
private static final ClientRegistration GOOGLE_CLIENT_REGISTRATION = CommonOAuth2Provider.GOOGLE
|
||||
.getBuilder("google").clientId("clientId").clientSecret("clientSecret").build();
|
||||
.getBuilder("google")
|
||||
.clientId("clientId")
|
||||
.clientSecret("clientSecret")
|
||||
.build();
|
||||
// @formatter:on
|
||||
|
||||
// @formatter:off
|
||||
private static final ClientRegistration GITHUB_CLIENT_REGISTRATION = CommonOAuth2Provider.GITHUB
|
||||
.getBuilder("github").clientId("clientId").clientSecret("clientSecret").build();
|
||||
.getBuilder("github")
|
||||
.clientId("clientId")
|
||||
.clientSecret("clientSecret")
|
||||
.build();
|
||||
// @formatter:on
|
||||
|
||||
private ConfigurableApplicationContext context;
|
||||
|
||||
|
@ -296,11 +306,15 @@ public class OAuth2LoginConfigurerTests {
|
|||
loadConfig(OAuth2LoginConfigCustomAuthorizationRequestResolver.class);
|
||||
OAuth2AuthorizationRequestResolver resolver = this.context
|
||||
.getBean(OAuth2LoginConfigCustomAuthorizationRequestResolver.class).resolver;
|
||||
// @formatter:off
|
||||
OAuth2AuthorizationRequest result = OAuth2AuthorizationRequest.authorizationCode()
|
||||
.authorizationUri("https://accounts.google.com/authorize").clientId("client-id").state("adsfa")
|
||||
.authorizationUri("https://accounts.google.com/authorize")
|
||||
.clientId("client-id")
|
||||
.state("adsfa")
|
||||
.authorizationRequestUri(
|
||||
"https://accounts.google.com/o/oauth2/v2/auth?response_type=code&client_id=clientId&scope=openid+profile+email&state=state&redirect_uri=http%3A%2F%2Flocalhost%2Flogin%2Foauth2%2Fcode%2Fgoogle&custom-param1=custom-value1")
|
||||
.build();
|
||||
// @formatter:on
|
||||
given(resolver.resolve(any())).willReturn(result);
|
||||
String requestUri = "/oauth2/authorization/google";
|
||||
this.request = new MockHttpServletRequest("GET", requestUri);
|
||||
|
@ -316,11 +330,15 @@ public class OAuth2LoginConfigurerTests {
|
|||
loadConfig(OAuth2LoginConfigCustomAuthorizationRequestResolverInLambda.class);
|
||||
OAuth2AuthorizationRequestResolver resolver = this.context
|
||||
.getBean(OAuth2LoginConfigCustomAuthorizationRequestResolverInLambda.class).resolver;
|
||||
// @formatter:off
|
||||
OAuth2AuthorizationRequest result = OAuth2AuthorizationRequest.authorizationCode()
|
||||
.authorizationUri("https://accounts.google.com/authorize").clientId("client-id").state("adsfa")
|
||||
.authorizationUri("https://accounts.google.com/authorize")
|
||||
.clientId("client-id")
|
||||
.state("adsfa")
|
||||
.authorizationRequestUri(
|
||||
"https://accounts.google.com/o/oauth2/v2/auth?response_type=code&client_id=clientId&scope=openid+profile+email&state=state&redirect_uri=http%3A%2F%2Flocalhost%2Flogin%2Foauth2%2Fcode%2Fgoogle&custom-param1=custom-value1")
|
||||
.build();
|
||||
// @formatter:on
|
||||
given(resolver.resolve(any())).willReturn(result);
|
||||
String requestUri = "/oauth2/authorization/google";
|
||||
this.request = new MockHttpServletRequest("GET", requestUri);
|
||||
|
@ -511,12 +529,17 @@ public class OAuth2LoginConfigurerTests {
|
|||
|
||||
private OAuth2AuthorizationRequest createOAuth2AuthorizationRequest(ClientRegistration registration,
|
||||
String... scopes) {
|
||||
// @formatter:off
|
||||
return OAuth2AuthorizationRequest.authorizationCode()
|
||||
.authorizationUri(registration.getProviderDetails().getAuthorizationUri())
|
||||
.clientId(registration.getClientId()).state("state123").redirectUri("http://localhost")
|
||||
.clientId(registration.getClientId())
|
||||
.state("state123")
|
||||
.redirectUri("http://localhost")
|
||||
.attributes(Collections.singletonMap(OAuth2ParameterNames.REGISTRATION_ID,
|
||||
registration.getRegistrationId()))
|
||||
.scope(scopes).build();
|
||||
.scope(scopes)
|
||||
.build();
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
private static OAuth2AccessTokenResponseClient<OAuth2AuthorizationCodeGrantRequest> createOauth2AccessTokenResponseClient() {
|
||||
|
|
|
@ -121,6 +121,7 @@ import org.springframework.security.web.access.AccessDeniedHandlerImpl;
|
|||
import org.springframework.test.web.servlet.MockMvc;
|
||||
import org.springframework.test.web.servlet.MvcResult;
|
||||
import org.springframework.test.web.servlet.ResultMatcher;
|
||||
import org.springframework.test.web.servlet.request.MockHttpServletRequestBuilder;
|
||||
import org.springframework.test.web.servlet.request.RequestPostProcessor;
|
||||
import org.springframework.util.LinkedMultiValueMap;
|
||||
import org.springframework.util.MultiValueMap;
|
||||
|
@ -199,8 +200,11 @@ public class OAuth2ResourceServerConfigurerTests {
|
|||
this.spring.register(RestOperationsConfig.class, DefaultConfig.class, BasicController.class).autowire();
|
||||
mockRestOperations(jwks("Default"));
|
||||
String token = this.token("ValidNoScopes");
|
||||
this.mvc.perform(get("/").with(bearerToken(token))).andExpect(status().isOk())
|
||||
// @formatter:off
|
||||
this.mvc.perform(get("/").with(bearerToken(token)))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(content().string("ok"));
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -208,8 +212,11 @@ public class OAuth2ResourceServerConfigurerTests {
|
|||
this.spring.register(RestOperationsConfig.class, DefaultInLambdaConfig.class, BasicController.class).autowire();
|
||||
mockRestOperations(jwks("Default"));
|
||||
String token = this.token("ValidNoScopes");
|
||||
this.mvc.perform(get("/").with(bearerToken(token))).andExpect(status().isOk())
|
||||
// @formatter:off
|
||||
this.mvc.perform(get("/").with(bearerToken(token)))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(content().string("ok"));
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -217,8 +224,11 @@ public class OAuth2ResourceServerConfigurerTests {
|
|||
this.spring.register(WebServerConfig.class, JwkSetUriConfig.class, BasicController.class).autowire();
|
||||
mockWebServer(jwks("Default"));
|
||||
String token = this.token("ValidNoScopes");
|
||||
this.mvc.perform(get("/").with(bearerToken(token))).andExpect(status().isOk())
|
||||
// @formatter:off
|
||||
this.mvc.perform(get("/").with(bearerToken(token)))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(content().string("ok"));
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -226,8 +236,11 @@ public class OAuth2ResourceServerConfigurerTests {
|
|||
this.spring.register(WebServerConfig.class, JwkSetUriInLambdaConfig.class, BasicController.class).autowire();
|
||||
mockWebServer(jwks("Default"));
|
||||
String token = this.token("ValidNoScopes");
|
||||
this.mvc.perform(get("/").with(bearerToken(token))).andExpect(status().isOk())
|
||||
// @formatter:off
|
||||
this.mvc.perform(get("/").with(bearerToken(token)))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(content().string("ok"));
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -235,8 +248,11 @@ public class OAuth2ResourceServerConfigurerTests {
|
|||
this.spring.register(RestOperationsConfig.class, DefaultConfig.class, BasicController.class).autowire();
|
||||
mockRestOperations(jwks("Default"));
|
||||
String token = this.token("Expired");
|
||||
this.mvc.perform(get("/").with(bearerToken(token))).andExpect(status().isUnauthorized())
|
||||
// @formatter:off
|
||||
this.mvc.perform(get("/").with(bearerToken(token)))
|
||||
.andExpect(status().isUnauthorized())
|
||||
.andExpect(invalidTokenHeader("An error occurred while attempting to decode the Jwt"));
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -244,8 +260,11 @@ public class OAuth2ResourceServerConfigurerTests {
|
|||
this.spring.register(RestOperationsConfig.class, DefaultConfig.class).autowire();
|
||||
mockRestOperations("malformed");
|
||||
String token = this.token("ValidNoScopes");
|
||||
this.mvc.perform(get("/").with(bearerToken(token))).andExpect(status().isUnauthorized())
|
||||
// @formatter:off
|
||||
this.mvc.perform(get("/").with(bearerToken(token)))
|
||||
.andExpect(status().isUnauthorized())
|
||||
.andExpect(header().string("WWW-Authenticate", "Bearer"));
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -253,15 +272,21 @@ public class OAuth2ResourceServerConfigurerTests {
|
|||
this.spring.register(WebServerConfig.class, JwkSetUriConfig.class).autowire();
|
||||
this.web.shutdown();
|
||||
String token = this.token("ValidNoScopes");
|
||||
this.mvc.perform(get("/").with(bearerToken(token))).andExpect(status().isUnauthorized())
|
||||
// @formatter:off
|
||||
this.mvc.perform(get("/").with(bearerToken(token)))
|
||||
.andExpect(status().isUnauthorized())
|
||||
.andExpect(header().string("WWW-Authenticate", "Bearer"));
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getWhenUsingDefaultsWithMalformedBearerTokenThenInvalidToken() throws Exception {
|
||||
this.spring.register(JwkSetUriConfig.class).autowire();
|
||||
this.mvc.perform(get("/").with(bearerToken("an\"invalid\"token"))).andExpect(status().isUnauthorized())
|
||||
// @formatter:off
|
||||
this.mvc.perform(get("/").with(bearerToken("an\"invalid\"token")))
|
||||
.andExpect(status().isUnauthorized())
|
||||
.andExpect(invalidTokenHeader("Bearer token is malformed"));
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -269,16 +294,22 @@ public class OAuth2ResourceServerConfigurerTests {
|
|||
this.spring.register(RestOperationsConfig.class, DefaultConfig.class).autowire();
|
||||
mockRestOperations(jwks("Default"));
|
||||
String token = this.token("MalformedPayload");
|
||||
this.mvc.perform(get("/").with(bearerToken(token))).andExpect(status().isUnauthorized()).andExpect(
|
||||
invalidTokenHeader("An error occurred while attempting to decode the Jwt: Malformed payload"));
|
||||
// @formatter:off
|
||||
this.mvc.perform(get("/").with(bearerToken(token)))
|
||||
.andExpect(status().isUnauthorized())
|
||||
.andExpect(invalidTokenHeader("An error occurred while attempting to decode the Jwt: Malformed payload"));
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getWhenUsingDefaultsWithUnsignedBearerTokenThenInvalidToken() throws Exception {
|
||||
this.spring.register(JwkSetUriConfig.class).autowire();
|
||||
String token = this.token("Unsigned");
|
||||
this.mvc.perform(get("/").with(bearerToken(token))).andExpect(status().isUnauthorized())
|
||||
// @formatter:off
|
||||
this.mvc.perform(get("/").with(bearerToken(token)))
|
||||
.andExpect(status().isUnauthorized())
|
||||
.andExpect(invalidTokenHeader("Unsupported algorithm of none"));
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -286,16 +317,21 @@ public class OAuth2ResourceServerConfigurerTests {
|
|||
this.spring.register(RestOperationsConfig.class, DefaultConfig.class).autowire();
|
||||
this.mockRestOperations(jwks("Default"));
|
||||
String token = this.token("TooEarly");
|
||||
this.mvc.perform(get("/").with(bearerToken(token))).andExpect(status().isUnauthorized())
|
||||
// @formatter:off
|
||||
this.mvc.perform(get("/").with(bearerToken(token)))
|
||||
.andExpect(status().isUnauthorized())
|
||||
.andExpect(invalidTokenHeader("An error occurred while attempting to decode the Jwt"));
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getWhenUsingDefaultsWithBearerTokenInTwoPlacesThenInvalidRequest() throws Exception {
|
||||
this.spring.register(JwkSetUriConfig.class).autowire();
|
||||
// @formatter:off
|
||||
this.mvc.perform(get("/").with(bearerToken("token")).with(bearerToken("token").asParam()))
|
||||
.andExpect(status().isBadRequest())
|
||||
.andExpect(invalidRequestHeader("Found multiple bearer tokens in the request"));
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -304,23 +340,32 @@ public class OAuth2ResourceServerConfigurerTests {
|
|||
MultiValueMap<String, String> params = new LinkedMultiValueMap<>();
|
||||
params.add("access_token", "token1");
|
||||
params.add("access_token", "token2");
|
||||
this.mvc.perform(get("/").params(params)).andExpect(status().isBadRequest())
|
||||
// @formatter:off
|
||||
this.mvc.perform(get("/").params(params))
|
||||
.andExpect(status().isBadRequest())
|
||||
.andExpect(invalidRequestHeader("Found multiple bearer tokens in the request"));
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
public void postWhenUsingDefaultsWithBearerTokenAsFormParameterThenIgnoresToken() throws Exception {
|
||||
this.spring.register(JwkSetUriConfig.class).autowire();
|
||||
this.mvc.perform(post("/") // engage csrf
|
||||
.with(bearerToken("token").asParam())).andExpect(status().isForbidden())
|
||||
// engage csrf
|
||||
// @formatter:off
|
||||
this.mvc.perform(post("/").with(bearerToken("token").asParam()))
|
||||
.andExpect(status().isForbidden())
|
||||
.andExpect(header().doesNotExist(HttpHeaders.WWW_AUTHENTICATE));
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
public void postWhenCsrfDisabledWithBearerTokenAsFormParameterThenIgnoresToken() throws Exception {
|
||||
this.spring.register(CsrfDisabledConfig.class).autowire();
|
||||
this.mvc.perform(post("/").with(bearerToken("token").asParam())).andExpect(status().isUnauthorized())
|
||||
// @formatter:off
|
||||
this.mvc.perform(post("/").with(bearerToken("token").asParam()))
|
||||
.andExpect(status().isUnauthorized())
|
||||
.andExpect(header().string(HttpHeaders.WWW_AUTHENTICATE, "Bearer"));
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
// gh-8031
|
||||
|
@ -329,14 +374,20 @@ public class OAuth2ResourceServerConfigurerTests {
|
|||
this.spring.register(RestOperationsConfig.class, AnonymousDisabledConfig.class).autowire();
|
||||
mockRestOperations(jwks("Default"));
|
||||
String token = token("ValidNoScopes");
|
||||
this.mvc.perform(get("/authenticated").with(bearerToken(token))).andExpect(status().isNotFound());
|
||||
// @formatter:off
|
||||
this.mvc.perform(get("/authenticated").with(bearerToken(token)))
|
||||
.andExpect(status().isNotFound());
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getWhenUsingDefaultsWithNoBearerTokenThenUnauthorized() throws Exception {
|
||||
this.spring.register(JwkSetUriConfig.class).autowire();
|
||||
this.mvc.perform(get("/")).andExpect(status().isUnauthorized())
|
||||
// @formatter:off
|
||||
this.mvc.perform(get("/"))
|
||||
.andExpect(status().isUnauthorized())
|
||||
.andExpect(header().string(HttpHeaders.WWW_AUTHENTICATE, "Bearer"));
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -344,8 +395,11 @@ public class OAuth2ResourceServerConfigurerTests {
|
|||
this.spring.register(RestOperationsConfig.class, DefaultConfig.class, BasicController.class).autowire();
|
||||
mockRestOperations(jwks("Default"));
|
||||
String token = this.token("ValidMessageReadScope");
|
||||
this.mvc.perform(get("/requires-read-scope").with(bearerToken(token))).andExpect(status().isOk())
|
||||
// @formatter:off
|
||||
this.mvc.perform(get("/requires-read-scope").with(bearerToken(token)))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(content().string("[SCOPE_message:read]"));
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -353,8 +407,11 @@ public class OAuth2ResourceServerConfigurerTests {
|
|||
this.spring.register(RestOperationsConfig.class, DefaultConfig.class, BasicController.class).autowire();
|
||||
mockRestOperations(jwks("Default"));
|
||||
String token = this.token("ValidNoScopes");
|
||||
this.mvc.perform(get("/requires-read-scope").with(bearerToken(token))).andExpect(status().isForbidden())
|
||||
// @formatter:off
|
||||
this.mvc.perform(get("/requires-read-scope").with(bearerToken(token)))
|
||||
.andExpect(status().isForbidden())
|
||||
.andExpect(insufficientScopeHeader());
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -362,8 +419,11 @@ public class OAuth2ResourceServerConfigurerTests {
|
|||
this.spring.register(RestOperationsConfig.class, DefaultConfig.class, BasicController.class).autowire();
|
||||
mockRestOperations(jwks("Default"));
|
||||
String token = this.token("ValidMessageWriteScp");
|
||||
this.mvc.perform(get("/requires-read-scope").with(bearerToken(token))).andExpect(status().isForbidden())
|
||||
// @formatter:off
|
||||
this.mvc.perform(get("/requires-read-scope").with(bearerToken(token)))
|
||||
.andExpect(status().isForbidden())
|
||||
.andExpect(insufficientScopeHeader());
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -371,8 +431,11 @@ public class OAuth2ResourceServerConfigurerTests {
|
|||
this.spring.register(RestOperationsConfig.class, DefaultConfig.class).autowire();
|
||||
mockRestOperations(jwks("Empty"));
|
||||
String token = this.token("ValidNoScopes");
|
||||
this.mvc.perform(get("/").with(bearerToken(token))).andExpect(status().isUnauthorized())
|
||||
// @formatter:off
|
||||
this.mvc.perform(get("/").with(bearerToken(token)))
|
||||
.andExpect(status().isUnauthorized())
|
||||
.andExpect(invalidTokenHeader("An error occurred while attempting to decode the Jwt"));
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -380,8 +443,11 @@ public class OAuth2ResourceServerConfigurerTests {
|
|||
this.spring.register(RestOperationsConfig.class, DefaultConfig.class, BasicController.class).autowire();
|
||||
mockRestOperations(jwks("TwoKeys"));
|
||||
String token = this.token("ValidNoScopes");
|
||||
this.mvc.perform(get("/authenticated").with(bearerToken(token))).andExpect(status().isOk())
|
||||
// @formatter:off
|
||||
this.mvc.perform(get("/authenticated").with(bearerToken(token)))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(content().string("test-subject"));
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -389,8 +455,11 @@ public class OAuth2ResourceServerConfigurerTests {
|
|||
this.spring.register(RestOperationsConfig.class, DefaultConfig.class, BasicController.class).autowire();
|
||||
mockRestOperations(jwks("TwoKeys"));
|
||||
String token = this.token("Kid");
|
||||
this.mvc.perform(get("/authenticated").with(bearerToken(token))).andExpect(status().isOk())
|
||||
// @formatter:off
|
||||
this.mvc.perform(get("/authenticated").with(bearerToken(token)))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(content().string("test-subject"));
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -398,8 +467,11 @@ public class OAuth2ResourceServerConfigurerTests {
|
|||
this.spring.register(RestOperationsConfig.class, MethodSecurityConfig.class, BasicController.class).autowire();
|
||||
mockRestOperations(jwks("Default"));
|
||||
String token = this.token("ValidMessageReadScope");
|
||||
this.mvc.perform(get("/ms-requires-read-scope").with(bearerToken(token))).andExpect(status().isOk())
|
||||
// @formatter:off
|
||||
this.mvc.perform(get("/ms-requires-read-scope").with(bearerToken(token)))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(content().string("[SCOPE_message:read]"));
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -407,8 +479,11 @@ public class OAuth2ResourceServerConfigurerTests {
|
|||
this.spring.register(RestOperationsConfig.class, MethodSecurityConfig.class, BasicController.class).autowire();
|
||||
mockRestOperations(jwks("Default"));
|
||||
String token = this.token("ValidMessageReadScp");
|
||||
this.mvc.perform(get("/ms-requires-read-scope").with(bearerToken(token))).andExpect(status().isOk())
|
||||
// @formatter:off
|
||||
this.mvc.perform(get("/ms-requires-read-scope").with(bearerToken(token)))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(content().string("[SCOPE_message:read]"));
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -416,8 +491,11 @@ public class OAuth2ResourceServerConfigurerTests {
|
|||
this.spring.register(RestOperationsConfig.class, MethodSecurityConfig.class, BasicController.class).autowire();
|
||||
mockRestOperations(jwks("Default"));
|
||||
String token = this.token("ValidNoScopes");
|
||||
this.mvc.perform(get("/ms-requires-read-scope").with(bearerToken(token))).andExpect(status().isForbidden())
|
||||
// @formatter:off
|
||||
this.mvc.perform(get("/ms-requires-read-scope").with(bearerToken(token)))
|
||||
.andExpect(status().isForbidden())
|
||||
.andExpect(insufficientScopeHeader());
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -425,8 +503,11 @@ public class OAuth2ResourceServerConfigurerTests {
|
|||
this.spring.register(RestOperationsConfig.class, MethodSecurityConfig.class, BasicController.class).autowire();
|
||||
mockRestOperations(jwks("Default"));
|
||||
String token = this.token("ValidMessageWriteScp");
|
||||
this.mvc.perform(get("/ms-requires-read-scope").with(bearerToken(token))).andExpect(status().isForbidden())
|
||||
// @formatter:off
|
||||
this.mvc.perform(get("/ms-requires-read-scope").with(bearerToken(token)))
|
||||
.andExpect(status().isForbidden())
|
||||
.andExpect(insufficientScopeHeader());
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -434,8 +515,11 @@ public class OAuth2ResourceServerConfigurerTests {
|
|||
this.spring.register(RestOperationsConfig.class, MethodSecurityConfig.class, BasicController.class).autowire();
|
||||
mockRestOperations(jwks("Default"));
|
||||
String token = this.token("ValidMessageReadScope");
|
||||
this.mvc.perform(get("/ms-deny").with(bearerToken(token))).andExpect(status().isForbidden())
|
||||
// @formatter:off
|
||||
this.mvc.perform(get("/ms-deny").with(bearerToken(token)))
|
||||
.andExpect(status().isForbidden())
|
||||
.andExpect(insufficientScopeHeader());
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -443,15 +527,21 @@ public class OAuth2ResourceServerConfigurerTests {
|
|||
this.spring.register(RestOperationsConfig.class, DefaultConfig.class, BasicController.class).autowire();
|
||||
mockRestOperations(jwks("Default"));
|
||||
String token = this.token("ValidNoScopes");
|
||||
this.mvc.perform(post("/authenticated").with(bearerToken(token))).andExpect(status().isOk())
|
||||
// @formatter:off
|
||||
this.mvc.perform(post("/authenticated").with(bearerToken(token)))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(content().string("test-subject"));
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
public void postWhenUsingDefaultsWithNoBearerTokenThenCsrfDenies() throws Exception {
|
||||
this.spring.register(JwkSetUriConfig.class).autowire();
|
||||
this.mvc.perform(post("/authenticated")).andExpect(status().isForbidden())
|
||||
// @formatter:off
|
||||
this.mvc.perform(post("/authenticated"))
|
||||
.andExpect(status().isForbidden())
|
||||
.andExpect(header().doesNotExist(HttpHeaders.WWW_AUTHENTICATE));
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -459,8 +549,11 @@ public class OAuth2ResourceServerConfigurerTests {
|
|||
this.spring.register(RestOperationsConfig.class, DefaultConfig.class).autowire();
|
||||
mockRestOperations(jwks("Default"));
|
||||
String token = this.token("Expired");
|
||||
this.mvc.perform(post("/authenticated").with(bearerToken(token))).andExpect(status().isUnauthorized())
|
||||
// @formatter:off
|
||||
this.mvc.perform(post("/authenticated").with(bearerToken(token)))
|
||||
.andExpect(status().isUnauthorized())
|
||||
.andExpect(invalidTokenHeader("An error occurred while attempting to decode the Jwt"));
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -468,7 +561,11 @@ public class OAuth2ResourceServerConfigurerTests {
|
|||
this.spring.register(RestOperationsConfig.class, DefaultConfig.class, BasicController.class).autowire();
|
||||
mockRestOperations(jwks("Default"));
|
||||
String token = this.token("ValidNoScopes");
|
||||
MvcResult result = this.mvc.perform(get("/").with(bearerToken(token))).andExpect(status().isOk()).andReturn();
|
||||
// @formatter:off
|
||||
MvcResult result = this.mvc.perform(get("/").with(bearerToken(token)))
|
||||
.andExpect(status().isOk())
|
||||
.andReturn();
|
||||
// @formatter:on
|
||||
assertThat(result.getRequest().getSession(false)).isNull();
|
||||
}
|
||||
|
||||
|
@ -476,15 +573,23 @@ public class OAuth2ResourceServerConfigurerTests {
|
|||
public void requestWhenIntrospectionConfiguredThenSessionIsNotCreated() throws Exception {
|
||||
this.spring.register(RestOperationsConfig.class, OpaqueTokenConfig.class, BasicController.class).autowire();
|
||||
mockRestOperations(json("Active"));
|
||||
MvcResult result = this.mvc.perform(get("/authenticated").with(bearerToken("token"))).andExpect(status().isOk())
|
||||
.andExpect(content().string("test-subject")).andReturn();
|
||||
// @formatter:off
|
||||
MvcResult result = this.mvc.perform(get("/authenticated").with(bearerToken("token")))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(content().string("test-subject"))
|
||||
.andReturn();
|
||||
// @formatter:on
|
||||
assertThat(result.getRequest().getSession(false)).isNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void requestWhenUsingDefaultsAndNoBearerTokenThenSessionIsCreated() throws Exception {
|
||||
this.spring.register(JwkSetUriConfig.class, BasicController.class).autowire();
|
||||
MvcResult result = this.mvc.perform(get("/")).andExpect(status().isUnauthorized()).andReturn();
|
||||
// @formatter:off
|
||||
MvcResult result = this.mvc.perform(get("/"))
|
||||
.andExpect(status().isUnauthorized())
|
||||
.andReturn();
|
||||
// @formatter:on
|
||||
assertThat(result.getRequest().getSession(false)).isNotNull();
|
||||
}
|
||||
|
||||
|
@ -494,7 +599,11 @@ public class OAuth2ResourceServerConfigurerTests {
|
|||
.autowire();
|
||||
mockRestOperations(jwks("Default"));
|
||||
String token = this.token("ValidNoScopes");
|
||||
MvcResult result = this.mvc.perform(get("/").with(bearerToken(token))).andExpect(status().isOk()).andReturn();
|
||||
// @formatter:off
|
||||
MvcResult result = this.mvc.perform(get("/").with(bearerToken(token)))
|
||||
.andExpect(status().isOk())
|
||||
.andReturn();
|
||||
// @formatter:on
|
||||
assertThat(result.getRequest().getSession(false)).isNotNull();
|
||||
}
|
||||
|
||||
|
@ -505,10 +614,14 @@ public class OAuth2ResourceServerConfigurerTests {
|
|||
.autowire();
|
||||
JwtDecoder decoder = this.spring.getContext().getBean(JwtDecoder.class);
|
||||
given(decoder.decode(anyString())).willReturn(JWT);
|
||||
this.mvc.perform(get("/authenticated").with(bearerToken(JWT_TOKEN))).andExpect(status().isOk())
|
||||
// @formatter:off
|
||||
this.mvc.perform(get("/authenticated").with(bearerToken(JWT_TOKEN)))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(content().string(JWT_SUBJECT));
|
||||
this.mvc.perform(post("/authenticated").param("access_token", JWT_TOKEN)).andExpect(status().isOk())
|
||||
this.mvc.perform(post("/authenticated").param("access_token", JWT_TOKEN))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(content().string(JWT_SUBJECT));
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -519,10 +632,14 @@ public class OAuth2ResourceServerConfigurerTests {
|
|||
.autowire();
|
||||
JwtDecoder decoder = this.spring.getContext().getBean(JwtDecoder.class);
|
||||
given(decoder.decode(anyString())).willReturn(JWT);
|
||||
this.mvc.perform(get("/authenticated").with(bearerToken(JWT_TOKEN))).andExpect(status().isOk())
|
||||
// @formatter:off
|
||||
this.mvc.perform(get("/authenticated").with(bearerToken(JWT_TOKEN)))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(content().string(JWT_SUBJECT));
|
||||
this.mvc.perform(get("/authenticated").param("access_token", JWT_TOKEN)).andExpect(status().isOk())
|
||||
this.mvc.perform(get("/authenticated").param("access_token", JWT_TOKEN))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(content().string(JWT_SUBJECT));
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -532,10 +649,15 @@ public class OAuth2ResourceServerConfigurerTests {
|
|||
.autowire();
|
||||
JwtDecoder decoder = this.spring.getContext().getBean(JwtDecoder.class);
|
||||
given(decoder.decode(anyString())).willReturn(JWT);
|
||||
this.mvc.perform(
|
||||
post("/authenticated").param("access_token", JWT_TOKEN).with(bearerToken(JWT_TOKEN)).with(csrf()))
|
||||
// @formatter:off
|
||||
MockHttpServletRequestBuilder request = post("/authenticated")
|
||||
.param("access_token", JWT_TOKEN)
|
||||
.with(bearerToken(JWT_TOKEN))
|
||||
.with(csrf());
|
||||
this.mvc.perform(request)
|
||||
.andExpect(status().isBadRequest())
|
||||
.andExpect(header().string(HttpHeaders.WWW_AUTHENTICATE, containsString("invalid_request")));
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -546,9 +668,14 @@ public class OAuth2ResourceServerConfigurerTests {
|
|||
.autowire();
|
||||
JwtDecoder decoder = this.spring.getContext().getBean(JwtDecoder.class);
|
||||
given(decoder.decode(anyString())).willReturn(JWT);
|
||||
this.mvc.perform(get("/authenticated").with(bearerToken(JWT_TOKEN)).param("access_token", JWT_TOKEN))
|
||||
// @formatter:off
|
||||
MockHttpServletRequestBuilder request = get("/authenticated")
|
||||
.with(bearerToken(JWT_TOKEN))
|
||||
.param("access_token", JWT_TOKEN);
|
||||
this.mvc.perform(request)
|
||||
.andExpect(status().isBadRequest())
|
||||
.andExpect(header().string(HttpHeaders.WWW_AUTHENTICATE, containsString("invalid_request")));
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -597,8 +724,11 @@ public class OAuth2ResourceServerConfigurerTests {
|
|||
CustomJwtDecoderOnDsl config = this.spring.getContext().getBean(CustomJwtDecoderOnDsl.class);
|
||||
JwtDecoder decoder = config.decoder();
|
||||
given(decoder.decode(anyString())).willReturn(JWT);
|
||||
this.mvc.perform(get("/authenticated").with(bearerToken(JWT_TOKEN))).andExpect(status().isOk())
|
||||
// @formatter:off
|
||||
this.mvc.perform(get("/authenticated").with(bearerToken(JWT_TOKEN)))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(content().string(JWT_SUBJECT));
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -607,8 +737,11 @@ public class OAuth2ResourceServerConfigurerTests {
|
|||
CustomJwtDecoderInLambdaOnDsl config = this.spring.getContext().getBean(CustomJwtDecoderInLambdaOnDsl.class);
|
||||
JwtDecoder decoder = config.decoder();
|
||||
given(decoder.decode(anyString())).willReturn(JWT);
|
||||
this.mvc.perform(get("/authenticated").with(bearerToken(JWT_TOKEN))).andExpect(status().isOk())
|
||||
// @formatter:off
|
||||
this.mvc.perform(get("/authenticated").with(bearerToken(JWT_TOKEN)))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(content().string(JWT_SUBJECT));
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -616,8 +749,11 @@ public class OAuth2ResourceServerConfigurerTests {
|
|||
this.spring.register(CustomJwtDecoderAsBean.class, BasicController.class).autowire();
|
||||
JwtDecoder decoder = this.spring.getContext().getBean(JwtDecoder.class);
|
||||
given(decoder.decode(anyString())).willReturn(JWT);
|
||||
this.mvc.perform(get("/authenticated").with(bearerToken(JWT_TOKEN))).andExpect(status().isOk())
|
||||
// @formatter:off
|
||||
this.mvc.perform(get("/authenticated").with(bearerToken(JWT_TOKEN)))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(content().string(JWT_SUBJECT));
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -686,8 +822,11 @@ public class OAuth2ResourceServerConfigurerTests {
|
|||
this.spring.register(RealmNameConfiguredOnEntryPoint.class, JwtDecoderConfig.class).autowire();
|
||||
JwtDecoder decoder = this.spring.getContext().getBean(JwtDecoder.class);
|
||||
given(decoder.decode(anyString())).willThrow(JwtException.class);
|
||||
this.mvc.perform(get("/authenticated").with(bearerToken("invalid_token"))).andExpect(status().isUnauthorized())
|
||||
// @formatter:off
|
||||
this.mvc.perform(get("/authenticated").with(bearerToken("invalid_token")))
|
||||
.andExpect(status().isUnauthorized())
|
||||
.andExpect(header().string(HttpHeaders.WWW_AUTHENTICATE, startsWith("Bearer realm=\"myRealm\"")));
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -695,9 +834,11 @@ public class OAuth2ResourceServerConfigurerTests {
|
|||
this.spring.register(RealmNameConfiguredOnAccessDeniedHandler.class, JwtDecoderConfig.class).autowire();
|
||||
JwtDecoder decoder = this.spring.getContext().getBean(JwtDecoder.class);
|
||||
given(decoder.decode(anyString())).willReturn(JWT);
|
||||
// @formatter:off
|
||||
this.mvc.perform(get("/authenticated").with(bearerToken("insufficiently_scoped")))
|
||||
.andExpect(status().isForbidden())
|
||||
.andExpect(header().string(HttpHeaders.WWW_AUTHENTICATE, startsWith("Bearer realm=\"myRealm\"")));
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -723,8 +864,11 @@ public class OAuth2ResourceServerConfigurerTests {
|
|||
.getJwtValidator();
|
||||
OAuth2Error error = new OAuth2Error("custom-error", "custom-description", "custom-uri");
|
||||
given(jwtValidator.validate(any(Jwt.class))).willReturn(OAuth2TokenValidatorResult.failure(error));
|
||||
this.mvc.perform(get("/").with(bearerToken(token))).andExpect(status().isUnauthorized())
|
||||
// @formatter:off
|
||||
this.mvc.perform(get("/").with(bearerToken(token)))
|
||||
.andExpect(status().isUnauthorized())
|
||||
.andExpect(header().string(HttpHeaders.WWW_AUTHENTICATE, containsString("custom-description")));
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -733,7 +877,10 @@ public class OAuth2ResourceServerConfigurerTests {
|
|||
.autowire();
|
||||
mockRestOperations(jwks("Default"));
|
||||
String token = this.token("ExpiresAt4687177990");
|
||||
this.mvc.perform(get("/").with(bearerToken(token))).andExpect(status().isOk());
|
||||
// @formatter:off
|
||||
this.mvc.perform(get("/").with(bearerToken(token)))
|
||||
.andExpect(status().isOk());
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -742,8 +889,11 @@ public class OAuth2ResourceServerConfigurerTests {
|
|||
.autowire();
|
||||
mockRestOperations(jwks("Default"));
|
||||
String token = this.token("ExpiresAt4687177990");
|
||||
this.mvc.perform(get("/").with(bearerToken(token))).andExpect(status().isUnauthorized())
|
||||
// @formatter:off
|
||||
this.mvc.perform(get("/").with(bearerToken(token)))
|
||||
.andExpect(status().isUnauthorized())
|
||||
.andExpect(invalidTokenHeader("Jwt expired at"));
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -755,7 +905,10 @@ public class OAuth2ResourceServerConfigurerTests {
|
|||
given(jwtAuthenticationConverter.convert(JWT)).willReturn(JWT_AUTHENTICATION_TOKEN);
|
||||
JwtDecoder jwtDecoder = this.spring.getContext().getBean(JwtDecoder.class);
|
||||
given(jwtDecoder.decode(anyString())).willReturn(JWT);
|
||||
this.mvc.perform(get("/").with(bearerToken(JWT_TOKEN))).andExpect(status().isOk());
|
||||
// @formatter:off
|
||||
this.mvc.perform(get("/").with(bearerToken(JWT_TOKEN)))
|
||||
.andExpect(status().isOk());
|
||||
// @formatter:on
|
||||
verify(jwtAuthenticationConverter).convert(JWT);
|
||||
}
|
||||
|
||||
|
@ -766,28 +919,40 @@ public class OAuth2ResourceServerConfigurerTests {
|
|||
.autowire();
|
||||
JwtDecoder decoder = this.spring.getContext().getBean(JwtDecoder.class);
|
||||
given(decoder.decode(JWT_TOKEN)).willReturn(JWT);
|
||||
this.mvc.perform(get("/requires-read-scope").with(bearerToken(JWT_TOKEN))).andExpect(status().isOk());
|
||||
// @formatter:off
|
||||
this.mvc.perform(get("/requires-read-scope").with(bearerToken(JWT_TOKEN)))
|
||||
.andExpect(status().isOk());
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
public void requestWhenUsingPublicKeyAndValidTokenThenAuthenticates() throws Exception {
|
||||
this.spring.register(SingleKeyConfig.class, BasicController.class).autowire();
|
||||
String token = this.token("ValidNoScopes");
|
||||
this.mvc.perform(get("/").with(bearerToken(token))).andExpect(status().isOk());
|
||||
// @formatter:off
|
||||
this.mvc.perform(get("/").with(bearerToken(token)))
|
||||
.andExpect(status().isOk());
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
public void requestWhenUsingPublicKeyAndSignatureFailsThenReturnsInvalidToken() throws Exception {
|
||||
this.spring.register(SingleKeyConfig.class).autowire();
|
||||
String token = this.token("WrongSignature");
|
||||
this.mvc.perform(get("/").with(bearerToken(token))).andExpect(invalidTokenHeader("signature"));
|
||||
// @formatter:off
|
||||
this.mvc.perform(get("/").with(bearerToken(token)))
|
||||
.andExpect(invalidTokenHeader("signature"));
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
public void requestWhenUsingPublicKeyAlgorithmDoesNotMatchThenReturnsInvalidToken() throws Exception {
|
||||
this.spring.register(SingleKeyConfig.class).autowire();
|
||||
String token = this.token("WrongAlgorithm");
|
||||
this.mvc.perform(get("/").with(bearerToken(token))).andExpect(invalidTokenHeader("algorithm"));
|
||||
// @formatter:off
|
||||
this.mvc.perform(get("/").with(bearerToken(token)))
|
||||
.andExpect(invalidTokenHeader("algorithm"));
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
// gh-7793
|
||||
|
@ -805,8 +970,11 @@ public class OAuth2ResourceServerConfigurerTests {
|
|||
this.spring.register(JwtAuthenticationManagerConfig.class, BasicController.class).autowire();
|
||||
given(bean(AuthenticationProvider.class).authenticate(any(Authentication.class)))
|
||||
.willReturn(JWT_AUTHENTICATION_TOKEN);
|
||||
this.mvc.perform(get("/authenticated").with(bearerToken("token"))).andExpect(status().isOk())
|
||||
// @formatter:off
|
||||
this.mvc.perform(get("/authenticated").with(bearerToken("token")))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(content().string("mock-test-subject"));
|
||||
// @formatter:on
|
||||
verifyBean(AuthenticationProvider.class).authenticate(any(Authentication.class));
|
||||
}
|
||||
|
||||
|
@ -814,8 +982,11 @@ public class OAuth2ResourceServerConfigurerTests {
|
|||
public void getWhenIntrospectingThenOk() throws Exception {
|
||||
this.spring.register(RestOperationsConfig.class, OpaqueTokenConfig.class, BasicController.class).autowire();
|
||||
mockRestOperations(json("Active"));
|
||||
this.mvc.perform(get("/authenticated").with(bearerToken("token"))).andExpect(status().isOk())
|
||||
// @formatter:off
|
||||
this.mvc.perform(get("/authenticated").with(bearerToken("token")))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(content().string("test-subject"));
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -823,24 +994,33 @@ public class OAuth2ResourceServerConfigurerTests {
|
|||
this.spring.register(RestOperationsConfig.class, OpaqueTokenInLambdaConfig.class, BasicController.class)
|
||||
.autowire();
|
||||
mockRestOperations(json("Active"));
|
||||
this.mvc.perform(get("/authenticated").with(bearerToken("token"))).andExpect(status().isOk())
|
||||
// @formatter:off
|
||||
this.mvc.perform(get("/authenticated").with(bearerToken("token")))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(content().string("test-subject"));
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getWhenIntrospectionFailsThenUnauthorized() throws Exception {
|
||||
this.spring.register(RestOperationsConfig.class, OpaqueTokenConfig.class).autowire();
|
||||
mockRestOperations(json("Inactive"));
|
||||
this.mvc.perform(get("/").with(bearerToken("token"))).andExpect(status().isUnauthorized()).andExpect(
|
||||
header().string(HttpHeaders.WWW_AUTHENTICATE, containsString("Provided token isn't active")));
|
||||
// @formatter:off
|
||||
this.mvc.perform(get("/").with(bearerToken("token")))
|
||||
.andExpect(status().isUnauthorized())
|
||||
.andExpect(header().string(HttpHeaders.WWW_AUTHENTICATE, containsString("Provided token isn't active")));
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getWhenIntrospectionLacksScopeThenForbidden() throws Exception {
|
||||
this.spring.register(RestOperationsConfig.class, OpaqueTokenConfig.class).autowire();
|
||||
mockRestOperations(json("ActiveNoScopes"));
|
||||
this.mvc.perform(get("/requires-read-scope").with(bearerToken("token"))).andExpect(status().isForbidden())
|
||||
// @formatter:off
|
||||
this.mvc.perform(get("/requires-read-scope").with(bearerToken("token")))
|
||||
.andExpect(status().isForbidden())
|
||||
.andExpect(header().string(HttpHeaders.WWW_AUTHENTICATE, containsString("scope")));
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -848,8 +1028,11 @@ public class OAuth2ResourceServerConfigurerTests {
|
|||
this.spring.register(OpaqueTokenAuthenticationManagerConfig.class, BasicController.class).autowire();
|
||||
given(bean(AuthenticationProvider.class).authenticate(any(Authentication.class)))
|
||||
.willReturn(INTROSPECTION_AUTHENTICATION_TOKEN);
|
||||
this.mvc.perform(get("/authenticated").with(bearerToken("token"))).andExpect(status().isOk())
|
||||
// @formatter:off
|
||||
this.mvc.perform(get("/authenticated").with(bearerToken("token")))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(content().string("mock-test-subject"));
|
||||
// @formatter:on
|
||||
verifyBean(AuthenticationProvider.class).authenticate(any(Authentication.class));
|
||||
}
|
||||
|
||||
|
@ -858,8 +1041,11 @@ public class OAuth2ResourceServerConfigurerTests {
|
|||
this.spring.register(OpaqueTokenAuthenticationManagerInLambdaConfig.class, BasicController.class).autowire();
|
||||
given(bean(AuthenticationProvider.class).authenticate(any(Authentication.class)))
|
||||
.willReturn(INTROSPECTION_AUTHENTICATION_TOKEN);
|
||||
this.mvc.perform(get("/authenticated").with(bearerToken("token"))).andExpect(status().isOk())
|
||||
// @formatter:off
|
||||
this.mvc.perform(get("/authenticated").with(bearerToken("token")))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(content().string("mock-test-subject"));
|
||||
// @formatter:on
|
||||
verifyBean(AuthenticationProvider.class).authenticate(any(Authentication.class));
|
||||
}
|
||||
|
||||
|
@ -903,12 +1089,17 @@ public class OAuth2ResourceServerConfigurerTests {
|
|||
this.spring.register(BasicAndResourceServerConfig.class, JwtDecoderConfig.class).autowire();
|
||||
JwtDecoder decoder = this.spring.getContext().getBean(JwtDecoder.class);
|
||||
given(decoder.decode(anyString())).willThrow(JwtException.class);
|
||||
this.mvc.perform(get("/authenticated").with(httpBasic("some", "user"))).andExpect(status().isUnauthorized())
|
||||
// @formatter:off
|
||||
this.mvc.perform(get("/authenticated").with(httpBasic("some", "user")))
|
||||
.andExpect(status().isUnauthorized())
|
||||
.andExpect(header().string(HttpHeaders.WWW_AUTHENTICATE, startsWith("Basic")));
|
||||
this.mvc.perform(get("/authenticated")).andExpect(status().isUnauthorized())
|
||||
this.mvc.perform(get("/authenticated"))
|
||||
.andExpect(status().isUnauthorized())
|
||||
.andExpect(header().string(HttpHeaders.WWW_AUTHENTICATE, startsWith("Basic")));
|
||||
this.mvc.perform(get("/authenticated").with(bearerToken("invalid_token"))).andExpect(status().isUnauthorized())
|
||||
this.mvc.perform(get("/authenticated").with(bearerToken("invalid_token")))
|
||||
.andExpect(status().isUnauthorized())
|
||||
.andExpect(header().string(HttpHeaders.WWW_AUTHENTICATE, startsWith("Bearer")));
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -916,11 +1107,18 @@ public class OAuth2ResourceServerConfigurerTests {
|
|||
this.spring.register(FormAndResourceServerConfig.class, JwtDecoderConfig.class).autowire();
|
||||
JwtDecoder decoder = this.spring.getContext().getBean(JwtDecoder.class);
|
||||
given(decoder.decode(anyString())).willThrow(JwtException.class);
|
||||
MvcResult result = this.mvc.perform(get("/authenticated")).andExpect(status().isFound())
|
||||
.andExpect(redirectedUrl("http://localhost/login")).andReturn();
|
||||
assertThat(result.getRequest().getSession(false)).isNotNull();
|
||||
result = this.mvc.perform(get("/authenticated").with(bearerToken("token"))).andExpect(status().isUnauthorized())
|
||||
// @formatter:off
|
||||
MvcResult result = this.mvc.perform(get("/authenticated"))
|
||||
.andExpect(status().isFound())
|
||||
.andExpect(redirectedUrl("http://localhost/login"))
|
||||
.andReturn();
|
||||
// @formatter:on
|
||||
assertThat(result.getRequest().getSession(false)).isNotNull();
|
||||
// @formatter:off
|
||||
result = this.mvc.perform(get("/authenticated").with(bearerToken("token")))
|
||||
.andExpect(status().isUnauthorized())
|
||||
.andReturn();
|
||||
// @formatter:on
|
||||
assertThat(result.getRequest().getSession(false)).isNull();
|
||||
}
|
||||
|
||||
|
@ -931,11 +1129,14 @@ public class OAuth2ResourceServerConfigurerTests {
|
|||
.autowire();
|
||||
JwtDecoder decoder = this.spring.getContext().getBean(JwtDecoder.class);
|
||||
given(decoder.decode(anyString())).willReturn(JWT);
|
||||
// @formatter:off
|
||||
this.mvc.perform(get("/authenticated").with(httpBasic("basic-user", "basic-password")))
|
||||
.andExpect(status().isForbidden()).andExpect(header().doesNotExist(HttpHeaders.WWW_AUTHENTICATE));
|
||||
.andExpect(status().isForbidden())
|
||||
.andExpect(header().doesNotExist(HttpHeaders.WWW_AUTHENTICATE));
|
||||
this.mvc.perform(get("/authenticated").with(bearerToken("insufficiently_scoped")))
|
||||
.andExpect(status().isForbidden())
|
||||
.andExpect(header().string(HttpHeaders.WWW_AUTHENTICATE, startsWith("Bearer")));
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -944,10 +1145,14 @@ public class OAuth2ResourceServerConfigurerTests {
|
|||
.autowire();
|
||||
mockRestOperations(jwks("Default"));
|
||||
String token = this.token("ValidNoScopes");
|
||||
this.mvc.perform(get("/authenticated").with(bearerToken(token))).andExpect(status().isOk())
|
||||
// @formatter:off
|
||||
this.mvc.perform(get("/authenticated").with(bearerToken(token)))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(content().string("test-subject"));
|
||||
this.mvc.perform(get("/authenticated").with(httpBasic("basic-user", "basic-password")))
|
||||
.andExpect(status().isOk()).andExpect(content().string("basic-user"));
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(content().string("basic-user"));
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -980,16 +1185,25 @@ public class OAuth2ResourceServerConfigurerTests {
|
|||
String jwtThree = jwtFromIssuer(issuerThree);
|
||||
mockWebServer(String.format(metadata, issuerOne, issuerOne));
|
||||
mockWebServer(jwkSet);
|
||||
this.mvc.perform(get("/authenticated").with(bearerToken(jwtOne))).andExpect(status().isOk())
|
||||
// @formatter:off
|
||||
this.mvc.perform(get("/authenticated").with(bearerToken(jwtOne)))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(content().string("test-subject"));
|
||||
// @formatter:on
|
||||
mockWebServer(String.format(metadata, issuerTwo, issuerTwo));
|
||||
mockWebServer(jwkSet);
|
||||
this.mvc.perform(get("/authenticated").with(bearerToken(jwtTwo))).andExpect(status().isOk())
|
||||
// @formatter:off
|
||||
this.mvc.perform(get("/authenticated").with(bearerToken(jwtTwo)))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(content().string("test-subject"));
|
||||
// @formatter:on
|
||||
mockWebServer(String.format(metadata, issuerThree, issuerThree));
|
||||
mockWebServer(jwkSet);
|
||||
this.mvc.perform(get("/authenticated").with(bearerToken(jwtThree))).andExpect(status().isUnauthorized())
|
||||
// @formatter:off
|
||||
this.mvc.perform(get("/authenticated").with(bearerToken(jwtThree)))
|
||||
.andExpect(status().isUnauthorized())
|
||||
.andExpect(invalidTokenHeader("Invalid issuer"));
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
|
@ -40,6 +40,7 @@ import org.springframework.security.openid.OpenIDAuthenticationFilter;
|
|||
import org.springframework.security.openid.OpenIDAuthenticationProvider;
|
||||
import org.springframework.test.web.servlet.MockMvc;
|
||||
import org.springframework.test.web.servlet.MvcResult;
|
||||
import org.springframework.test.web.servlet.request.MockHttpServletRequestBuilder;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
|
@ -84,15 +85,21 @@ public class OpenIDLoginConfigurerTests {
|
|||
@Test
|
||||
public void openidLoginWhenInvokedTwiceThenUsesOriginalLoginPage() throws Exception {
|
||||
this.spring.register(InvokeTwiceDoesNotOverrideConfig.class).autowire();
|
||||
this.mvc.perform(get("/")).andExpect(status().isFound())
|
||||
// @formatter:off
|
||||
this.mvc.perform(get("/"))
|
||||
.andExpect(status().isFound())
|
||||
.andExpect(redirectedUrl("http://localhost/login/custom"));
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
public void requestWhenOpenIdLoginPageInLambdaThenRedirectsToLoginPAge() throws Exception {
|
||||
this.spring.register(OpenIdLoginPageInLambdaConfig.class).autowire();
|
||||
this.mvc.perform(get("/")).andExpect(status().isFound())
|
||||
// @formatter:off
|
||||
this.mvc.perform(get("/"))
|
||||
.andExpect(status().isFound())
|
||||
.andExpect(redirectedUrl("http://localhost/login/custom"));
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -144,11 +151,15 @@ public class OpenIDLoginConfigurerTests {
|
|||
server.enqueue(new MockResponse().addHeader(YadisResolver.YADIS_XRDS_LOCATION, endpoint));
|
||||
server.enqueue(new MockResponse()
|
||||
.setBody(String.format("<XRDS><XRD><Service><URI>%s</URI></Service></XRD></XRDS>", endpoint)));
|
||||
MvcResult mvcResult = this.mvc.perform(
|
||||
get("/login/openid").param(OpenIDAuthenticationFilter.DEFAULT_CLAIMED_IDENTITY_FIELD, endpoint))
|
||||
.andExpect(status().isFound()).andReturn();
|
||||
// @formatter:off
|
||||
MockHttpServletRequestBuilder request = get("/login/openid")
|
||||
.param(OpenIDAuthenticationFilter.DEFAULT_CLAIMED_IDENTITY_FIELD, endpoint);
|
||||
MvcResult mvcResult = this.mvc.perform(request)
|
||||
.andExpect(status().isFound())
|
||||
.andReturn();
|
||||
Object attributeObject = mvcResult.getRequest().getSession()
|
||||
.getAttribute("SPRING_SECURITY_OPEN_ID_ATTRIBUTES_FETCH_LIST");
|
||||
// @formatter:on
|
||||
assertThat(attributeObject).isInstanceOf(List.class);
|
||||
List<OpenIDAttribute> attributeList = (List<OpenIDAttribute>) attributeObject;
|
||||
assertThat(attributeList).hasSize(1);
|
||||
|
|
|
@ -82,6 +82,7 @@ import org.springframework.security.web.context.SecurityContextRepository;
|
|||
import org.springframework.test.util.ReflectionTestUtils;
|
||||
import org.springframework.test.web.servlet.MockMvc;
|
||||
import org.springframework.test.web.servlet.MvcResult;
|
||||
import org.springframework.test.web.servlet.request.MockHttpServletRequestBuilder;
|
||||
import org.springframework.web.util.UriComponents;
|
||||
import org.springframework.web.util.UriComponentsBuilder;
|
||||
|
||||
|
@ -198,8 +199,11 @@ public class Saml2LoginConfigurerTests {
|
|||
String response = new String(samlDecode(SIGNED_RESPONSE));
|
||||
given(CustomAuthenticationConverter.authenticationConverter.convert(any(HttpServletRequest.class)))
|
||||
.willReturn(new Saml2AuthenticationToken(relyingPartyRegistration, response));
|
||||
this.mvc.perform(post("/login/saml2/sso/" + relyingPartyRegistration.getRegistrationId()).param("SAMLResponse",
|
||||
SIGNED_RESPONSE)).andExpect(redirectedUrl("/"));
|
||||
// @formatter:off
|
||||
MockHttpServletRequestBuilder request = post("/login/saml2/sso/" + relyingPartyRegistration.getRegistrationId())
|
||||
.param("SAMLResponse", SIGNED_RESPONSE);
|
||||
// @formatter:on
|
||||
this.mvc.perform(request).andExpect(redirectedUrl("/"));
|
||||
verify(CustomAuthenticationConverter.authenticationConverter).convert(any(HttpServletRequest.class));
|
||||
}
|
||||
|
||||
|
|
|
@ -35,6 +35,7 @@ public final class TestSaml2Credentials {
|
|||
}
|
||||
|
||||
static Saml2X509Credential verificationCertificate() {
|
||||
// @formatter:off
|
||||
String certificate = "-----BEGIN CERTIFICATE-----\n"
|
||||
+ "MIIEEzCCAvugAwIBAgIJAIc1qzLrv+5nMA0GCSqGSIb3DQEBCwUAMIGfMQswCQYD\n"
|
||||
+ "VQQGEwJVUzELMAkGA1UECAwCQ08xFDASBgNVBAcMC0Nhc3RsZSBSb2NrMRwwGgYD\n"
|
||||
|
@ -57,7 +58,9 @@ public final class TestSaml2Credentials {
|
|||
+ "ZnrV+oc2zGD+no1/ySFOe3EiJCO5dehxKjYEmBRv5sU/LZFKZpozKN/BMEa6CqLu\n"
|
||||
+ "xbzb7ykxVr7EVFXwltPxzE9TmL9OACNNyF5eJHWMRMllarUvkcXlh4pux4ks9e6z\n"
|
||||
+ "V9DQBy2zds9f1I3qxg0eX6JnGrXi/ZiCT+lJgVe3ZFXiejiLAiKB04sXW3ti0LW3\n"
|
||||
+ "lx13Y1YlQ4/tlpgTgfIJxKV6nyPiLoK0nywbMd+vpAirDt2Oc+hk\n" + "-----END CERTIFICATE-----";
|
||||
+ "lx13Y1YlQ4/tlpgTgfIJxKV6nyPiLoK0nywbMd+vpAirDt2Oc+hk\n"
|
||||
+ "-----END CERTIFICATE-----";
|
||||
// @formatter:on
|
||||
return new Saml2X509Credential(x509Certificate(certificate), Saml2X509CredentialType.VERIFICATION);
|
||||
}
|
||||
|
||||
|
@ -73,6 +76,7 @@ public final class TestSaml2Credentials {
|
|||
}
|
||||
|
||||
static Saml2X509Credential signingCredential() {
|
||||
// @formatter:off
|
||||
String key = "-----BEGIN PRIVATE KEY-----\n"
|
||||
+ "MIICeAIBADANBgkqhkiG9w0BAQEFAASCAmIwggJeAgEAAoGBANG7v8QjQGU3MwQE\n"
|
||||
+ "VUBxvH6Uuiy/MhZT7TV0ZNjyAF2ExA1gpn3aUxx6jYK5UnrpxRRE/KbeLucYbOhK\n"
|
||||
|
@ -86,8 +90,11 @@ public final class TestSaml2Credentials {
|
|||
+ "EGvYtQJBAMm/i9NR7IVyyNIgZUpz5q4LI21rl1r4gUQuD8vA36zM81i4ROeuCly0\n"
|
||||
+ "KkfdxR4PUfnKcQCX11YnHjk9uTFj75ECQEFY/gBnxDjzqyF35hAzrYIiMPQVfznt\n"
|
||||
+ "YX/sDTE2AdVBVGaMj1Cb51bPHnNC6Q5kXKQnj/YrLqRQND09Q7ParX0CQQC5NxZr\n"
|
||||
+ "9jKqhHj8yQD6PlXTsY4Occ7DH6/IoDenfdEVD5qlet0zmd50HatN2Jiqm5ubN7CM\n" + "INrtuLp4YHbgk1mi\n"
|
||||
+ "9jKqhHj8yQD6PlXTsY4Occ7DH6/IoDenfdEVD5qlet0zmd50HatN2Jiqm5ubN7CM\n"
|
||||
+ "INrtuLp4YHbgk1mi\n"
|
||||
+ "-----END PRIVATE KEY-----";
|
||||
// @formatter:on
|
||||
// @formatter:off
|
||||
String certificate = "-----BEGIN CERTIFICATE-----\n"
|
||||
+ "MIICgTCCAeoCCQCuVzyqFgMSyDANBgkqhkiG9w0BAQsFADCBhDELMAkGA1UEBhMC\n"
|
||||
+ "VVMxEzARBgNVBAgMCldhc2hpbmd0b24xEjAQBgNVBAcMCVZhbmNvdXZlcjEdMBsG\n"
|
||||
|
@ -102,7 +109,9 @@ public final class TestSaml2Credentials {
|
|||
+ "y3Q6x+I4qakY/9qhBQIDAQABMA0GCSqGSIb3DQEBCwUAA4GBAAeViTvHOyQopWEi\n"
|
||||
+ "XOfI2Z9eukwrSknDwq/zscR0YxwwqDBMt/QdAODfSwAfnciiYLkmEjlozWRtOeN+\n"
|
||||
+ "qK7UFgP1bRl5qksrYX5S0z2iGJh0GvonLUt3e20Ssfl5tTEDDnAEUMLfBkyaxEHD\n"
|
||||
+ "RZ/nbTJ7VTeZOSyRoVn5XHhpuJ0B\n" + "-----END CERTIFICATE-----";
|
||||
+ "RZ/nbTJ7VTeZOSyRoVn5XHhpuJ0B\n"
|
||||
+ "-----END CERTIFICATE-----";
|
||||
// @formatter:on
|
||||
PrivateKey pk = RsaKeyConverters.pkcs8().convert(new ByteArrayInputStream(key.getBytes()));
|
||||
X509Certificate cert = x509Certificate(certificate);
|
||||
return new Saml2X509Credential(pk, cert, Saml2X509CredentialType.SIGNING, Saml2X509CredentialType.DECRYPTION);
|
||||
|
|
|
@ -49,9 +49,12 @@ public class MessageSecurityMetadataSourceRegistryTests {
|
|||
@Before
|
||||
public void setup() {
|
||||
this.messages = new MessageSecurityMetadataSourceRegistry();
|
||||
// @formatter:off
|
||||
this.message = MessageBuilder.withPayload("Hi")
|
||||
.setHeader(SimpMessageHeaderAccessor.DESTINATION_HEADER, "location")
|
||||
.setHeader(SimpMessageHeaderAccessor.MESSAGE_TYPE_HEADER, SimpMessageType.MESSAGE).build();
|
||||
.setHeader(SimpMessageHeaderAccessor.MESSAGE_TYPE_HEADER, SimpMessageType.MESSAGE)
|
||||
.build();
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
// See
|
||||
|
@ -59,24 +62,36 @@ public class MessageSecurityMetadataSourceRegistryTests {
|
|||
// https://jira.spring.io/browse/SPR-11660
|
||||
@Test
|
||||
public void simpDestMatchersCustom() {
|
||||
// @formatter:off
|
||||
this.message = MessageBuilder.withPayload("Hi")
|
||||
.setHeader(SimpMessageHeaderAccessor.DESTINATION_HEADER, "price.stock.1.2").build();
|
||||
.setHeader(SimpMessageHeaderAccessor.DESTINATION_HEADER, "price.stock.1.2")
|
||||
.build();
|
||||
// @formatter:on
|
||||
this.messages.simpDestPathMatcher(new AntPathMatcher(".")).simpDestMatchers("price.stock.*").permitAll();
|
||||
assertThat(getAttribute()).isNull();
|
||||
// @formatter:off
|
||||
this.message = MessageBuilder.withPayload("Hi")
|
||||
.setHeader(SimpMessageHeaderAccessor.DESTINATION_HEADER, "price.stock.1.2").build();
|
||||
.setHeader(SimpMessageHeaderAccessor.DESTINATION_HEADER, "price.stock.1.2")
|
||||
.build();
|
||||
// @formatter:on
|
||||
this.messages.simpDestPathMatcher(new AntPathMatcher(".")).simpDestMatchers("price.stock.**").permitAll();
|
||||
assertThat(getAttribute()).isEqualTo("permitAll");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void simpDestMatchersCustomSetAfterMatchersDoesNotMatter() {
|
||||
// @formatter:off
|
||||
this.message = MessageBuilder.withPayload("Hi")
|
||||
.setHeader(SimpMessageHeaderAccessor.DESTINATION_HEADER, "price.stock.1.2").build();
|
||||
.setHeader(SimpMessageHeaderAccessor.DESTINATION_HEADER, "price.stock.1.2")
|
||||
.build();
|
||||
// @formatter:on
|
||||
this.messages.simpDestMatchers("price.stock.*").permitAll().simpDestPathMatcher(new AntPathMatcher("."));
|
||||
assertThat(getAttribute()).isNull();
|
||||
// @formatter:off
|
||||
this.message = MessageBuilder.withPayload("Hi")
|
||||
.setHeader(SimpMessageHeaderAccessor.DESTINATION_HEADER, "price.stock.1.2").build();
|
||||
.setHeader(SimpMessageHeaderAccessor.DESTINATION_HEADER, "price.stock.1.2")
|
||||
.build();
|
||||
// @formatter:on
|
||||
this.messages.simpDestMatchers("price.stock.**").permitAll().simpDestPathMatcher(new AntPathMatcher("."));
|
||||
assertThat(getAttribute()).isEqualTo("permitAll");
|
||||
}
|
||||
|
@ -107,26 +122,41 @@ public class MessageSecurityMetadataSourceRegistryTests {
|
|||
|
||||
@Test
|
||||
public void simpDestMatchersMulti() {
|
||||
this.messages.simpDestMatchers("admin/**", "api/**").hasRole("ADMIN").simpDestMatchers("location").permitAll();
|
||||
// @formatter:off
|
||||
this.messages
|
||||
.simpDestMatchers("admin/**", "api/**").hasRole("ADMIN")
|
||||
.simpDestMatchers("location").permitAll();
|
||||
// @formatter:on
|
||||
assertThat(getAttribute()).isEqualTo("permitAll");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void simpDestMatchersRole() {
|
||||
this.messages.simpDestMatchers("admin/**", "location/**").hasRole("ADMIN").anyMessage().denyAll();
|
||||
// @formatter:off
|
||||
this.messages
|
||||
.simpDestMatchers("admin/**", "location/**").hasRole("ADMIN")
|
||||
.anyMessage().denyAll();
|
||||
// @formatter:on
|
||||
assertThat(getAttribute()).isEqualTo("hasRole('ROLE_ADMIN')");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void simpDestMatchersAnyRole() {
|
||||
this.messages.simpDestMatchers("admin/**", "location/**").hasAnyRole("ADMIN", "ROOT").anyMessage().denyAll();
|
||||
// @formatter:off
|
||||
this.messages
|
||||
.simpDestMatchers("admin/**", "location/**").hasAnyRole("ADMIN", "ROOT")
|
||||
.anyMessage().denyAll();
|
||||
// @formatter:on
|
||||
assertThat(getAttribute()).isEqualTo("hasAnyRole('ROLE_ADMIN','ROLE_ROOT')");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void simpDestMatchersAuthority() {
|
||||
this.messages.simpDestMatchers("admin/**", "location/**").hasAuthority("ROLE_ADMIN").anyMessage()
|
||||
.fullyAuthenticated();
|
||||
// @formatter:off
|
||||
this.messages
|
||||
.simpDestMatchers("admin/**", "location/**").hasAuthority("ROLE_ADMIN")
|
||||
.anyMessage().fullyAuthenticated();
|
||||
// @formatter:on
|
||||
assertThat(getAttribute()).isEqualTo("hasAuthority('ROLE_ADMIN')");
|
||||
}
|
||||
|
||||
|
@ -139,98 +169,157 @@ public class MessageSecurityMetadataSourceRegistryTests {
|
|||
|
||||
@Test
|
||||
public void simpDestMatchersAnyAuthority() {
|
||||
this.messages.simpDestMatchers("admin/**", "location/**").hasAnyAuthority("ROLE_ADMIN", "ROLE_ROOT")
|
||||
// @formatter:off
|
||||
this.messages
|
||||
.simpDestMatchers("admin/**", "location/**").hasAnyAuthority("ROLE_ADMIN", "ROLE_ROOT")
|
||||
.anyMessage().denyAll();
|
||||
// @formatter:on
|
||||
assertThat(getAttribute()).isEqualTo("hasAnyAuthority('ROLE_ADMIN','ROLE_ROOT')");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void simpDestMatchersRememberMe() {
|
||||
this.messages.simpDestMatchers("admin/**", "location/**").rememberMe().anyMessage().denyAll();
|
||||
// @formatter:off
|
||||
this.messages
|
||||
.simpDestMatchers("admin/**", "location/**").rememberMe()
|
||||
.anyMessage().denyAll();
|
||||
// @formatter:on
|
||||
assertThat(getAttribute()).isEqualTo("rememberMe");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void simpDestMatchersAnonymous() {
|
||||
this.messages.simpDestMatchers("admin/**", "location/**").anonymous().anyMessage().denyAll();
|
||||
// @formatter:off
|
||||
this.messages
|
||||
.simpDestMatchers("admin/**", "location/**").anonymous()
|
||||
.anyMessage().denyAll();
|
||||
// @formatter:on
|
||||
assertThat(getAttribute()).isEqualTo("anonymous");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void simpDestMatchersFullyAuthenticated() {
|
||||
this.messages.simpDestMatchers("admin/**", "location/**").fullyAuthenticated().anyMessage().denyAll();
|
||||
// @formatter:off
|
||||
this.messages
|
||||
.simpDestMatchers("admin/**", "location/**").fullyAuthenticated()
|
||||
.anyMessage().denyAll();
|
||||
// @formatter:on
|
||||
assertThat(getAttribute()).isEqualTo("fullyAuthenticated");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void simpDestMatchersDenyAll() {
|
||||
this.messages.simpDestMatchers("admin/**", "location/**").denyAll().anyMessage().permitAll();
|
||||
// @formatter:off
|
||||
this.messages
|
||||
.simpDestMatchers("admin/**", "location/**").denyAll()
|
||||
.anyMessage().permitAll();
|
||||
// @formatter:on
|
||||
assertThat(getAttribute()).isEqualTo("denyAll");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void simpDestMessageMatchersNotMatch() {
|
||||
this.messages.simpMessageDestMatchers("admin/**").denyAll().anyMessage().permitAll();
|
||||
// @formatter:off
|
||||
this.messages.
|
||||
simpMessageDestMatchers("admin/**").denyAll()
|
||||
.anyMessage().permitAll();
|
||||
// @formatter:on
|
||||
assertThat(getAttribute()).isEqualTo("permitAll");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void simpDestMessageMatchersMatch() {
|
||||
this.messages.simpMessageDestMatchers("location/**").denyAll().anyMessage().permitAll();
|
||||
// @formatter:off
|
||||
this.messages
|
||||
.simpMessageDestMatchers("location/**").denyAll()
|
||||
.anyMessage().permitAll();
|
||||
// @formatter:on
|
||||
assertThat(getAttribute()).isEqualTo("denyAll");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void simpDestSubscribeMatchersNotMatch() {
|
||||
this.messages.simpSubscribeDestMatchers("location/**").denyAll().anyMessage().permitAll();
|
||||
// @formatter:off
|
||||
this.messages
|
||||
.simpSubscribeDestMatchers("location/**").denyAll()
|
||||
.anyMessage().permitAll();
|
||||
// @formatter:on
|
||||
assertThat(getAttribute()).isEqualTo("permitAll");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void simpDestSubscribeMatchersMatch() {
|
||||
// @formatter:off
|
||||
this.message = MessageBuilder.fromMessage(this.message)
|
||||
.setHeader(SimpMessageHeaderAccessor.MESSAGE_TYPE_HEADER, SimpMessageType.SUBSCRIBE).build();
|
||||
this.messages.simpSubscribeDestMatchers("location/**").denyAll().anyMessage().permitAll();
|
||||
.setHeader(SimpMessageHeaderAccessor.MESSAGE_TYPE_HEADER, SimpMessageType.SUBSCRIBE)
|
||||
.build();
|
||||
this.messages
|
||||
.simpSubscribeDestMatchers("location/**").denyAll()
|
||||
.anyMessage().permitAll();
|
||||
// @formatter:on
|
||||
assertThat(getAttribute()).isEqualTo("denyAll");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void nullDestMatcherNotMatches() {
|
||||
this.messages.nullDestMatcher().denyAll().anyMessage().permitAll();
|
||||
// @formatter:off
|
||||
this.messages
|
||||
.nullDestMatcher().denyAll()
|
||||
.anyMessage().permitAll();
|
||||
// @formatter:on
|
||||
assertThat(getAttribute()).isEqualTo("permitAll");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void nullDestMatcherMatch() {
|
||||
// @formatter:off
|
||||
this.message = MessageBuilder.withPayload("Hi")
|
||||
.setHeader(SimpMessageHeaderAccessor.MESSAGE_TYPE_HEADER, SimpMessageType.CONNECT).build();
|
||||
this.messages.nullDestMatcher().denyAll().anyMessage().permitAll();
|
||||
.setHeader(SimpMessageHeaderAccessor.MESSAGE_TYPE_HEADER, SimpMessageType.CONNECT)
|
||||
.build();
|
||||
this.messages
|
||||
.nullDestMatcher().denyAll()
|
||||
.anyMessage().permitAll();
|
||||
// @formatter:on
|
||||
assertThat(getAttribute()).isEqualTo("denyAll");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void simpTypeMatchersMatch() {
|
||||
this.messages.simpTypeMatchers(SimpMessageType.MESSAGE).denyAll().anyMessage().permitAll();
|
||||
// @formatter:off
|
||||
this.messages
|
||||
.simpTypeMatchers(SimpMessageType.MESSAGE).denyAll()
|
||||
.anyMessage().permitAll();
|
||||
// @formatter:on
|
||||
assertThat(getAttribute()).isEqualTo("denyAll");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void simpTypeMatchersMatchMulti() {
|
||||
this.messages.simpTypeMatchers(SimpMessageType.CONNECT, SimpMessageType.MESSAGE).denyAll().anyMessage()
|
||||
.permitAll();
|
||||
// @formatter:off
|
||||
this.messages
|
||||
.simpTypeMatchers(SimpMessageType.CONNECT, SimpMessageType.MESSAGE).denyAll()
|
||||
.anyMessage().permitAll();
|
||||
// @formatter:on
|
||||
assertThat(getAttribute()).isEqualTo("denyAll");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void simpTypeMatchersNotMatch() {
|
||||
this.messages.simpTypeMatchers(SimpMessageType.CONNECT).denyAll().anyMessage().permitAll();
|
||||
// @formatter:off
|
||||
this.messages
|
||||
.simpTypeMatchers(SimpMessageType.CONNECT).denyAll()
|
||||
.anyMessage().permitAll();
|
||||
// @formatter:on
|
||||
assertThat(getAttribute()).isEqualTo("permitAll");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void simpTypeMatchersNotMatchMulti() {
|
||||
this.messages.simpTypeMatchers(SimpMessageType.CONNECT, SimpMessageType.DISCONNECT).denyAll().anyMessage()
|
||||
.permitAll();
|
||||
// @formatter:off
|
||||
this.messages
|
||||
.simpTypeMatchers(SimpMessageType.CONNECT, SimpMessageType.DISCONNECT).denyAll()
|
||||
.anyMessage().permitAll();
|
||||
// @formatter:on
|
||||
assertThat(getAttribute()).isEqualTo("permitAll");
|
||||
}
|
||||
|
||||
|
|
|
@ -22,6 +22,7 @@ import java.security.Principal;
|
|||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.springframework.web.server.WebFilter;
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
|
@ -72,6 +73,7 @@ import org.springframework.web.reactive.function.BodyInserters;
|
|||
import org.springframework.web.reactive.result.view.AbstractView;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.springframework.security.test.web.reactive.server.SecurityMockServerConfigurers.csrf;
|
||||
|
||||
/**
|
||||
* @author Rob Winch
|
||||
|
@ -90,24 +92,48 @@ public class EnableWebFluxSecurityTests {
|
|||
@Test
|
||||
public void defaultRequiresAuthentication() {
|
||||
this.spring.register(Config.class).autowire();
|
||||
WebTestClient client = WebTestClientBuilder.bindToWebFilters(this.springSecurityFilterChain).build();
|
||||
client.get().uri("/").exchange().expectStatus().isUnauthorized().expectBody().isEmpty();
|
||||
// @formatter:off
|
||||
WebTestClient client = WebTestClientBuilder
|
||||
.bindToWebFilters(this.springSecurityFilterChain)
|
||||
.build();
|
||||
client.get()
|
||||
.uri("/")
|
||||
.exchange()
|
||||
.expectStatus().isUnauthorized()
|
||||
.expectBody().isEmpty();
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
// gh-4831
|
||||
@Test
|
||||
public void defaultMediaAllThenUnAuthorized() {
|
||||
this.spring.register(Config.class).autowire();
|
||||
WebTestClient client = WebTestClientBuilder.bindToWebFilters(this.springSecurityFilterChain).build();
|
||||
client.get().uri("/").accept(MediaType.ALL).exchange().expectStatus().isUnauthorized().expectBody().isEmpty();
|
||||
// @formatter:off
|
||||
WebTestClient client = WebTestClientBuilder
|
||||
.bindToWebFilters(this.springSecurityFilterChain)
|
||||
.build();
|
||||
client.get()
|
||||
.uri("/")
|
||||
.accept(MediaType.ALL)
|
||||
.exchange()
|
||||
.expectStatus().isUnauthorized()
|
||||
.expectBody().isEmpty();
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
public void authenticateWhenBasicThenNoSession() {
|
||||
this.spring.register(Config.class).autowire();
|
||||
WebTestClient client = WebTestClientBuilder.bindToWebFilters(this.springSecurityFilterChain).build();
|
||||
FluxExchangeResult<String> result = client.get().headers((headers) -> headers.setBasicAuth("user", "password"))
|
||||
.exchange().expectStatus().isOk().returnResult(String.class);
|
||||
// @formatter:off
|
||||
WebTestClient client = WebTestClientBuilder
|
||||
.bindToWebFilters(this.springSecurityFilterChain)
|
||||
.build();
|
||||
FluxExchangeResult<String> result = client.get()
|
||||
.headers((headers) -> headers.setBasicAuth("user", "password"))
|
||||
.exchange()
|
||||
.expectStatus().isOk()
|
||||
.returnResult(String.class);
|
||||
// @formatter:on
|
||||
result.assertWithDiagnostics(() -> assertThat(result.getResponseCookies().isEmpty()));
|
||||
}
|
||||
|
||||
|
@ -117,33 +143,45 @@ public class EnableWebFluxSecurityTests {
|
|||
Authentication currentPrincipal = new TestingAuthenticationToken("user", "password", "ROLE_USER");
|
||||
WebSessionServerSecurityContextRepository contextRepository = new WebSessionServerSecurityContextRepository();
|
||||
SecurityContext context = new SecurityContextImpl(currentPrincipal);
|
||||
// @formatter:off
|
||||
WebFilter contextRepositoryWebFilter = (exchange, chain) -> contextRepository.save(exchange, context)
|
||||
.switchIfEmpty(chain.filter(exchange))
|
||||
.flatMap((e) -> chain.filter(exchange));
|
||||
WebTestClient client = WebTestClientBuilder
|
||||
.bindToWebFilters(
|
||||
(exchange, chain) -> contextRepository.save(exchange, context)
|
||||
.switchIfEmpty(chain.filter(exchange)).flatMap((e) -> chain.filter(exchange)),
|
||||
this.springSecurityFilterChain,
|
||||
(exchange,
|
||||
chain) -> ReactiveSecurityContextHolder.getContext()
|
||||
.map(SecurityContext::getAuthentication).flatMap((principal) -> exchange
|
||||
.getResponse().writeWith(Mono.just(toDataBuffer(principal.getName())))))
|
||||
.bindToWebFilters(contextRepositoryWebFilter, this.springSecurityFilterChain, writePrincipalWebFilter())
|
||||
.build();
|
||||
client.get().uri("/").exchange().expectStatus().isOk().expectBody(String.class)
|
||||
.consumeWith((result) -> assertThat(result.getResponseBody()).isEqualTo(currentPrincipal.getName()));
|
||||
client.get()
|
||||
.uri("/")
|
||||
.exchange()
|
||||
.expectStatus().isOk()
|
||||
.expectBody(String.class).consumeWith((result) -> assertThat(result.getResponseBody()).isEqualTo(currentPrincipal.getName()));
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
private WebFilter writePrincipalWebFilter() {
|
||||
// @formatter:off
|
||||
return (exchange, chain) -> ReactiveSecurityContextHolder.getContext()
|
||||
.map(SecurityContext::getAuthentication)
|
||||
.flatMap((principal) -> exchange.getResponse()
|
||||
.writeWith(Mono.just(toDataBuffer(principal.getName())))
|
||||
);
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
public void defaultPopulatesReactorContextWhenAuthenticating() {
|
||||
this.spring.register(Config.class).autowire();
|
||||
// @formatter:off
|
||||
WebTestClient client = WebTestClientBuilder
|
||||
.bindToWebFilters(this.springSecurityFilterChain,
|
||||
(exchange,
|
||||
chain) -> ReactiveSecurityContextHolder.getContext()
|
||||
.map(SecurityContext::getAuthentication).flatMap((principal) -> exchange
|
||||
.getResponse().writeWith(Mono.just(toDataBuffer(principal.getName())))))
|
||||
.bindToWebFilters(this.springSecurityFilterChain, writePrincipalWebFilter())
|
||||
.build();
|
||||
client.get().uri("/").headers((headers) -> headers.setBasicAuth("user", "password")).exchange().expectStatus()
|
||||
.isOk().expectBody(String.class)
|
||||
.consumeWith((result) -> assertThat(result.getResponseBody()).isEqualTo("user"));
|
||||
client.get()
|
||||
.uri("/")
|
||||
.headers((headers) -> headers.setBasicAuth("user", "password"))
|
||||
.exchange()
|
||||
.expectStatus().isOk()
|
||||
.expectBody(String.class).consumeWith((result) -> assertThat(result.getResponseBody()).isEqualTo("user"));
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -158,23 +196,30 @@ public class EnableWebFluxSecurityTests {
|
|||
@Test
|
||||
public void passwordEncoderBeanIsUsed() {
|
||||
this.spring.register(CustomPasswordEncoderConfig.class).autowire();
|
||||
// @formatter:off
|
||||
WebTestClient client = WebTestClientBuilder
|
||||
.bindToWebFilters(this.springSecurityFilterChain,
|
||||
(exchange,
|
||||
chain) -> ReactiveSecurityContextHolder.getContext()
|
||||
.map(SecurityContext::getAuthentication).flatMap((principal) -> exchange
|
||||
.getResponse().writeWith(Mono.just(toDataBuffer(principal.getName())))))
|
||||
.bindToWebFilters(this.springSecurityFilterChain, writePrincipalWebFilter())
|
||||
.build();
|
||||
client.get().uri("/").headers((headers) -> headers.setBasicAuth("user", "password")).exchange().expectStatus()
|
||||
.isOk().expectBody(String.class)
|
||||
client.get().uri("/").headers((headers) -> headers.setBasicAuth("user", "password"))
|
||||
.exchange().expectStatus().isOk()
|
||||
.expectBody(String.class)
|
||||
.consumeWith((result) -> assertThat(result.getResponseBody()).isEqualTo("user"));
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
public void passwordUpdateManagerUsed() {
|
||||
this.spring.register(MapReactiveUserDetailsServiceConfig.class).autowire();
|
||||
WebTestClient client = WebTestClientBuilder.bindToWebFilters(this.springSecurityFilterChain).build();
|
||||
client.get().uri("/").headers((h) -> h.setBasicAuth("user", "password")).exchange().expectStatus().isOk();
|
||||
// @formatter:off
|
||||
WebTestClient client = WebTestClientBuilder
|
||||
.bindToWebFilters(this.springSecurityFilterChain)
|
||||
.build();
|
||||
client.get()
|
||||
.uri("/")
|
||||
.headers((h) -> h.setBasicAuth("user", "password"))
|
||||
.exchange()
|
||||
.expectStatus().isOk();
|
||||
// @formatter:on
|
||||
ReactiveUserDetailsService users = this.spring.getContext().getBean(ReactiveUserDetailsService.class);
|
||||
assertThat(users.findByUsername("user").block().getPassword()).startsWith("{bcrypt}");
|
||||
}
|
||||
|
@ -182,32 +227,58 @@ public class EnableWebFluxSecurityTests {
|
|||
@Test
|
||||
public void formLoginWorks() {
|
||||
this.spring.register(Config.class).autowire();
|
||||
WebTestClient client = WebTestClientBuilder.bindToWebFilters(this.springSecurityFilterChain, (exchange,
|
||||
chain) -> Mono.subscriberContext().flatMap((c) -> c.<Mono<Principal>>get(Authentication.class)).flatMap(
|
||||
(principal) -> exchange.getResponse().writeWith(Mono.just(toDataBuffer(principal.getName())))))
|
||||
// @formatter:off
|
||||
WebTestClient client = WebTestClientBuilder
|
||||
.bindToWebFilters(this.springSecurityFilterChain, writePrincipalWebFilter())
|
||||
.build();
|
||||
// @formatter:on
|
||||
MultiValueMap<String, String> data = new LinkedMultiValueMap<>();
|
||||
data.add("username", "user");
|
||||
data.add("password", "password");
|
||||
client.mutateWith(SecurityMockServerConfigurers.csrf()).post().uri("/login")
|
||||
.body(BodyInserters.fromFormData(data)).exchange().expectStatus().is3xxRedirection().expectHeader()
|
||||
.valueMatches("Location", "/");
|
||||
// @formatter:off
|
||||
client.mutateWith(csrf())
|
||||
.post()
|
||||
.uri("/login")
|
||||
.body(BodyInserters.fromFormData(data))
|
||||
.exchange()
|
||||
.expectStatus().is3xxRedirection()
|
||||
.expectHeader().valueMatches("Location", "/");
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
public void multiWorks() {
|
||||
this.spring.register(MultiSecurityHttpConfig.class).autowire();
|
||||
WebTestClient client = WebTestClientBuilder.bindToWebFilters(this.springSecurityFilterChain).build();
|
||||
client.get().uri("/api/test").exchange().expectStatus().isUnauthorized().expectBody().isEmpty();
|
||||
client.get().uri("/test").exchange().expectStatus().isOk();
|
||||
// @formatter:off
|
||||
WebTestClient client = WebTestClientBuilder
|
||||
.bindToWebFilters(this.springSecurityFilterChain)
|
||||
.build();
|
||||
client.get()
|
||||
.uri("/api/test")
|
||||
.exchange()
|
||||
.expectStatus().isUnauthorized()
|
||||
.expectBody().isEmpty();
|
||||
client.get()
|
||||
.uri("/test")
|
||||
.exchange()
|
||||
.expectStatus().isOk();
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
@WithMockUser
|
||||
public void authenticationPrincipalArgumentResolverWhenSpelThenWorks() {
|
||||
this.spring.register(AuthenticationPrincipalConfig.class).autowire();
|
||||
WebTestClient client = WebTestClient.bindToApplicationContext(this.spring.getContext()).build();
|
||||
client.get().uri("/spel").exchange().expectStatus().isOk().expectBody(String.class).isEqualTo("user");
|
||||
// @formatter:off
|
||||
WebTestClient client = WebTestClient
|
||||
.bindToApplicationContext(this.spring.getContext())
|
||||
.build();
|
||||
client.get()
|
||||
.uri("/spel")
|
||||
.exchange()
|
||||
.expectStatus().isOk()
|
||||
.expectBody(String.class).isEqualTo("user");
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
private static DataBuffer toDataBuffer(String body) {
|
||||
|
|
|
@ -590,10 +590,12 @@ public class AbstractSecurityWebSocketMessageBrokerConfigurerTests {
|
|||
|
||||
@Override
|
||||
public void registerStompEndpoints(StompEndpointRegistry registry) {
|
||||
registry.addEndpoint("/other").setHandshakeHandler(testHandshakeHandler()).withSockJS()
|
||||
.setInterceptors(new HttpSessionHandshakeInterceptor());
|
||||
registry.addEndpoint("/chat").setHandshakeHandler(testHandshakeHandler()).withSockJS()
|
||||
.setInterceptors(new HttpSessionHandshakeInterceptor());
|
||||
// @formatter:off
|
||||
registry.addEndpoint("/other").setHandshakeHandler(testHandshakeHandler())
|
||||
.withSockJS().setInterceptors(new HttpSessionHandshakeInterceptor());
|
||||
registry.addEndpoint("/chat").setHandshakeHandler(testHandshakeHandler())
|
||||
.withSockJS().setInterceptors(new HttpSessionHandshakeInterceptor());
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
// @formatter:off
|
||||
|
@ -646,8 +648,12 @@ public class AbstractSecurityWebSocketMessageBrokerConfigurerTests {
|
|||
|
||||
@Override
|
||||
public void registerStompEndpoints(StompEndpointRegistry registry) {
|
||||
registry.addEndpoint("/other").withSockJS().setInterceptors(new HttpSessionHandshakeInterceptor());
|
||||
registry.addEndpoint("/chat").withSockJS().setInterceptors(new HttpSessionHandshakeInterceptor());
|
||||
// @formatter:off
|
||||
registry.addEndpoint("/other")
|
||||
.withSockJS().setInterceptors(new HttpSessionHandshakeInterceptor());
|
||||
registry.addEndpoint("/chat")
|
||||
.withSockJS().setInterceptors(new HttpSessionHandshakeInterceptor());
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -684,19 +690,23 @@ public class AbstractSecurityWebSocketMessageBrokerConfigurerTests {
|
|||
|
||||
@Override
|
||||
public void registerStompEndpoints(StompEndpointRegistry registry) {
|
||||
registry.addEndpoint("/websocket").setHandshakeHandler(testHandshakeHandler())
|
||||
// @formatter:off
|
||||
registry.addEndpoint("/websocket")
|
||||
.setHandshakeHandler(testHandshakeHandler())
|
||||
.addInterceptors(new HttpSessionHandshakeInterceptor());
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
// @formatter:off
|
||||
@Override
|
||||
protected void configureInbound(MessageSecurityMetadataSourceRegistry messages) {
|
||||
// @formatter:off
|
||||
messages
|
||||
.simpDestMatchers("/permitAll/**").permitAll()
|
||||
.simpDestMatchers("/customExpression/**").access("denyRob")
|
||||
.anyMessage().denyAll();
|
||||
// @formatter:on
|
||||
}
|
||||
// @formatter:on
|
||||
|
||||
@Bean
|
||||
public TestHandshakeHandler testHandshakeHandler() {
|
||||
return new TestHandshakeHandler();
|
||||
|
@ -713,8 +723,11 @@ public class AbstractSecurityWebSocketMessageBrokerConfigurerTests {
|
|||
|
||||
@Override
|
||||
public void registerStompEndpoints(StompEndpointRegistry registry) {
|
||||
registry.addEndpoint("/chat").setHandshakeHandler(this.context.getBean(TestHandshakeHandler.class))
|
||||
// @formatter:off
|
||||
registry.addEndpoint("/chat")
|
||||
.setHandshakeHandler(this.context.getBean(TestHandshakeHandler.class))
|
||||
.withSockJS().setInterceptors(new HttpSessionHandshakeInterceptor());
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Autowired
|
||||
|
|
|
@ -44,10 +44,15 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.
|
|||
*/
|
||||
public class AuthenticationManagerBeanDefinitionParserTests {
|
||||
|
||||
private static final String CONTEXT = "<authentication-manager id='am'>" + " <authentication-provider>"
|
||||
// @formatter:off
|
||||
private static final String CONTEXT = "<authentication-manager id='am'>"
|
||||
+ " <authentication-provider>"
|
||||
+ " <user-service>"
|
||||
+ " <user name='bob' password='{noop}bobspassword' authorities='ROLE_A,ROLE_B' />"
|
||||
+ " </user-service>" + " </authentication-provider>" + "</authentication-manager>";
|
||||
+ " </user-service>"
|
||||
+ " </authentication-provider>"
|
||||
+ "</authentication-manager>";
|
||||
// @formatter:on
|
||||
|
||||
@Rule
|
||||
public final SpringTestRule spring = new SpringTestRule();
|
||||
|
@ -92,12 +97,17 @@ public class AuthenticationManagerBeanDefinitionParserTests {
|
|||
|
||||
@Test
|
||||
public void passwordEncoderBeanUsed() throws Exception {
|
||||
this.spring.context(
|
||||
"<b:bean id='passwordEncoder' class='org.springframework.security.crypto.password.NoOpPasswordEncoder' factory-method='getInstance'/>"
|
||||
+ "<user-service>" + " <user name='user' password='password' authorities='ROLE_A,ROLE_B' />"
|
||||
+ "</user-service>" + "<http/>")
|
||||
.mockMvcAfterSpringSecurityOk().autowire();
|
||||
this.mockMvc.perform(get("/").with(httpBasic("user", "password"))).andExpect(status().isOk());
|
||||
// @formatter:off
|
||||
this.spring.context("<b:bean id='passwordEncoder' class='org.springframework.security.crypto.password.NoOpPasswordEncoder' factory-method='getInstance'/>"
|
||||
+ "<user-service>"
|
||||
+ " <user name='user' password='password' authorities='ROLE_A,ROLE_B' />"
|
||||
+ "</user-service>"
|
||||
+ "<http/>")
|
||||
.mockMvcAfterSpringSecurityOk()
|
||||
.autowire();
|
||||
this.mockMvc.perform(get("/").with(httpBasic("user", "password")))
|
||||
.andExpect(status().isOk());
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
private static class AuthListener implements ApplicationListener<AbstractAuthenticationEvent> {
|
||||
|
|
|
@ -51,73 +51,107 @@ public class AuthenticationProviderBeanDefinitionParserTests {
|
|||
|
||||
@Test
|
||||
public void worksWithEmbeddedUserService() {
|
||||
setContext(" <authentication-provider>" + " <user-service>"
|
||||
// @formatter:off
|
||||
setContext(" <authentication-provider>"
|
||||
+ " <user-service>"
|
||||
+ " <user name='bob' password='{noop}bobspassword' authorities='ROLE_A' />"
|
||||
+ " </user-service>" + " </authentication-provider>");
|
||||
+ " </user-service>"
|
||||
+ " </authentication-provider>");
|
||||
// @formatter:on
|
||||
getProvider().authenticate(this.bob);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void externalUserServiceRefWorks() {
|
||||
// @formatter:off
|
||||
this.appContext = new InMemoryXmlApplicationContext(
|
||||
" <authentication-manager>" + " <authentication-provider user-service-ref='myUserService' />"
|
||||
+ " </authentication-manager>" + " <user-service id='myUserService'>"
|
||||
+ " <user name='bob' password='{noop}bobspassword' authorities='ROLE_A' />"
|
||||
+ " </user-service>");
|
||||
" <authentication-manager>"
|
||||
+ " <authentication-provider user-service-ref='myUserService' />"
|
||||
+ " </authentication-manager>" + " <user-service id='myUserService'>"
|
||||
+ " <user name='bob' password='{noop}bobspassword' authorities='ROLE_A' />"
|
||||
+ " </user-service>");
|
||||
// @formatter:on
|
||||
getProvider().authenticate(this.bob);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void providerWithBCryptPasswordEncoderWorks() {
|
||||
setContext(" <authentication-provider>" + " <password-encoder hash='bcrypt'/>" + " <user-service>"
|
||||
// @formatter:off
|
||||
setContext(" <authentication-provider>"
|
||||
+ " <password-encoder hash='bcrypt'/>"
|
||||
+ " <user-service>"
|
||||
+ " <user name='bob' password='$2a$05$dRmjl1T05J7rvCPD2NgsHesCEJHww3pdmesUhjM3PD4m/gaEYyx/G' authorities='ROLE_A' />"
|
||||
+ " </user-service>" + " </authentication-provider>");
|
||||
+ " </user-service>"
|
||||
// @formatter:on
|
||||
+ " </authentication-provider>");
|
||||
getProvider().authenticate(this.bob);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void providerWithMd5PasswordEncoderWorks() {
|
||||
this.appContext = new InMemoryXmlApplicationContext(" <authentication-manager>" + " <authentication-provider>"
|
||||
+ " <password-encoder ref='passwordEncoder'/>" + " <user-service>"
|
||||
// @formatter:off
|
||||
this.appContext = new InMemoryXmlApplicationContext(" <authentication-manager>"
|
||||
+ " <authentication-provider>"
|
||||
+ " <password-encoder ref='passwordEncoder'/>"
|
||||
+ " <user-service>"
|
||||
+ " <user name='bob' password='12b141f35d58b8b3a46eea65e6ac179e' authorities='ROLE_A' />"
|
||||
+ " </user-service>" + " </authentication-provider>" + " </authentication-manager>"
|
||||
+ " </user-service>"
|
||||
+ " </authentication-provider>"
|
||||
+ " </authentication-manager>"
|
||||
+ " <b:bean id='passwordEncoder' class='" + MessageDigestPasswordEncoder.class.getName() + "'>"
|
||||
+ " <b:constructor-arg value='MD5'/>" + " </b:bean>");
|
||||
+ " <b:constructor-arg value='MD5'/>"
|
||||
+ " </b:bean>");
|
||||
// @formatter:on
|
||||
getProvider().authenticate(this.bob);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void providerWithShaPasswordEncoderWorks() {
|
||||
this.appContext = new InMemoryXmlApplicationContext(" <authentication-manager>" + " <authentication-provider>"
|
||||
+ " <password-encoder ref='passwordEncoder'/>" + " <user-service>"
|
||||
// @formatter:off
|
||||
this.appContext = new InMemoryXmlApplicationContext(" <authentication-manager>"
|
||||
+ " <authentication-provider>"
|
||||
+ " <password-encoder ref='passwordEncoder'/>"
|
||||
+ " <user-service>"
|
||||
+ " <user name='bob' password='{SSHA}PpuEwfdj7M1rs0C2W4ssSM2XEN/Y6S5U' authorities='ROLE_A' />"
|
||||
+ " </user-service>" + " </authentication-provider>" + " </authentication-manager>"
|
||||
+ " </user-service>"
|
||||
+ " </authentication-provider>"
|
||||
+ " </authentication-manager>"
|
||||
+ " <b:bean id='passwordEncoder' class='" + LdapShaPasswordEncoder.class.getName() + "'/>");
|
||||
// @formatter:on
|
||||
getProvider().authenticate(this.bob);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void passwordIsBase64EncodedWhenBase64IsEnabled() {
|
||||
this.appContext = new InMemoryXmlApplicationContext(" <authentication-manager>" + " <authentication-provider>"
|
||||
+ " <password-encoder ref='passwordEncoder'/>" + " <user-service>"
|
||||
// @formatter:off
|
||||
this.appContext = new InMemoryXmlApplicationContext(" <authentication-manager>"
|
||||
+ " <authentication-provider>"
|
||||
+ " <password-encoder ref='passwordEncoder'/>"
|
||||
+ " <user-service>"
|
||||
+ " <user name='bob' password='ErFB811YuLOkbupl5qwXng==' authorities='ROLE_A' />"
|
||||
+ " </user-service>" + " </authentication-provider>" + " </authentication-manager>"
|
||||
+ " </user-service>"
|
||||
+ " </authentication-provider>"
|
||||
+ " </authentication-manager>"
|
||||
+ " <b:bean id='passwordEncoder' class='" + MessageDigestPasswordEncoder.class.getName() + "'>"
|
||||
+ " <b:constructor-arg value='MD5'/>" + " <b:property name='encodeHashAsBase64' value='true'/>"
|
||||
+ " </b:bean>");
|
||||
// @formatter:on
|
||||
getProvider().authenticate(this.bob);
|
||||
}
|
||||
|
||||
// SEC-1466
|
||||
@Test(expected = BeanDefinitionParsingException.class)
|
||||
public void exernalProviderDoesNotSupportChildElements() {
|
||||
// @formatter:off
|
||||
this.appContext = new InMemoryXmlApplicationContext(" <authentication-manager>"
|
||||
+ " <authentication-provider ref='aProvider'> "
|
||||
+ " <password-encoder ref='customPasswordEncoder'/>" + " </authentication-provider>"
|
||||
+ " <password-encoder ref='customPasswordEncoder'/>"
|
||||
+ " </authentication-provider>"
|
||||
+ " </authentication-manager>"
|
||||
+ " <b:bean id='aProvider' class='org.springframework.security.authentication.TestingAuthenticationProvider'/>"
|
||||
+ " <b:bean id='customPasswordEncoder' "
|
||||
+ " class='org.springframework.security.authentication.encoding.Md5PasswordEncoder'/>");
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
private AuthenticationProvider getProvider() {
|
||||
|
|
|
@ -44,10 +44,14 @@ public class JdbcUserServiceBeanDefinitionParserTests {
|
|||
|
||||
private static String USER_CACHE_XML = "<b:bean id='userCache' class='org.springframework.security.authentication.dao.MockUserCache'/>";
|
||||
|
||||
// @formatter:off
|
||||
private static String DATA_SOURCE = " <b:bean id='populator' class='org.springframework.security.config.DataSourcePopulator'>"
|
||||
+ " <b:property name='dataSource' ref='dataSource'/>" + " </b:bean>"
|
||||
+ " <b:property name='dataSource' ref='dataSource'/>"
|
||||
+ " </b:bean>"
|
||||
+ " <b:bean id='dataSource' class='org.springframework.security.TestDataSource'>"
|
||||
+ " <b:constructor-arg value='jdbcnamespaces'/>" + " </b:bean>";
|
||||
+ " <b:constructor-arg value='jdbcnamespaces'/>"
|
||||
+ " </b:bean>";
|
||||
// @formatter:on
|
||||
|
||||
private InMemoryXmlApplicationContext appContext;
|
||||
|
||||
|
@ -81,9 +85,13 @@ public class JdbcUserServiceBeanDefinitionParserTests {
|
|||
public void usernameAndAuthorityQueriesAreParsedCorrectly() throws Exception {
|
||||
String userQuery = "select username, password, true from users where username = ?";
|
||||
String authoritiesQuery = "select username, authority from authorities where username = ? and 1 = 1";
|
||||
setContext("<jdbc-user-service id='myUserService' " + "data-source-ref='dataSource' "
|
||||
+ "users-by-username-query='" + userQuery + "' " + "authorities-by-username-query='" + authoritiesQuery
|
||||
// @formatter:off
|
||||
setContext("<jdbc-user-service id='myUserService' "
|
||||
+ "data-source-ref='dataSource' "
|
||||
+ "users-by-username-query='" + userQuery + "' "
|
||||
+ "authorities-by-username-query='" + authoritiesQuery
|
||||
+ "'/>" + DATA_SOURCE);
|
||||
// @formatter:on
|
||||
JdbcUserDetailsManager mgr = (JdbcUserDetailsManager) this.appContext.getBean("myUserService");
|
||||
assertThat(FieldUtils.getFieldValue(mgr, "usersByUsernameQuery")).isEqualTo(userQuery);
|
||||
assertThat(FieldUtils.getFieldValue(mgr, "authoritiesByUsernameQuery")).isEqualTo(authoritiesQuery);
|
||||
|
@ -112,18 +120,29 @@ public class JdbcUserServiceBeanDefinitionParserTests {
|
|||
|
||||
@Test
|
||||
public void isSupportedByAuthenticationProviderElement() {
|
||||
setContext("<authentication-manager>" + " <authentication-provider>"
|
||||
+ " <jdbc-user-service data-source-ref='dataSource'/>" + " </authentication-provider>"
|
||||
+ "</authentication-manager>" + DATA_SOURCE);
|
||||
// @formatter:off
|
||||
setContext("<authentication-manager>"
|
||||
+ " <authentication-provider>"
|
||||
+ " <jdbc-user-service data-source-ref='dataSource'/>"
|
||||
+ " </authentication-provider>"
|
||||
+ "</authentication-manager>"
|
||||
+ DATA_SOURCE);
|
||||
// @formatter:on
|
||||
AuthenticationManager mgr = (AuthenticationManager) this.appContext.getBean(BeanIds.AUTHENTICATION_MANAGER);
|
||||
mgr.authenticate(new UsernamePasswordAuthenticationToken("rod", "koala"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void cacheIsInjectedIntoAuthenticationProvider() {
|
||||
setContext("<authentication-manager>" + " <authentication-provider>"
|
||||
// @formatter:off
|
||||
setContext("<authentication-manager>"
|
||||
+ " <authentication-provider>"
|
||||
+ " <jdbc-user-service cache-ref='userCache' data-source-ref='dataSource'/>"
|
||||
+ " </authentication-provider>" + "</authentication-manager>" + DATA_SOURCE + USER_CACHE_XML);
|
||||
+ " </authentication-provider>"
|
||||
+ "</authentication-manager>"
|
||||
+ DATA_SOURCE
|
||||
+ USER_CACHE_XML);
|
||||
// @formatter:on
|
||||
ProviderManager mgr = (ProviderManager) this.appContext.getBean(BeanIds.AUTHENTICATION_MANAGER);
|
||||
DaoAuthenticationProvider provider = (DaoAuthenticationProvider) mgr.getProviders().get(0);
|
||||
assertThat(this.appContext.getBean("userCache")).isSameAs(provider.getUserCache());
|
||||
|
|
|
@ -44,7 +44,10 @@ public class PasswordEncoderParserTests {
|
|||
this.spring.configLocations(
|
||||
"classpath:org/springframework/security/config/authentication/PasswordEncoderParserTests-default.xml")
|
||||
.mockMvcAfterSpringSecurityOk().autowire();
|
||||
this.mockMvc.perform(get("/").with(httpBasic("user", "password"))).andExpect(status().isOk());
|
||||
// @formatter:off
|
||||
this.mockMvc.perform(get("/").with(httpBasic("user", "password")))
|
||||
.andExpect(status().isOk());
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -52,7 +55,10 @@ public class PasswordEncoderParserTests {
|
|||
this.spring.configLocations(
|
||||
"classpath:org/springframework/security/config/authentication/PasswordEncoderParserTests-bean.xml")
|
||||
.mockMvcAfterSpringSecurityOk().autowire();
|
||||
this.mockMvc.perform(get("/").with(httpBasic("user", "password"))).andExpect(status().isOk());
|
||||
// @formatter:off
|
||||
this.mockMvc.perform(get("/").with(httpBasic("user", "password")))
|
||||
.andExpect(status().isOk());
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -52,8 +52,11 @@ public class UserServiceBeanDefinitionParserTests {
|
|||
|
||||
@Test
|
||||
public void userServiceWithEmbeddedUsersWorksSuccessfully() {
|
||||
setContext("<user-service id='service'>" + " <user name='joe' password='joespassword' authorities='ROLE_A'/>"
|
||||
// @formatter:off
|
||||
setContext("<user-service id='service'>"
|
||||
+ " <user name='joe' password='joespassword' authorities='ROLE_A'/>"
|
||||
+ "</user-service>");
|
||||
// @formatter:on
|
||||
UserDetailsService userService = (UserDetailsService) this.appContext.getBean("service");
|
||||
userService.loadUserByUsername("joe");
|
||||
}
|
||||
|
@ -63,10 +66,12 @@ public class UserServiceBeanDefinitionParserTests {
|
|||
System.setProperty("principal.name", "joe");
|
||||
System.setProperty("principal.pass", "joespassword");
|
||||
System.setProperty("principal.authorities", "ROLE_A,ROLE_B");
|
||||
// @formatter:off
|
||||
setContext("<b:bean class='org.springframework.beans.factory.config.PropertyPlaceholderConfigurer'/>"
|
||||
+ "<user-service id='service'>"
|
||||
+ " <user name='${principal.name}' password='${principal.pass}' authorities='${principal.authorities}'/>"
|
||||
+ "</user-service>");
|
||||
// @formatter:on
|
||||
UserDetailsService userService = (UserDetailsService) this.appContext.getBean("service");
|
||||
UserDetails joe = userService.loadUserByUsername("joe");
|
||||
assertThat(joe.getPassword()).isEqualTo("joespassword");
|
||||
|
@ -75,7 +80,11 @@ public class UserServiceBeanDefinitionParserTests {
|
|||
|
||||
@Test
|
||||
public void embeddedUsersWithNoPasswordIsGivenGeneratedValue() {
|
||||
setContext("<user-service id='service'>" + " <user name='joe' authorities='ROLE_A'/>" + "</user-service>");
|
||||
// @formatter:off
|
||||
setContext("<user-service id='service'>"
|
||||
+ " <user name='joe' authorities='ROLE_A'/>"
|
||||
+ "</user-service>");
|
||||
// @formatter:on
|
||||
UserDetailsService userService = (UserDetailsService) this.appContext.getBean("service");
|
||||
UserDetails joe = userService.loadUserByUsername("joe");
|
||||
assertThat(joe.getPassword().length() > 0).isTrue();
|
||||
|
@ -84,9 +93,12 @@ public class UserServiceBeanDefinitionParserTests {
|
|||
|
||||
@Test
|
||||
public void worksWithOpenIDUrlsAsNames() {
|
||||
setContext("<user-service id='service'>" + " <user name='https://joe.myopenid.com/' authorities='ROLE_A'/>"
|
||||
// @formatter:off
|
||||
setContext("<user-service id='service'>"
|
||||
+ " <user name='https://joe.myopenid.com/' authorities='ROLE_A'/>"
|
||||
+ " <user name='https://www.google.com/accounts/o8/id?id=MPtOaenBIk5yzW9n7n9' authorities='ROLE_A'/>"
|
||||
+ "</user-service>");
|
||||
// @formatter:on
|
||||
UserDetailsService userService = (UserDetailsService) this.appContext.getBean("service");
|
||||
assertThat(userService.loadUserByUsername("https://joe.myopenid.com/").getUsername())
|
||||
.isEqualTo("https://joe.myopenid.com/");
|
||||
|
@ -96,10 +108,12 @@ public class UserServiceBeanDefinitionParserTests {
|
|||
|
||||
@Test
|
||||
public void disabledAndEmbeddedFlagsAreSupported() {
|
||||
// @formatter:off
|
||||
setContext("<user-service id='service'>"
|
||||
+ " <user name='joe' password='joespassword' authorities='ROLE_A' locked='true'/>"
|
||||
+ " <user name='Bob' password='bobspassword' authorities='ROLE_A' disabled='true'/>"
|
||||
+ "</user-service>");
|
||||
// @formatter:on
|
||||
UserDetailsService userService = (UserDetailsService) this.appContext.getBean("service");
|
||||
UserDetails joe = userService.loadUserByUsername("joe");
|
||||
assertThat(joe.isAccountNonLocked()).isFalse();
|
||||
|
@ -110,8 +124,11 @@ public class UserServiceBeanDefinitionParserTests {
|
|||
|
||||
@Test(expected = FatalBeanException.class)
|
||||
public void userWithBothPropertiesAndEmbeddedUsersThrowsException() {
|
||||
// @formatter:off
|
||||
setContext("<user-service id='service' properties='doesntmatter.props'>"
|
||||
+ " <user name='joe' password='joespassword' authorities='ROLE_A'/>" + "</user-service>");
|
||||
+ " <user name='joe' password='joespassword' authorities='ROLE_A'/>"
|
||||
+ "</user-service>");
|
||||
// @formatter:on
|
||||
UserDetailsService userService = (UserDetailsService) this.appContext.getBean("service");
|
||||
userService.loadUserByUsername("Joe");
|
||||
}
|
||||
|
|
|
@ -46,15 +46,21 @@ public class UserDetailsResourceFactoryBeanTests {
|
|||
|
||||
@Test
|
||||
public void setResourceLoaderWhenNullThenThrowsException() {
|
||||
assertThatIllegalArgumentException().isThrownBy(() -> this.factory.setResourceLoader(null))
|
||||
// @formatter:off
|
||||
assertThatIllegalArgumentException()
|
||||
.isThrownBy(() -> this.factory.setResourceLoader(null))
|
||||
.withStackTraceContaining("resourceLoader cannot be null");
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getObjectWhenPropertiesResourceLocationNullThenThrowsIllegalStateException() {
|
||||
this.factory.setResourceLoader(this.resourceLoader);
|
||||
assertThatIllegalArgumentException().isThrownBy(() -> this.factory.getObject())
|
||||
// @formatter:off
|
||||
assertThatIllegalArgumentException()
|
||||
.isThrownBy(() -> this.factory.getObject())
|
||||
.withStackTraceContaining("resource cannot be null if resourceLocation is null");
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -73,8 +79,12 @@ public class UserDetailsResourceFactoryBeanTests {
|
|||
@Test
|
||||
public void getObjectWhenInvalidUserThenThrowsMeaningfulException() {
|
||||
this.factory.setResource(new InMemoryResource("user=invalidFormatHere"));
|
||||
assertThatIllegalStateException().isThrownBy(() -> this.factory.getObject()).withStackTraceContaining("user")
|
||||
// @formatter:off
|
||||
assertThatIllegalStateException()
|
||||
.isThrownBy(() -> this.factory.getObject())
|
||||
.withStackTraceContaining("user")
|
||||
.withStackTraceContaining("invalidFormatHere");
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
|
@ -45,6 +45,7 @@ import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
|
|||
*/
|
||||
public class RsaKeyConversionServicePostProcessorTests {
|
||||
|
||||
// @formatter:off
|
||||
private static final String PKCS8_PRIVATE_KEY = "-----BEGIN PRIVATE KEY-----\n"
|
||||
+ "MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQCMk7CKSTfu3QoV\n"
|
||||
+ "HoPVXxwZO+qweztd36cVWYqGOZinrOR2crWFu50AgR2CsdIH0+cqo7F4Vx7/3O8i\n"
|
||||
|
@ -70,8 +71,10 @@ public class RsaKeyConversionServicePostProcessorTests {
|
|||
+ "OHjxffBM0hH+fySx8m53gFfr2BpaqDX5f6ZGBlly1SlsWZ4CchCVsc71nshipi7I\n"
|
||||
+ "k8HL9F5/OpQdDNprJ5RMBNfkWE65Nrcsb1e6oPkCgYAxwgdiSOtNg8PjDVDmAhwT\n"
|
||||
+ "Mxj0Dtwi2fAqQ76RVrrXpNp3uCOIAu4CfruIb5llcJ3uak0ZbnWri32AxSgk80y3\n"
|
||||
+ "EWiRX/WEDu5znejF+5O3pI02atWWcnxifEKGGlxwkcMbQdA67MlrJLFaSnnGpNXo\n" + "yPfcul058SOqhafIZQMEKQ==\n"
|
||||
+ "EWiRX/WEDu5znejF+5O3pI02atWWcnxifEKGGlxwkcMbQdA67MlrJLFaSnnGpNXo\n"
|
||||
+ "yPfcul058SOqhafIZQMEKQ==\n"
|
||||
+ "-----END PRIVATE KEY-----";
|
||||
// @formatter:on
|
||||
|
||||
private static final String X509_PUBLIC_KEY_LOCATION = "classpath:org/springframework/security/config/annotation/web/configuration/simple.pub";
|
||||
|
||||
|
|
|
@ -124,12 +124,19 @@ public class SpringSecurityXsdParser {
|
|||
while (!"schema".equals(root.simpleName())) {
|
||||
root = root.parent().get();
|
||||
}
|
||||
return expand(root).filter((node) -> name.equals(node.attribute("name"))).findFirst()
|
||||
// @formatter:off
|
||||
return expand(root)
|
||||
.filter((node) -> name.equals(node.attribute("name")))
|
||||
.findFirst()
|
||||
.orElseThrow(IllegalArgumentException::new);
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
private Stream<XmlNode> expand(XmlNode root) {
|
||||
return Stream.concat(Stream.of(root), root.children().flatMap(this::expand));
|
||||
// @formatter:off
|
||||
return Stream.concat(Stream.of(root), root.children()
|
||||
.flatMap(this::expand));
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -45,20 +45,33 @@ public class XmlNode {
|
|||
|
||||
public Stream<XmlNode> children() {
|
||||
NodeList children = this.node.getChildNodes();
|
||||
return IntStream.range(0, children.getLength()).mapToObj(children::item).map(XmlNode::new);
|
||||
// @formatter:off
|
||||
return IntStream.range(0, children.getLength())
|
||||
.mapToObj(children::item)
|
||||
.map(XmlNode::new);
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
public Optional<XmlNode> child(String name) {
|
||||
return this.children().filter((child) -> name.equals(child.simpleName())).findFirst();
|
||||
return this.children()
|
||||
.filter((child) -> name.equals(child.simpleName()))
|
||||
.findFirst();
|
||||
}
|
||||
|
||||
public Optional<XmlNode> parent() {
|
||||
return Optional.ofNullable(this.node.getParentNode()).map((parent) -> new XmlNode(parent));
|
||||
// @formatter:off
|
||||
return Optional.ofNullable(this.node.getParentNode())
|
||||
.map((parent) -> new XmlNode(parent));
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
public String attribute(String name) {
|
||||
return Optional.ofNullable(this.node.getAttributes()).map((attrs) -> attrs.getNamedItem(name))
|
||||
.map((attr) -> attr.getTextContent()).orElse(null);
|
||||
// @formatter:off
|
||||
return Optional.ofNullable(this.node.getAttributes())
|
||||
.map((attrs) -> attrs.getNamedItem(name))
|
||||
.map((attr) -> attr.getTextContent())
|
||||
.orElse(null);
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
public Node node() {
|
||||
|
|
|
@ -46,11 +46,20 @@ import static org.assertj.core.api.Assertions.assertThat;
|
|||
*/
|
||||
public class XsdDocumentedTests {
|
||||
|
||||
Collection<String> ignoredIds = Arrays.asList("nsa-any-user-service", "nsa-any-user-service-parents",
|
||||
"nsa-authentication", "nsa-websocket-security", "nsa-ldap", "nsa-method-security", "nsa-web",
|
||||
// @formatter:off
|
||||
Collection<String> ignoredIds = Arrays.asList("nsa-any-user-service",
|
||||
"nsa-any-user-service-parents",
|
||||
"nsa-authentication",
|
||||
"nsa-websocket-security",
|
||||
"nsa-ldap",
|
||||
"nsa-method-security",
|
||||
"nsa-web",
|
||||
// deprecated and for removal
|
||||
"nsa-frame-options-strategy", "nsa-frame-options-ref", "nsa-frame-options-value",
|
||||
"nsa-frame-options-strategy",
|
||||
"nsa-frame-options-ref",
|
||||
"nsa-frame-options-value",
|
||||
"nsa-frame-options-from-parameter");
|
||||
// @formatter:on
|
||||
|
||||
String referenceLocation = "../docs/manual/src/docs/asciidoc/_includes/servlet/appendix/namespace.adoc";
|
||||
|
||||
|
@ -68,28 +77,61 @@ public class XsdDocumentedTests {
|
|||
@Test
|
||||
public void parseWhenLatestXsdThenAllNamedSecurityFiltersAreDefinedAndOrderedProperly() throws IOException {
|
||||
XmlNode root = this.xml.parse(this.schemaDocumentLocation);
|
||||
List<String> nodes = root.child("schema").map(XmlNode::children).orElse(Stream.empty())
|
||||
// @formatter:off
|
||||
List<String> nodes = root.child("schema")
|
||||
.map(XmlNode::children)
|
||||
.orElse(Stream.empty())
|
||||
.filter((node) -> "simpleType".equals(node.simpleName())
|
||||
&& "named-security-filter".equals(node.attribute("name")))
|
||||
.flatMap(XmlNode::children).flatMap(XmlNode::children).map((node) -> node.attribute("value"))
|
||||
.filter(StringUtils::isNotEmpty).collect(Collectors.toList());
|
||||
.flatMap(XmlNode::children)
|
||||
.flatMap(XmlNode::children)
|
||||
.map((node) -> node.attribute("value"))
|
||||
.filter(StringUtils::isNotEmpty)
|
||||
.collect(Collectors.toList());
|
||||
// @formatter:on
|
||||
SecurityFiltersAssertions.assertEquals(nodes);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void parseWhen31XsdThenAllNamedSecurityFiltersAreDefinedAndOrderedProperly() throws IOException {
|
||||
List<String> expected = Arrays.asList("FIRST", "CHANNEL_FILTER", "SECURITY_CONTEXT_FILTER",
|
||||
"CONCURRENT_SESSION_FILTER", "LOGOUT_FILTER", "X509_FILTER", "PRE_AUTH_FILTER", "CAS_FILTER",
|
||||
"FORM_LOGIN_FILTER", "OPENID_FILTER", "LOGIN_PAGE_FILTER", "DIGEST_AUTH_FILTER", "BASIC_AUTH_FILTER",
|
||||
"REQUEST_CACHE_FILTER", "SERVLET_API_SUPPORT_FILTER", "JAAS_API_SUPPORT_FILTER", "REMEMBER_ME_FILTER",
|
||||
"ANONYMOUS_FILTER", "SESSION_MANAGEMENT_FILTER", "EXCEPTION_TRANSLATION_FILTER",
|
||||
"FILTER_SECURITY_INTERCEPTOR", "SWITCH_USER_FILTER", "LAST");
|
||||
// @formatter:off
|
||||
List<String> expected = Arrays.asList("FIRST",
|
||||
"CHANNEL_FILTER",
|
||||
"SECURITY_CONTEXT_FILTER",
|
||||
"CONCURRENT_SESSION_FILTER",
|
||||
"LOGOUT_FILTER",
|
||||
"X509_FILTER",
|
||||
"PRE_AUTH_FILTER",
|
||||
"CAS_FILTER",
|
||||
"FORM_LOGIN_FILTER",
|
||||
"OPENID_FILTER",
|
||||
"LOGIN_PAGE_FILTER",
|
||||
"DIGEST_AUTH_FILTER",
|
||||
"BASIC_AUTH_FILTER",
|
||||
"REQUEST_CACHE_FILTER",
|
||||
"SERVLET_API_SUPPORT_FILTER",
|
||||
"JAAS_API_SUPPORT_FILTER",
|
||||
"REMEMBER_ME_FILTER",
|
||||
"ANONYMOUS_FILTER",
|
||||
"SESSION_MANAGEMENT_FILTER",
|
||||
"EXCEPTION_TRANSLATION_FILTER",
|
||||
"FILTER_SECURITY_INTERCEPTOR",
|
||||
"SWITCH_USER_FILTER",
|
||||
"LAST");
|
||||
// @formatter:on
|
||||
XmlNode root = this.xml.parse(this.schema31xDocumentLocation);
|
||||
List<String> nodes = root.child("schema").map(XmlNode::children).orElse(Stream.empty())
|
||||
// @formatter:off
|
||||
List<String> nodes = root.child("schema")
|
||||
.map(XmlNode::children)
|
||||
.orElse(Stream.empty())
|
||||
.filter((node) -> "simpleType".equals(node.simpleName())
|
||||
&& "named-security-filter".equals(node.attribute("name")))
|
||||
.flatMap(XmlNode::children).flatMap(XmlNode::children).map((node) -> node.attribute("value"))
|
||||
.filter(StringUtils::isNotEmpty).collect(Collectors.toList());
|
||||
.flatMap(XmlNode::children)
|
||||
.flatMap(XmlNode::children)
|
||||
.map((node) -> node.attribute("value"))
|
||||
.filter(StringUtils::isNotEmpty)
|
||||
.collect(Collectors.toList());
|
||||
// @formatter:on
|
||||
assertThat(nodes).isEqualTo(expected);
|
||||
}
|
||||
|
||||
|
@ -103,7 +145,11 @@ public class XsdDocumentedTests {
|
|||
@Test
|
||||
public void sizeWhenReadingFilesystemThenIsCorrectNumberOfSchemaFiles() throws IOException {
|
||||
ClassPathResource resource = new ClassPathResource(this.schemaDocumentLocation);
|
||||
String[] schemas = resource.getFile().getParentFile().list((dir, name) -> name.endsWith(".xsd"));
|
||||
// @formatter:off
|
||||
String[] schemas = resource.getFile()
|
||||
.getParentFile()
|
||||
.list((dir, name) -> name.endsWith(".xsd"));
|
||||
// @formatter:on
|
||||
assertThat(schemas.length).isEqualTo(16)
|
||||
.withFailMessage("the count is equal to 16, if not then schemaDocument needs updating");
|
||||
}
|
||||
|
@ -117,11 +163,16 @@ public class XsdDocumentedTests {
|
|||
@Test
|
||||
public void countReferencesWhenReviewingDocumentationThenEntireSchemaIsIncluded() throws IOException {
|
||||
Map<String, Element> elementsByElementName = this.xml.elementsByElementName(this.schemaDocumentLocation);
|
||||
// @formatter:off
|
||||
List<String> documentIds = Files.lines(Paths.get(this.referenceLocation))
|
||||
.filter((line) -> line.matches("\\[\\[(nsa-.*)\\]\\]"))
|
||||
.map((line) -> line.substring(2, line.length() - 2)).collect(Collectors.toList());
|
||||
Set<String> expectedIds = elementsByElementName.values().stream()
|
||||
.flatMap((element) -> element.getIds().stream()).collect(Collectors.toSet());
|
||||
.map((line) -> line.substring(2, line.length() - 2))
|
||||
.collect(Collectors.toList());
|
||||
Set<String> expectedIds = elementsByElementName.values()
|
||||
.stream()
|
||||
.flatMap((element) -> element.getIds().stream())
|
||||
.collect(Collectors.toSet());
|
||||
// @formatter:on
|
||||
documentIds.removeAll(this.ignoredIds);
|
||||
expectedIds.removeAll(this.ignoredIds);
|
||||
assertThat(documentIds).containsAll(expectedIds);
|
||||
|
@ -172,15 +223,28 @@ public class XsdDocumentedTests {
|
|||
if (this.ignoredIds.contains(key)) {
|
||||
return;
|
||||
}
|
||||
List<String> parentIds = entry.getValue().getAllParentElmts().values().stream()
|
||||
.filter((element) -> !this.ignoredIds.contains(element.getId())).map((element) -> element.getId())
|
||||
.sorted().collect(Collectors.toList());
|
||||
// @formatter:off
|
||||
List<String> parentIds = entry.getValue()
|
||||
.getAllParentElmts()
|
||||
.values()
|
||||
.stream()
|
||||
.filter((element) -> !this.ignoredIds.contains(element.getId()))
|
||||
.map((element) -> element.getId())
|
||||
.sorted()
|
||||
.collect(Collectors.toList());
|
||||
// @formatter:on
|
||||
if (!parentIds.isEmpty()) {
|
||||
schemaAttrNameToParents.put(key, parentIds);
|
||||
}
|
||||
List<String> childIds = entry.getValue().getAllChildElmts().values().stream()
|
||||
// @formatter:off
|
||||
List<String> childIds = entry.getValue()
|
||||
.getAllChildElmts()
|
||||
.values()
|
||||
.stream()
|
||||
.filter((element) -> !this.ignoredIds.contains(element.getId())).map((element) -> element.getId())
|
||||
.sorted().collect(Collectors.toList());
|
||||
.sorted()
|
||||
.collect(Collectors.toList());
|
||||
// @formatter:on
|
||||
if (!childIds.isEmpty()) {
|
||||
schemaAttrNameToChildren.put(key, childIds);
|
||||
}
|
||||
|
@ -196,14 +260,23 @@ public class XsdDocumentedTests {
|
|||
@Test
|
||||
public void countWhenReviewingDocumentationThenAllElementsDocumented() throws IOException {
|
||||
Map<String, Element> elementNameToElement = this.xml.elementsByElementName(this.schemaDocumentLocation);
|
||||
String notDocElmtIds = elementNameToElement.values().stream()
|
||||
// @formatter:off
|
||||
String notDocElmtIds = elementNameToElement.values()
|
||||
.stream()
|
||||
.filter((element) -> StringUtils.isEmpty(element.getDesc())
|
||||
&& !this.ignoredIds.contains(element.getId()))
|
||||
.map((element) -> element.getId()).sorted().collect(Collectors.joining("\n"));
|
||||
String notDocAttrIds = elementNameToElement.values().stream().flatMap((element) -> element.getAttrs().stream())
|
||||
.map((element) -> element.getId())
|
||||
.sorted()
|
||||
.collect(Collectors.joining("\n"));
|
||||
String notDocAttrIds = elementNameToElement.values()
|
||||
.stream()
|
||||
.flatMap((element) -> element.getAttrs().stream())
|
||||
.filter((element) -> StringUtils.isEmpty(element.getDesc())
|
||||
&& !this.ignoredIds.contains(element.getId()))
|
||||
.map((element) -> element.getId()).sorted().collect(Collectors.joining("\n"));
|
||||
.map((element) -> element.getId())
|
||||
.sorted()
|
||||
.collect(Collectors.joining("\n"));
|
||||
// @formatter:on
|
||||
assertThat(notDocElmtIds).isEmpty();
|
||||
assertThat(notDocAttrIds).isEmpty();
|
||||
}
|
||||
|
|
|
@ -48,6 +48,7 @@ import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
|||
import org.springframework.test.web.servlet.MockMvc;
|
||||
import org.springframework.test.web.servlet.MvcResult;
|
||||
import org.springframework.test.web.servlet.ResultMatcher;
|
||||
import org.springframework.test.web.servlet.request.MockHttpServletRequestBuilder;
|
||||
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
|
@ -90,124 +91,190 @@ public class CsrfConfigTests {
|
|||
@Test
|
||||
public void postWhenDefaultConfigurationThenForbiddenSinceCsrfIsEnabled() throws Exception {
|
||||
this.spring.configLocations(this.xml("AutoConfig")).autowire();
|
||||
this.mvc.perform(post("/csrf")).andExpect(status().isForbidden()).andExpect(csrfCreated());
|
||||
// @formatter:off
|
||||
this.mvc.perform(post("/csrf"))
|
||||
.andExpect(status().isForbidden())
|
||||
.andExpect(csrfCreated());
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
public void putWhenDefaultConfigurationThenForbiddenSinceCsrfIsEnabled() throws Exception {
|
||||
this.spring.configLocations(this.xml("AutoConfig")).autowire();
|
||||
this.mvc.perform(put("/csrf")).andExpect(status().isForbidden()).andExpect(csrfCreated());
|
||||
// @formatter:off
|
||||
this.mvc.perform(put("/csrf"))
|
||||
.andExpect(status().isForbidden())
|
||||
.andExpect(csrfCreated());
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
public void patchWhenDefaultConfigurationThenForbiddenSinceCsrfIsEnabled() throws Exception {
|
||||
this.spring.configLocations(this.xml("AutoConfig")).autowire();
|
||||
this.mvc.perform(patch("/csrf")).andExpect(status().isForbidden()).andExpect(csrfCreated());
|
||||
// @formatter:off
|
||||
this.mvc.perform(patch("/csrf"))
|
||||
.andExpect(status().isForbidden())
|
||||
.andExpect(csrfCreated());
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
public void deleteWhenDefaultConfigurationThenForbiddenSinceCsrfIsEnabled() throws Exception {
|
||||
this.spring.configLocations(this.xml("AutoConfig")).autowire();
|
||||
this.mvc.perform(delete("/csrf")).andExpect(status().isForbidden()).andExpect(csrfCreated());
|
||||
// @formatter:off
|
||||
this.mvc.perform(delete("/csrf"))
|
||||
.andExpect(status().isForbidden())
|
||||
.andExpect(csrfCreated());
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
public void invalidWhenDefaultConfigurationThenForbiddenSinceCsrfIsEnabled() throws Exception {
|
||||
this.spring.configLocations(this.xml("AutoConfig")).autowire();
|
||||
this.mvc.perform(request("INVALID", new URI("/csrf"))).andExpect(status().isForbidden())
|
||||
// @formatter:off
|
||||
this.mvc.perform(request("INVALID", new URI("/csrf")))
|
||||
.andExpect(status().isForbidden())
|
||||
.andExpect(csrfCreated());
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getWhenDefaultConfigurationThenCsrfIsEnabled() throws Exception {
|
||||
this.spring.configLocations(this.xml("shared-controllers"), this.xml("AutoConfig")).autowire();
|
||||
this.mvc.perform(get("/csrf")).andExpect(csrfInBody());
|
||||
// @formatter:off
|
||||
this.mvc.perform(get("/csrf"))
|
||||
.andExpect(csrfInBody());
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
public void headWhenDefaultConfigurationThenCsrfIsEnabled() throws Exception {
|
||||
this.spring.configLocations(this.xml("shared-controllers"), this.xml("AutoConfig")).autowire();
|
||||
this.mvc.perform(head("/csrf-in-header")).andExpect(csrfInHeader());
|
||||
// @formatter:off
|
||||
this.mvc.perform(head("/csrf-in-header"))
|
||||
.andExpect(csrfInHeader());
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
public void traceWhenDefaultConfigurationThenCsrfIsEnabled() throws Exception {
|
||||
this.spring.configLocations(this.xml("shared-controllers"), this.xml("AutoConfig")).autowire();
|
||||
MockMvc traceEnabled = MockMvcBuilders.webAppContextSetup(this.spring.getContext()).apply(springSecurity())
|
||||
// @formatter:off
|
||||
MockMvc traceEnabled = MockMvcBuilders.webAppContextSetup(this.spring.getContext())
|
||||
.apply(springSecurity())
|
||||
.addDispatcherServletCustomizer((dispatcherServlet) -> dispatcherServlet.setDispatchTraceRequest(true))
|
||||
.build();
|
||||
traceEnabled.perform(request(HttpMethod.TRACE, "/csrf-in-header")).andExpect(csrfInHeader());
|
||||
traceEnabled.perform(request(HttpMethod.TRACE, "/csrf-in-header"))
|
||||
.andExpect(csrfInHeader());
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
public void optionsWhenDefaultConfigurationThenCsrfIsEnabled() throws Exception {
|
||||
this.spring.configLocations(this.xml("shared-controllers"), this.xml("AutoConfig")).autowire();
|
||||
this.mvc.perform(options("/csrf-in-header")).andExpect(csrfInHeader());
|
||||
// @formatter:off
|
||||
this.mvc.perform(options("/csrf-in-header"))
|
||||
.andExpect(csrfInHeader());
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
public void postWhenCsrfDisabledThenRequestAllowed() throws Exception {
|
||||
this.spring.configLocations(this.xml("shared-controllers"), this.xml("CsrfDisabled")).autowire();
|
||||
this.mvc.perform(post("/ok")).andExpect(status().isOk());
|
||||
// @formatter:off
|
||||
this.mvc.perform(post("/ok"))
|
||||
.andExpect(status().isOk());
|
||||
// @formatter:on
|
||||
assertThat(getFilter(this.spring, CsrfFilter.class)).isNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void postWhenCsrfElementEnabledThenForbidden() throws Exception {
|
||||
this.spring.configLocations(this.xml("CsrfEnabled")).autowire();
|
||||
this.mvc.perform(post("/csrf")).andExpect(status().isForbidden()).andExpect(csrfCreated());
|
||||
// @formatter:off
|
||||
this.mvc.perform(post("/csrf"))
|
||||
.andExpect(status().isForbidden())
|
||||
.andExpect(csrfCreated());
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
public void putWhenCsrfElementEnabledThenForbidden() throws Exception {
|
||||
this.spring.configLocations(this.xml("CsrfEnabled")).autowire();
|
||||
this.mvc.perform(put("/csrf")).andExpect(status().isForbidden()).andExpect(csrfCreated());
|
||||
// @formatter:off
|
||||
this.mvc.perform(put("/csrf"))
|
||||
.andExpect(status().isForbidden())
|
||||
.andExpect(csrfCreated());
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
public void patchWhenCsrfElementEnabledThenForbidden() throws Exception {
|
||||
this.spring.configLocations(this.xml("CsrfEnabled")).autowire();
|
||||
this.mvc.perform(patch("/csrf")).andExpect(status().isForbidden()).andExpect(csrfCreated());
|
||||
// @formatter:off
|
||||
this.mvc.perform(patch("/csrf"))
|
||||
.andExpect(status().isForbidden())
|
||||
.andExpect(csrfCreated());
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
public void deleteWhenCsrfElementEnabledThenForbidden() throws Exception {
|
||||
this.spring.configLocations(this.xml("CsrfEnabled")).autowire();
|
||||
this.mvc.perform(delete("/csrf")).andExpect(status().isForbidden()).andExpect(csrfCreated());
|
||||
// @formatter:off
|
||||
this.mvc.perform(delete("/csrf"))
|
||||
.andExpect(status().isForbidden())
|
||||
.andExpect(csrfCreated());
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
public void invalidWhenCsrfElementEnabledThenForbidden() throws Exception {
|
||||
this.spring.configLocations(this.xml("CsrfEnabled")).autowire();
|
||||
this.mvc.perform(request("INVALID", new URI("/csrf"))).andExpect(status().isForbidden())
|
||||
// @formatter:off
|
||||
this.mvc.perform(request("INVALID", new URI("/csrf")))
|
||||
.andExpect(status().isForbidden())
|
||||
.andExpect(csrfCreated());
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getWhenCsrfElementEnabledThenOk() throws Exception {
|
||||
this.spring.configLocations(this.xml("shared-controllers"), this.xml("CsrfEnabled")).autowire();
|
||||
this.mvc.perform(get("/csrf")).andExpect(csrfInBody());
|
||||
// @formatter:off
|
||||
this.mvc.perform(get("/csrf"))
|
||||
.andExpect(csrfInBody());
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
public void headWhenCsrfElementEnabledThenOk() throws Exception {
|
||||
this.spring.configLocations(this.xml("shared-controllers"), this.xml("CsrfEnabled")).autowire();
|
||||
this.mvc.perform(head("/csrf-in-header")).andExpect(csrfInHeader());
|
||||
// @formatter:off
|
||||
this.mvc.perform(head("/csrf-in-header"))
|
||||
.andExpect(csrfInHeader());
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
public void traceWhenCsrfElementEnabledThenOk() throws Exception {
|
||||
this.spring.configLocations(this.xml("shared-controllers"), this.xml("CsrfEnabled")).autowire();
|
||||
MockMvc traceEnabled = MockMvcBuilders.webAppContextSetup(this.spring.getContext()).apply(springSecurity())
|
||||
// @formatter:off
|
||||
MockMvc traceEnabled = MockMvcBuilders.webAppContextSetup(this.spring.getContext())
|
||||
.apply(springSecurity())
|
||||
.addDispatcherServletCustomizer((dispatcherServlet) -> dispatcherServlet.setDispatchTraceRequest(true))
|
||||
.build();
|
||||
// @formatter:on
|
||||
traceEnabled.perform(request(HttpMethod.TRACE, "/csrf-in-header")).andExpect(csrfInHeader());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void optionsWhenCsrfElementEnabledThenOk() throws Exception {
|
||||
this.spring.configLocations(this.xml("shared-controllers"), this.xml("CsrfEnabled")).autowire();
|
||||
this.mvc.perform(options("/csrf-in-header")).andExpect(csrfInHeader());
|
||||
// @formatter:off
|
||||
this.mvc.perform(options("/csrf-in-header"))
|
||||
.andExpect(csrfInHeader());
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -220,7 +287,10 @@ public class CsrfConfigTests {
|
|||
public void postWhenUsingCsrfAndCustomAccessDeniedHandlerThenTheHandlerIsAppropriatelyEngaged() throws Exception {
|
||||
this.spring.configLocations(this.xml("WithAccessDeniedHandler"), this.xml("shared-access-denied-handler"))
|
||||
.autowire();
|
||||
this.mvc.perform(post("/ok")).andExpect(status().isIAmATeapot());
|
||||
// @formatter:off
|
||||
this.mvc.perform(post("/ok"))
|
||||
.andExpect(status().isIAmATeapot());
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -233,9 +303,15 @@ public class CsrfConfigTests {
|
|||
MockHttpSession session = (MockHttpSession) result.getRequest().getSession();
|
||||
// if the request cache is consulted, then it will redirect back to /some-url,
|
||||
// which we don't want
|
||||
this.mvc.perform(
|
||||
post("/login").param("username", "user").param("password", "password").session(session).with(csrf()))
|
||||
// @formatter:off
|
||||
MockHttpServletRequestBuilder login = post("/login")
|
||||
.param("username", "user")
|
||||
.param("password", "password")
|
||||
.session(session)
|
||||
.with(csrf());
|
||||
this.mvc.perform(login)
|
||||
.andExpect(redirectedUrl("/"));
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -248,9 +324,15 @@ public class CsrfConfigTests {
|
|||
MockHttpSession session = (MockHttpSession) result.getRequest().getSession();
|
||||
// if the request cache is consulted, then it will redirect back to /some-url,
|
||||
// which we do want
|
||||
this.mvc.perform(
|
||||
post("/login").param("username", "user").param("password", "password").session(session).with(csrf()))
|
||||
// @formatter:off
|
||||
MockHttpServletRequestBuilder login = post("/login")
|
||||
.param("username", "user")
|
||||
.param("password", "password")
|
||||
.session(session)
|
||||
.with(csrf());
|
||||
this.mvc.perform(login)
|
||||
.andExpect(redirectedUrl("http://localhost/authenticated"));
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -260,10 +342,16 @@ public class CsrfConfigTests {
|
|||
public void postWhenUsingCsrfAndCustomSessionManagementAndNoSessionThenStillRedirectsToInvalidSessionUrl()
|
||||
throws Exception {
|
||||
this.spring.configLocations(this.xml("WithSessionManagement")).autowire();
|
||||
MvcResult result = this.mvc.perform(post("/ok").param("_csrf", "abc"))
|
||||
.andExpect(redirectedUrl("/error/sessionError")).andReturn();
|
||||
// @formatter:off
|
||||
MockHttpServletRequestBuilder postToOk = post("/ok")
|
||||
.param("_csrf", "abc");
|
||||
MvcResult result = this.mvc.perform(postToOk)
|
||||
.andExpect(redirectedUrl("/error/sessionError"))
|
||||
.andReturn();
|
||||
MockHttpSession session = (MockHttpSession) result.getRequest().getSession();
|
||||
this.mvc.perform(post("/csrf").session(session)).andExpect(status().isForbidden());
|
||||
this.mvc.perform(post("/csrf").session(session))
|
||||
.andExpect(status().isForbidden());
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -273,15 +361,24 @@ public class CsrfConfigTests {
|
|||
context.autowire();
|
||||
RequestMatcher matcher = context.getContext().getBean(RequestMatcher.class);
|
||||
given(matcher.matches(any(HttpServletRequest.class))).willReturn(false);
|
||||
this.mvc.perform(post("/ok")).andExpect(status().isOk());
|
||||
// @formatter:off
|
||||
this.mvc.perform(post("/ok"))
|
||||
.andExpect(status().isOk());
|
||||
// @formatter:on
|
||||
given(matcher.matches(any(HttpServletRequest.class))).willReturn(true);
|
||||
this.mvc.perform(get("/ok")).andExpect(status().isForbidden());
|
||||
// @formatter:off
|
||||
this.mvc.perform(get("/ok"))
|
||||
.andExpect(status().isForbidden());
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getWhenDefaultConfigurationThenSessionNotImmediatelyCreated() throws Exception {
|
||||
this.spring.configLocations(this.xml("shared-controllers"), this.xml("AutoConfig")).autowire();
|
||||
MvcResult result = this.mvc.perform(get("/ok")).andExpect(status().isOk()).andReturn();
|
||||
// @formatter:off
|
||||
MvcResult result = this.mvc.perform(get("/ok"))
|
||||
.andExpect(status().isOk()).andReturn();
|
||||
// @formatter:on
|
||||
assertThat(result.getRequest().getSession(false)).isNull();
|
||||
}
|
||||
|
||||
|
@ -291,7 +388,13 @@ public class CsrfConfigTests {
|
|||
this.spring.configLocations(this.xml("shared-controllers"), this.xml("AutoConfig")).autowire();
|
||||
MvcResult result = this.mvc.perform(get("/ok")).andReturn();
|
||||
MockHttpSession session = (MockHttpSession) result.getRequest().getSession();
|
||||
this.mvc.perform(post("/ok").session(session).with(csrf().useInvalidToken())).andExpect(status().isForbidden());
|
||||
// @formatter:off
|
||||
MockHttpServletRequestBuilder postOk = post("/ok")
|
||||
.session(session)
|
||||
.with(csrf().useInvalidToken());
|
||||
this.mvc.perform(postOk)
|
||||
.andExpect(status().isForbidden());
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -299,10 +402,17 @@ public class CsrfConfigTests {
|
|||
this.spring.configLocations(this.xml("shared-controllers"), this.xml("AutoConfig")).autowire();
|
||||
MvcResult result = this.mvc.perform(get("/csrf")).andReturn();
|
||||
MockHttpSession session = (MockHttpSession) result.getRequest().getSession();
|
||||
this.mvc.perform(
|
||||
post("/login").param("username", "user").param("password", "password").session(session).with(csrf()))
|
||||
// @formatter:off
|
||||
MockHttpServletRequestBuilder loginRequest = post("/login")
|
||||
.param("username", "user")
|
||||
.param("password", "password")
|
||||
.session(session)
|
||||
.with(csrf());
|
||||
this.mvc.perform(loginRequest)
|
||||
.andExpect(status().isFound());
|
||||
this.mvc.perform(get("/csrf").session(session)).andExpect(csrfChanged(result));
|
||||
this.mvc.perform(get("/csrf").session(session))
|
||||
.andExpect(csrfChanged(result));
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -310,8 +420,12 @@ public class CsrfConfigTests {
|
|||
this.spring.configLocations(this.xml("shared-controllers"), this.xml("AutoConfig")).autowire();
|
||||
MvcResult result = this.mvc.perform(get("/csrf")).andReturn();
|
||||
MockHttpSession session = (MockHttpSession) result.getRequest().getSession();
|
||||
this.mvc.perform(post("/logout").session(session).with(csrf())).andExpect(status().isFound());
|
||||
this.mvc.perform(get("/csrf").session(session)).andExpect(csrfChanged(result));
|
||||
// @formatter:off
|
||||
this.mvc.perform(post("/logout").session(session).with(csrf()))
|
||||
.andExpect(status().isFound());
|
||||
this.mvc.perform(get("/csrf").session(session))
|
||||
.andExpect(csrfChanged(result));
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -321,13 +435,16 @@ public class CsrfConfigTests {
|
|||
@WithMockUser
|
||||
public void logoutWhenDefaultConfigurationThenDisabled() throws Exception {
|
||||
this.spring.configLocations(this.xml("shared-controllers"), this.xml("CsrfEnabled")).autowire();
|
||||
this.mvc.perform(get("/logout")).andExpect(status().isOk()); // renders form to
|
||||
// log out but
|
||||
// does not
|
||||
// perform a
|
||||
// redirect
|
||||
// renders form to log out but does not perform a redirect
|
||||
// @formatter:off
|
||||
this.mvc.perform(get("/logout"))
|
||||
.andExpect(status().isOk());
|
||||
// @formatter:on
|
||||
// still logged in
|
||||
this.mvc.perform(get("/authenticated")).andExpect(status().isOk());
|
||||
// @formatter:off
|
||||
this.mvc.perform(get("/authenticated"))
|
||||
.andExpect(status().isOk());
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
private <T extends Filter> T getFilter(SpringTestContext context, Class<T> type) {
|
||||
|
|
|
@ -60,8 +60,11 @@ public class FilterSecurityMetadataSourceBeanDefinitionParserTests {
|
|||
|
||||
@Test
|
||||
public void parsingMinimalConfigurationIsSuccessful() {
|
||||
// @formatter:off
|
||||
setContext("<filter-security-metadata-source id='fids' use-expressions='false'>"
|
||||
+ " <intercept-url pattern='/**' access='ROLE_A'/>" + "</filter-security-metadata-source>");
|
||||
+ " <intercept-url pattern='/**' access='ROLE_A'/>"
|
||||
+ "</filter-security-metadata-source>");
|
||||
// @formatter:on
|
||||
DefaultFilterInvocationSecurityMetadataSource fids = (DefaultFilterInvocationSecurityMetadataSource) this.appContext
|
||||
.getBean("fids");
|
||||
Collection<ConfigAttribute> cad = fids.getAttributes(createFilterInvocation("/anything", "GET"));
|
||||
|
@ -70,9 +73,11 @@ public class FilterSecurityMetadataSourceBeanDefinitionParserTests {
|
|||
|
||||
@Test
|
||||
public void expressionsAreSupported() {
|
||||
// @formatter:off
|
||||
setContext("<filter-security-metadata-source id='fids'>"
|
||||
+ " <intercept-url pattern='/**' access=\"hasRole('ROLE_A')\" />"
|
||||
+ "</filter-security-metadata-source>");
|
||||
// @formatter:on
|
||||
ExpressionBasedFilterInvocationSecurityMetadataSource fids = (ExpressionBasedFilterInvocationSecurityMetadataSource) this.appContext
|
||||
.getBean("fids");
|
||||
ConfigAttribute[] cad = fids.getAttributes(createFilterInvocation("/anything", "GET"))
|
||||
|
@ -98,6 +103,7 @@ public class FilterSecurityMetadataSourceBeanDefinitionParserTests {
|
|||
|
||||
@Test
|
||||
public void parsingWithinFilterSecurityInterceptorIsSuccessful() {
|
||||
// @formatter:off
|
||||
setContext("<http auto-config='true' use-expressions='false'/>"
|
||||
+ "<b:bean id='fsi' class='org.springframework.security.web.access.intercept.FilterSecurityInterceptor' autowire='byType'>"
|
||||
+ " <b:property name='securityMetadataSource'>"
|
||||
|
@ -105,9 +111,12 @@ public class FilterSecurityMetadataSourceBeanDefinitionParserTests {
|
|||
+ " <intercept-url pattern='/secure/extreme/**' access='ROLE_SUPERVISOR'/>"
|
||||
+ " <intercept-url pattern='/secure/**' access='ROLE_USER'/>"
|
||||
+ " <intercept-url pattern='/**' access='ROLE_USER'/>"
|
||||
+ " </filter-security-metadata-source>" + " </b:property>"
|
||||
+ " </filter-security-metadata-source>"
|
||||
+ " </b:property>"
|
||||
+ " <b:property name='authenticationManager' ref='" + BeanIds.AUTHENTICATION_MANAGER + "'/>"
|
||||
+ "</b:bean>" + ConfigTestUtils.AUTH_PROVIDER_XML);
|
||||
+ "</b:bean>"
|
||||
+ ConfigTestUtils.AUTH_PROVIDER_XML);
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test(expected = BeanDefinitionParsingException.class)
|
||||
|
|
|
@ -23,6 +23,7 @@ import org.springframework.beans.factory.annotation.Autowired;
|
|||
import org.springframework.security.config.test.SpringTestRule;
|
||||
import org.springframework.security.web.WebAttributes;
|
||||
import org.springframework.test.web.servlet.MockMvc;
|
||||
import org.springframework.test.web.servlet.request.MockHttpServletRequestBuilder;
|
||||
|
||||
import static org.hamcrest.CoreMatchers.containsString;
|
||||
import static org.hamcrest.CoreMatchers.not;
|
||||
|
@ -51,24 +52,35 @@ public class FormLoginBeanDefinitionParserTests {
|
|||
@Test
|
||||
public void getLoginWhenAutoConfigThenShowsDefaultLoginPage() throws Exception {
|
||||
this.spring.configLocations(this.xml("Simple")).autowire();
|
||||
String expectedContent = "<!DOCTYPE html>\n" + "<html lang=\"en\">\n" + " <head>\n"
|
||||
// @formatter:off
|
||||
String expectedContent = "<!DOCTYPE html>\n"
|
||||
+ "<html lang=\"en\">\n"
|
||||
+ " <head>\n"
|
||||
+ " <meta charset=\"utf-8\">\n"
|
||||
+ " <meta name=\"viewport\" content=\"width=device-width, initial-scale=1, shrink-to-fit=no\">\n"
|
||||
+ " <meta name=\"description\" content=\"\">\n" + " <meta name=\"author\" content=\"\">\n"
|
||||
+ " <meta name=\"description\" content=\"\">\n"
|
||||
+ " <meta name=\"author\" content=\"\">\n"
|
||||
+ " <title>Please sign in</title>\n"
|
||||
+ " <link href=\"https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-beta/css/bootstrap.min.css\" rel=\"stylesheet\" integrity=\"sha384-/Y6pD6FV/Vv2HJnA6t+vslU6fwYXjCFtcEpHbNJ0lyAFsXTsjBbfaDjzALeQsN6M\" crossorigin=\"anonymous\">\n"
|
||||
+ " <link href=\"https://getbootstrap.com/docs/4.0/examples/signin/signin.css\" rel=\"stylesheet\" crossorigin=\"anonymous\"/>\n"
|
||||
+ " </head>\n" + " <body>\n" + " <div class=\"container\">\n"
|
||||
+ " </head>\n"
|
||||
+ " <body>\n"
|
||||
+ " <div class=\"container\">\n"
|
||||
+ " <form class=\"form-signin\" method=\"post\" action=\"/login\">\n"
|
||||
+ " <h2 class=\"form-signin-heading\">Please sign in</h2>\n" + " <p>\n"
|
||||
+ " <h2 class=\"form-signin-heading\">Please sign in</h2>\n"
|
||||
+ " <p>\n"
|
||||
+ " <label for=\"username\" class=\"sr-only\">Username</label>\n"
|
||||
+ " <input type=\"text\" id=\"username\" name=\"username\" class=\"form-control\" placeholder=\"Username\" required autofocus>\n"
|
||||
+ " </p>\n" + " <p>\n"
|
||||
+ " </p>\n"
|
||||
+ " <p>\n"
|
||||
+ " <label for=\"password\" class=\"sr-only\">Password</label>\n"
|
||||
+ " <input type=\"password\" id=\"password\" name=\"password\" class=\"form-control\" placeholder=\"Password\" required>\n"
|
||||
+ " </p>\n"
|
||||
+ " <button class=\"btn btn-lg btn-primary btn-block\" type=\"submit\">Sign in</button>\n"
|
||||
+ " </form>\n" + "</div>\n" + "</body></html>";
|
||||
+ " </form>\n"
|
||||
+ "</div>\n"
|
||||
+ "</body></html>";
|
||||
// @formatter:on
|
||||
this.mvc.perform(get("/login")).andExpect(content().string(expectedContent));
|
||||
}
|
||||
|
||||
|
@ -81,75 +93,108 @@ public class FormLoginBeanDefinitionParserTests {
|
|||
@Test
|
||||
public void getLoginWhenConfiguredWithCustomAttributesThenLoginPageReflects() throws Exception {
|
||||
this.spring.configLocations(this.xml("WithCustomAttributes")).autowire();
|
||||
String expectedContent = "<!DOCTYPE html>\n" + "<html lang=\"en\">\n" + " <head>\n"
|
||||
// @formatter:off
|
||||
String expectedContent = "<!DOCTYPE html>\n"
|
||||
+ "<html lang=\"en\">\n"
|
||||
+ " <head>\n"
|
||||
+ " <meta charset=\"utf-8\">\n"
|
||||
+ " <meta name=\"viewport\" content=\"width=device-width, initial-scale=1, shrink-to-fit=no\">\n"
|
||||
+ " <meta name=\"description\" content=\"\">\n" + " <meta name=\"author\" content=\"\">\n"
|
||||
+ " <meta name=\"description\" content=\"\">\n"
|
||||
+ " <meta name=\"author\" content=\"\">\n"
|
||||
+ " <title>Please sign in</title>\n"
|
||||
+ " <link href=\"https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-beta/css/bootstrap.min.css\" rel=\"stylesheet\" integrity=\"sha384-/Y6pD6FV/Vv2HJnA6t+vslU6fwYXjCFtcEpHbNJ0lyAFsXTsjBbfaDjzALeQsN6M\" crossorigin=\"anonymous\">\n"
|
||||
+ " <link href=\"https://getbootstrap.com/docs/4.0/examples/signin/signin.css\" rel=\"stylesheet\" crossorigin=\"anonymous\"/>\n"
|
||||
+ " </head>\n" + " <body>\n" + " <div class=\"container\">\n"
|
||||
+ " </head>\n"
|
||||
+ " <body>\n"
|
||||
+ " <div class=\"container\">\n"
|
||||
+ " <form class=\"form-signin\" method=\"post\" action=\"/signin\">\n"
|
||||
+ " <h2 class=\"form-signin-heading\">Please sign in</h2>\n" + " <p>\n"
|
||||
+ " <h2 class=\"form-signin-heading\">Please sign in</h2>\n"
|
||||
+ " <p>\n"
|
||||
+ " <label for=\"username\" class=\"sr-only\">Username</label>\n"
|
||||
+ " <input type=\"text\" id=\"username\" name=\"custom_user\" class=\"form-control\" placeholder=\"Username\" required autofocus>\n"
|
||||
+ " </p>\n" + " <p>\n"
|
||||
+ " </p>\n"
|
||||
+ " <p>\n"
|
||||
+ " <label for=\"password\" class=\"sr-only\">Password</label>\n"
|
||||
+ " <input type=\"password\" id=\"password\" name=\"custom_pass\" class=\"form-control\" placeholder=\"Password\" required>\n"
|
||||
+ " </p>\n"
|
||||
+ " <button class=\"btn btn-lg btn-primary btn-block\" type=\"submit\">Sign in</button>\n"
|
||||
+ " </form>\n" + "</div>\n" + "</body></html>";
|
||||
this.mvc.perform(get("/login")).andExpect(content().string(expectedContent));
|
||||
this.mvc.perform(get("/logout")).andExpect(status().is3xxRedirection());
|
||||
+ " </form>\n"
|
||||
+ "</div>\n"
|
||||
+ "</body></html>";
|
||||
this.mvc.perform(get("/login"))
|
||||
.andExpect(content().string(expectedContent));
|
||||
this.mvc.perform(get("/logout"))
|
||||
.andExpect(status().is3xxRedirection());
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getLoginWhenConfiguredForOpenIdThenLoginPageReflects() throws Exception {
|
||||
this.spring.configLocations(this.xml("WithOpenId")).autowire();
|
||||
String expectedContent = "<!DOCTYPE html>\n" + "<html lang=\"en\">\n" + " <head>\n"
|
||||
// @formatter:off
|
||||
String expectedContent = "<!DOCTYPE html>\n"
|
||||
+ "<html lang=\"en\">\n"
|
||||
+ " <head>\n"
|
||||
+ " <meta charset=\"utf-8\">\n"
|
||||
+ " <meta name=\"viewport\" content=\"width=device-width, initial-scale=1, shrink-to-fit=no\">\n"
|
||||
+ " <meta name=\"description\" content=\"\">\n" + " <meta name=\"author\" content=\"\">\n"
|
||||
+ " <meta name=\"description\" content=\"\">\n"
|
||||
+ " <meta name=\"author\" content=\"\">\n"
|
||||
+ " <title>Please sign in</title>\n"
|
||||
+ " <link href=\"https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-beta/css/bootstrap.min.css\" rel=\"stylesheet\" integrity=\"sha384-/Y6pD6FV/Vv2HJnA6t+vslU6fwYXjCFtcEpHbNJ0lyAFsXTsjBbfaDjzALeQsN6M\" crossorigin=\"anonymous\">\n"
|
||||
+ " <link href=\"https://getbootstrap.com/docs/4.0/examples/signin/signin.css\" rel=\"stylesheet\" crossorigin=\"anonymous\"/>\n"
|
||||
+ " </head>\n" + " <body>\n" + " <div class=\"container\">\n"
|
||||
+ " </head>\n"
|
||||
+ " <body>\n"
|
||||
+ " <div class=\"container\">\n"
|
||||
+ " <form class=\"form-signin\" method=\"post\" action=\"/login\">\n"
|
||||
+ " <h2 class=\"form-signin-heading\">Please sign in</h2>\n" + " <p>\n"
|
||||
+ " <h2 class=\"form-signin-heading\">Please sign in</h2>\n"
|
||||
+ " <p>\n"
|
||||
+ " <label for=\"username\" class=\"sr-only\">Username</label>\n"
|
||||
+ " <input type=\"text\" id=\"username\" name=\"username\" class=\"form-control\" placeholder=\"Username\" required autofocus>\n"
|
||||
+ " </p>\n" + " <p>\n"
|
||||
+ " </p>\n"
|
||||
+ " <p>\n"
|
||||
+ " <label for=\"password\" class=\"sr-only\">Password</label>\n"
|
||||
+ " <input type=\"password\" id=\"password\" name=\"password\" class=\"form-control\" placeholder=\"Password\" required>\n"
|
||||
+ " </p>\n"
|
||||
+ " <button class=\"btn btn-lg btn-primary btn-block\" type=\"submit\">Sign in</button>\n"
|
||||
+ " </form>\n"
|
||||
+ " <form name=\"oidf\" class=\"form-signin\" method=\"post\" action=\"/login/openid\">\n"
|
||||
+ " <h2 class=\"form-signin-heading\">Login with OpenID Identity</h2>\n" + " <p>\n"
|
||||
+ " <h2 class=\"form-signin-heading\">Login with OpenID Identity</h2>\n"
|
||||
+ " <p>\n"
|
||||
+ " <label for=\"username\" class=\"sr-only\">Identity</label>\n"
|
||||
+ " <input type=\"text\" id=\"username\" name=\"openid_identifier\" class=\"form-control\" placeholder=\"Username\" required autofocus>\n"
|
||||
+ " </p>\n"
|
||||
+ " <button class=\"btn btn-lg btn-primary btn-block\" type=\"submit\">Sign in</button>\n"
|
||||
+ " </form>\n" + "</div>\n" + "</body></html>";
|
||||
+ " </form>\n"
|
||||
+ "</div>\n"
|
||||
+ "</body></html>";
|
||||
// @formatter:on
|
||||
this.mvc.perform(get("/login")).andExpect(content().string(expectedContent));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getLoginWhenConfiguredForOpenIdWithCustomAttributesThenLoginPageReflects() throws Exception {
|
||||
this.spring.configLocations(this.xml("WithOpenIdCustomAttributes")).autowire();
|
||||
String expectedContent = "<!DOCTYPE html>\n" + "<html lang=\"en\">\n" + " <head>\n"
|
||||
// @formatter:off
|
||||
String expectedContent = "<!DOCTYPE html>\n"
|
||||
+ "<html lang=\"en\">\n"
|
||||
+ " <head>\n"
|
||||
+ " <meta charset=\"utf-8\">\n"
|
||||
+ " <meta name=\"viewport\" content=\"width=device-width, initial-scale=1, shrink-to-fit=no\">\n"
|
||||
+ " <meta name=\"description\" content=\"\">\n" + " <meta name=\"author\" content=\"\">\n"
|
||||
+ " <meta name=\"description\" content=\"\">\n"
|
||||
+ " <meta name=\"author\" content=\"\">\n"
|
||||
+ " <title>Please sign in</title>\n"
|
||||
+ " <link href=\"https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-beta/css/bootstrap.min.css\" rel=\"stylesheet\" integrity=\"sha384-/Y6pD6FV/Vv2HJnA6t+vslU6fwYXjCFtcEpHbNJ0lyAFsXTsjBbfaDjzALeQsN6M\" crossorigin=\"anonymous\">\n"
|
||||
+ " <link href=\"https://getbootstrap.com/docs/4.0/examples/signin/signin.css\" rel=\"stylesheet\" crossorigin=\"anonymous\"/>\n"
|
||||
+ " </head>\n" + " <body>\n" + " <div class=\"container\">\n"
|
||||
+ " </head>\n"
|
||||
+ " <body>\n"
|
||||
+ " <div class=\"container\">\n"
|
||||
+ " <form class=\"form-signin\" method=\"post\" action=\"/login\">\n"
|
||||
+ " <h2 class=\"form-signin-heading\">Please sign in</h2>\n" + " <p>\n"
|
||||
+ " <h2 class=\"form-signin-heading\">Please sign in</h2>\n"
|
||||
+ " <p>\n"
|
||||
+ " <label for=\"username\" class=\"sr-only\">Username</label>\n"
|
||||
+ " <input type=\"text\" id=\"username\" name=\"username\" class=\"form-control\" placeholder=\"Username\" required autofocus>\n"
|
||||
+ " </p>\n" + " <p>\n"
|
||||
+ " </p>\n"
|
||||
+ " <p>\n"
|
||||
+ " <label for=\"password\" class=\"sr-only\">Password</label>\n"
|
||||
+ " <input type=\"password\" id=\"password\" name=\"password\" class=\"form-control\" placeholder=\"Password\" required>\n"
|
||||
+ " </p>\n"
|
||||
|
@ -161,23 +206,38 @@ public class FormLoginBeanDefinitionParserTests {
|
|||
+ " <input type=\"text\" id=\"username\" name=\"openid_identifier\" class=\"form-control\" placeholder=\"Username\" required autofocus>\n"
|
||||
+ " </p>\n"
|
||||
+ " <button class=\"btn btn-lg btn-primary btn-block\" type=\"submit\">Sign in</button>\n"
|
||||
+ " </form>\n" + "</div>\n" + "</body></html>";
|
||||
+ " </form>\n"
|
||||
+ "</div>\n"
|
||||
+ "</body></html>";
|
||||
// @formatter:on
|
||||
this.mvc.perform(get("/login")).andExpect(content().string(expectedContent));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void failedLoginWhenConfiguredWithCustomAuthenticationFailureThenForwardsAccordingly() throws Exception {
|
||||
this.spring.configLocations(this.xml("WithAuthenticationFailureForwardUrl")).autowire();
|
||||
this.mvc.perform(post("/login").param("username", "bob").param("password", "invalidpassword"))
|
||||
.andExpect(status().isOk()).andExpect(forwardedUrl("/failure_forward_url"))
|
||||
// @formatter:off
|
||||
MockHttpServletRequestBuilder loginRequest = post("/login")
|
||||
.param("username", "bob")
|
||||
.param("password", "invalidpassword");
|
||||
this.mvc.perform(loginRequest)
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(forwardedUrl("/failure_forward_url"))
|
||||
.andExpect(request().attribute(WebAttributes.AUTHENTICATION_EXCEPTION, not(nullValue())));
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
public void successfulLoginWhenConfiguredWithCustomAuthenticationSuccessThenForwardsAccordingly() throws Exception {
|
||||
this.spring.configLocations(this.xml("WithAuthenticationSuccessForwardUrl")).autowire();
|
||||
this.mvc.perform(post("/login").param("username", "user").param("password", "password"))
|
||||
.andExpect(status().isOk()).andExpect(forwardedUrl("/success_forward_url"));
|
||||
// @formatter:off
|
||||
MockHttpServletRequestBuilder loginRequest = post("/login")
|
||||
.param("username", "user")
|
||||
.param("password", "password");
|
||||
this.mvc.perform(loginRequest)
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(forwardedUrl("/success_forward_url"));
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
private String xml(String configName) {
|
||||
|
|
|
@ -38,6 +38,7 @@ import org.springframework.security.web.authentication.AuthenticationFailureHand
|
|||
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
|
||||
import org.springframework.security.web.authentication.ui.DefaultLoginPageGeneratingFilter;
|
||||
import org.springframework.test.web.servlet.MockMvc;
|
||||
import org.springframework.test.web.servlet.request.MockHttpServletRequestBuilder;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
|
@ -67,24 +68,44 @@ public class FormLoginConfigTests {
|
|||
@Test
|
||||
public void getProtectedPageWhenFormLoginConfiguredThenRedirectsToDefaultLoginPage() throws Exception {
|
||||
this.spring.configLocations(this.xml("WithAntRequestMatcher")).autowire();
|
||||
this.mvc.perform(get("/")).andExpect(redirectedUrl("http://localhost/login"));
|
||||
// @formatter:off
|
||||
this.mvc.perform(get("/"))
|
||||
.andExpect(redirectedUrl("http://localhost/login"));
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
public void authenticateWhenDefaultTargetUrlConfiguredThenRedirectsAccordingly() throws Exception {
|
||||
this.spring.configLocations(this.xml("WithDefaultTargetUrl")).autowire();
|
||||
this.mvc.perform(post("/login").param("username", "user").param("password", "password").with(csrf()))
|
||||
// @formatter:off
|
||||
MockHttpServletRequestBuilder loginRequest = post("/login")
|
||||
.param("username", "user")
|
||||
.param("password", "password")
|
||||
.with(csrf());
|
||||
this.mvc.perform(loginRequest)
|
||||
.andExpect(redirectedUrl("/default"));
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
public void authenticateWhenConfiguredWithSpelThenRedirectsAccordingly() throws Exception {
|
||||
this.spring.configLocations(this.xml("UsingSpel")).autowire();
|
||||
this.mvc.perform(post("/login").param("username", "user").param("password", "password").with(csrf()))
|
||||
// @formatter:off
|
||||
MockHttpServletRequestBuilder loginRequest = post("/login")
|
||||
.param("username", "user")
|
||||
.param("password", "password")
|
||||
.with(csrf());
|
||||
this.mvc.perform(loginRequest)
|
||||
.andExpect(redirectedUrl(WebConfigUtilsTests.URL + "/default"));
|
||||
this.mvc.perform(post("/login").param("username", "user").param("password", "wrong").with(csrf()))
|
||||
MockHttpServletRequestBuilder invalidPassword = post("/login")
|
||||
.param("username", "user")
|
||||
.param("password", "wrong")
|
||||
.with(csrf());
|
||||
this.mvc.perform(invalidPassword)
|
||||
.andExpect(redirectedUrl(WebConfigUtilsTests.URL + "/failure"));
|
||||
this.mvc.perform(get("/")).andExpect(redirectedUrl("http://localhost" + WebConfigUtilsTests.URL + "/login"));
|
||||
this.mvc.perform(get("/"))
|
||||
.andExpect(redirectedUrl("http://localhost" + WebConfigUtilsTests.URL + "/login"));
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -102,10 +123,20 @@ public class FormLoginConfigTests {
|
|||
@Test
|
||||
public void authenticateWhenCustomHandlerBeansConfiguredThenInvokesAccordingly() throws Exception {
|
||||
this.spring.configLocations(this.xml("WithSuccessAndFailureHandlers")).autowire();
|
||||
this.mvc.perform(post("/login").param("username", "user").param("password", "password").with(csrf()))
|
||||
// @formatter:off
|
||||
MockHttpServletRequestBuilder loginRequest = post("/login")
|
||||
.param("username", "user")
|
||||
.param("password", "password")
|
||||
.with(csrf());
|
||||
this.mvc.perform(loginRequest)
|
||||
.andExpect(status().isIAmATeapot());
|
||||
this.mvc.perform(post("/login").param("username", "user").param("password", "wrong").with(csrf()))
|
||||
MockHttpServletRequestBuilder invalidPassword = post("/login")
|
||||
.param("username", "user")
|
||||
.param("password", "wrong")
|
||||
.with(csrf());
|
||||
this.mvc.perform(invalidPassword)
|
||||
.andExpect(status().isIAmATeapot());
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -129,15 +160,25 @@ public class FormLoginConfigTests {
|
|||
@Test
|
||||
public void authenticateWhenCsrfIsEnabledThenRequiresToken() throws Exception {
|
||||
this.spring.configLocations(this.xml("WithCsrfEnabled")).autowire();
|
||||
this.mvc.perform(post("/login").param("username", "user").param("password", "password"))
|
||||
// @formatter:off
|
||||
MockHttpServletRequestBuilder loginRequest = post("/login")
|
||||
.param("username", "user")
|
||||
.param("password", "password");
|
||||
this.mvc.perform(loginRequest)
|
||||
.andExpect(status().isForbidden());
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
public void authenticateWhenCsrfIsDisabledThenDoesNotRequireToken() throws Exception {
|
||||
this.spring.configLocations(this.xml("WithCsrfDisabled")).autowire();
|
||||
this.mvc.perform(post("/login").param("username", "user").param("password", "password"))
|
||||
// @formatter:off
|
||||
MockHttpServletRequestBuilder loginRequest = post("/login")
|
||||
.param("username", "user")
|
||||
.param("password", "password");
|
||||
this.mvc.perform(loginRequest)
|
||||
.andExpect(status().isFound());
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -148,8 +189,14 @@ public class FormLoginConfigTests {
|
|||
public void authenticateWhenLoginPageIsSlashLoginAndAuthenticationFailsThenRedirectContainsErrorParameter()
|
||||
throws Exception {
|
||||
this.spring.configLocations(this.xml("ForSec3147")).autowire();
|
||||
this.mvc.perform(post("/login").param("username", "user").param("password", "wrong").with(csrf()))
|
||||
// @formatter:off
|
||||
MockHttpServletRequestBuilder loginRequest = post("/login")
|
||||
.param("username", "user")
|
||||
.param("password", "wrong")
|
||||
.with(csrf());
|
||||
this.mvc.perform(loginRequest)
|
||||
.andExpect(redirectedUrl("/login?error"));
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
private Filter getFilter(ApplicationContext context, Class<? extends Filter> filterClass) {
|
||||
|
|
|
@ -52,7 +52,11 @@ public class HttpConfigTests {
|
|||
@Test
|
||||
public void getWhenUsingMinimalConfigurationThenRedirectsToLogin() throws Exception {
|
||||
this.spring.configLocations(this.xml("Minimal")).autowire();
|
||||
this.mvc.perform(get("/")).andExpect(status().isFound()).andExpect(redirectedUrl("http://localhost/login"));
|
||||
// @formatter:off
|
||||
this.mvc.perform(get("/"))
|
||||
.andExpect(status().isFound())
|
||||
.andExpect(redirectedUrl("http://localhost/login"));
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
|
@ -68,28 +68,40 @@ public class HttpCorsConfigTests {
|
|||
@Test
|
||||
public void getWhenUsingCorsThenDoesSpringSecurityCorsHandshake() throws Exception {
|
||||
this.spring.configLocations(this.xml("WithCors")).autowire();
|
||||
this.mvc.perform(get("/").with(this.approved())).andExpect(corsResponseHeaders())
|
||||
// @formatter:off
|
||||
this.mvc.perform(get("/").with(this.approved()))
|
||||
.andExpect(corsResponseHeaders())
|
||||
.andExpect((status().isIAmATeapot()));
|
||||
this.mvc.perform(options("/").with(this.preflight())).andExpect(corsResponseHeaders())
|
||||
this.mvc.perform(options("/").with(this.preflight()))
|
||||
.andExpect(corsResponseHeaders())
|
||||
.andExpect(status().isOk());
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getWhenUsingCustomCorsConfigurationSourceThenDoesSpringSecurityCorsHandshake() throws Exception {
|
||||
this.spring.configLocations(this.xml("WithCorsConfigurationSource")).autowire();
|
||||
this.mvc.perform(get("/").with(this.approved())).andExpect(corsResponseHeaders())
|
||||
// @formatter:off
|
||||
this.mvc.perform(get("/").with(this.approved()))
|
||||
.andExpect(corsResponseHeaders())
|
||||
.andExpect((status().isIAmATeapot()));
|
||||
this.mvc.perform(options("/").with(this.preflight())).andExpect(corsResponseHeaders())
|
||||
this.mvc.perform(options("/").with(this.preflight()))
|
||||
.andExpect(corsResponseHeaders())
|
||||
.andExpect(status().isOk());
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getWhenUsingCustomCorsFilterThenDoesSPringSecurityCorsHandshake() throws Exception {
|
||||
this.spring.configLocations(this.xml("WithCorsFilter")).autowire();
|
||||
this.mvc.perform(get("/").with(this.approved())).andExpect(corsResponseHeaders())
|
||||
// @formatter:off
|
||||
this.mvc.perform(get("/").with(this.approved()))
|
||||
.andExpect(corsResponseHeaders())
|
||||
.andExpect((status().isIAmATeapot()));
|
||||
this.mvc.perform(options("/").with(this.preflight())).andExpect(corsResponseHeaders())
|
||||
this.mvc.perform(options("/").with(this.preflight()))
|
||||
.andExpect(corsResponseHeaders())
|
||||
.andExpect(status().isOk());
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
private String xml(String configName) {
|
||||
|
|
|
@ -51,11 +51,16 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.
|
|||
public class HttpHeadersConfigTests {
|
||||
|
||||
private static final String CONFIG_LOCATION_PREFIX = "classpath:org/springframework/security/config/http/HttpHeadersConfigTests";
|
||||
// @formatter:off
|
||||
static final Map<String, String> defaultHeaders = ImmutableMap.<String, String>builder()
|
||||
.put("X-Content-Type-Options", "nosniff").put("X-Frame-Options", "DENY")
|
||||
.put("Strict-Transport-Security", "max-age=31536000 ; includeSubDomains")
|
||||
.put("Cache-Control", "no-cache, no-store, max-age=0, must-revalidate").put("Expires", "0")
|
||||
.put("Pragma", "no-cache").put("X-XSS-Protection", "1; mode=block").build();
|
||||
.put("Cache-Control", "no-cache, no-store, max-age=0, must-revalidate")
|
||||
.put("Expires", "0")
|
||||
.put("Pragma", "no-cache")
|
||||
.put("X-XSS-Protection", "1; mode=block")
|
||||
.build();
|
||||
// @formatter:on
|
||||
|
||||
@Rule
|
||||
public final SpringTestRule spring = new SpringTestRule();
|
||||
|
@ -66,28 +71,44 @@ public class HttpHeadersConfigTests {
|
|||
@Test
|
||||
public void requestWhenHeadersDisabledThenResponseExcludesAllSecureHeaders() throws Exception {
|
||||
this.spring.configLocations(this.xml("HeadersDisabled")).autowire();
|
||||
this.mvc.perform(get("/")).andExpect(status().isOk()).andExpect(excludesDefaults());
|
||||
// @formatter:off
|
||||
this.mvc.perform(get("/"))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(excludesDefaults());
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
public void requestWhenHeadersDisabledViaPlaceholderThenResponseExcludesAllSecureHeaders() throws Exception {
|
||||
System.setProperty("security.headers.disabled", "true");
|
||||
this.spring.configLocations(this.xml("DisabledWithPlaceholder")).autowire();
|
||||
this.mvc.perform(get("/").secure(true)).andExpect(status().isOk()).andExpect(excludesDefaults());
|
||||
// @formatter:off
|
||||
this.mvc.perform(get("/").secure(true))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(excludesDefaults());
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
public void requestWhenHeadersEnabledViaPlaceholderThenResponseIncludesAllSecureHeaders() throws Exception {
|
||||
System.setProperty("security.headers.disabled", "false");
|
||||
this.spring.configLocations(this.xml("DisabledWithPlaceholder")).autowire();
|
||||
this.mvc.perform(get("/").secure(true)).andExpect(status().isOk()).andExpect(includesDefaults());
|
||||
// @formatter:off
|
||||
this.mvc.perform(get("/").secure(true))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(includesDefaults());
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
public void requestWhenHeadersDisabledRefMissingPlaceholderThenResponseIncludesAllSecureHeaders() throws Exception {
|
||||
System.clearProperty("security.headers.disabled");
|
||||
this.spring.configLocations(this.xml("DisabledWithPlaceholder")).autowire();
|
||||
this.mvc.perform(get("/").secure(true)).andExpect(status().isOk()).andExpect(includesDefaults());
|
||||
// @formatter:off
|
||||
this.mvc.perform(get("/").secure(true))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(includesDefaults());
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -100,13 +121,21 @@ public class HttpHeadersConfigTests {
|
|||
@Test
|
||||
public void requestWhenHeadersEnabledThenResponseContainsAllSecureHeaders() throws Exception {
|
||||
this.spring.configLocations(this.xml("DefaultConfig")).autowire();
|
||||
this.mvc.perform(get("/").secure(true)).andExpect(status().isOk()).andExpect(includesDefaults());
|
||||
// @formatter:off
|
||||
this.mvc.perform(get("/").secure(true))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(includesDefaults());
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
public void requestWhenHeadersElementUsedThenResponseContainsAllSecureHeaders() throws Exception {
|
||||
this.spring.configLocations(this.xml("HeadersEnabled")).autowire();
|
||||
this.mvc.perform(get("/").secure(true)).andExpect(status().isOk()).andExpect(includesDefaults());
|
||||
// @formatter:off
|
||||
this.mvc.perform(get("/").secure(true))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(includesDefaults());
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -114,7 +143,11 @@ public class HttpHeadersConfigTests {
|
|||
Map<String, String> headers = new HashMap(defaultHeaders);
|
||||
headers.put("X-Frame-Options", "SAMEORIGIN");
|
||||
this.spring.configLocations(this.xml("WithFrameOptions")).autowire();
|
||||
this.mvc.perform(get("/").secure(true)).andExpect(status().isOk()).andExpect(includes(headers));
|
||||
// @formatter:off
|
||||
this.mvc.perform(get("/").secure(true))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(includes(headers));
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -123,28 +156,44 @@ public class HttpHeadersConfigTests {
|
|||
@Test
|
||||
public void requestWhenDefaultsDisabledWithNoOverrideThenExcludesAllSecureHeaders() throws Exception {
|
||||
this.spring.configLocations(this.xml("DefaultsDisabledWithNoOverride")).autowire();
|
||||
this.mvc.perform(get("/").secure(true)).andExpect(status().isOk()).andExpect(excludesDefaults());
|
||||
// @formatter:off
|
||||
this.mvc.perform(get("/").secure(true))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(excludesDefaults());
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
public void requestWhenDefaultsDisabledWithPlaceholderTrueThenExcludesAllSecureHeaders() throws Exception {
|
||||
System.setProperty("security.headers.defaults.disabled", "true");
|
||||
this.spring.configLocations(this.xml("DefaultsDisabledWithPlaceholder")).autowire();
|
||||
this.mvc.perform(get("/").secure(true)).andExpect(status().isOk()).andExpect(excludesDefaults());
|
||||
// @formatter:off
|
||||
this.mvc.perform(get("/").secure(true))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(excludesDefaults());
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
public void requestWhenDefaultsDisabledWithPlaceholderFalseThenIncludeAllSecureHeaders() throws Exception {
|
||||
System.setProperty("security.headers.defaults.disabled", "false");
|
||||
this.spring.configLocations(this.xml("DefaultsDisabledWithPlaceholder")).autowire();
|
||||
this.mvc.perform(get("/").secure(true)).andExpect(status().isOk()).andExpect(includesDefaults());
|
||||
// @formatter:off
|
||||
this.mvc.perform(get("/").secure(true))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(includesDefaults());
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
public void requestWhenDefaultsDisabledWithPlaceholderMissingThenIncludeAllSecureHeaders() throws Exception {
|
||||
System.clearProperty("security.headers.defaults.disabled");
|
||||
this.spring.configLocations(this.xml("DefaultsDisabledWithPlaceholder")).autowire();
|
||||
this.mvc.perform(get("/").secure(true)).andExpect(status().isOk()).andExpect(includesDefaults());
|
||||
// @formatter:off
|
||||
this.mvc.perform(get("/").secure(true))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(includesDefaults());
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -152,8 +201,12 @@ public class HttpHeadersConfigTests {
|
|||
Set<String> excludedHeaders = new HashSet<>(defaultHeaders.keySet());
|
||||
excludedHeaders.remove("X-Content-Type-Options");
|
||||
this.spring.configLocations(this.xml("DefaultsDisabledWithContentTypeOptions")).autowire();
|
||||
this.mvc.perform(get("/")).andExpect(status().isOk())
|
||||
.andExpect(header().string("X-Content-Type-Options", "nosniff")).andExpect(excludes(excludedHeaders));
|
||||
// @formatter:off
|
||||
this.mvc.perform(get("/"))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(header().string("X-Content-Type-Options", "nosniff"))
|
||||
.andExpect(excludes(excludedHeaders));
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -161,8 +214,12 @@ public class HttpHeadersConfigTests {
|
|||
Set<String> excludedHeaders = new HashSet<>(defaultHeaders.keySet());
|
||||
excludedHeaders.remove("X-Frame-Options");
|
||||
this.spring.configLocations(this.xml("DefaultsDisabledWithFrameOptions")).autowire();
|
||||
this.mvc.perform(get("/")).andExpect(status().isOk()).andExpect(header().string("X-Frame-Options", "DENY"))
|
||||
// @formatter:off
|
||||
this.mvc.perform(get("/"))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(header().string("X-Frame-Options", "DENY"))
|
||||
.andExpect(excludes(excludedHeaders));
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -170,8 +227,12 @@ public class HttpHeadersConfigTests {
|
|||
Set<String> excludedHeaders = new HashSet<>(defaultHeaders.keySet());
|
||||
excludedHeaders.remove("X-Frame-Options");
|
||||
this.spring.configLocations(this.xml("DefaultsDisabledWithFrameOptionsDeny")).autowire();
|
||||
this.mvc.perform(get("/")).andExpect(status().isOk()).andExpect(header().string("X-Frame-Options", "DENY"))
|
||||
// @formatter:off
|
||||
this.mvc.perform(get("/"))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(header().string("X-Frame-Options", "DENY"))
|
||||
.andExpect(excludes(excludedHeaders));
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -179,8 +240,12 @@ public class HttpHeadersConfigTests {
|
|||
Set<String> excludedHeaders = new HashSet<>(defaultHeaders.keySet());
|
||||
excludedHeaders.remove("X-Frame-Options");
|
||||
this.spring.configLocations(this.xml("DefaultsDisabledWithFrameOptionsSameOrigin")).autowire();
|
||||
this.mvc.perform(get("/")).andExpect(status().isOk())
|
||||
.andExpect(header().string("X-Frame-Options", "SAMEORIGIN")).andExpect(excludes(excludedHeaders));
|
||||
// @formatter:off
|
||||
this.mvc.perform(get("/"))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(header().string("X-Frame-Options", "SAMEORIGIN"))
|
||||
.andExpect(excludes(excludedHeaders));
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -206,9 +271,12 @@ public class HttpHeadersConfigTests {
|
|||
Set<String> excludedHeaders = new HashSet<>(defaultHeaders.keySet());
|
||||
excludedHeaders.remove("X-Frame-Options");
|
||||
this.spring.configLocations(this.xml("DefaultsDisabledWithFrameOptionsAllowFrom")).autowire();
|
||||
this.mvc.perform(get("/")).andExpect(status().isOk())
|
||||
// @formatter:off
|
||||
this.mvc.perform(get("/"))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(header().string("X-Frame-Options", "ALLOW-FROM https://example.org"))
|
||||
.andExpect(excludes(excludedHeaders));
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -216,25 +284,39 @@ public class HttpHeadersConfigTests {
|
|||
Set<String> excludedHeaders = new HashSet<>(defaultHeaders.keySet());
|
||||
excludedHeaders.remove("X-Frame-Options");
|
||||
this.spring.configLocations(this.xml("DefaultsDisabledWithFrameOptionsAllowFromWhitelist")).autowire();
|
||||
this.mvc.perform(get("/").param("from", "https://example.org")).andExpect(status().isOk())
|
||||
// @formatter:off
|
||||
this.mvc.perform(get("/").param("from", "https://example.org"))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(header().string("X-Frame-Options", "ALLOW-FROM https://example.org"))
|
||||
.andExpect(excludes(excludedHeaders));
|
||||
this.mvc.perform(get("/")).andExpect(status().isOk()).andExpect(header().string("X-Frame-Options", "DENY"))
|
||||
this.mvc.perform(get("/"))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(header().string("X-Frame-Options", "DENY"))
|
||||
.andExpect(excludes(excludedHeaders));
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
public void requestWhenUsingCustomHeaderThenRespondsWithThatHeader() throws Exception {
|
||||
this.spring.configLocations(this.xml("DefaultsDisabledWithCustomHeader")).autowire();
|
||||
this.mvc.perform(get("/")).andExpect(status().isOk()).andExpect(header().string("a", "b"))
|
||||
.andExpect(header().string("c", "d")).andExpect(excludesDefaults());
|
||||
// @formatter:off
|
||||
this.mvc.perform(get("/"))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(header().string("a", "b"))
|
||||
.andExpect(header().string("c", "d"))
|
||||
.andExpect(excludesDefaults());
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
public void requestWhenUsingCustomHeaderWriterThenRespondsWithThatHeader() throws Exception {
|
||||
this.spring.configLocations(this.xml("DefaultsDisabledWithCustomHeaderWriter")).autowire();
|
||||
this.mvc.perform(get("/")).andExpect(status().isOk()).andExpect(header().string("abc", "def"))
|
||||
// @formatter:off
|
||||
this.mvc.perform(get("/"))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(header().string("abc", "def"))
|
||||
.andExpect(excludesDefaults());
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -254,8 +336,12 @@ public class HttpHeadersConfigTests {
|
|||
Set<String> excludedHeaders = new HashSet<>(defaultHeaders.keySet());
|
||||
excludedHeaders.remove("X-XSS-Protection");
|
||||
this.spring.configLocations(this.xml("DefaultsDisabledWithXssProtection")).autowire();
|
||||
this.mvc.perform(get("/")).andExpect(status().isOk())
|
||||
.andExpect(header().string("X-XSS-Protection", "1; mode=block")).andExpect(excludes(excludedHeaders));
|
||||
// @formatter:off
|
||||
this.mvc.perform(get("/"))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(header().string("X-XSS-Protection", "1; mode=block"))
|
||||
.andExpect(excludes(excludedHeaders));
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -263,8 +349,12 @@ public class HttpHeadersConfigTests {
|
|||
Set<String> excludedHeaders = new HashSet<>(defaultHeaders.keySet());
|
||||
excludedHeaders.remove("X-XSS-Protection");
|
||||
this.spring.configLocations(this.xml("DefaultsDisabledWithXssProtectionEnabled")).autowire();
|
||||
this.mvc.perform(get("/")).andExpect(status().isOk())
|
||||
.andExpect(header().string("X-XSS-Protection", "1; mode=block")).andExpect(excludes(excludedHeaders));
|
||||
// @formatter:off
|
||||
this.mvc.perform(get("/"))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(header().string("X-XSS-Protection", "1; mode=block"))
|
||||
.andExpect(excludes(excludedHeaders));
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -272,8 +362,12 @@ public class HttpHeadersConfigTests {
|
|||
Set<String> excludedHeaders = new HashSet<>(defaultHeaders.keySet());
|
||||
excludedHeaders.remove("X-XSS-Protection");
|
||||
this.spring.configLocations(this.xml("DefaultsDisabledWithXssProtectionDisabled")).autowire();
|
||||
this.mvc.perform(get("/")).andExpect(status().isOk()).andExpect(header().string("X-XSS-Protection", "0"))
|
||||
// @formatter:off
|
||||
this.mvc.perform(get("/"))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(header().string("X-XSS-Protection", "0"))
|
||||
.andExpect(excludes(excludedHeaders));
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -290,7 +384,11 @@ public class HttpHeadersConfigTests {
|
|||
.put("Cache-Control", "no-cache, no-store, max-age=0, must-revalidate").put("Expires", "0")
|
||||
.put("Pragma", "no-cache").build();
|
||||
this.spring.configLocations(this.xml("DefaultsDisabledWithCacheControl")).autowire();
|
||||
this.mvc.perform(get("/")).andExpect(status().isOk()).andExpect(includes(includedHeaders));
|
||||
// @formatter:off
|
||||
this.mvc.perform(get("/"))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(includes(includedHeaders));
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -298,15 +396,22 @@ public class HttpHeadersConfigTests {
|
|||
Set<String> excludedHeaders = new HashSet<>(defaultHeaders.keySet());
|
||||
excludedHeaders.remove("Strict-Transport-Security");
|
||||
this.spring.configLocations(this.xml("DefaultsDisabledWithHsts")).autowire();
|
||||
this.mvc.perform(get("/").secure(true)).andExpect(status().isOk())
|
||||
// @formatter:off
|
||||
this.mvc.perform(get("/").secure(true))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(header().string("Strict-Transport-Security", "max-age=31536000 ; includeSubDomains"))
|
||||
.andExpect(excludes(excludedHeaders));
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
public void insecureRequestWhenUsingHstsThenExcludesHstsHeader() throws Exception {
|
||||
this.spring.configLocations(this.xml("DefaultsDisabledWithHsts")).autowire();
|
||||
this.mvc.perform(get("/")).andExpect(status().isOk()).andExpect(excludesDefaults());
|
||||
// @formatter:off
|
||||
this.mvc.perform(get("/"))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(excludesDefaults());
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -314,9 +419,12 @@ public class HttpHeadersConfigTests {
|
|||
Set<String> excludedHeaders = new HashSet<>(defaultHeaders.keySet());
|
||||
excludedHeaders.remove("Strict-Transport-Security");
|
||||
this.spring.configLocations(this.xml("DefaultsDisabledWithCustomHstsRequestMatcher")).autowire();
|
||||
this.mvc.perform(get("/")).andExpect(status().isOk())
|
||||
// @formatter:off
|
||||
this.mvc.perform(get("/"))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(header().string("Strict-Transport-Security", "max-age=1"))
|
||||
.andExpect(excludes(excludedHeaders));
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -336,62 +444,84 @@ public class HttpHeadersConfigTests {
|
|||
@Test
|
||||
public void requestWhenUsingHpkpThenIncludesHpkpHeader() throws Exception {
|
||||
this.spring.configLocations(this.xml("DefaultsDisabledWithHpkp")).autowire();
|
||||
this.mvc.perform(get("/").secure(true)).andExpect(status().isOk())
|
||||
// @formatter:off
|
||||
this.mvc.perform(get("/").secure(true))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(header().string("Public-Key-Pins-Report-Only",
|
||||
"max-age=5184000 ; pin-sha256=\"d6qzRu9zOECb90Uez27xWltNsj0e1Md7GkYYkVoZWmM=\""))
|
||||
.andExpect(excludesDefaults());
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
public void requestWhenUsingHpkpDefaultsThenIncludesHpkpHeaderUsingSha256() throws Exception {
|
||||
this.spring.configLocations(this.xml("DefaultsDisabledWithHpkpDefaults")).autowire();
|
||||
this.mvc.perform(get("/").secure(true)).andExpect(status().isOk())
|
||||
// @formatter:off
|
||||
this.mvc.perform(get("/").secure(true))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(header().string("Public-Key-Pins-Report-Only",
|
||||
"max-age=5184000 ; pin-sha256=\"d6qzRu9zOECb90Uez27xWltNsj0e1Md7GkYYkVoZWmM=\""))
|
||||
.andExpect(excludesDefaults());
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
public void insecureRequestWhenUsingHpkpThenExcludesHpkpHeader() throws Exception {
|
||||
this.spring.configLocations(this.xml("DefaultsDisabledWithHpkpDefaults")).autowire();
|
||||
this.mvc.perform(get("/")).andExpect(status().isOk())
|
||||
.andExpect(header().doesNotExist("Public-Key-Pins-Report-Only")).andExpect(excludesDefaults());
|
||||
// @formatter:off
|
||||
this.mvc.perform(get("/"))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(header().doesNotExist("Public-Key-Pins-Report-Only"))
|
||||
.andExpect(excludesDefaults());
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
public void requestWhenUsingHpkpCustomMaxAgeThenIncludesHpkpHeaderAccordingly() throws Exception {
|
||||
this.spring.configLocations(this.xml("DefaultsDisabledWithHpkpMaxAge")).autowire();
|
||||
this.mvc.perform(get("/").secure(true)).andExpect(status().isOk())
|
||||
// @formatter:off
|
||||
this.mvc.perform(get("/").secure(true))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(header().string("Public-Key-Pins-Report-Only",
|
||||
"max-age=604800 ; pin-sha256=\"d6qzRu9zOECb90Uez27xWltNsj0e1Md7GkYYkVoZWmM=\""))
|
||||
.andExpect(excludesDefaults());
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
public void requestWhenUsingHpkpReportThenIncludesHpkpHeaderAccordingly() throws Exception {
|
||||
this.spring.configLocations(this.xml("DefaultsDisabledWithHpkpReport")).autowire();
|
||||
this.mvc.perform(get("/").secure(true)).andExpect(status().isOk())
|
||||
// @formatter:off
|
||||
this.mvc.perform(get("/").secure(true))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(header().string("Public-Key-Pins",
|
||||
"max-age=5184000 ; pin-sha256=\"d6qzRu9zOECb90Uez27xWltNsj0e1Md7GkYYkVoZWmM=\""))
|
||||
.andExpect(excludesDefaults());
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
public void requestWhenUsingHpkpIncludeSubdomainsThenIncludesHpkpHeaderAccordingly() throws Exception {
|
||||
this.spring.configLocations(this.xml("DefaultsDisabledWithHpkpIncludeSubdomains")).autowire();
|
||||
this.mvc.perform(get("/").secure(true)).andExpect(status().isOk()).andExpect(header().string(
|
||||
"Public-Key-Pins-Report-Only",
|
||||
"max-age=5184000 ; pin-sha256=\"d6qzRu9zOECb90Uez27xWltNsj0e1Md7GkYYkVoZWmM=\" ; includeSubDomains"))
|
||||
// @formatter:off
|
||||
this.mvc.perform(get("/").secure(true))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(header().string("Public-Key-Pins-Report-Only",
|
||||
"max-age=5184000 ; pin-sha256=\"d6qzRu9zOECb90Uez27xWltNsj0e1Md7GkYYkVoZWmM=\" ; includeSubDomains"))
|
||||
.andExpect(excludesDefaults());
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
public void requestWhenUsingHpkpReportUriThenIncludesHpkpHeaderAccordingly() throws Exception {
|
||||
this.spring.configLocations(this.xml("DefaultsDisabledWithHpkpReportUri")).autowire();
|
||||
this.mvc.perform(get("/").secure(true)).andExpect(status().isOk()).andExpect(header().string(
|
||||
"Public-Key-Pins-Report-Only",
|
||||
"max-age=5184000 ; pin-sha256=\"d6qzRu9zOECb90Uez27xWltNsj0e1Md7GkYYkVoZWmM=\" ; report-uri=\"https://example.net/pkp-report\""))
|
||||
// @formatter:off
|
||||
this.mvc.perform(get("/").secure(true))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(header().string("Public-Key-Pins-Report-Only",
|
||||
"max-age=5184000 ; pin-sha256=\"d6qzRu9zOECb90Uez27xWltNsj0e1Md7GkYYkVoZWmM=\" ; report-uri=\"https://example.net/pkp-report\""))
|
||||
.andExpect(excludesDefaults());
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -399,8 +529,12 @@ public class HttpHeadersConfigTests {
|
|||
Collection<String> cacheControl = Arrays.asList("Cache-Control", "Expires", "Pragma");
|
||||
Map<String, String> allButCacheControl = remove(defaultHeaders, cacheControl);
|
||||
this.spring.configLocations(this.xml("CacheControlDisabled")).autowire();
|
||||
this.mvc.perform(get("/").secure(true)).andExpect(status().isOk()).andExpect(includes(allButCacheControl))
|
||||
// @formatter:off
|
||||
this.mvc.perform(get("/").secure(true))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(includes(allButCacheControl))
|
||||
.andExpect(excludes(cacheControl));
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -408,8 +542,12 @@ public class HttpHeadersConfigTests {
|
|||
Collection<String> contentTypeOptions = Arrays.asList("X-Content-Type-Options");
|
||||
Map<String, String> allButContentTypeOptions = remove(defaultHeaders, contentTypeOptions);
|
||||
this.spring.configLocations(this.xml("ContentTypeOptionsDisabled")).autowire();
|
||||
this.mvc.perform(get("/").secure(true)).andExpect(status().isOk()).andExpect(includes(allButContentTypeOptions))
|
||||
// @formatter:off
|
||||
this.mvc.perform(get("/").secure(true))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(includes(allButContentTypeOptions))
|
||||
.andExpect(excludes(contentTypeOptions));
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -417,14 +555,22 @@ public class HttpHeadersConfigTests {
|
|||
Collection<String> hsts = Arrays.asList("Strict-Transport-Security");
|
||||
Map<String, String> allButHsts = remove(defaultHeaders, hsts);
|
||||
this.spring.configLocations(this.xml("HstsDisabled")).autowire();
|
||||
this.mvc.perform(get("/").secure(true)).andExpect(status().isOk()).andExpect(includes(allButHsts))
|
||||
// @formatter:off
|
||||
this.mvc.perform(get("/").secure(true))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(includes(allButHsts))
|
||||
.andExpect(excludes(hsts));
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
public void requestWhenHpkpDisabledThenExcludesHeader() throws Exception {
|
||||
this.spring.configLocations(this.xml("HpkpDisabled")).autowire();
|
||||
this.mvc.perform(get("/").secure(true)).andExpect(status().isOk()).andExpect(includesDefaults());
|
||||
// @formatter:off
|
||||
this.mvc.perform(get("/").secure(true))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(includesDefaults());
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -432,8 +578,12 @@ public class HttpHeadersConfigTests {
|
|||
Collection<String> frameOptions = Arrays.asList("X-Frame-Options");
|
||||
Map<String, String> allButFrameOptions = remove(defaultHeaders, frameOptions);
|
||||
this.spring.configLocations(this.xml("FrameOptionsDisabled")).autowire();
|
||||
this.mvc.perform(get("/").secure(true)).andExpect(status().isOk()).andExpect(includes(allButFrameOptions))
|
||||
// @formatter:off
|
||||
this.mvc.perform(get("/").secure(true))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(includes(allButFrameOptions))
|
||||
.andExpect(excludes(frameOptions));
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -441,8 +591,12 @@ public class HttpHeadersConfigTests {
|
|||
Collection<String> xssProtection = Arrays.asList("X-XSS-Protection");
|
||||
Map<String, String> allButXssProtection = remove(defaultHeaders, xssProtection);
|
||||
this.spring.configLocations(this.xml("XssProtectionDisabled")).autowire();
|
||||
this.mvc.perform(get("/").secure(true)).andExpect(status().isOk()).andExpect(includes(allButXssProtection))
|
||||
// @formatter:off
|
||||
this.mvc.perform(get("/").secure(true))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(includes(allButXssProtection))
|
||||
.andExpect(excludes(xssProtection));
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -495,21 +649,33 @@ public class HttpHeadersConfigTests {
|
|||
Map<String, String> includedHeaders = new HashMap<>(defaultHeaders);
|
||||
includedHeaders.put("Content-Security-Policy", "default-src 'self'");
|
||||
this.spring.configLocations(this.xml("ContentSecurityPolicyWithPolicyDirectives")).autowire();
|
||||
this.mvc.perform(get("/").secure(true)).andExpect(status().isOk()).andExpect(includes(includedHeaders));
|
||||
// @formatter:off
|
||||
this.mvc.perform(get("/").secure(true))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(includes(includedHeaders));
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
public void requestWhenHeadersDisabledAndContentSecurityPolicyConfiguredThenExcludesHeader() throws Exception {
|
||||
this.spring.configLocations(this.xml("HeadersDisabledWithContentSecurityPolicy")).autowire();
|
||||
this.mvc.perform(get("/")).andExpect(status().isOk()).andExpect(excludesDefaults())
|
||||
// @formatter:off
|
||||
this.mvc.perform(get("/"))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(excludesDefaults())
|
||||
.andExpect(excludes("Content-Security-Policy"));
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
public void requestWhenDefaultsDisabledAndContentSecurityPolicyConfiguredThenIncludesHeader() throws Exception {
|
||||
this.spring.configLocations(this.xml("DefaultsDisabledWithContentSecurityPolicy")).autowire();
|
||||
this.mvc.perform(get("/")).andExpect(status().isOk()).andExpect(excludesDefaults())
|
||||
// @formatter:off
|
||||
this.mvc.perform(get("/"))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(excludesDefaults())
|
||||
.andExpect(header().string("Content-Security-Policy", "default-src 'self'"));
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -525,21 +691,33 @@ public class HttpHeadersConfigTests {
|
|||
includedHeaders.put("Content-Security-Policy-Report-Only",
|
||||
"default-src https:; report-uri https://example.org/");
|
||||
this.spring.configLocations(this.xml("ContentSecurityPolicyWithReportOnly")).autowire();
|
||||
this.mvc.perform(get("/").secure(true)).andExpect(status().isOk()).andExpect(includes(includedHeaders));
|
||||
// @formatter:off
|
||||
this.mvc.perform(get("/").secure(true))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(includes(includedHeaders));
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
public void requestWhenReferrerPolicyConfiguredThenResponseDefaultsToNoReferrer() throws Exception {
|
||||
this.spring.configLocations(this.xml("DefaultsDisabledWithReferrerPolicy")).autowire();
|
||||
this.mvc.perform(get("/")).andExpect(status().isOk()).andExpect(excludesDefaults())
|
||||
// @formatter:off
|
||||
this.mvc.perform(get("/"))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(excludesDefaults())
|
||||
.andExpect(header().string("Referrer-Policy", "no-referrer"));
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
public void requestWhenReferrerPolicyConfiguredWithSameOriginThenRespondsWithSameOrigin() throws Exception {
|
||||
this.spring.configLocations(this.xml("DefaultsDisabledWithReferrerPolicySameOrigin")).autowire();
|
||||
this.mvc.perform(get("/")).andExpect(status().isOk()).andExpect(excludesDefaults())
|
||||
// @formatter:off
|
||||
this.mvc.perform(get("/"))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(excludesDefaults())
|
||||
.andExpect(header().string("Referrer-Policy", "same-origin"));
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
private static ResultMatcher includesDefaults() {
|
||||
|
|
|
@ -48,9 +48,14 @@ public class HttpInterceptUrlTests {
|
|||
@Test
|
||||
public void interceptUrlWhenRequestMatcherRefThenWorks() throws Exception {
|
||||
loadConfig("interceptUrlWhenRequestMatcherRefThenWorks.xml");
|
||||
this.mockMvc.perform(get("/foo")).andExpect(status().isUnauthorized());
|
||||
this.mockMvc.perform(get("/FOO")).andExpect(status().isUnauthorized());
|
||||
this.mockMvc.perform(get("/other")).andExpect(status().isOk());
|
||||
// @formatter:off
|
||||
this.mockMvc.perform(get("/foo"))
|
||||
.andExpect(status().isUnauthorized());
|
||||
this.mockMvc.perform(get("/FOO"))
|
||||
.andExpect(status().isUnauthorized());
|
||||
this.mockMvc.perform(get("/other"))
|
||||
.andExpect(status().isOk());
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
private void loadConfig(String... configLocations) {
|
||||
|
|
|
@ -30,6 +30,7 @@ import org.springframework.beans.factory.parsing.BeanDefinitionParsingException;
|
|||
import org.springframework.mock.web.MockServletContext;
|
||||
import org.springframework.security.config.test.SpringTestRule;
|
||||
import org.springframework.test.web.servlet.MockMvc;
|
||||
import org.springframework.test.web.servlet.request.RequestPostProcessor;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
@ -65,8 +66,12 @@ public class InterceptUrlConfigTests {
|
|||
@Test
|
||||
public void requestWhenMethodIsSpecifiedThenItIsNotGivenPriority() throws Exception {
|
||||
this.spring.configLocations(this.xml("Sec2256")).autowire();
|
||||
this.mvc.perform(post("/path").with(httpBasic("user", "password"))).andExpect(status().isOk());
|
||||
this.mvc.perform(get("/path").with(httpBasic("user", "password"))).andExpect(status().isOk());
|
||||
// @formatter:off
|
||||
this.mvc.perform(post("/path").with(userCredentials()))
|
||||
.andExpect(status().isOk());
|
||||
this.mvc.perform(get("/path").with(userCredentials()))
|
||||
.andExpect(status().isOk());
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -75,16 +80,25 @@ public class InterceptUrlConfigTests {
|
|||
@Test
|
||||
public void requestWhenUsingPatchThenAuthorizesRequestsAccordingly() throws Exception {
|
||||
this.spring.configLocations(this.xml("PatchMethod")).autowire();
|
||||
this.mvc.perform(get("/path").with(httpBasic("user", "password"))).andExpect(status().isOk());
|
||||
this.mvc.perform(patch("/path").with(httpBasic("user", "password"))).andExpect(status().isForbidden());
|
||||
this.mvc.perform(patch("/path").with(httpBasic("admin", "password"))).andExpect(status().isOk());
|
||||
// @formatter:off
|
||||
this.mvc.perform(get("/path").with(userCredentials()))
|
||||
.andExpect(status().isOk());
|
||||
this.mvc.perform(patch("/path").with(userCredentials()))
|
||||
.andExpect(status().isForbidden());
|
||||
this.mvc.perform(patch("/path").with(adminCredentials()))
|
||||
.andExpect(status().isOk());
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
public void requestWhenUsingHasAnyRoleThenAuthorizesRequestsAccordingly() throws Exception {
|
||||
this.spring.configLocations(this.xml("HasAnyRole")).autowire();
|
||||
this.mvc.perform(get("/path").with(httpBasic("user", "password"))).andExpect(status().isOk());
|
||||
this.mvc.perform(get("/path").with(httpBasic("admin", "password"))).andExpect(status().isForbidden());
|
||||
// @formatter:off
|
||||
this.mvc.perform(get("/path").with(userCredentials()))
|
||||
.andExpect(status().isOk());
|
||||
this.mvc.perform(get("/path").with(adminCredentials()))
|
||||
.andExpect(status().isForbidden());
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -93,10 +107,14 @@ public class InterceptUrlConfigTests {
|
|||
@Test
|
||||
public void requestWhenUsingPathVariablesThenAuthorizesRequestsAccordingly() throws Exception {
|
||||
this.spring.configLocations(this.xml("PathVariables")).autowire();
|
||||
this.mvc.perform(get("/path/user/path").with(httpBasic("user", "password"))).andExpect(status().isOk());
|
||||
this.mvc.perform(get("/path/otheruser/path").with(httpBasic("user", "password")))
|
||||
// @formatter:off
|
||||
this.mvc.perform(get("/path/user/path").with(userCredentials()))
|
||||
.andExpect(status().isOk());
|
||||
this.mvc.perform(get("/path/otheruser/path").with(userCredentials()))
|
||||
.andExpect(status().isForbidden());
|
||||
this.mvc.perform(get("/path").with(httpBasic("user", "password"))).andExpect(status().isForbidden());
|
||||
this.mvc.perform(get("/path").with(userCredentials()))
|
||||
.andExpect(status().isForbidden());
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -105,10 +123,14 @@ public class InterceptUrlConfigTests {
|
|||
@Test
|
||||
public void requestWhenUsingCamelCasePathVariablesThenAuthorizesRequestsAccordingly() throws Exception {
|
||||
this.spring.configLocations(this.xml("CamelCasePathVariables")).autowire();
|
||||
this.mvc.perform(get("/path/user/path").with(httpBasic("user", "password"))).andExpect(status().isOk());
|
||||
this.mvc.perform(get("/path/otheruser/path").with(httpBasic("user", "password")))
|
||||
// @formatter:off
|
||||
this.mvc.perform(get("/path/user/path").with(userCredentials()))
|
||||
.andExpect(status().isOk());
|
||||
this.mvc.perform(get("/path/otheruser/path").with(userCredentials()))
|
||||
.andExpect(status().isForbidden());
|
||||
this.mvc.perform(get("/PATH/user/path").with(httpBasic("user", "password"))).andExpect(status().isForbidden());
|
||||
this.mvc.perform(get("/PATH/user/path").with(userCredentials()))
|
||||
.andExpect(status().isForbidden());
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -117,25 +139,36 @@ public class InterceptUrlConfigTests {
|
|||
@Test
|
||||
public void requestWhenUsingPathVariablesAndTypeConversionThenAuthorizesRequestsAccordingly() throws Exception {
|
||||
this.spring.configLocations(this.xml("TypeConversionPathVariables")).autowire();
|
||||
this.mvc.perform(get("/path/1/path").with(httpBasic("user", "password"))).andExpect(status().isOk());
|
||||
this.mvc.perform(get("/path/2/path").with(httpBasic("user", "password"))).andExpect(status().isForbidden());
|
||||
// @formatter:off
|
||||
this.mvc.perform(get("/path/1/path").with(userCredentials()))
|
||||
.andExpect(status().isOk());
|
||||
this.mvc.perform(get("/path/2/path").with(userCredentials()))
|
||||
.andExpect(status().isForbidden());
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
public void requestWhenUsingMvcMatchersThenAuthorizesRequestsAccordingly() throws Exception {
|
||||
this.spring.configLocations(this.xml("MvcMatchers")).autowire();
|
||||
this.mvc.perform(get("/path")).andExpect(status().isUnauthorized());
|
||||
this.mvc.perform(get("/path.html")).andExpect(status().isUnauthorized());
|
||||
this.mvc.perform(get("/path/")).andExpect(status().isUnauthorized());
|
||||
this.mvc.perform(get("/path"))
|
||||
.andExpect(status().isUnauthorized());
|
||||
this.mvc.perform(get("/path.html"))
|
||||
.andExpect(status().isUnauthorized());
|
||||
this.mvc.perform(get("/path/"))
|
||||
.andExpect(status().isUnauthorized());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void requestWhenUsingMvcMatchersAndPathVariablesThenAuthorizesRequestsAccordingly() throws Exception {
|
||||
this.spring.configLocations(this.xml("MvcMatchersPathVariables")).autowire();
|
||||
this.mvc.perform(get("/path/user/path").with(httpBasic("user", "password"))).andExpect(status().isOk());
|
||||
this.mvc.perform(get("/path/otheruser/path").with(httpBasic("user", "password")))
|
||||
// @formatter:off
|
||||
this.mvc.perform(get("/path/user/path").with(userCredentials()))
|
||||
.andExpect(status().isOk());
|
||||
this.mvc.perform(get("/path/otheruser/path").with(userCredentials()))
|
||||
.andExpect(status().isForbidden());
|
||||
this.mvc.perform(get("/PATH/user/path").with(httpBasic("user", "password"))).andExpect(status().isForbidden());
|
||||
this.mvc.perform(get("/PATH/user/path").with(userCredentials()))
|
||||
.andExpect(status().isForbidden());
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -144,9 +177,14 @@ public class InterceptUrlConfigTests {
|
|||
MockServletContext servletContext = mockServletContext("/spring");
|
||||
ConfigurableWebApplicationContext context = this.spring.getContext();
|
||||
context.setServletContext(servletContext);
|
||||
this.mvc.perform(get("/spring/path").servletPath("/spring")).andExpect(status().isUnauthorized());
|
||||
this.mvc.perform(get("/spring/path.html").servletPath("/spring")).andExpect(status().isUnauthorized());
|
||||
this.mvc.perform(get("/spring/path/").servletPath("/spring")).andExpect(status().isUnauthorized());
|
||||
// @formatter:off
|
||||
this.mvc.perform(get("/spring/path").servletPath("/spring"))
|
||||
.andExpect(status().isUnauthorized());
|
||||
this.mvc.perform(get("/spring/path.html").servletPath("/spring"))
|
||||
.andExpect(status().isUnauthorized());
|
||||
this.mvc.perform(get("/spring/path/").servletPath("/spring"))
|
||||
.andExpect(status().isUnauthorized());
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -173,6 +211,14 @@ public class InterceptUrlConfigTests {
|
|||
.isThrownBy(() -> this.spring.configLocations(this.xml("DefaultMatcherServletPath")).autowire());
|
||||
}
|
||||
|
||||
private static RequestPostProcessor adminCredentials() {
|
||||
return httpBasic("admin", "password");
|
||||
}
|
||||
|
||||
private static RequestPostProcessor userCredentials() {
|
||||
return httpBasic("user", "password");
|
||||
}
|
||||
|
||||
private MockServletContext mockServletContext(String servletPath) {
|
||||
MockServletContext servletContext = spy(new MockServletContext());
|
||||
final ServletRegistration registration = mock(ServletRegistration.class);
|
||||
|
|
|
@ -43,6 +43,7 @@ import ch.qos.logback.classic.spi.ILoggingEvent;
|
|||
import ch.qos.logback.core.Appender;
|
||||
import org.apache.http.HttpStatus;
|
||||
import org.assertj.core.api.iterable.Extractor;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.mockito.stubbing.Answer;
|
||||
|
@ -105,6 +106,8 @@ import org.springframework.security.web.session.SessionManagementFilter;
|
|||
import org.springframework.test.util.ReflectionTestUtils;
|
||||
import org.springframework.test.web.servlet.MockMvc;
|
||||
import org.springframework.test.web.servlet.MvcResult;
|
||||
import org.springframework.test.web.servlet.request.MockHttpServletRequestBuilder;
|
||||
import org.springframework.test.web.servlet.request.RequestPostProcessor;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
@ -162,29 +165,45 @@ public class MiscHttpConfigTests {
|
|||
@Test
|
||||
public void requestWhenUsingDebugFilterAndPatternIsNotConfigureForSecurityThenRespondsOk() throws Exception {
|
||||
this.spring.configLocations(xml("NoSecurityForPattern")).autowire();
|
||||
this.mvc.perform(get("/unprotected")).andExpect(status().isNotFound());
|
||||
this.mvc.perform(get("/nomatch")).andExpect(status().isNotFound());
|
||||
// @formatter:off
|
||||
this.mvc.perform(get("/unprotected"))
|
||||
.andExpect(status().isNotFound());
|
||||
this.mvc.perform(get("/nomatch"))
|
||||
.andExpect(status().isNotFound());
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
public void requestWhenHttpPatternUsesRegexMatchingThenMatchesAccordingly() throws Exception {
|
||||
this.spring.configLocations(xml("RegexSecurityPattern")).autowire();
|
||||
this.mvc.perform(get("/protected")).andExpect(status().isUnauthorized());
|
||||
this.mvc.perform(get("/unprotected")).andExpect(status().isNotFound());
|
||||
// @formatter:off
|
||||
this.mvc.perform(get("/protected"))
|
||||
.andExpect(status().isUnauthorized());
|
||||
this.mvc.perform(get("/unprotected"))
|
||||
.andExpect(status().isNotFound());
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
public void requestWhenHttpPatternUsesCiRegexMatchingThenMatchesAccordingly() throws Exception {
|
||||
this.spring.configLocations(xml("CiRegexSecurityPattern")).autowire();
|
||||
this.mvc.perform(get("/ProTectEd")).andExpect(status().isUnauthorized());
|
||||
this.mvc.perform(get("/UnProTectEd")).andExpect(status().isNotFound());
|
||||
// @formatter:off
|
||||
this.mvc.perform(get("/ProTectEd"))
|
||||
.andExpect(status().isUnauthorized());
|
||||
this.mvc.perform(get("/UnProTectEd"))
|
||||
.andExpect(status().isNotFound());
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
public void requestWhenHttpPatternUsesCustomRequestMatcherThenMatchesAccordingly() throws Exception {
|
||||
this.spring.configLocations(xml("CustomRequestMatcher")).autowire();
|
||||
this.mvc.perform(get("/protected")).andExpect(status().isUnauthorized());
|
||||
this.mvc.perform(get("/unprotected")).andExpect(status().isNotFound());
|
||||
// @formatter:off
|
||||
this.mvc.perform(get("/protected"))
|
||||
.andExpect(status().isUnauthorized());
|
||||
this.mvc.perform(get("/unprotected"))
|
||||
.andExpect(status().isNotFound());
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -193,65 +212,98 @@ public class MiscHttpConfigTests {
|
|||
@Test
|
||||
public void requestWhenUsingMinimalConfigurationThenHonorsAnonymousEndpoints() throws Exception {
|
||||
this.spring.configLocations(xml("AnonymousEndpoints")).autowire();
|
||||
this.mvc.perform(get("/protected")).andExpect(status().isUnauthorized());
|
||||
this.mvc.perform(get("/unprotected")).andExpect(status().isNotFound());
|
||||
// @formatter:off
|
||||
this.mvc.perform(get("/protected"))
|
||||
.andExpect(status().isUnauthorized());
|
||||
this.mvc.perform(get("/unprotected"))
|
||||
.andExpect(status().isNotFound());
|
||||
// @formatter:on
|
||||
assertThat(getFilter(AnonymousAuthenticationFilter.class)).isNotNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void requestWhenAnonymousIsDisabledThenRejectsAnonymousEndpoints() throws Exception {
|
||||
this.spring.configLocations(xml("AnonymousDisabled")).autowire();
|
||||
this.mvc.perform(get("/protected")).andExpect(status().isUnauthorized());
|
||||
this.mvc.perform(get("/unprotected")).andExpect(status().isUnauthorized());
|
||||
// @formatter:off
|
||||
this.mvc.perform(get("/protected"))
|
||||
.andExpect(status().isUnauthorized());
|
||||
this.mvc.perform(get("/unprotected"))
|
||||
.andExpect(status().isUnauthorized());
|
||||
// @formatter:on
|
||||
assertThat(getFilter(AnonymousAuthenticationFilter.class)).isNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void requestWhenAnonymousUsesCustomAttributesThenRespondsWithThoseAttributes() throws Exception {
|
||||
this.spring.configLocations(xml("AnonymousCustomAttributes")).autowire();
|
||||
this.mvc.perform(get("/protected").with(httpBasic("user", "password"))).andExpect(status().isForbidden());
|
||||
this.mvc.perform(get("/protected")).andExpect(status().isOk()).andExpect(content().string("josh"));
|
||||
this.mvc.perform(get("/customKey")).andExpect(status().isOk())
|
||||
// @formatter:off
|
||||
this.mvc.perform(get("/protected").with(userCredentials()))
|
||||
.andExpect(status().isForbidden());
|
||||
this.mvc.perform(get("/protected"))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(content().string("josh"));
|
||||
this.mvc.perform(get("/customKey"))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(content().string(String.valueOf("myCustomKey".hashCode())));
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
public void requestWhenAnonymousUsesMultipleGrantedAuthoritiesThenRespondsWithThoseAttributes() throws Exception {
|
||||
this.spring.configLocations(xml("AnonymousMultipleAuthorities")).autowire();
|
||||
this.mvc.perform(get("/protected").with(httpBasic("user", "password"))).andExpect(status().isForbidden());
|
||||
this.mvc.perform(get("/protected")).andExpect(status().isOk()).andExpect(content().string("josh"));
|
||||
this.mvc.perform(get("/customKey")).andExpect(status().isOk())
|
||||
// @formatter:off
|
||||
this.mvc.perform(get("/protected").with(userCredentials()))
|
||||
.andExpect(status().isForbidden());
|
||||
this.mvc.perform(get("/protected"))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(content().string("josh"));
|
||||
this.mvc.perform(get("/customKey"))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(content().string(String.valueOf("myCustomKey".hashCode())));
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
public void requestWhenInterceptUrlMatchesMethodThenSecuresAccordingly() throws Exception {
|
||||
this.spring.configLocations(xml("InterceptUrlMethod")).autowire();
|
||||
this.mvc.perform(get("/protected").with(httpBasic("user", "password"))).andExpect(status().isOk());
|
||||
this.mvc.perform(post("/protected").with(httpBasic("user", "password"))).andExpect(status().isForbidden());
|
||||
this.mvc.perform(post("/protected").with(httpBasic("poster", "password"))).andExpect(status().isOk());
|
||||
this.mvc.perform(delete("/protected").with(httpBasic("poster", "password"))).andExpect(status().isForbidden());
|
||||
this.mvc.perform(delete("/protected").with(httpBasic("admin", "password"))).andExpect(status().isOk());
|
||||
// @formatter:off
|
||||
this.mvc.perform(get("/protected").with(userCredentials()))
|
||||
.andExpect(status().isOk());
|
||||
this.mvc.perform(post("/protected").with(userCredentials()))
|
||||
.andExpect(status().isForbidden());
|
||||
this.mvc.perform(post("/protected").with(postCredentials()))
|
||||
.andExpect(status().isOk());
|
||||
this.mvc.perform(delete("/protected").with(postCredentials()))
|
||||
.andExpect(status().isForbidden());
|
||||
this.mvc.perform(delete("/protected").with(adminCredentials()))
|
||||
.andExpect(status().isOk());
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
public void requestWhenInterceptUrlMatchesMethodAndRequiresHttpsThenSecuresAccordingly() throws Exception {
|
||||
this.spring.configLocations(xml("InterceptUrlMethodRequiresHttps")).autowire();
|
||||
this.mvc.perform(post("/protected").with(csrf())).andExpect(status().isOk());
|
||||
this.mvc.perform(get("/protected").secure(true).with(httpBasic("user", "password")))
|
||||
.andExpect(status().isForbidden());
|
||||
this.mvc.perform(get("/protected").secure(true).with(httpBasic("admin", "password")))
|
||||
// @formatter:off
|
||||
this.mvc.perform(post("/protected").with(csrf()))
|
||||
.andExpect(status().isOk());
|
||||
this.mvc.perform(get("/protected").secure(true).with(userCredentials()))
|
||||
.andExpect(status().isForbidden());
|
||||
this.mvc.perform(get("/protected").secure(true).with(adminCredentials()))
|
||||
.andExpect(status().isOk());
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
public void requestWhenInterceptUrlMatchesAnyPatternAndRequiresHttpsThenSecuresAccordingly() throws Exception {
|
||||
this.spring.configLocations(xml("InterceptUrlMethodRequiresHttpsAny")).autowire();
|
||||
this.mvc.perform(post("/protected").with(csrf())).andExpect(status().isOk());
|
||||
this.mvc.perform(get("/protected").secure(true).with(httpBasic("user", "password")))
|
||||
.andExpect(status().isForbidden());
|
||||
this.mvc.perform(get("/protected").secure(true).with(httpBasic("admin", "password")))
|
||||
// @formatter:off
|
||||
this.mvc.perform(post("/protected").with(csrf()))
|
||||
.andExpect(status().isOk());
|
||||
this.mvc.perform(get("/protected").secure(true).with(userCredentials()))
|
||||
.andExpect(status().isForbidden());
|
||||
this.mvc.perform(get("/protected").secure(true).with(adminCredentials()))
|
||||
.andExpect(status().isOk());
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -265,7 +317,10 @@ public class MiscHttpConfigTests {
|
|||
public void requestWhenCustomHttpBasicEntryPointRefThenInvokesOnCommence() throws Exception {
|
||||
this.spring.configLocations(xml("CustomHttpBasicEntryPointRef")).autowire();
|
||||
AuthenticationEntryPoint entryPoint = this.spring.getContext().getBean(AuthenticationEntryPoint.class);
|
||||
this.mvc.perform(get("/protected")).andExpect(status().isOk());
|
||||
// @formatter:off
|
||||
this.mvc.perform(get("/protected"))
|
||||
.andExpect(status().isOk());
|
||||
// @formatter:on
|
||||
verify(entryPoint).commence(any(HttpServletRequest.class), any(HttpServletResponse.class),
|
||||
any(AuthenticationException.class));
|
||||
}
|
||||
|
@ -279,8 +334,10 @@ public class MiscHttpConfigTests {
|
|||
@Test
|
||||
public void getWhenPortsMappedThenRedirectedAccordingly() throws Exception {
|
||||
this.spring.configLocations(xml("PortsMappedInterceptUrlMethodRequiresAny")).autowire();
|
||||
// @formatter:off
|
||||
this.mvc.perform(get("http://localhost:9080/protected"))
|
||||
.andExpect(redirectedUrl("https://localhost:9443/protected"));
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -312,9 +369,11 @@ public class MiscHttpConfigTests {
|
|||
public void getWhenUsingX509AndPropertyPlaceholderThenSubjectPrincipalRegexIsConfigured() throws Exception {
|
||||
System.setProperty("subject_principal_regex", "OU=(.*?)(?:,|$)");
|
||||
this.spring.configLocations(xml("X509")).autowire();
|
||||
this.mvc.perform(get("/protected")
|
||||
.with(x509("classpath:org/springframework/security/config/http/MiscHttpConfigTests-certificate.pem")))
|
||||
RequestPostProcessor x509 = x509("classpath:org/springframework/security/config/http/MiscHttpConfigTests-certificate.pem");
|
||||
// @formatter:off
|
||||
this.mvc.perform(get("/protected").with(x509))
|
||||
.andExpect(status().isOk());
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -335,7 +394,10 @@ public class MiscHttpConfigTests {
|
|||
@Test
|
||||
public void logoutWhenSpecifyingSuccessHandlerRefThenResponseHandledAccordingly() throws Exception {
|
||||
this.spring.configLocations(xml("LogoutSuccessHandlerRef")).autowire();
|
||||
this.mvc.perform(post("/logout").with(csrf())).andExpect(redirectedUrl("/logoutSuccessEndpoint"));
|
||||
// @formatter:off
|
||||
this.mvc.perform(post("/logout").with(csrf()))
|
||||
.andExpect(redirectedUrl("/logoutSuccessEndpoint"));
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -374,8 +436,12 @@ public class MiscHttpConfigTests {
|
|||
@Test
|
||||
public void getWhenUsingTwoIdenticalInterceptUrlsThenTheSecondTakesPrecedence() throws Exception {
|
||||
this.spring.configLocations(xml("Sec934")).autowire();
|
||||
this.mvc.perform(get("/protected").with(httpBasic("user", "password"))).andExpect(status().isOk());
|
||||
this.mvc.perform(get("/protected").with(httpBasic("admin", "password"))).andExpect(status().isForbidden());
|
||||
// @formatter:off
|
||||
this.mvc.perform(get("/protected").with(userCredentials()))
|
||||
.andExpect(status().isOk());
|
||||
this.mvc.perform(get("/protected").with(adminCredentials()))
|
||||
.andExpect(status().isForbidden());
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -384,8 +450,11 @@ public class MiscHttpConfigTests {
|
|||
SecurityContextRepository repository = this.spring.getContext().getBean(SecurityContextRepository.class);
|
||||
SecurityContext context = new SecurityContextImpl(new TestingAuthenticationToken("user", "password"));
|
||||
given(repository.loadContext(any(HttpRequestResponseHolder.class))).willReturn(context);
|
||||
MvcResult result = this.mvc.perform(get("/protected").with(httpBasic("user", "password")))
|
||||
.andExpect(status().isOk()).andReturn();
|
||||
// @formatter:off
|
||||
MvcResult result = this.mvc.perform(get("/protected").with(userCredentials()))
|
||||
.andExpect(status().isOk())
|
||||
.andReturn();
|
||||
// @formatter:on
|
||||
assertThat(result.getRequest().getSession(false)).isNotNull();
|
||||
verify(repository, atLeastOnce()).saveContext(any(SecurityContext.class), any(HttpServletRequest.class),
|
||||
any(HttpServletResponse.class));
|
||||
|
@ -394,9 +463,14 @@ public class MiscHttpConfigTests {
|
|||
@Test
|
||||
public void getWhenUsingInterceptUrlExpressionsThenAuthorizesAccordingly() throws Exception {
|
||||
this.spring.configLocations(xml("InterceptUrlExpressions")).autowire();
|
||||
this.mvc.perform(get("/protected").with(httpBasic("admin", "password"))).andExpect(status().isOk());
|
||||
this.mvc.perform(get("/protected").with(httpBasic("user", "password"))).andExpect(status().isForbidden());
|
||||
this.mvc.perform(get("/unprotected").with(httpBasic("user", "password"))).andExpect(status().isOk());
|
||||
// @formatter:off
|
||||
this.mvc.perform(get("/protected").with(adminCredentials()))
|
||||
.andExpect(status().isOk());
|
||||
this.mvc.perform(get("/protected").with(userCredentials()))
|
||||
.andExpect(status().isForbidden());
|
||||
this.mvc.perform(get("/unprotected").with(userCredentials()))
|
||||
.andExpect(status().isOk());
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -405,7 +479,10 @@ public class MiscHttpConfigTests {
|
|||
PermissionEvaluator permissionEvaluator = this.spring.getContext().getBean(PermissionEvaluator.class);
|
||||
given(permissionEvaluator.hasPermission(any(Authentication.class), any(Object.class), any(Object.class)))
|
||||
.willReturn(false);
|
||||
this.mvc.perform(get("/").with(httpBasic("user", "password"))).andExpect(status().isForbidden());
|
||||
// @formatter:off
|
||||
this.mvc.perform(get("/").with(userCredentials()))
|
||||
.andExpect(status().isForbidden());
|
||||
// @formatter:on
|
||||
verify(permissionEvaluator).hasPermission(any(Authentication.class), any(Object.class), any(Object.class));
|
||||
}
|
||||
|
||||
|
@ -449,21 +526,32 @@ public class MiscHttpConfigTests {
|
|||
public void loginWhenConfiguredWithNoInternalAuthenticationProvidersThenSuccessfullyAuthenticates()
|
||||
throws Exception {
|
||||
this.spring.configLocations(xml("NoInternalAuthenticationProviders")).autowire();
|
||||
this.mvc.perform(post("/login").param("username", "user").param("password", "password"))
|
||||
// @formatter:off
|
||||
MockHttpServletRequestBuilder loginRequest = post("/login")
|
||||
.param("username", "user")
|
||||
.param("password", "password");
|
||||
this.mvc.perform(loginRequest)
|
||||
.andExpect(redirectedUrl("/"));
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
public void loginWhenUsingDefaultsThenErasesCredentialsAfterAuthentication() throws Exception {
|
||||
this.spring.configLocations(xml("HttpBasic")).autowire();
|
||||
this.mvc.perform(get("/password").with(httpBasic("user", "password"))).andExpect(content().string(""));
|
||||
// @formatter:off
|
||||
this.mvc.perform(get("/password").with(userCredentials()))
|
||||
.andExpect(content().string(""));
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
public void loginWhenAuthenticationManagerConfiguredToEraseCredentialsThenErasesCredentialsAfterAuthentication()
|
||||
throws Exception {
|
||||
this.spring.configLocations(xml("AuthenticationManagerEraseCredentials")).autowire();
|
||||
this.mvc.perform(get("/password").with(httpBasic("user", "password"))).andExpect(content().string(""));
|
||||
// @formatter:off
|
||||
this.mvc.perform(get("/password").with(userCredentials()))
|
||||
.andExpect(content().string(""));
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -473,14 +561,20 @@ public class MiscHttpConfigTests {
|
|||
public void loginWhenAuthenticationManagerRefConfiguredToKeepCredentialsThenKeepsCredentialsAfterAuthentication()
|
||||
throws Exception {
|
||||
this.spring.configLocations(xml("AuthenticationManagerRefKeepCredentials")).autowire();
|
||||
this.mvc.perform(get("/password").with(httpBasic("user", "password"))).andExpect(content().string("password"));
|
||||
// @formatter:off
|
||||
this.mvc.perform(get("/password").with(userCredentials()))
|
||||
.andExpect(content().string("password"));
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
public void loginWhenAuthenticationManagerRefIsNotAProviderManagerThenKeepsCredentialsAccordingly()
|
||||
throws Exception {
|
||||
this.spring.configLocations(xml("AuthenticationManagerRefNotProviderManager")).autowire();
|
||||
this.mvc.perform(get("/password").with(httpBasic("user", "password"))).andExpect(content().string("password"));
|
||||
// @formatter:off
|
||||
this.mvc.perform(get("/password").with(userCredentials()))
|
||||
.andExpect(content().string("password"));
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -488,12 +582,18 @@ public class MiscHttpConfigTests {
|
|||
this.spring.configLocations(xml("JeeFilter")).autowire();
|
||||
Principal user = mock(Principal.class);
|
||||
given(user.getName()).willReturn("joe");
|
||||
this.mvc.perform(get("/roles").principal(user).with((request) -> {
|
||||
request.addUserRole("admin");
|
||||
request.addUserRole("user");
|
||||
request.addUserRole("unmapped");
|
||||
return request;
|
||||
})).andExpect(content().string("ROLE_admin,ROLE_user"));
|
||||
// @formatter:off
|
||||
MockHttpServletRequestBuilder rolesRequest = get("/roles")
|
||||
.principal(user)
|
||||
.with((request) -> {
|
||||
request.addUserRole("admin");
|
||||
request.addUserRole("user");
|
||||
request.addUserRole("unmapped");
|
||||
return request;
|
||||
});
|
||||
this.mvc.perform(rolesRequest)
|
||||
.andExpect(content().string("ROLE_admin,ROLE_user"));
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -503,15 +603,23 @@ public class MiscHttpConfigTests {
|
|||
Object details = mock(Object.class);
|
||||
AuthenticationDetailsSource source = this.spring.getContext().getBean(AuthenticationDetailsSource.class);
|
||||
given(source.buildDetails(any(Object.class))).willReturn(details);
|
||||
this.mvc.perform(get("/details").with(httpBasic("user", "password")))
|
||||
RequestPostProcessor x509 = x509("classpath:org/springframework/security/config/http/MiscHttpConfigTests-certificate.pem");
|
||||
// @formatter:off
|
||||
this.mvc.perform(get("/details").with(userCredentials()))
|
||||
.andExpect(content().string(details.getClass().getName()));
|
||||
this.mvc.perform(get("/details")
|
||||
.with(x509("classpath:org/springframework/security/config/http/MiscHttpConfigTests-certificate.pem")))
|
||||
this.mvc.perform(get("/details").with(x509))
|
||||
.andExpect(content().string(details.getClass().getName()));
|
||||
MockHttpSession session = (MockHttpSession) this.mvc
|
||||
.perform(post("/login").param("username", "user").param("password", "password").with(csrf()))
|
||||
.andReturn().getRequest().getSession(false);
|
||||
this.mvc.perform(get("/details").session(session)).andExpect(content().string(details.getClass().getName()));
|
||||
MockHttpServletRequestBuilder loginRequest = post("/login")
|
||||
.param("username", "user")
|
||||
.param("password", "password")
|
||||
.with(csrf());
|
||||
MockHttpSession session = (MockHttpSession) this.mvc.perform(loginRequest)
|
||||
.andReturn()
|
||||
.getRequest()
|
||||
.getSession(false);
|
||||
this.mvc.perform(get("/details").session(session))
|
||||
.andExpect(content().string(details.getClass().getName()));
|
||||
// @formatter:on
|
||||
assertThat(ReflectionTestUtils.getField(getFilter(OpenIDAuthenticationFilter.class),
|
||||
"authenticationDetailsSource")).isEqualTo(source);
|
||||
}
|
||||
|
@ -521,7 +629,10 @@ public class MiscHttpConfigTests {
|
|||
this.spring.configLocations(xml("Jaas")).autowire();
|
||||
AuthorityGranter granter = this.spring.getContext().getBean(AuthorityGranter.class);
|
||||
given(granter.grant(any(Principal.class))).willReturn(new HashSet<>(Arrays.asList("USER")));
|
||||
this.mvc.perform(get("/username").with(httpBasic("user", "password"))).andExpect(content().string("user"));
|
||||
// @formatter:off
|
||||
this.mvc.perform(get("/username").with(userCredentials()))
|
||||
.andExpect(content().string("user"));
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -556,7 +667,10 @@ public class MiscHttpConfigTests {
|
|||
@Test
|
||||
public void getWhenUsingCustomAccessDecisionManagerThenAuthorizesAccordingly() throws Exception {
|
||||
this.spring.configLocations(xml("CustomAccessDecisionManager")).autowire();
|
||||
this.mvc.perform(get("/unprotected").with(httpBasic("user", "password"))).andExpect(status().isForbidden());
|
||||
// @formatter:off
|
||||
this.mvc.perform(get("/unprotected").with(userCredentials()))
|
||||
.andExpect(status().isForbidden());
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -565,15 +679,25 @@ public class MiscHttpConfigTests {
|
|||
@Test
|
||||
public void authenticateWhenUsingPortMapperThenRedirectsAppropriately() throws Exception {
|
||||
this.spring.configLocations(xml("PortsMappedRequiresHttps")).autowire();
|
||||
// @formatter:off
|
||||
MockHttpSession session = (MockHttpSession) this.mvc.perform(get("https://localhost:9080/protected"))
|
||||
.andExpect(redirectedUrl("https://localhost:9443/login")).andReturn().getRequest().getSession(false);
|
||||
session = (MockHttpSession) this.mvc
|
||||
.perform(post("/login").param("username", "user").param("password", "password").session(session)
|
||||
.with(csrf()))
|
||||
.andExpect(redirectedUrl("https://localhost:9443/protected")).andReturn().getRequest()
|
||||
.andExpect(redirectedUrl("https://localhost:9443/login"))
|
||||
.andReturn()
|
||||
.getRequest()
|
||||
.getSession(false);
|
||||
MockHttpServletRequestBuilder loginRequest = post("/login")
|
||||
.param("username", "user")
|
||||
.param("password", "password")
|
||||
.session(session)
|
||||
.with(csrf());
|
||||
session = (MockHttpSession) this.mvc.perform(loginRequest)
|
||||
.andExpect(redirectedUrl("https://localhost:9443/protected"))
|
||||
.andReturn()
|
||||
.getRequest()
|
||||
.getSession(false);
|
||||
this.mvc.perform(get("http://localhost:9080/protected").session(session))
|
||||
.andExpect(redirectedUrl("https://localhost:9443/protected"));
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
private void redirectLogsTo(OutputStream os, Class<?> clazz) {
|
||||
|
@ -624,6 +748,21 @@ public class MiscHttpConfigTests {
|
|||
return proxy.getFilters(url);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static RequestPostProcessor userCredentials() {
|
||||
return httpBasic("user", "password");
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static RequestPostProcessor adminCredentials() {
|
||||
return httpBasic("admin", "password");
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static RequestPostProcessor postCredentials() {
|
||||
return httpBasic("poster", "password");
|
||||
}
|
||||
|
||||
private static String xml(String configName) {
|
||||
return CONFIG_LOCATION_PREFIX + "-" + configName + ".xml";
|
||||
}
|
||||
|
|
|
@ -24,7 +24,7 @@ import org.springframework.beans.factory.annotation.Autowired;
|
|||
import org.springframework.security.config.test.SpringTestRule;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.test.web.servlet.MockMvc;
|
||||
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
|
||||
import org.springframework.test.web.servlet.request.MockHttpServletRequestBuilder;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
|
||||
|
@ -53,10 +53,17 @@ public class MultiHttpBlockConfigTests {
|
|||
@Test
|
||||
public void requestWhenUsingMutuallyExclusiveHttpElementsThenIsRoutedAccordingly() throws Exception {
|
||||
this.spring.configLocations(this.xml("DistinctHttpElements")).autowire();
|
||||
this.mvc.perform(MockMvcRequestBuilders.get("/first").with(httpBasic("user", "password")))
|
||||
// @formatter:off
|
||||
this.mvc.perform(get("/first").with(httpBasic("user", "password")))
|
||||
.andExpect(status().isOk());
|
||||
this.mvc.perform(post("/second/login").param("username", "user").param("password", "password").with(csrf()))
|
||||
.andExpect(status().isFound()).andExpect(redirectedUrl("/"));
|
||||
MockHttpServletRequestBuilder formLoginRequest = post("/second/login")
|
||||
.param("username", "user")
|
||||
.param("password", "password")
|
||||
.with(csrf());
|
||||
this.mvc.perform(formLoginRequest)
|
||||
.andExpect(status().isFound())
|
||||
.andExpect(redirectedUrl("/"));
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -80,9 +87,19 @@ public class MultiHttpBlockConfigTests {
|
|||
public void requestWhenTargettingAuthenticationManagersToCorrespondingHttpElementsThenAuthenticationProceeds()
|
||||
throws Exception {
|
||||
this.spring.configLocations(this.xml("Sec1937")).autowire();
|
||||
this.mvc.perform(get("/first").with(httpBasic("first", "password")).with(csrf())).andExpect(status().isOk());
|
||||
this.mvc.perform(post("/second/login").param("username", "second").param("password", "password").with(csrf()))
|
||||
// @formatter:off
|
||||
MockHttpServletRequestBuilder basicLoginRequest = get("/first")
|
||||
.with(httpBasic("first", "password"))
|
||||
.with(csrf());
|
||||
this.mvc.perform(basicLoginRequest)
|
||||
.andExpect(status().isOk());
|
||||
MockHttpServletRequestBuilder formLoginRequest = post("/second/login")
|
||||
.param("username", "second")
|
||||
.param("password", "password")
|
||||
.with(csrf());
|
||||
this.mvc.perform(formLoginRequest)
|
||||
.andExpect(redirectedUrl("/"));
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
private String xml(String configName) {
|
||||
|
|
|
@ -72,24 +72,23 @@ public class NamespaceHttpBasicTests {
|
|||
@Test
|
||||
public void httpBasicWithPasswordEncoder() throws Exception {
|
||||
// @formatter:off
|
||||
loadContext("<http>\n" +
|
||||
" <intercept-url pattern=\"/**\" access=\"hasRole('USER')\" />\n" +
|
||||
" <http-basic />\n" +
|
||||
" </http>\n" +
|
||||
"\n" +
|
||||
" <authentication-manager id=\"authenticationManager\">\n" +
|
||||
" <authentication-provider>\n" +
|
||||
" <password-encoder ref=\"passwordEncoder\" />\n" +
|
||||
" <user-service>\n" +
|
||||
" <user name=\"user\" password=\"$2a$10$Zk1MxFEt7YYji4Ccy9xlfuewWzUMsmHZfy4UcCmNKVV6z5i/JNGJW\" authorities=\"ROLE_USER\"/>\n" +
|
||||
" </user-service>\n" +
|
||||
" </authentication-provider>\n" +
|
||||
" </authentication-manager>\n" +
|
||||
" <b:bean id=\"passwordEncoder\"\n" +
|
||||
" class=\"org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder\" />");
|
||||
// @formatter:on
|
||||
this.request.addHeader("Authorization",
|
||||
"Basic " + Base64.getEncoder().encodeToString("user:test".getBytes("UTF-8")));
|
||||
loadContext("<http>\n"
|
||||
+ " <intercept-url pattern=\"/**\" access=\"hasRole('USER')\" />\n"
|
||||
+ " <http-basic />\n"
|
||||
+ "</http>\n"
|
||||
+ "\n"
|
||||
+ "<authentication-manager id=\"authenticationManager\">\n"
|
||||
+ " <authentication-provider>\n"
|
||||
+ " <password-encoder ref=\"passwordEncoder\" />\n"
|
||||
+ " <user-service>\n"
|
||||
+ " <user name=\"user\" password=\"$2a$10$Zk1MxFEt7YYji4Ccy9xlfuewWzUMsmHZfy4UcCmNKVV6z5i/JNGJW\" authorities=\"ROLE_USER\"/>\n"
|
||||
+ " </user-service>\n"
|
||||
+ " </authentication-provider>\n"
|
||||
+ "</authentication-manager>\n"
|
||||
+ "<b:bean id=\"passwordEncoder\"\n"
|
||||
+ " class=\"org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder\" />");
|
||||
// @formatter:on
|
||||
this.request.addHeader("Authorization", "Basic " + Base64.getEncoder().encodeToString("user:test".getBytes("UTF-8")));
|
||||
this.springSecurityFilterChain.doFilter(this.request, this.response, this.chain);
|
||||
assertThat(this.response.getStatus()).isEqualTo(HttpServletResponse.SC_OK);
|
||||
}
|
||||
|
@ -98,12 +97,12 @@ public class NamespaceHttpBasicTests {
|
|||
@Test
|
||||
public void httpBasicUnauthorizedOnDefault() throws Exception {
|
||||
// @formatter:off
|
||||
loadContext("<http>\n" +
|
||||
" <intercept-url pattern=\"/**\" access=\"hasRole('USER')\" />\n" +
|
||||
" <http-basic />\n" +
|
||||
" </http>\n" +
|
||||
"\n" +
|
||||
" <authentication-manager />");
|
||||
loadContext("<http>\n"
|
||||
+ " <intercept-url pattern=\"/**\" access=\"hasRole('USER')\" />\n"
|
||||
+ " <http-basic />\n"
|
||||
+ "</http>\n"
|
||||
+ "\n"
|
||||
+ "<authentication-manager />");
|
||||
// @formatter:on
|
||||
this.springSecurityFilterChain.doFilter(this.request, this.response, this.chain);
|
||||
assertThat(this.response.getStatus()).isEqualTo(HttpServletResponse.SC_UNAUTHORIZED);
|
||||
|
|
|
@ -100,8 +100,11 @@ public class OAuth2ClientBeanDefinitionParserTests {
|
|||
@Test
|
||||
public void requestWhenAuthorizeThenRedirect() throws Exception {
|
||||
this.spring.configLocations(xml("Minimal")).autowire();
|
||||
MvcResult result = this.mvc.perform(get("/oauth2/authorization/google")).andExpect(status().is3xxRedirection())
|
||||
// @formatter:off
|
||||
MvcResult result = this.mvc.perform(get("/oauth2/authorization/google"))
|
||||
.andExpect(status().is3xxRedirection())
|
||||
.andReturn();
|
||||
// @formatter:on
|
||||
assertThat(result.getResponse().getRedirectedUrl()).matches(
|
||||
"https://accounts.google.com/o/oauth2/v2/auth\\?" + "response_type=code&client_id=google-client-id&"
|
||||
+ "scope=scope1%20scope2&state=.{15,}&redirect_uri=http://localhost/callback/google");
|
||||
|
@ -110,12 +113,20 @@ public class OAuth2ClientBeanDefinitionParserTests {
|
|||
@Test
|
||||
public void requestWhenCustomClientRegistrationRepositoryThenCalled() throws Exception {
|
||||
this.spring.configLocations(xml("CustomClientRegistrationRepository")).autowire();
|
||||
// @formatter:off
|
||||
ClientRegistration clientRegistration = CommonOAuth2Provider.GOOGLE.getBuilder("google")
|
||||
.clientId("google-client-id").clientSecret("google-client-secret")
|
||||
.redirectUri("http://localhost/callback/google").scope("scope1", "scope2").build();
|
||||
.clientId("google-client-id")
|
||||
.clientSecret("google-client-secret")
|
||||
.redirectUri("http://localhost/callback/google")
|
||||
.scope("scope1", "scope2")
|
||||
.build();
|
||||
// @formatter:on
|
||||
given(this.clientRegistrationRepository.findByRegistrationId(any())).willReturn(clientRegistration);
|
||||
MvcResult result = this.mvc.perform(get("/oauth2/authorization/google")).andExpect(status().is3xxRedirection())
|
||||
// @formatter:off
|
||||
MvcResult result = this.mvc.perform(get("/oauth2/authorization/google"))
|
||||
.andExpect(status().is3xxRedirection())
|
||||
.andReturn();
|
||||
// @formatter:on
|
||||
assertThat(result.getResponse().getRedirectedUrl()).matches(
|
||||
"https://accounts.google.com/o/oauth2/v2/auth\\?" + "response_type=code&client_id=google-client-id&"
|
||||
+ "scope=scope1%20scope2&state=.{15,}&redirect_uri=http://localhost/callback/google");
|
||||
|
@ -128,10 +139,13 @@ public class OAuth2ClientBeanDefinitionParserTests {
|
|||
ClientRegistration clientRegistration = this.clientRegistrationRepository.findByRegistrationId("google");
|
||||
OAuth2AuthorizationRequest authorizationRequest = createAuthorizationRequest(clientRegistration);
|
||||
given(this.authorizationRequestResolver.resolve(any())).willReturn(authorizationRequest);
|
||||
this.mvc.perform(get("/oauth2/authorization/google")).andExpect(status().is3xxRedirection())
|
||||
// @formatter:off
|
||||
this.mvc.perform(get("/oauth2/authorization/google"))
|
||||
.andExpect(status().is3xxRedirection())
|
||||
.andExpect(redirectedUrl("https://accounts.google.com/o/oauth2/v2/auth?"
|
||||
+ "response_type=code&client_id=google-client-id&"
|
||||
+ "scope=scope1%20scope2&state=state&redirect_uri=http://localhost/callback/google"));
|
||||
// @formatter:on
|
||||
verify(this.authorizationRequestResolver).resolve(any());
|
||||
}
|
||||
|
||||
|
@ -148,8 +162,11 @@ public class OAuth2ClientBeanDefinitionParserTests {
|
|||
MultiValueMap<String, String> params = new LinkedMultiValueMap<>();
|
||||
params.add("code", "code123");
|
||||
params.add("state", authorizationRequest.getState());
|
||||
// @formatter:off
|
||||
this.mvc.perform(get(authorizationRequest.getRedirectUri()).params(params))
|
||||
.andExpect(status().is3xxRedirection()).andExpect(redirectedUrl(authorizationRequest.getRedirectUri()));
|
||||
.andExpect(status().is3xxRedirection())
|
||||
.andExpect(redirectedUrl(authorizationRequest.getRedirectUri()));
|
||||
// @formatter:on
|
||||
ArgumentCaptor<OAuth2AuthorizedClient> authorizedClientCaptor = ArgumentCaptor
|
||||
.forClass(OAuth2AuthorizedClient.class);
|
||||
verify(this.authorizedClientRepository).saveAuthorizedClient(authorizedClientCaptor.capture(), any(), any(),
|
||||
|
@ -173,8 +190,11 @@ public class OAuth2ClientBeanDefinitionParserTests {
|
|||
MultiValueMap<String, String> params = new LinkedMultiValueMap<>();
|
||||
params.add("code", "code123");
|
||||
params.add("state", authorizationRequest.getState());
|
||||
// @formatter:off
|
||||
this.mvc.perform(get(authorizationRequest.getRedirectUri()).params(params))
|
||||
.andExpect(status().is3xxRedirection()).andExpect(redirectedUrl(authorizationRequest.getRedirectUri()));
|
||||
.andExpect(status().is3xxRedirection())
|
||||
.andExpect(redirectedUrl(authorizationRequest.getRedirectUri()));
|
||||
// @formatter:on
|
||||
verify(this.authorizedClientService).saveAuthorizedClient(any(), any());
|
||||
}
|
||||
|
||||
|
@ -192,10 +212,15 @@ public class OAuth2ClientBeanDefinitionParserTests {
|
|||
private static OAuth2AuthorizationRequest createAuthorizationRequest(ClientRegistration clientRegistration) {
|
||||
Map<String, Object> attributes = new HashMap<>();
|
||||
attributes.put(OAuth2ParameterNames.REGISTRATION_ID, clientRegistration.getRegistrationId());
|
||||
// @formatter:off
|
||||
return OAuth2AuthorizationRequest.authorizationCode()
|
||||
.authorizationUri(clientRegistration.getProviderDetails().getAuthorizationUri())
|
||||
.clientId(clientRegistration.getClientId()).redirectUri(clientRegistration.getRedirectUri())
|
||||
.scopes(clientRegistration.getScopes()).state("state").attributes(attributes).build();
|
||||
.scopes(clientRegistration.getScopes())
|
||||
.state("state")
|
||||
.attributes(attributes)
|
||||
.build();
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
private static String xml(String configName) {
|
||||
|
|
|
@ -144,7 +144,11 @@ public class OAuth2LoginBeanDefinitionParserTests {
|
|||
@Test
|
||||
public void requestLoginWhenMultiClientRegistrationThenReturnLoginPageWithClients() throws Exception {
|
||||
this.spring.configLocations(this.xml("MultiClientRegistration")).autowire();
|
||||
MvcResult result = this.mvc.perform(get("/login")).andExpect(status().is2xxSuccessful()).andReturn();
|
||||
// @formatter:off
|
||||
MvcResult result = this.mvc.perform(get("/login"))
|
||||
.andExpect(status().is2xxSuccessful())
|
||||
.andReturn();
|
||||
// @formatter:on
|
||||
assertThat(result.getResponse().getContentAsString())
|
||||
.contains("<a href=\"/oauth2/authorization/google-login\">Google</a>");
|
||||
assertThat(result.getResponse().getContentAsString())
|
||||
|
@ -155,8 +159,11 @@ public class OAuth2LoginBeanDefinitionParserTests {
|
|||
@Test
|
||||
public void requestWhenSingleClientRegistrationThenAutoRedirect() throws Exception {
|
||||
this.spring.configLocations(this.xml("SingleClientRegistration")).autowire();
|
||||
this.mvc.perform(get("/")).andExpect(status().is3xxRedirection())
|
||||
// @formatter:off
|
||||
this.mvc.perform(get("/"))
|
||||
.andExpect(status().is3xxRedirection())
|
||||
.andExpect(redirectedUrl("http://localhost/oauth2/authorization/google-login"));
|
||||
// @formatter:on
|
||||
verify(this.requestCache).saveRequest(any(), any());
|
||||
}
|
||||
|
||||
|
@ -165,8 +172,11 @@ public class OAuth2LoginBeanDefinitionParserTests {
|
|||
public void requestWhenSingleClientRegistrationAndRequestFaviconNotAuthenticatedThenRedirectDefaultLoginPage()
|
||||
throws Exception {
|
||||
this.spring.configLocations(this.xml("SingleClientRegistration")).autowire();
|
||||
this.mvc.perform(get("/favicon.ico").accept(new MediaType("image", "*"))).andExpect(status().is3xxRedirection())
|
||||
// @formatter:off
|
||||
this.mvc.perform(get("/favicon.ico").accept(new MediaType("image", "*")))
|
||||
.andExpect(status().is3xxRedirection())
|
||||
.andExpect(redirectedUrl("http://localhost/login"));
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
// gh-6812
|
||||
|
@ -174,8 +184,11 @@ public class OAuth2LoginBeanDefinitionParserTests {
|
|||
public void requestWhenSingleClientRegistrationAndRequestXHRNotAuthenticatedThenDoesNotRedirectForAuthorization()
|
||||
throws Exception {
|
||||
this.spring.configLocations(this.xml("SingleClientRegistration")).autowire();
|
||||
this.mvc.perform(get("/").header("X-Requested-With", "XMLHttpRequest")).andExpect(status().is3xxRedirection())
|
||||
// @formatter:off
|
||||
this.mvc.perform(get("/").header("X-Requested-With", "XMLHttpRequest"))
|
||||
.andExpect(status().is3xxRedirection())
|
||||
.andExpect(redirectedUrl("http://localhost/login"));
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -211,7 +224,10 @@ public class OAuth2LoginBeanDefinitionParserTests {
|
|||
MultiValueMap<String, String> params = new LinkedMultiValueMap<>();
|
||||
params.add("code", "code123");
|
||||
params.add("state", authorizationRequest.getState());
|
||||
this.mvc.perform(get("/login/oauth2/code/github-login").params(params)).andExpect(status().is2xxSuccessful());
|
||||
// @formatter:off
|
||||
this.mvc.perform(get("/login/oauth2/code/github-login").params(params))
|
||||
.andExpect(status().is2xxSuccessful());
|
||||
// @formatter:on
|
||||
ArgumentCaptor<Authentication> authenticationCaptor = ArgumentCaptor.forClass(Authentication.class);
|
||||
verify(this.authenticationSuccessHandler).onAuthenticationSuccess(any(), any(), authenticationCaptor.capture());
|
||||
Authentication authentication = authenticationCaptor.getValue();
|
||||
|
@ -257,8 +273,11 @@ public class OAuth2LoginBeanDefinitionParserTests {
|
|||
MultiValueMap<String, String> params = new LinkedMultiValueMap<>();
|
||||
params.add("code", "code123");
|
||||
params.add("state", authorizationRequest.getState());
|
||||
this.mvc.perform(get("/login/oauth2/code/google-login").params(params)).andExpect(status().is3xxRedirection())
|
||||
// @formatter:off
|
||||
this.mvc.perform(get("/login/oauth2/code/google-login").params(params))
|
||||
.andExpect(status().is3xxRedirection())
|
||||
.andExpect(redirectedUrl("/"));
|
||||
// @formatter:on
|
||||
verify(this.jwtDecoderFactory).createDecoder(any());
|
||||
verify(this.requestCache).getRequest(any(), any());
|
||||
}
|
||||
|
@ -302,7 +321,10 @@ public class OAuth2LoginBeanDefinitionParserTests {
|
|||
given(this.jwtDecoderFactory.createDecoder(any())).willReturn((token) -> jwt);
|
||||
given(this.userAuthoritiesMapper.mapAuthorities(any()))
|
||||
.willReturn((Collection) AuthorityUtils.createAuthorityList("ROLE_OIDC_USER"));
|
||||
this.mvc.perform(get("/login/oauth2/code/google-login").params(params)).andExpect(status().is2xxSuccessful());
|
||||
// @formatter:off
|
||||
this.mvc.perform(get("/login/oauth2/code/google-login").params(params))
|
||||
.andExpect(status().is2xxSuccessful());
|
||||
// @formatter:on
|
||||
authenticationCaptor = ArgumentCaptor.forClass(Authentication.class);
|
||||
verify(this.authenticationSuccessHandler, times(2)).onAuthenticationSuccess(any(), any(),
|
||||
authenticationCaptor.capture());
|
||||
|
@ -330,7 +352,10 @@ public class OAuth2LoginBeanDefinitionParserTests {
|
|||
MultiValueMap<String, String> params = new LinkedMultiValueMap<>();
|
||||
params.add("code", "code123");
|
||||
params.add("state", authorizationRequest.getState());
|
||||
this.mvc.perform(get("/login/oauth2/github-login").params(params)).andExpect(status().is2xxSuccessful());
|
||||
// @formatter:off
|
||||
this.mvc.perform(get("/login/oauth2/github-login").params(params))
|
||||
.andExpect(status().is2xxSuccessful());
|
||||
// @formatter:on
|
||||
ArgumentCaptor<Authentication> authenticationCaptor = ArgumentCaptor.forClass(Authentication.class);
|
||||
verify(this.authenticationSuccessHandler).onAuthenticationSuccess(any(), any(), authenticationCaptor.capture());
|
||||
Authentication authentication = authenticationCaptor.getValue();
|
||||
|
@ -342,7 +367,10 @@ public class OAuth2LoginBeanDefinitionParserTests {
|
|||
public void requestWhenCustomAuthorizationRequestResolverThenCalled() throws Exception {
|
||||
this.spring.configLocations(this.xml("SingleClientRegistration-WithCustomAuthorizationRequestResolver"))
|
||||
.autowire();
|
||||
this.mvc.perform(get("/oauth2/authorization/google-login")).andExpect(status().is3xxRedirection());
|
||||
// @formatter:off
|
||||
this.mvc.perform(get("/oauth2/authorization/google-login"))
|
||||
.andExpect(status().is3xxRedirection());
|
||||
// @formatter:on
|
||||
verify(this.authorizationRequestResolver).resolve(any());
|
||||
}
|
||||
|
||||
|
@ -350,15 +378,21 @@ public class OAuth2LoginBeanDefinitionParserTests {
|
|||
@Test
|
||||
public void requestWhenMultiClientRegistrationThenRedirectDefaultLoginPage() throws Exception {
|
||||
this.spring.configLocations(this.xml("MultiClientRegistration")).autowire();
|
||||
this.mvc.perform(get("/")).andExpect(status().is3xxRedirection())
|
||||
// @formatter:off
|
||||
this.mvc.perform(get("/"))
|
||||
.andExpect(status().is3xxRedirection())
|
||||
.andExpect(redirectedUrl("http://localhost/login"));
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
public void requestWhenCustomLoginPageThenRedirectCustomLoginPage() throws Exception {
|
||||
this.spring.configLocations(this.xml("SingleClientRegistration-WithCustomLoginPage")).autowire();
|
||||
this.mvc.perform(get("/")).andExpect(status().is3xxRedirection())
|
||||
// @formatter:off
|
||||
this.mvc.perform(get("/"))
|
||||
.andExpect(status().is3xxRedirection())
|
||||
.andExpect(redirectedUrl("http://localhost/custom-login"));
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
// gh-6802
|
||||
|
@ -366,8 +400,11 @@ public class OAuth2LoginBeanDefinitionParserTests {
|
|||
public void requestWhenSingleClientRegistrationAndFormLoginConfiguredThenRedirectDefaultLoginPage()
|
||||
throws Exception {
|
||||
this.spring.configLocations(this.xml("SingleClientRegistration-WithFormLogin")).autowire();
|
||||
this.mvc.perform(get("/")).andExpect(status().is3xxRedirection())
|
||||
// @formatter:off
|
||||
this.mvc.perform(get("/"))
|
||||
.andExpect(status().is3xxRedirection())
|
||||
.andExpect(redirectedUrl("http://localhost/login"));
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -444,7 +481,11 @@ public class OAuth2LoginBeanDefinitionParserTests {
|
|||
OAuth2AuthorizedClient authorizedClient = new OAuth2AuthorizedClient(clientRegistration, "user",
|
||||
TestOAuth2AccessTokens.noScopes());
|
||||
given(this.authorizedClientRepository.loadAuthorizedClient(any(), any(), any())).willReturn(authorizedClient);
|
||||
this.mvc.perform(get("/authorized-client")).andExpect(status().isOk()).andExpect(content().string("resolved"));
|
||||
// @formatter:off
|
||||
this.mvc.perform(get("/authorized-client"))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(content().string("resolved"));
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
private String xml(String configName) {
|
||||
|
|
|
@ -50,6 +50,7 @@ import org.junit.Rule;
|
|||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Mockito;
|
||||
import org.springframework.test.web.servlet.request.MockHttpServletRequestBuilder;
|
||||
import org.w3c.dom.Element;
|
||||
|
||||
import org.springframework.beans.factory.DisposableBean;
|
||||
|
@ -137,7 +138,10 @@ public class OAuth2ResourceServerBeanDefinitionParserTests {
|
|||
this.spring.configLocations(xml("JwtRestOperations"), xml("Jwt")).autowire();
|
||||
mockRestOperations(jwks("Default"));
|
||||
String token = this.token("ValidNoScopes");
|
||||
this.mvc.perform(get("/").header("Authorization", "Bearer " + token)).andExpect(status().isNotFound());
|
||||
// @formatter:off
|
||||
this.mvc.perform(get("/").header("Authorization", "Bearer " + token))
|
||||
.andExpect(status().isNotFound());
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -145,7 +149,10 @@ public class OAuth2ResourceServerBeanDefinitionParserTests {
|
|||
this.spring.configLocations(xml("WebServer"), xml("JwkSetUri")).autowire();
|
||||
mockWebServer(jwks("Default"));
|
||||
String token = this.token("ValidNoScopes");
|
||||
this.mvc.perform(get("/").header("Authorization", "Bearer " + token)).andExpect(status().isNotFound());
|
||||
// @formatter:off
|
||||
this.mvc.perform(get("/").header("Authorization", "Bearer " + token))
|
||||
.andExpect(status().isNotFound());
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -153,8 +160,11 @@ public class OAuth2ResourceServerBeanDefinitionParserTests {
|
|||
this.spring.configLocations(xml("JwtRestOperations"), xml("Jwt")).autowire();
|
||||
mockRestOperations(jwks("Default"));
|
||||
String token = this.token("Expired");
|
||||
this.mvc.perform(get("/").header("Authorization", "Bearer " + token)).andExpect(status().isUnauthorized())
|
||||
// @formatter:off
|
||||
this.mvc.perform(get("/").header("Authorization", "Bearer " + token))
|
||||
.andExpect(status().isUnauthorized())
|
||||
.andExpect(invalidTokenHeader("An error occurred while attempting to decode the Jwt"));
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -162,8 +172,11 @@ public class OAuth2ResourceServerBeanDefinitionParserTests {
|
|||
this.spring.configLocations(xml("JwtRestOperations"), xml("Jwt")).autowire();
|
||||
mockRestOperations("malformed");
|
||||
String token = this.token("ValidNoScopes");
|
||||
this.mvc.perform(get("/").header("Authorization", "Bearer " + token)).andExpect(status().isUnauthorized())
|
||||
// @formatter:off
|
||||
this.mvc.perform(get("/").header("Authorization", "Bearer " + token))
|
||||
.andExpect(status().isUnauthorized())
|
||||
.andExpect(header().string("WWW-Authenticate", "Bearer"));
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -171,15 +184,21 @@ public class OAuth2ResourceServerBeanDefinitionParserTests {
|
|||
this.spring.configLocations(xml("WebServer"), xml("JwkSetUri")).autowire();
|
||||
this.web.shutdown();
|
||||
String token = this.token("ValidNoScopes");
|
||||
this.mvc.perform(get("/").header("Authorization", "Bearer " + token)).andExpect(status().isUnauthorized())
|
||||
// @formatter:off
|
||||
this.mvc.perform(get("/").header("Authorization", "Bearer " + token))
|
||||
.andExpect(status().isUnauthorized())
|
||||
.andExpect(header().string("WWW-Authenticate", "Bearer"));
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getWhenMalformedBearerTokenThenInvalidToken() throws Exception {
|
||||
this.spring.configLocations(xml("JwkSetUri")).autowire();
|
||||
// @formatter:off
|
||||
this.mvc.perform(get("/").header("Authorization", "Bearer an\"invalid\"token"))
|
||||
.andExpect(status().isUnauthorized()).andExpect(invalidTokenHeader("Bearer token is malformed"));
|
||||
.andExpect(status().isUnauthorized())
|
||||
.andExpect(invalidTokenHeader("Bearer token is malformed"));
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -187,17 +206,22 @@ public class OAuth2ResourceServerBeanDefinitionParserTests {
|
|||
this.spring.configLocations(xml("JwtRestOperations"), xml("Jwt")).autowire();
|
||||
mockRestOperations(jwks("Default"));
|
||||
String token = this.token("MalformedPayload");
|
||||
this.mvc.perform(get("/").header("Authorization", "Bearer " + token)).andExpect(status().isUnauthorized())
|
||||
.andExpect(
|
||||
invalidTokenHeader("An error occurred while attempting to decode the Jwt: Malformed payload"));
|
||||
// @formatter:off
|
||||
this.mvc.perform(get("/").header("Authorization", "Bearer " + token))
|
||||
.andExpect(status().isUnauthorized())
|
||||
.andExpect(invalidTokenHeader("An error occurred while attempting to decode the Jwt: Malformed payload"));
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getWhenUnsignedBearerTokenThenInvalidToken() throws Exception {
|
||||
this.spring.configLocations(xml("JwkSetUri")).autowire();
|
||||
String token = this.token("Unsigned");
|
||||
this.mvc.perform(get("/").header("Authorization", "Bearer " + token)).andExpect(status().isUnauthorized())
|
||||
// @formatter:off
|
||||
this.mvc.perform(get("/").header("Authorization", "Bearer " + token))
|
||||
.andExpect(status().isUnauthorized())
|
||||
.andExpect(invalidTokenHeader("Unsupported algorithm of none"));
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -205,16 +229,21 @@ public class OAuth2ResourceServerBeanDefinitionParserTests {
|
|||
this.spring.configLocations(xml("JwtRestOperations"), xml("Jwt")).autowire();
|
||||
this.mockRestOperations(jwks("Default"));
|
||||
String token = this.token("TooEarly");
|
||||
this.mvc.perform(get("/").header("Authorization", "Bearer " + token)).andExpect(status().isUnauthorized())
|
||||
// @formatter:off
|
||||
this.mvc.perform(get("/").header("Authorization", "Bearer " + token))
|
||||
.andExpect(status().isUnauthorized())
|
||||
.andExpect(invalidTokenHeader("An error occurred while attempting to decode the Jwt"));
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getWhenBearerTokenInTwoPlacesThenInvalidRequest() throws Exception {
|
||||
this.spring.configLocations(xml("JwkSetUri")).autowire();
|
||||
// @formatter:off
|
||||
this.mvc.perform(get("/").header("Authorization", "Bearer token").param("access_token", "token"))
|
||||
.andExpect(status().isBadRequest())
|
||||
.andExpect(invalidRequestHeader("Found multiple bearer tokens in the request"));
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -223,8 +252,11 @@ public class OAuth2ResourceServerBeanDefinitionParserTests {
|
|||
MultiValueMap<String, String> params = new LinkedMultiValueMap<>();
|
||||
params.add("access_token", "token1");
|
||||
params.add("access_token", "token2");
|
||||
this.mvc.perform(get("/").params(params)).andExpect(status().isBadRequest())
|
||||
// @formatter:off
|
||||
this.mvc.perform(get("/").params(params))
|
||||
.andExpect(status().isBadRequest())
|
||||
.andExpect(invalidRequestHeader("Found multiple bearer tokens in the request"));
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -240,8 +272,11 @@ public class OAuth2ResourceServerBeanDefinitionParserTests {
|
|||
@Test
|
||||
public void getWhenNoBearerTokenThenUnauthorized() throws Exception {
|
||||
this.spring.configLocations(xml("JwkSetUri")).autowire();
|
||||
this.mvc.perform(get("/")).andExpect(status().isUnauthorized())
|
||||
// @formatter:off
|
||||
this.mvc.perform(get("/"))
|
||||
.andExpect(status().isUnauthorized())
|
||||
.andExpect(header().string(HttpHeaders.WWW_AUTHENTICATE, "Bearer"));
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -249,8 +284,10 @@ public class OAuth2ResourceServerBeanDefinitionParserTests {
|
|||
this.spring.configLocations(xml("JwtRestOperations"), xml("Jwt")).autowire();
|
||||
mockRestOperations(jwks("Default"));
|
||||
String token = this.token("ValidMessageReadScope");
|
||||
// @formatter:off
|
||||
this.mvc.perform(get("/requires-read-scope").header("Authorization", "Bearer " + token))
|
||||
.andExpect(status().isNotFound());
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -258,8 +295,11 @@ public class OAuth2ResourceServerBeanDefinitionParserTests {
|
|||
this.spring.configLocations(xml("JwtRestOperations"), xml("Jwt")).autowire();
|
||||
mockRestOperations(jwks("Default"));
|
||||
String token = this.token("ValidNoScopes");
|
||||
// @formatter:off
|
||||
this.mvc.perform(get("/requires-read-scope").header("Authorization", "Bearer " + token))
|
||||
.andExpect(status().isForbidden()).andExpect(insufficientScopeHeader());
|
||||
.andExpect(status().isForbidden())
|
||||
.andExpect(insufficientScopeHeader());
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -267,8 +307,11 @@ public class OAuth2ResourceServerBeanDefinitionParserTests {
|
|||
this.spring.configLocations(xml("JwtRestOperations"), xml("Jwt")).autowire();
|
||||
mockRestOperations(jwks("Default"));
|
||||
String token = this.token("ValidMessageWriteScp");
|
||||
// @formatter:off
|
||||
this.mvc.perform(get("/requires-read-scope").header("Authorization", "Bearer " + token))
|
||||
.andExpect(status().isForbidden()).andExpect(insufficientScopeHeader());
|
||||
.andExpect(status().isForbidden())
|
||||
.andExpect(insufficientScopeHeader());
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -276,8 +319,11 @@ public class OAuth2ResourceServerBeanDefinitionParserTests {
|
|||
this.spring.configLocations(xml("JwtRestOperations"), xml("Jwt")).autowire();
|
||||
mockRestOperations(jwks("Empty"));
|
||||
String token = this.token("ValidNoScopes");
|
||||
this.mvc.perform(get("/").header("Authorization", "Bearer " + token)).andExpect(status().isUnauthorized())
|
||||
// @formatter:off
|
||||
this.mvc.perform(get("/").header("Authorization", "Bearer " + token))
|
||||
.andExpect(status().isUnauthorized())
|
||||
.andExpect(invalidTokenHeader("An error occurred while attempting to decode the Jwt"));
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -285,8 +331,10 @@ public class OAuth2ResourceServerBeanDefinitionParserTests {
|
|||
this.spring.configLocations(xml("JwtRestOperations"), xml("Jwt")).autowire();
|
||||
mockRestOperations(jwks("TwoKeys"));
|
||||
String token = this.token("ValidNoScopes");
|
||||
// @formatter:off
|
||||
this.mvc.perform(get("/authenticated").header("Authorization", "Bearer " + token))
|
||||
.andExpect(status().isNotFound());
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -294,8 +342,10 @@ public class OAuth2ResourceServerBeanDefinitionParserTests {
|
|||
this.spring.configLocations(xml("JwtRestOperations"), xml("Jwt")).autowire();
|
||||
mockRestOperations(jwks("TwoKeys"));
|
||||
String token = this.token("Kid");
|
||||
// @formatter:off
|
||||
this.mvc.perform(get("/authenticated").header("Authorization", "Bearer " + token))
|
||||
.andExpect(status().isNotFound());
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -303,17 +353,21 @@ public class OAuth2ResourceServerBeanDefinitionParserTests {
|
|||
this.spring.configLocations(xml("JwtRestOperations"), xml("Jwt")).autowire();
|
||||
mockRestOperations(jwks("Default"));
|
||||
String token = this.token("ValidNoScopes");
|
||||
// @formatter:off
|
||||
this.mvc.perform(post("/authenticated").header("Authorization", "Bearer " + token))
|
||||
.andExpect(status().isNotFound());
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
public void postWhenNoBearerTokenThenCsrfDenies() throws Exception {
|
||||
this.spring.configLocations(xml("JwkSetUri")).autowire();
|
||||
this.mvc.perform(post("/authenticated")).andExpect(status().isForbidden())
|
||||
.andExpect(header().string(HttpHeaders.WWW_AUTHENTICATE, "Bearer")); // different
|
||||
// from
|
||||
// DSL
|
||||
// @formatter:off
|
||||
this.mvc.perform(post("/authenticated"))
|
||||
.andExpect(status().isForbidden())
|
||||
// different from DSL
|
||||
.andExpect(header().string(HttpHeaders.WWW_AUTHENTICATE, "Bearer"));
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -321,9 +375,11 @@ public class OAuth2ResourceServerBeanDefinitionParserTests {
|
|||
this.spring.configLocations(xml("JwtRestOperations"), xml("Jwt")).autowire();
|
||||
mockRestOperations(jwks("Default"));
|
||||
String token = this.token("Expired");
|
||||
// @formatter:off
|
||||
this.mvc.perform(post("/authenticated").header("Authorization", "Bearer " + token))
|
||||
.andExpect(status().isUnauthorized())
|
||||
.andExpect(invalidTokenHeader("An error occurred while attempting to decode the Jwt"));
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -331,8 +387,11 @@ public class OAuth2ResourceServerBeanDefinitionParserTests {
|
|||
this.spring.configLocations(xml("JwtRestOperations"), xml("Jwt")).autowire();
|
||||
mockRestOperations(jwks("Default"));
|
||||
String token = this.token("ValidNoScopes");
|
||||
// @formatter:off
|
||||
MvcResult result = this.mvc.perform(get("/").header("Authorization", "Bearer " + token))
|
||||
.andExpect(status().isNotFound()).andReturn();
|
||||
.andExpect(status().isNotFound())
|
||||
.andReturn();
|
||||
// @formatter:on
|
||||
assertThat(result.getRequest().getSession(false)).isNull();
|
||||
}
|
||||
|
||||
|
@ -340,15 +399,22 @@ public class OAuth2ResourceServerBeanDefinitionParserTests {
|
|||
public void requestWhenIntrospectionThenSessionIsNotCreated() throws Exception {
|
||||
this.spring.configLocations(xml("WebServer"), xml("IntrospectionUri")).autowire();
|
||||
mockWebServer(json("Active"));
|
||||
// @formatter:off
|
||||
MvcResult result = this.mvc.perform(get("/authenticated").header("Authorization", "Bearer token"))
|
||||
.andExpect(status().isNotFound()).andReturn();
|
||||
.andExpect(status().isNotFound())
|
||||
.andReturn();
|
||||
// @formatter:on
|
||||
assertThat(result.getRequest().getSession(false)).isNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void requestWhenNoBearerTokenThenSessionIsCreated() throws Exception {
|
||||
this.spring.configLocations(xml("JwkSetUri")).autowire();
|
||||
MvcResult result = this.mvc.perform(get("/")).andExpect(status().isUnauthorized()).andReturn();
|
||||
// @formatter:off
|
||||
MvcResult result = this.mvc.perform(get("/"))
|
||||
.andExpect(status().isUnauthorized())
|
||||
.andReturn();
|
||||
// @formatter:on
|
||||
assertThat(result.getRequest().getSession(false)).isNotNull();
|
||||
}
|
||||
|
||||
|
@ -357,8 +423,11 @@ public class OAuth2ResourceServerBeanDefinitionParserTests {
|
|||
this.spring.configLocations(xml("JwtRestOperations"), xml("AlwaysSessionCreation")).autowire();
|
||||
mockRestOperations(jwks("Default"));
|
||||
String token = this.token("ValidNoScopes");
|
||||
// @formatter:off
|
||||
MvcResult result = this.mvc.perform(get("/").header("Authorization", "Bearer " + token))
|
||||
.andExpect(status().isNotFound()).andReturn();
|
||||
.andExpect(status().isNotFound())
|
||||
.andReturn();
|
||||
// @formatter:on
|
||||
assertThat(result.getRequest().getSession(false)).isNotNull();
|
||||
}
|
||||
|
||||
|
@ -381,9 +450,12 @@ public class OAuth2ResourceServerBeanDefinitionParserTests {
|
|||
this.spring.configLocations(xml("MockJwtDecoder"), xml("AllowBearerTokenInBody")).autowire();
|
||||
JwtDecoder decoder = this.spring.getContext().getBean(JwtDecoder.class);
|
||||
given(decoder.decode(anyString())).willReturn(TestJwts.jwt().build());
|
||||
// @formatter:off
|
||||
this.mvc.perform(get("/authenticated").header("Authorization", "Bearer token"))
|
||||
.andExpect(status().isNotFound());
|
||||
this.mvc.perform(post("/authenticated").param("access_token", "token")).andExpect(status().isNotFound());
|
||||
this.mvc.perform(post("/authenticated").param("access_token", "token"))
|
||||
.andExpect(status().isNotFound());
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -392,9 +464,12 @@ public class OAuth2ResourceServerBeanDefinitionParserTests {
|
|||
this.spring.configLocations(xml("MockJwtDecoder"), xml("AllowBearerTokenInQuery")).autowire();
|
||||
JwtDecoder decoder = this.spring.getContext().getBean(JwtDecoder.class);
|
||||
given(decoder.decode(anyString())).willReturn(TestJwts.jwt().build());
|
||||
// @formatter:off
|
||||
this.mvc.perform(get("/authenticated").header("Authorization", "Bearer token"))
|
||||
.andExpect(status().isNotFound());
|
||||
this.mvc.perform(get("/authenticated").param("access_token", "token")).andExpect(status().isNotFound());
|
||||
this.mvc.perform(get("/authenticated").param("access_token", "token"))
|
||||
.andExpect(status().isNotFound());
|
||||
// @formatter:on
|
||||
verify(decoder, times(2)).decode("token");
|
||||
}
|
||||
|
||||
|
@ -402,18 +477,29 @@ public class OAuth2ResourceServerBeanDefinitionParserTests {
|
|||
public void requestWhenBearerTokenResolverAllowsRequestBodyAndRequestContainsTwoTokensThenInvalidRequest()
|
||||
throws Exception {
|
||||
this.spring.configLocations(xml("MockJwtDecoder"), xml("AllowBearerTokenInBody")).autowire();
|
||||
this.mvc.perform(post("/authenticated").param("access_token", "token").header("Authorization", "Bearer token")
|
||||
.with(csrf())).andExpect(status().isBadRequest())
|
||||
// @formatter:off
|
||||
MockHttpServletRequestBuilder request = post("/authenticated")
|
||||
.param("access_token", "token")
|
||||
.header("Authorization", "Bearer token")
|
||||
.with(csrf());
|
||||
this.mvc.perform(request)
|
||||
.andExpect(status().isBadRequest())
|
||||
.andExpect(header().string(HttpHeaders.WWW_AUTHENTICATE, containsString("invalid_request")));
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
public void requestWhenBearerTokenResolverAllowsQueryParameterAndRequestContainsTwoTokensThenInvalidRequest()
|
||||
throws Exception {
|
||||
this.spring.configLocations(xml("MockJwtDecoder"), xml("AllowBearerTokenInQuery")).autowire();
|
||||
this.mvc.perform(get("/authenticated").header("Authorization", "Bearer token").param("access_token", "token"))
|
||||
// @formatter:off
|
||||
MockHttpServletRequestBuilder request = get("/authenticated")
|
||||
.header("Authorization", "Bearer token")
|
||||
.param("access_token", "token");
|
||||
this.mvc.perform(request)
|
||||
.andExpect(status().isBadRequest())
|
||||
.andExpect(header().string(HttpHeaders.WWW_AUTHENTICATE, containsString("invalid_request")));
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -444,9 +530,11 @@ public class OAuth2ResourceServerBeanDefinitionParserTests {
|
|||
this.spring.configLocations(xml("MockJwtDecoder"), xml("AuthenticationEntryPoint")).autowire();
|
||||
JwtDecoder decoder = this.spring.getContext().getBean(JwtDecoder.class);
|
||||
Mockito.when(decoder.decode(anyString())).thenThrow(JwtException.class);
|
||||
// @formatter:off
|
||||
this.mvc.perform(get("/authenticated").header("Authorization", "Bearer invalid_token"))
|
||||
.andExpect(status().isUnauthorized())
|
||||
.andExpect(header().string(HttpHeaders.WWW_AUTHENTICATE, startsWith("Bearer realm=\"myRealm\"")));
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -454,9 +542,11 @@ public class OAuth2ResourceServerBeanDefinitionParserTests {
|
|||
this.spring.configLocations(xml("MockJwtDecoder"), xml("AccessDeniedHandler")).autowire();
|
||||
JwtDecoder decoder = this.spring.getContext().getBean(JwtDecoder.class);
|
||||
given(decoder.decode(anyString())).willReturn(TestJwts.jwt().build());
|
||||
// @formatter:off
|
||||
this.mvc.perform(get("/authenticated").header("Authorization", "Bearer insufficiently_scoped"))
|
||||
.andExpect(status().isForbidden())
|
||||
.andExpect(header().string(HttpHeaders.WWW_AUTHENTICATE, startsWith("Bearer realm=\"myRealm\"")));
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -467,8 +557,11 @@ public class OAuth2ResourceServerBeanDefinitionParserTests {
|
|||
OAuth2TokenValidator<Jwt> jwtValidator = this.spring.getContext().getBean(OAuth2TokenValidator.class);
|
||||
OAuth2Error error = new OAuth2Error("custom-error", "custom-description", "custom-uri");
|
||||
given(jwtValidator.validate(any(Jwt.class))).willReturn(OAuth2TokenValidatorResult.failure(error));
|
||||
this.mvc.perform(get("/").header("Authorization", "Bearer " + token)).andExpect(status().isUnauthorized())
|
||||
// @formatter:off
|
||||
this.mvc.perform(get("/").header("Authorization", "Bearer " + token))
|
||||
.andExpect(status().isUnauthorized())
|
||||
.andExpect(header().string(HttpHeaders.WWW_AUTHENTICATE, containsString("custom-description")));
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -476,7 +569,10 @@ public class OAuth2ResourceServerBeanDefinitionParserTests {
|
|||
this.spring.configLocations(xml("UnexpiredJwtClockSkew"), xml("Jwt")).autowire();
|
||||
mockRestOperations(jwks("Default"));
|
||||
String token = this.token("ExpiresAt4687177990");
|
||||
this.mvc.perform(get("/").header("Authorization", "Bearer " + token)).andExpect(status().isNotFound());
|
||||
// @formatter:off
|
||||
this.mvc.perform(get("/").header("Authorization", "Bearer " + token))
|
||||
.andExpect(status().isNotFound());
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -484,8 +580,11 @@ public class OAuth2ResourceServerBeanDefinitionParserTests {
|
|||
this.spring.configLocations(xml("ExpiredJwtClockSkew"), xml("Jwt")).autowire();
|
||||
mockRestOperations(jwks("Default"));
|
||||
String token = this.token("ExpiresAt4687177990");
|
||||
this.mvc.perform(get("/").header("Authorization", "Bearer " + token)).andExpect(status().isUnauthorized())
|
||||
// @formatter:off
|
||||
this.mvc.perform(get("/").header("Authorization", "Bearer " + token))
|
||||
.andExpect(status().isUnauthorized())
|
||||
.andExpect(invalidTokenHeader("Jwt expired at"));
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -498,7 +597,10 @@ public class OAuth2ResourceServerBeanDefinitionParserTests {
|
|||
.willReturn(new JwtAuthenticationToken(TestJwts.jwt().build(), Collections.emptyList()));
|
||||
JwtDecoder jwtDecoder = this.spring.getContext().getBean(JwtDecoder.class);
|
||||
given(jwtDecoder.decode(anyString())).willReturn(TestJwts.jwt().build());
|
||||
this.mvc.perform(get("/").header("Authorization", "Bearer token")).andExpect(status().isNotFound());
|
||||
// @formatter:off
|
||||
this.mvc.perform(get("/").header("Authorization", "Bearer token"))
|
||||
.andExpect(status().isNotFound());
|
||||
// @formatter:on
|
||||
verify(jwtAuthenticationConverter).convert(any(Jwt.class));
|
||||
}
|
||||
|
||||
|
@ -506,49 +608,64 @@ public class OAuth2ResourceServerBeanDefinitionParserTests {
|
|||
public void requestWhenUsingPublicKeyAndValidTokenThenAuthenticates() throws Exception {
|
||||
this.spring.configLocations(xml("SingleKey"), xml("Jwt")).autowire();
|
||||
String token = this.token("ValidNoScopes");
|
||||
this.mvc.perform(get("/").header("Authorization", "Bearer " + token)).andExpect(status().isNotFound());
|
||||
// @formatter:off
|
||||
this.mvc.perform(get("/").header("Authorization", "Bearer " + token))
|
||||
.andExpect(status().isNotFound());
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
public void requestWhenUsingPublicKeyAndSignatureFailsThenReturnsInvalidToken() throws Exception {
|
||||
this.spring.configLocations(xml("SingleKey"), xml("Jwt")).autowire();
|
||||
String token = this.token("WrongSignature");
|
||||
// @formatter:off
|
||||
this.mvc.perform(get("/").header("Authorization", "Bearer " + token))
|
||||
.andExpect(invalidTokenHeader("signature"));
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
public void requestWhenUsingPublicKeyAlgorithmDoesNotMatchThenReturnsInvalidToken() throws Exception {
|
||||
this.spring.configLocations(xml("SingleKey"), xml("Jwt")).autowire();
|
||||
String token = this.token("WrongAlgorithm");
|
||||
// @formatter:off
|
||||
this.mvc.perform(get("/").header("Authorization", "Bearer " + token))
|
||||
.andExpect(invalidTokenHeader("algorithm"));
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getWhenIntrospectingThenOk() throws Exception {
|
||||
this.spring.configLocations(xml("OpaqueTokenRestOperations"), xml("OpaqueToken")).autowire();
|
||||
mockRestOperations(json("Active"));
|
||||
// @formatter:off
|
||||
this.mvc.perform(get("/authenticated").header("Authorization", "Bearer token"))
|
||||
.andExpect(status().isNotFound());
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getWhenIntrospectionFailsThenUnauthorized() throws Exception {
|
||||
this.spring.configLocations(xml("OpaqueTokenRestOperations"), xml("OpaqueToken")).autowire();
|
||||
mockRestOperations(json("Inactive"));
|
||||
this.mvc.perform(get("/").header("Authorization", "Bearer token")).andExpect(status().isUnauthorized())
|
||||
.andExpect(
|
||||
header().string(HttpHeaders.WWW_AUTHENTICATE, containsString("Provided token isn't active")));
|
||||
// @formatter:off
|
||||
MockHttpServletRequestBuilder request = get("/")
|
||||
.header("Authorization", "Bearer token");
|
||||
this.mvc.perform(request)
|
||||
.andExpect(status().isUnauthorized())
|
||||
.andExpect(header().string(HttpHeaders.WWW_AUTHENTICATE, containsString("Provided token isn't active")));
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getWhenIntrospectionLacksScopeThenForbidden() throws Exception {
|
||||
this.spring.configLocations(xml("OpaqueTokenRestOperations"), xml("OpaqueToken")).autowire();
|
||||
mockRestOperations(json("ActiveNoScopes"));
|
||||
// @formatter:off
|
||||
this.mvc.perform(get("/requires-read-scope").header("Authorization", "Bearer token"))
|
||||
.andExpect(status().isForbidden())
|
||||
.andExpect(header().string(HttpHeaders.WWW_AUTHENTICATE, containsString("scope")));
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -570,7 +687,10 @@ public class OAuth2ResourceServerBeanDefinitionParserTests {
|
|||
.getBean(AuthenticationManagerResolver.class);
|
||||
given(authenticationManagerResolver.resolve(any(HttpServletRequest.class))).willReturn(
|
||||
(authentication) -> new JwtAuthenticationToken(TestJwts.jwt().build(), Collections.emptyList()));
|
||||
this.mvc.perform(get("/").header("Authorization", "Bearer token")).andExpect(status().isNotFound());
|
||||
// @formatter:off
|
||||
this.mvc.perform(get("/").header("Authorization", "Bearer token"))
|
||||
.andExpect(status().isNotFound());
|
||||
// @formatter:on
|
||||
verify(authenticationManagerResolver).resolve(any(HttpServletRequest.class));
|
||||
}
|
||||
|
||||
|
@ -589,16 +709,23 @@ public class OAuth2ResourceServerBeanDefinitionParserTests {
|
|||
String jwtThree = jwtFromIssuer(issuerThree);
|
||||
mockWebServer(String.format(metadata, issuerOne, issuerOne));
|
||||
mockWebServer(jwkSet);
|
||||
// @formatter:off
|
||||
this.mvc.perform(get("/authenticated").header("Authorization", "Bearer " + jwtOne))
|
||||
.andExpect(status().isNotFound());
|
||||
// @formatter:on
|
||||
mockWebServer(String.format(metadata, issuerTwo, issuerTwo));
|
||||
mockWebServer(jwkSet);
|
||||
// @formatter:off
|
||||
this.mvc.perform(get("/authenticated").header("Authorization", "Bearer " + jwtTwo))
|
||||
.andExpect(status().isNotFound());
|
||||
// @formatter:on
|
||||
mockWebServer(String.format(metadata, issuerThree, issuerThree));
|
||||
mockWebServer(jwkSet);
|
||||
// @formatter:off
|
||||
this.mvc.perform(get("/authenticated").header("Authorization", "Bearer " + jwtThree))
|
||||
.andExpect(status().isUnauthorized()).andExpect(invalidTokenHeader("Invalid issuer"));
|
||||
.andExpect(status().isUnauthorized())
|
||||
.andExpect(invalidTokenHeader("Invalid issuer"));
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -607,13 +734,17 @@ public class OAuth2ResourceServerBeanDefinitionParserTests {
|
|||
this.spring.configLocations(xml("MockJwtDecoder"), xml("BasicAndResourceServer")).autowire();
|
||||
JwtDecoder decoder = this.spring.getContext().getBean(JwtDecoder.class);
|
||||
given(decoder.decode(anyString())).willThrow(JwtException.class);
|
||||
this.mvc.perform(get("/authenticated").with(httpBasic("some", "user"))).andExpect(status().isUnauthorized())
|
||||
// @formatter:off
|
||||
this.mvc.perform(get("/authenticated").with(httpBasic("some", "user")))
|
||||
.andExpect(status().isUnauthorized())
|
||||
.andExpect(header().string(HttpHeaders.WWW_AUTHENTICATE, startsWith("Basic")));
|
||||
this.mvc.perform(get("/authenticated")).andExpect(status().isUnauthorized())
|
||||
this.mvc.perform(get("/authenticated"))
|
||||
.andExpect(status().isUnauthorized())
|
||||
.andExpect(header().string(HttpHeaders.WWW_AUTHENTICATE, startsWith("Bearer")));
|
||||
this.mvc.perform(get("/authenticated").header("Authorization", "Bearer invalid_token"))
|
||||
.andExpect(status().isUnauthorized())
|
||||
.andExpect(header().string(HttpHeaders.WWW_AUTHENTICATE, startsWith("Bearer")));
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -624,8 +755,11 @@ public class OAuth2ResourceServerBeanDefinitionParserTests {
|
|||
given(decoder.decode(anyString())).willThrow(JwtException.class);
|
||||
MvcResult result = this.mvc.perform(get("/authenticated")).andExpect(status().isUnauthorized()).andReturn();
|
||||
assertThat(result.getRequest().getSession(false)).isNotNull();
|
||||
// @formatter:off
|
||||
result = this.mvc.perform(get("/authenticated").header("Authorization", "Bearer token"))
|
||||
.andExpect(status().isUnauthorized()).andReturn();
|
||||
.andExpect(status().isUnauthorized())
|
||||
.andReturn();
|
||||
// @formatter:on
|
||||
assertThat(result.getRequest().getSession(false)).isNull();
|
||||
}
|
||||
|
||||
|
@ -634,9 +768,12 @@ public class OAuth2ResourceServerBeanDefinitionParserTests {
|
|||
this.spring.configLocations(xml("JwtRestOperations"), xml("BasicAndResourceServer")).autowire();
|
||||
mockRestOperations(jwks("Default"));
|
||||
String token = this.token("ValidNoScopes");
|
||||
// @formatter:off
|
||||
this.mvc.perform(get("/authenticated").header("Authorization", "Bearer " + token))
|
||||
.andExpect(status().isNotFound());
|
||||
this.mvc.perform(get("/authenticated").with(httpBasic("user", "password"))).andExpect(status().isNotFound());
|
||||
this.mvc.perform(get("/authenticated").with(httpBasic("user", "password")))
|
||||
.andExpect(status().isNotFound());
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
|
@ -40,6 +40,7 @@ import org.springframework.security.web.FilterChainProxy;
|
|||
import org.springframework.security.web.authentication.rememberme.AbstractRememberMeServices;
|
||||
import org.springframework.security.web.authentication.ui.DefaultLoginPageGeneratingFilter;
|
||||
import org.springframework.test.web.servlet.MockMvc;
|
||||
import org.springframework.test.web.servlet.request.MockHttpServletRequestBuilder;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
|
@ -73,21 +74,32 @@ public class OpenIDConfigTests {
|
|||
@Test
|
||||
public void requestWhenOpenIDAndFormLoginBothConfiguredThenRedirectsToGeneratedLoginPage() throws Exception {
|
||||
this.spring.configLocations(this.xml("WithFormLogin")).autowire();
|
||||
this.mvc.perform(get("/")).andExpect(status().isFound()).andExpect(redirectedUrl("http://localhost/login"));
|
||||
// @formatter:off
|
||||
this.mvc.perform(get("/"))
|
||||
.andExpect(status().isFound())
|
||||
.andExpect(redirectedUrl("http://localhost/login"));
|
||||
// @formatter:on
|
||||
assertThat(getFilter(DefaultLoginPageGeneratingFilter.class)).isNotNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void requestWhenOpenIDAndFormLoginWithFormLoginPageConfiguredThenFormLoginPageWins() throws Exception {
|
||||
this.spring.configLocations(this.xml("WithFormLoginPage")).autowire();
|
||||
this.mvc.perform(get("/")).andExpect(status().isFound()).andExpect(redirectedUrl("http://localhost/form-page"));
|
||||
// @formatter:off
|
||||
this.mvc.perform(get("/"))
|
||||
.andExpect(status().isFound())
|
||||
.andExpect(redirectedUrl("http://localhost/form-page"));
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
public void requestWhenOpenIDAndFormLoginWithOpenIDLoginPageConfiguredThenOpenIDLoginPageWins() throws Exception {
|
||||
this.spring.configLocations(this.xml("WithOpenIDLoginPageAndFormLogin")).autowire();
|
||||
this.mvc.perform(get("/")).andExpect(status().isFound())
|
||||
// @formatter:off
|
||||
this.mvc.perform(get("/"))
|
||||
.andExpect(status().isFound())
|
||||
.andExpect(redirectedUrl("http://localhost/openid-page"));
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -110,13 +122,20 @@ public class OpenIDConfigTests {
|
|||
openIDFilter.setConsumer(consumer);
|
||||
String expectedReturnTo = new StringBuilder("http://localhost/login/openid").append("?")
|
||||
.append(AbstractRememberMeServices.DEFAULT_PARAMETER).append("=").append("on").toString();
|
||||
this.mvc.perform(get("/")).andExpect(status().isFound()).andExpect(redirectedUrl("http://localhost/login"));
|
||||
this.mvc.perform(get("/login")).andExpect(status().isOk())
|
||||
// @formatter:off
|
||||
this.mvc.perform(get("/"))
|
||||
.andExpect(status().isFound())
|
||||
.andExpect(redirectedUrl("http://localhost/login"));
|
||||
this.mvc.perform(get("/login"))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(content().string(containsString(AbstractRememberMeServices.DEFAULT_PARAMETER)));
|
||||
this.mvc.perform(get("/login/openid")
|
||||
MockHttpServletRequestBuilder openidLogin = get("/login/openid")
|
||||
.param(OpenIDAuthenticationFilter.DEFAULT_CLAIMED_IDENTITY_FIELD, "https://ww1.openid.com")
|
||||
.param(AbstractRememberMeServices.DEFAULT_PARAMETER, "on")).andExpect(status().isFound())
|
||||
.param(AbstractRememberMeServices.DEFAULT_PARAMETER, "on");
|
||||
this.mvc.perform(openidLogin)
|
||||
.andExpect(status().isFound())
|
||||
.andExpect(redirectedUrl(openIdEndpointUrl + expectedReturnTo));
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -131,8 +150,7 @@ public class OpenIDConfigTests {
|
|||
server.enqueue(new MockResponse().addHeader(YadisResolver.YADIS_XRDS_LOCATION, endpoint));
|
||||
server.enqueue(new MockResponse()
|
||||
.setBody(String.format("<XRDS><XRD><Service><URI>%s</URI></Service></XRD></XRDS>", endpoint)));
|
||||
this.mvc.perform(
|
||||
get("/login/openid").param(OpenIDAuthenticationFilter.DEFAULT_CLAIMED_IDENTITY_FIELD, endpoint))
|
||||
this.mvc.perform(get("/login/openid").param(OpenIDAuthenticationFilter.DEFAULT_CLAIMED_IDENTITY_FIELD, endpoint))
|
||||
.andExpect(status().isFound())
|
||||
.andExpect((result) -> result.getResponse().getRedirectedUrl().endsWith(
|
||||
"openid.ext1.type.nickname=http%3A%2F%2Fschema.openid.net%2FnamePerson%2Ffriendly&"
|
||||
|
@ -150,7 +168,11 @@ public class OpenIDConfigTests {
|
|||
throws Exception {
|
||||
this.spring.configLocations(this.xml("Sec2919")).autowire();
|
||||
assertThat(getFilter(DefaultLoginPageGeneratingFilter.class)).isNull();
|
||||
this.mvc.perform(get("/login")).andExpect(status().isOk()).andExpect(content().string("a custom login page"));
|
||||
// @formatter:off
|
||||
this.mvc.perform(get("/login"))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(content().string("a custom login page"));
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
private <T extends Filter> T getFilter(Class<T> clazz) {
|
||||
|
|
|
@ -54,7 +54,10 @@ public class PlaceHolderAndELConfigTests {
|
|||
public void getWhenUsingPlaceholderThenUnsecuredPatternCorrectlyConfigured() throws Exception {
|
||||
System.setProperty("pattern.nofilters", "/unsecured");
|
||||
this.spring.configLocations(this.xml("UnsecuredPattern")).autowire();
|
||||
this.mvc.perform(get("/unsecured")).andExpect(status().isOk());
|
||||
// @formatter:off
|
||||
this.mvc.perform(get("/unsecured"))
|
||||
.andExpect(status().isOk());
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -69,7 +72,9 @@ public class PlaceHolderAndELConfigTests {
|
|||
System.setProperty("auth.failure", "/authFailure");
|
||||
this.spring.configLocations(this.xml("InterceptUrlAndFormLogin")).autowire();
|
||||
// login-page setting
|
||||
this.mvc.perform(get("/secured")).andExpect(redirectedUrl("http://localhost/loginPage"));
|
||||
// @formatter:off
|
||||
this.mvc.perform(get("/secured"))
|
||||
.andExpect(redirectedUrl("http://localhost/loginPage"));
|
||||
// login-processing-url setting
|
||||
// default-target-url setting
|
||||
this.mvc.perform(post("/loginPage").param("username", "user").param("password", "password"))
|
||||
|
@ -77,6 +82,7 @@ public class PlaceHolderAndELConfigTests {
|
|||
// authentication-failure-url setting
|
||||
this.mvc.perform(post("/loginPage").param("username", "user").param("password", "wrong"))
|
||||
.andExpect(redirectedUrl("/authFailure"));
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -91,7 +97,9 @@ public class PlaceHolderAndELConfigTests {
|
|||
System.setProperty("auth.failure", "/authFailure");
|
||||
this.spring.configLocations(this.xml("InterceptUrlAndFormLoginWithSpEL")).autowire();
|
||||
// login-page setting
|
||||
this.mvc.perform(get("/secured")).andExpect(redirectedUrl("http://localhost/loginPage"));
|
||||
// @formatter:off
|
||||
this.mvc.perform(get("/secured"))
|
||||
.andExpect(redirectedUrl("http://localhost/loginPage"));
|
||||
// login-processing-url setting
|
||||
// default-target-url setting
|
||||
this.mvc.perform(post("/loginPage").param("username", "user").param("password", "password"))
|
||||
|
@ -99,6 +107,7 @@ public class PlaceHolderAndELConfigTests {
|
|||
// authentication-failure-url setting
|
||||
this.mvc.perform(post("/loginPage").param("username", "user").param("password", "wrong"))
|
||||
.andExpect(redirectedUrl("/authFailure"));
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -107,10 +116,14 @@ public class PlaceHolderAndELConfigTests {
|
|||
System.setProperty("http", "9080");
|
||||
System.setProperty("https", "9443");
|
||||
this.spring.configLocations(this.xml("PortMapping")).autowire();
|
||||
this.mvc.perform(get("http://localhost:9080/secured")).andExpect(status().isFound())
|
||||
// @formatter:off
|
||||
this.mvc.perform(get("http://localhost:9080/secured"))
|
||||
.andExpect(status().isFound())
|
||||
.andExpect(redirectedUrl("https://localhost:9443/secured"));
|
||||
this.mvc.perform(get("https://localhost:9443/unsecured")).andExpect(status().isFound())
|
||||
this.mvc.perform(get("https://localhost:9443/unsecured"))
|
||||
.andExpect(status().isFound())
|
||||
.andExpect(redirectedUrl("http://localhost:9080/unsecured"));
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -119,8 +132,11 @@ public class PlaceHolderAndELConfigTests {
|
|||
System.setProperty("secure.url", "/secured");
|
||||
System.setProperty("required.channel", "https");
|
||||
this.spring.configLocations(this.xml("RequiresChannel")).autowire();
|
||||
this.mvc.perform(get("http://localhost/secured")).andExpect(status().isFound())
|
||||
// @formatter:off
|
||||
this.mvc.perform(get("http://localhost/secured"))
|
||||
.andExpect(status().isFound())
|
||||
.andExpect(redirectedUrl("https://localhost/secured"));
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -128,14 +144,20 @@ public class PlaceHolderAndELConfigTests {
|
|||
public void requestWhenUsingPlaceholderThenAccessDeniedPageWorks() throws Exception {
|
||||
System.setProperty("accessDenied", "/go-away");
|
||||
this.spring.configLocations(this.xml("AccessDeniedPage")).autowire();
|
||||
this.mvc.perform(get("/secured")).andExpect(forwardedUrl("/go-away"));
|
||||
// @formatter:off
|
||||
this.mvc.perform(get("/secured"))
|
||||
.andExpect(forwardedUrl("/go-away"));
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
@WithMockUser
|
||||
public void requestWhenUsingSpELThenAccessDeniedPageWorks() throws Exception {
|
||||
this.spring.configLocations(this.xml("AccessDeniedPageWithSpEL")).autowire();
|
||||
this.mvc.perform(get("/secured")).andExpect(forwardedUrl("/go-away"));
|
||||
// @formatter:off
|
||||
this.mvc.perform(get("/secured"))
|
||||
.andExpect(forwardedUrl("/go-away"));
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
private String xml(String configName) {
|
||||
|
|
|
@ -69,12 +69,17 @@ public class RememberMeConfigTests {
|
|||
|
||||
@Test
|
||||
public void requestWithRememberMeWhenUsingCustomTokenRepositoryThenAutomaticallyReauthenticates() throws Exception {
|
||||
this.spring.configLocations(this.xml("WithTokenRepository")).autowire();
|
||||
MvcResult result = this.rememberAuthentication("user", "password")
|
||||
this.spring.configLocations(xml("WithTokenRepository")).autowire();
|
||||
// @formatter:off
|
||||
MvcResult result = rememberAuthentication("user", "password")
|
||||
.andExpect(cookie().secure(AbstractRememberMeServices.SPRING_SECURITY_REMEMBER_ME_COOKIE_KEY, false))
|
||||
.andReturn();
|
||||
// @formatter:on
|
||||
Cookie cookie = rememberMeCookie(result);
|
||||
this.mvc.perform(get("/authenticated").cookie(cookie)).andExpect(status().isOk());
|
||||
// @formatter:off
|
||||
this.mvc.perform(get("/authenticated").cookie(cookie))
|
||||
.andExpect(status().isOk());
|
||||
// @formatter:on
|
||||
JdbcTemplate template = this.spring.getContext().getBean(JdbcTemplate.class);
|
||||
int count = template.queryForObject("select count(*) from persistent_logins", int.class);
|
||||
assertThat(count).isEqualTo(1);
|
||||
|
@ -82,30 +87,40 @@ public class RememberMeConfigTests {
|
|||
|
||||
@Test
|
||||
public void requestWithRememberMeWhenUsingCustomDataSourceThenAutomaticallyReauthenticates() throws Exception {
|
||||
this.spring.configLocations(this.xml("WithDataSource")).autowire();
|
||||
this.spring.configLocations(xml("WithDataSource")).autowire();
|
||||
TestDataSource dataSource = this.spring.getContext().getBean(TestDataSource.class);
|
||||
JdbcTemplate template = new JdbcTemplate(dataSource);
|
||||
template.execute(JdbcTokenRepositoryImpl.CREATE_TABLE_SQL);
|
||||
MvcResult result = this.rememberAuthentication("user", "password")
|
||||
// @formatter:off
|
||||
MvcResult result = rememberAuthentication("user", "password")
|
||||
.andExpect(cookie().secure(AbstractRememberMeServices.SPRING_SECURITY_REMEMBER_ME_COOKIE_KEY, false))
|
||||
.andReturn();
|
||||
// @formatter:on
|
||||
Cookie cookie = rememberMeCookie(result);
|
||||
this.mvc.perform(get("/authenticated").cookie(cookie)).andExpect(status().isOk());
|
||||
// @formatter:off
|
||||
this.mvc.perform(get("/authenticated").cookie(cookie))
|
||||
.andExpect(status().isOk());
|
||||
// @formatter:on
|
||||
int count = template.queryForObject("select count(*) from persistent_logins", int.class);
|
||||
assertThat(count).isEqualTo(1);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void requestWithRememberMeWhenUsingAuthenticationSuccessHandlerThenInvokesHandler() throws Exception {
|
||||
this.spring.configLocations(this.xml("WithAuthenticationSuccessHandler")).autowire();
|
||||
this.spring.configLocations(xml("WithAuthenticationSuccessHandler")).autowire();
|
||||
TestDataSource dataSource = this.spring.getContext().getBean(TestDataSource.class);
|
||||
JdbcTemplate template = new JdbcTemplate(dataSource);
|
||||
template.execute(JdbcTokenRepositoryImpl.CREATE_TABLE_SQL);
|
||||
MvcResult result = this.rememberAuthentication("user", "password")
|
||||
// @formatter:off
|
||||
MvcResult result = rememberAuthentication("user", "password")
|
||||
.andExpect(cookie().secure(AbstractRememberMeServices.SPRING_SECURITY_REMEMBER_ME_COOKIE_KEY, false))
|
||||
.andReturn();
|
||||
// @formatter:on
|
||||
Cookie cookie = rememberMeCookie(result);
|
||||
this.mvc.perform(get("/authenticated").cookie(cookie)).andExpect(redirectedUrl("/target"));
|
||||
// @formatter:off
|
||||
this.mvc.perform(get("/authenticated").cookie(cookie))
|
||||
.andExpect(redirectedUrl("/target"));
|
||||
// @formatter:on
|
||||
int count = template.queryForObject("select count(*) from persistent_logins", int.class);
|
||||
assertThat(count).isEqualTo(1);
|
||||
}
|
||||
|
@ -113,64 +128,78 @@ public class RememberMeConfigTests {
|
|||
@Test
|
||||
public void requestWithRememberMeWhenUsingCustomRememberMeServicesThenAuthenticates() throws Exception {
|
||||
// SEC-1281 - using key with external services
|
||||
this.spring.configLocations(this.xml("WithServicesRef")).autowire();
|
||||
MvcResult result = this.rememberAuthentication("user", "password")
|
||||
this.spring.configLocations(xml("WithServicesRef")).autowire();
|
||||
// @formatter:off
|
||||
MvcResult result = rememberAuthentication("user", "password")
|
||||
.andExpect(cookie().secure(AbstractRememberMeServices.SPRING_SECURITY_REMEMBER_ME_COOKIE_KEY, false))
|
||||
.andExpect(cookie().maxAge(AbstractRememberMeServices.SPRING_SECURITY_REMEMBER_ME_COOKIE_KEY, 5000))
|
||||
.andReturn();
|
||||
// @formatter:on
|
||||
Cookie cookie = rememberMeCookie(result);
|
||||
this.mvc.perform(get("/authenticated").cookie(cookie)).andExpect(status().isOk());
|
||||
// @formatter:off
|
||||
this.mvc.perform(get("/authenticated").cookie(cookie))
|
||||
.andExpect(status().isOk());
|
||||
// SEC-909
|
||||
this.mvc.perform(post("/logout").cookie(cookie).with(csrf()))
|
||||
.andExpect(cookie().maxAge(AbstractRememberMeServices.SPRING_SECURITY_REMEMBER_ME_COOKIE_KEY, 0))
|
||||
.andReturn();
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
public void logoutWhenUsingRememberMeDefaultsThenCookieIsCancelled() throws Exception {
|
||||
this.spring.configLocations(this.xml("DefaultConfig")).autowire();
|
||||
MvcResult result = this.rememberAuthentication("user", "password").andReturn();
|
||||
this.spring.configLocations(xml("DefaultConfig")).autowire();
|
||||
MvcResult result = rememberAuthentication("user", "password").andReturn();
|
||||
Cookie cookie = rememberMeCookie(result);
|
||||
// @formatter:off
|
||||
this.mvc.perform(post("/logout").cookie(cookie).with(csrf()))
|
||||
.andExpect(cookie().maxAge(AbstractRememberMeServices.SPRING_SECURITY_REMEMBER_ME_COOKIE_KEY, 0));
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
public void requestWithRememberMeWhenTokenValidityIsConfiguredThenCookieReflectsCorrectExpiration()
|
||||
throws Exception {
|
||||
this.spring.configLocations(this.xml("TokenValidity")).autowire();
|
||||
MvcResult result = this.rememberAuthentication("user", "password")
|
||||
this.spring.configLocations(xml("TokenValidity")).autowire();
|
||||
// @formatter:off
|
||||
MvcResult result = rememberAuthentication("user", "password")
|
||||
.andExpect(cookie().maxAge(AbstractRememberMeServices.SPRING_SECURITY_REMEMBER_ME_COOKIE_KEY, 10000))
|
||||
.andReturn();
|
||||
// @formatter:on
|
||||
Cookie cookie = rememberMeCookie(result);
|
||||
this.mvc.perform(get("/authenticated").cookie(cookie)).andExpect(status().isOk());
|
||||
// @formatter:off
|
||||
this.mvc.perform(get("/authenticated").cookie(cookie))
|
||||
.andExpect(status().isOk());
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
public void requestWithRememberMeWhenTokenValidityIsNegativeThenCookieReflectsCorrectExpiration() throws Exception {
|
||||
this.spring.configLocations(this.xml("NegativeTokenValidity")).autowire();
|
||||
this.rememberAuthentication("user", "password")
|
||||
this.spring.configLocations(xml("NegativeTokenValidity")).autowire();
|
||||
// @formatter:off
|
||||
rememberAuthentication("user", "password")
|
||||
.andExpect(cookie().maxAge(AbstractRememberMeServices.SPRING_SECURITY_REMEMBER_ME_COOKIE_KEY, -1));
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
public void configureWhenUsingDataSourceAndANegativeTokenValidityThenThrowsWiringException() {
|
||||
assertThatExceptionOfType(FatalBeanException.class).isThrownBy(
|
||||
() -> this.spring.configLocations(this.xml("NegativeTokenValidityWithDataSource")).autowire());
|
||||
() -> this.spring.configLocations(xml("NegativeTokenValidityWithDataSource")).autowire());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void requestWithRememberMeWhenTokenValidityIsResolvedByPropertyPlaceholderThenCookieReflectsCorrectExpiration()
|
||||
throws Exception {
|
||||
this.spring.configLocations(this.xml("Sec2165")).autowire();
|
||||
this.rememberAuthentication("user", "password")
|
||||
this.spring.configLocations(xml("Sec2165")).autowire();
|
||||
rememberAuthentication("user", "password")
|
||||
.andExpect(cookie().maxAge(AbstractRememberMeServices.SPRING_SECURITY_REMEMBER_ME_COOKIE_KEY, 30));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void requestWithRememberMeWhenUseSecureCookieIsTrueThenCookieIsSecure() throws Exception {
|
||||
this.spring.configLocations(this.xml("SecureCookie")).autowire();
|
||||
this.rememberAuthentication("user", "password")
|
||||
this.spring.configLocations(xml("SecureCookie")).autowire();
|
||||
rememberAuthentication("user", "password")
|
||||
.andExpect(cookie().secure(AbstractRememberMeServices.SPRING_SECURITY_REMEMBER_ME_COOKIE_KEY, true));
|
||||
}
|
||||
|
||||
|
@ -179,27 +208,30 @@ public class RememberMeConfigTests {
|
|||
*/
|
||||
@Test
|
||||
public void requestWithRememberMeWhenUseSecureCookieIsFalseThenCookieIsNotSecure() throws Exception {
|
||||
this.spring.configLocations(this.xml("Sec1827")).autowire();
|
||||
this.rememberAuthentication("user", "password")
|
||||
this.spring.configLocations(xml("Sec1827")).autowire();
|
||||
rememberAuthentication("user", "password")
|
||||
.andExpect(cookie().secure(AbstractRememberMeServices.SPRING_SECURITY_REMEMBER_ME_COOKIE_KEY, false));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void configureWhenUsingPersistentTokenRepositoryAndANegativeTokenValidityThenThrowsWiringException() {
|
||||
assertThatExceptionOfType(BeanDefinitionParsingException.class).isThrownBy(() -> this.spring
|
||||
.configLocations(this.xml("NegativeTokenValidityWithPersistentRepository")).autowire());
|
||||
.configLocations(xml("NegativeTokenValidityWithPersistentRepository")).autowire());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void requestWithRememberMeWhenUsingCustomUserDetailsServiceThenInvokesThisUserDetailsService()
|
||||
throws Exception {
|
||||
this.spring.configLocations(this.xml("WithUserDetailsService")).autowire();
|
||||
this.spring.configLocations(xml("WithUserDetailsService")).autowire();
|
||||
UserDetailsService userDetailsService = this.spring.getContext().getBean(UserDetailsService.class);
|
||||
given(userDetailsService.loadUserByUsername("user"))
|
||||
.willAnswer((invocation) -> new User("user", "{noop}password", Collections.emptyList()));
|
||||
MvcResult result = this.rememberAuthentication("user", "password").andReturn();
|
||||
MvcResult result = rememberAuthentication("user", "password").andReturn();
|
||||
Cookie cookie = rememberMeCookie(result);
|
||||
this.mvc.perform(get("/authenticated").cookie(cookie)).andExpect(status().isOk());
|
||||
// @formatter:off
|
||||
this.mvc.perform(get("/authenticated").cookie(cookie))
|
||||
.andExpect(status().isOk());
|
||||
// @formatter:on
|
||||
verify(userDetailsService, atLeastOnce()).loadUserByUsername("user");
|
||||
}
|
||||
|
||||
|
@ -208,11 +240,17 @@ public class RememberMeConfigTests {
|
|||
*/
|
||||
@Test
|
||||
public void requestWithRememberMeWhenExcludingBasicAuthenticationFilterThenStillReauthenticates() throws Exception {
|
||||
this.spring.configLocations(this.xml("Sec742")).autowire();
|
||||
this.spring.configLocations(xml("Sec742")).autowire();
|
||||
// @formatter:off
|
||||
MvcResult result = this.mvc.perform(login("user", "password").param("remember-me", "true").with(csrf()))
|
||||
.andExpect(redirectedUrl("/messageList.html")).andReturn();
|
||||
.andExpect(redirectedUrl("/messageList.html"))
|
||||
.andReturn();
|
||||
// @formatter:on
|
||||
Cookie cookie = rememberMeCookie(result);
|
||||
this.mvc.perform(get("/authenticated").cookie(cookie)).andExpect(status().isOk());
|
||||
// @formatter:off
|
||||
this.mvc.perform(get("/authenticated").cookie(cookie))
|
||||
.andExpect(status().isOk());
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -220,18 +258,26 @@ public class RememberMeConfigTests {
|
|||
*/
|
||||
@Test
|
||||
public void requestWithRememberMeWhenUsingCustomRememberMeParameterThenReauthenticates() throws Exception {
|
||||
this.spring.configLocations(this.xml("WithRememberMeParameter")).autowire();
|
||||
MvcResult result = this.mvc
|
||||
.perform(login("user", "password").param("custom-remember-me-parameter", "true").with(csrf()))
|
||||
.andExpect(redirectedUrl("/")).andReturn();
|
||||
this.spring.configLocations(xml("WithRememberMeParameter")).autowire();
|
||||
// @formatter:off
|
||||
MockHttpServletRequestBuilder request = login("user", "password")
|
||||
.param("custom-remember-me-parameter", "true")
|
||||
.with(csrf());
|
||||
MvcResult result = this.mvc.perform(request)
|
||||
.andExpect(redirectedUrl("/"))
|
||||
.andReturn();
|
||||
// @formatter:on
|
||||
Cookie cookie = rememberMeCookie(result);
|
||||
this.mvc.perform(get("/authenticated").cookie(cookie)).andExpect(status().isOk());
|
||||
// @formatter:off
|
||||
this.mvc.perform(get("/authenticated").cookie(cookie))
|
||||
.andExpect(status().isOk());
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
public void configureWhenUsingRememberMeParameterAndServicesRefThenThrowsWiringException() {
|
||||
assertThatExceptionOfType(BeanDefinitionParsingException.class).isThrownBy(
|
||||
() -> this.spring.configLocations(this.xml("WithRememberMeParameterAndServicesRef")).autowire());
|
||||
() -> this.spring.configLocations(xml("WithRememberMeParameterAndServicesRef")).autowire());
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -239,8 +285,11 @@ public class RememberMeConfigTests {
|
|||
*/
|
||||
@Test
|
||||
public void authenticateWhenUsingCustomRememberMeCookieNameThenIssuesCookieWithThatName() throws Exception {
|
||||
this.spring.configLocations(this.xml("WithRememberMeCookie")).autowire();
|
||||
this.rememberAuthentication("user", "password").andExpect(cookie().exists("custom-remember-me-cookie"));
|
||||
this.spring.configLocations(xml("WithRememberMeCookie")).autowire();
|
||||
// @formatter:off
|
||||
rememberAuthentication("user", "password")
|
||||
.andExpect(cookie().exists("custom-remember-me-cookie"));
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -250,7 +299,7 @@ public class RememberMeConfigTests {
|
|||
public void configureWhenUsingRememberMeCookieAndServicesRefThenThrowsWiringException() {
|
||||
assertThatExceptionOfType(BeanDefinitionParsingException.class)
|
||||
.isThrownBy(
|
||||
() -> this.spring.configLocations(this.xml("WithRememberMeCookieAndServicesRef")).autowire())
|
||||
() -> this.spring.configLocations(xml("WithRememberMeCookieAndServicesRef")).autowire())
|
||||
.withMessageContaining(
|
||||
"Configuration problem: services-ref can't be used in combination with attributes "
|
||||
+ "token-repository-ref,data-source-ref, user-service-ref, token-validity-seconds, "
|
||||
|
@ -258,13 +307,21 @@ public class RememberMeConfigTests {
|
|||
}
|
||||
|
||||
private ResultActions rememberAuthentication(String username, String password) throws Exception {
|
||||
return this.mvc.perform(
|
||||
login(username, password).param(AbstractRememberMeServices.DEFAULT_PARAMETER, "true").with(csrf()))
|
||||
// @formatter:off
|
||||
MockHttpServletRequestBuilder request = login(username, password)
|
||||
.param(AbstractRememberMeServices.DEFAULT_PARAMETER, "true")
|
||||
.with(csrf());
|
||||
return this.mvc.perform(request)
|
||||
.andExpect(redirectedUrl("/"));
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
private static MockHttpServletRequestBuilder login(String username, String password) {
|
||||
return post("/login").param("username", username).param("password", password);
|
||||
// @formatter:off
|
||||
return post("/login")
|
||||
.param("username", username)
|
||||
.param("password", password);
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
private static Cookie rememberMeCookie(MvcResult result) {
|
||||
|
|
|
@ -67,14 +67,21 @@ public class SecurityContextHolderAwareRequestConfigTests {
|
|||
@Test
|
||||
public void servletLoginWhenUsingDefaultConfigurationThenUsesSpringSecurity() throws Exception {
|
||||
this.spring.configLocations(this.xml("Simple")).autowire();
|
||||
this.mvc.perform(get("/good-login")).andExpect(status().isOk()).andExpect(content().string("user"));
|
||||
// @formatter:off
|
||||
this.mvc.perform(get("/good-login"))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(content().string("user"));
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
public void servletAuthenticateWhenUsingDefaultConfigurationThenUsesSpringSecurity() throws Exception {
|
||||
this.spring.configLocations(this.xml("Simple")).autowire();
|
||||
this.mvc.perform(get("/authenticate")).andExpect(status().isFound())
|
||||
// @formatter:off
|
||||
this.mvc.perform(get("/authenticate"))
|
||||
.andExpect(status().isFound())
|
||||
.andExpect(redirectedUrl("http://localhost/login"));
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -83,8 +90,12 @@ public class SecurityContextHolderAwareRequestConfigTests {
|
|||
MvcResult result = this.mvc.perform(get("/good-login")).andReturn();
|
||||
MockHttpSession session = (MockHttpSession) result.getRequest().getSession(false);
|
||||
assertThat(session).isNotNull();
|
||||
result = this.mvc.perform(get("/do-logout").session(session)).andExpect(status().isOk())
|
||||
.andExpect(content().string("")).andReturn();
|
||||
// @formatter:off
|
||||
result = this.mvc.perform(get("/do-logout").session(session))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(content().string(""))
|
||||
.andReturn();
|
||||
// @formatter:on
|
||||
session = (MockHttpSession) result.getRequest().getSession(false);
|
||||
assertThat(session).isNull();
|
||||
}
|
||||
|
@ -92,31 +103,47 @@ public class SecurityContextHolderAwareRequestConfigTests {
|
|||
@Test
|
||||
public void servletAuthenticateWhenUsingHttpBasicThenUsesSpringSecurity() throws Exception {
|
||||
this.spring.configLocations(this.xml("HttpBasic")).autowire();
|
||||
this.mvc.perform(get("/authenticate")).andExpect(status().isUnauthorized())
|
||||
// @formatter:off
|
||||
this.mvc.perform(get("/authenticate"))
|
||||
.andExpect(status().isUnauthorized())
|
||||
.andExpect(header().string(HttpHeaders.WWW_AUTHENTICATE, containsString("discworld")));
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
public void servletAuthenticateWhenUsingFormLoginThenUsesSpringSecurity() throws Exception {
|
||||
this.spring.configLocations(this.xml("FormLogin")).autowire();
|
||||
this.mvc.perform(get("/authenticate")).andExpect(status().isFound())
|
||||
// @formatter:off
|
||||
this.mvc.perform(get("/authenticate"))
|
||||
.andExpect(status().isFound())
|
||||
.andExpect(redirectedUrl("http://localhost/login"));
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
public void servletLoginWhenUsingMultipleHttpConfigsThenUsesSpringSecurity() throws Exception {
|
||||
this.spring.configLocations(this.xml("MultiHttp")).autowire();
|
||||
this.mvc.perform(get("/good-login")).andExpect(status().isOk()).andExpect(content().string("user"));
|
||||
this.mvc.perform(get("/v2/good-login")).andExpect(status().isOk()).andExpect(content().string("user2"));
|
||||
// @formatter:off
|
||||
this.mvc.perform(get("/good-login"))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(content().string("user"));
|
||||
this.mvc.perform(get("/v2/good-login"))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(content().string("user2"));
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
public void servletAuthenticateWhenUsingMultipleHttpConfigsThenUsesSpringSecurity() throws Exception {
|
||||
this.spring.configLocations(this.xml("MultiHttp")).autowire();
|
||||
this.mvc.perform(get("/authenticate")).andExpect(status().isFound())
|
||||
// @formatter:off
|
||||
this.mvc.perform(get("/authenticate"))
|
||||
.andExpect(status().isFound())
|
||||
.andExpect(redirectedUrl("http://localhost/login"));
|
||||
this.mvc.perform(get("/v2/authenticate")).andExpect(status().isFound())
|
||||
this.mvc.perform(get("/v2/authenticate"))
|
||||
.andExpect(status().isFound())
|
||||
.andExpect(redirectedUrl("http://localhost/login2"));
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -125,15 +152,26 @@ public class SecurityContextHolderAwareRequestConfigTests {
|
|||
MvcResult result = this.mvc.perform(get("/good-login")).andReturn();
|
||||
MockHttpSession session = (MockHttpSession) result.getRequest().getSession(false);
|
||||
assertThat(session).isNotNull();
|
||||
result = this.mvc.perform(get("/do-logout").session(session)).andExpect(status().isOk())
|
||||
.andExpect(content().string("")).andReturn();
|
||||
// @formatter:off
|
||||
result = this.mvc.perform(get("/do-logout").session(session))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(content().string(""))
|
||||
.andReturn();
|
||||
// @formatter:on
|
||||
session = (MockHttpSession) result.getRequest().getSession(false);
|
||||
assertThat(session).isNotNull();
|
||||
result = this.mvc.perform(get("/v2/good-login")).andReturn();
|
||||
// @formatter:off
|
||||
result = this.mvc.perform(get("/v2/good-login"))
|
||||
.andReturn();
|
||||
// @formatter:on
|
||||
session = (MockHttpSession) result.getRequest().getSession(false);
|
||||
assertThat(session).isNotNull();
|
||||
result = this.mvc.perform(get("/v2/do-logout").session(session)).andExpect(status().isOk())
|
||||
.andExpect(content().string("")).andReturn();
|
||||
// @formatter:off
|
||||
result = this.mvc.perform(get("/v2/do-logout").session(session))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(content().string(""))
|
||||
.andReturn();
|
||||
// @formatter:on
|
||||
session = (MockHttpSession) result.getRequest().getSession(false);
|
||||
assertThat(session).isNull();
|
||||
}
|
||||
|
@ -143,11 +181,19 @@ public class SecurityContextHolderAwareRequestConfigTests {
|
|||
this.spring.configLocations(this.xml("Logout")).autowire();
|
||||
this.mvc.perform(get("/authenticate")).andExpect(status().isFound())
|
||||
.andExpect(redirectedUrl("http://localhost/signin"));
|
||||
MvcResult result = this.mvc.perform(get("/good-login")).andReturn();
|
||||
// @formatter:off
|
||||
MvcResult result = this.mvc.perform(get("/good-login"))
|
||||
.andReturn();
|
||||
// @formatter:on
|
||||
MockHttpSession session = (MockHttpSession) result.getRequest().getSession(false);
|
||||
assertThat(session).isNotNull();
|
||||
result = this.mvc.perform(get("/do-logout").session(session)).andExpect(status().isOk())
|
||||
.andExpect(content().string("")).andExpect(cookie().maxAge("JSESSIONID", 0)).andReturn();
|
||||
// @formatter:off
|
||||
result = this.mvc.perform(get("/do-logout").session(session))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(content().string(""))
|
||||
.andExpect(cookie().maxAge("JSESSIONID", 0))
|
||||
.andReturn();
|
||||
// @formatter:on
|
||||
session = (MockHttpSession) result.getRequest().getSession(false);
|
||||
assertThat(session).isNotNull();
|
||||
}
|
||||
|
@ -159,7 +205,10 @@ public class SecurityContextHolderAwareRequestConfigTests {
|
|||
@WithMockUser
|
||||
public void servletIsUserInRoleWhenUsingDefaultConfigThenRoleIsSet() throws Exception {
|
||||
this.spring.configLocations(this.xml("Simple")).autowire();
|
||||
this.mvc.perform(get("/role")).andExpect(content().string("true"));
|
||||
// @formatter:off
|
||||
this.mvc.perform(get("/role"))
|
||||
.andExpect(content().string("true"));
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
private String xml(String configName) {
|
||||
|
|
|
@ -51,9 +51,15 @@ import static org.assertj.core.api.Assertions.assertThat;
|
|||
@PowerMockIgnore({ "org.w3c.dom.*", "org.xml.sax.*", "org.apache.xerces.*", "javax.xml.parsers.*" })
|
||||
public class SessionManagementConfigServlet31Tests {
|
||||
|
||||
private static final String XML_AUTHENTICATION_MANAGER = "<authentication-manager>" + " <authentication-provider>"
|
||||
+ " <user-service>" + " <user name='user' password='{noop}password' authorities='ROLE_USER' />"
|
||||
+ " </user-service>" + " </authentication-provider>" + "</authentication-manager>";
|
||||
// @formatter:off
|
||||
private static final String XML_AUTHENTICATION_MANAGER = "<authentication-manager>"
|
||||
+ " <authentication-provider>"
|
||||
+ " <user-service>"
|
||||
+ " <user name='user' password='{noop}password' authorities='ROLE_USER' />"
|
||||
+ " </user-service>"
|
||||
+ " </authentication-provider>"
|
||||
+ "</authentication-manager>";
|
||||
// @formatter:on
|
||||
|
||||
@Mock
|
||||
Method method;
|
||||
|
@ -92,8 +98,14 @@ public class SessionManagementConfigServlet31Tests {
|
|||
request.setParameter("password", "password");
|
||||
request.getSession().setAttribute("attribute1", "value1");
|
||||
String id = request.getSession().getId();
|
||||
loadContext("<http>\n" + " <form-login/>\n" + " <session-management/>\n"
|
||||
+ " <csrf disabled='true'/>\n" + " </http>" + XML_AUTHENTICATION_MANAGER);
|
||||
// @formatter:off
|
||||
loadContext("<http>\n"
|
||||
+ " <form-login/>\n"
|
||||
+ " <session-management/>\n"
|
||||
+ " <csrf disabled='true'/>\n"
|
||||
+ " </http>"
|
||||
+ XML_AUTHENTICATION_MANAGER);
|
||||
// @formatter:on
|
||||
this.springSecurityFilterChain.doFilter(request, this.response, this.chain);
|
||||
assertThat(request.getSession().getId()).isNotEqualTo(id);
|
||||
assertThat(request.getSession().getAttribute("attribute1")).isEqualTo("value1");
|
||||
|
@ -108,9 +120,14 @@ public class SessionManagementConfigServlet31Tests {
|
|||
request.setParameter("username", "user");
|
||||
request.setParameter("password", "password");
|
||||
String id = request.getSession().getId();
|
||||
loadContext("<http>\n" + " <form-login/>\n"
|
||||
// @formatter:off
|
||||
loadContext("<http>\n"
|
||||
+ " <form-login/>\n"
|
||||
+ " <session-management session-fixation-protection='changeSessionId'/>\n"
|
||||
+ " <csrf disabled='true'/>\n" + " </http>" + XML_AUTHENTICATION_MANAGER);
|
||||
+ " <csrf disabled='true'/>\n"
|
||||
+ " </http>"
|
||||
+ XML_AUTHENTICATION_MANAGER);
|
||||
// @formatter:on
|
||||
this.springSecurityFilterChain.doFilter(request, this.response, this.chain);
|
||||
assertThat(request.getSession().getId()).isNotEqualTo(id);
|
||||
}
|
||||
|
|
|
@ -55,6 +55,7 @@ import org.springframework.security.web.session.SessionManagementFilter;
|
|||
import org.springframework.test.web.servlet.MockMvc;
|
||||
import org.springframework.test.web.servlet.MvcResult;
|
||||
import org.springframework.test.web.servlet.ResultMatcher;
|
||||
import org.springframework.test.web.servlet.request.MockHttpServletRequestBuilder;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
import org.springframework.web.context.WebApplicationContext;
|
||||
|
@ -91,7 +92,7 @@ public class SessionManagementConfigTests {
|
|||
|
||||
@Test
|
||||
public void requestWhenCreateSessionAlwaysThenAlwaysCreatesSession() throws Exception {
|
||||
this.spring.configLocations(this.xml("CreateSessionAlways")).autowire();
|
||||
this.spring.configLocations(xml("CreateSessionAlways")).autowire();
|
||||
MockHttpServletRequest request = get("/").buildRequest(this.servletContext());
|
||||
MockHttpServletResponse response = request(request, this.spring.getContext());
|
||||
assertThat(response.getStatus()).isEqualTo(HttpStatus.SC_OK);
|
||||
|
@ -100,7 +101,7 @@ public class SessionManagementConfigTests {
|
|||
|
||||
@Test
|
||||
public void requestWhenCreateSessionIsSetToNeverThenDoesNotCreateSessionOnLoginChallenge() throws Exception {
|
||||
this.spring.configLocations(this.xml("CreateSessionNever")).autowire();
|
||||
this.spring.configLocations(xml("CreateSessionNever")).autowire();
|
||||
MockHttpServletRequest request = get("/auth").buildRequest(this.servletContext());
|
||||
MockHttpServletResponse response = request(request, this.spring.getContext());
|
||||
assertThat(response.getStatus()).isEqualTo(HttpStatus.SC_MOVED_TEMPORARILY);
|
||||
|
@ -109,9 +110,13 @@ public class SessionManagementConfigTests {
|
|||
|
||||
@Test
|
||||
public void requestWhenCreateSessionIsSetToNeverThenDoesNotCreateSessionOnLogin() throws Exception {
|
||||
this.spring.configLocations(this.xml("CreateSessionNever")).autowire();
|
||||
MockHttpServletRequest request = post("/login").param("username", "user").param("password", "password")
|
||||
this.spring.configLocations(xml("CreateSessionNever")).autowire();
|
||||
// @formatter:off
|
||||
MockHttpServletRequest request = post("/login")
|
||||
.param("username", "user")
|
||||
.param("password", "password")
|
||||
.buildRequest(this.servletContext());
|
||||
// @formatter:on
|
||||
request = csrf().postProcessRequest(request);
|
||||
MockHttpServletResponse response = request(request, this.spring.getContext());
|
||||
assertThat(response.getStatus()).isEqualTo(HttpStatus.SC_MOVED_TEMPORARILY);
|
||||
|
@ -120,9 +125,13 @@ public class SessionManagementConfigTests {
|
|||
|
||||
@Test
|
||||
public void requestWhenCreateSessionIsSetToNeverThenUsesExistingSession() throws Exception {
|
||||
this.spring.configLocations(this.xml("CreateSessionNever")).autowire();
|
||||
MockHttpServletRequest request = post("/login").param("username", "user").param("password", "password")
|
||||
this.spring.configLocations(xml("CreateSessionNever")).autowire();
|
||||
// @formatter:off
|
||||
MockHttpServletRequest request = post("/login")
|
||||
.param("username", "user")
|
||||
.param("password", "password")
|
||||
.buildRequest(this.servletContext());
|
||||
// @formatter:on
|
||||
request = csrf().postProcessRequest(request);
|
||||
MockHttpSession session = new MockHttpSession();
|
||||
request.setSession(session);
|
||||
|
@ -135,31 +144,48 @@ public class SessionManagementConfigTests {
|
|||
|
||||
@Test
|
||||
public void requestWhenCreateSessionIsSetToStatelessThenDoesNotCreateSessionOnLoginChallenge() throws Exception {
|
||||
this.spring.configLocations(this.xml("CreateSessionStateless")).autowire();
|
||||
this.mvc.perform(get("/auth")).andExpect(status().isFound()).andExpect(session().exists(false));
|
||||
this.spring.configLocations(xml("CreateSessionStateless")).autowire();
|
||||
// @formatter:off
|
||||
this.mvc.perform(get("/auth"))
|
||||
.andExpect(status().isFound())
|
||||
.andExpect(session().exists(false));
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
public void requestWhenCreateSessionIsSetToStatelessThenDoesNotCreateSessionOnLogin() throws Exception {
|
||||
this.spring.configLocations(this.xml("CreateSessionStateless")).autowire();
|
||||
this.mvc.perform(post("/login").param("username", "user").param("password", "password").with(csrf()))
|
||||
.andExpect(status().isFound()).andExpect(session().exists(false));
|
||||
this.spring.configLocations(xml("CreateSessionStateless")).autowire();
|
||||
// @formatter:off
|
||||
MockHttpServletRequestBuilder loginRequest = post("/login")
|
||||
.param("username", "user")
|
||||
.param("password", "password")
|
||||
.with(csrf());
|
||||
this.mvc.perform(loginRequest)
|
||||
.andExpect(status().isFound())
|
||||
.andExpect(session().exists(false));
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
public void requestWhenCreateSessionIsSetToStatelessThenIgnoresExistingSession() throws Exception {
|
||||
this.spring.configLocations(this.xml("CreateSessionStateless")).autowire();
|
||||
MvcResult result = this.mvc
|
||||
.perform(post("/login").param("username", "user").param("password", "password")
|
||||
.session(new MockHttpSession()).with(csrf()))
|
||||
.andExpect(status().isFound()).andExpect(session()).andReturn();
|
||||
this.spring.configLocations(xml("CreateSessionStateless")).autowire();
|
||||
// @formatter:off
|
||||
MockHttpServletRequestBuilder loginRequest = post("/login")
|
||||
.param("username", "user")
|
||||
.param("password", "password")
|
||||
.session(new MockHttpSession())
|
||||
.with(csrf());
|
||||
MvcResult result = this.mvc.perform(loginRequest)
|
||||
.andExpect(status().isFound())
|
||||
.andExpect(session()).andReturn();
|
||||
// @formatter:on
|
||||
assertThat(result.getRequest().getSession(false)
|
||||
.getAttribute(HttpSessionSecurityContextRepository.SPRING_SECURITY_CONTEXT_KEY)).isNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void requestWhenCreateSessionIsSetToIfRequiredThenDoesNotCreateSessionOnPublicInvocation() throws Exception {
|
||||
this.spring.configLocations(this.xml("CreateSessionIfRequired")).autowire();
|
||||
this.spring.configLocations(xml("CreateSessionIfRequired")).autowire();
|
||||
ServletContext servletContext = this.mvc.getDispatcherServlet().getServletContext();
|
||||
MockHttpServletRequest request = get("/").buildRequest(servletContext);
|
||||
MockHttpServletResponse response = request(request, this.spring.getContext());
|
||||
|
@ -169,7 +195,7 @@ public class SessionManagementConfigTests {
|
|||
|
||||
@Test
|
||||
public void requestWhenCreateSessionIsSetToIfRequiredThenCreatesSessionOnLoginChallenge() throws Exception {
|
||||
this.spring.configLocations(this.xml("CreateSessionIfRequired")).autowire();
|
||||
this.spring.configLocations(xml("CreateSessionIfRequired")).autowire();
|
||||
ServletContext servletContext = this.mvc.getDispatcherServlet().getServletContext();
|
||||
MockHttpServletRequest request = get("/auth").buildRequest(servletContext);
|
||||
MockHttpServletResponse response = request(request, this.spring.getContext());
|
||||
|
@ -179,10 +205,14 @@ public class SessionManagementConfigTests {
|
|||
|
||||
@Test
|
||||
public void requestWhenCreateSessionIsSetToIfRequiredThenCreatesSessionOnLogin() throws Exception {
|
||||
this.spring.configLocations(this.xml("CreateSessionIfRequired")).autowire();
|
||||
this.spring.configLocations(xml("CreateSessionIfRequired")).autowire();
|
||||
ServletContext servletContext = this.mvc.getDispatcherServlet().getServletContext();
|
||||
MockHttpServletRequest request = post("/login").param("username", "user").param("password", "password")
|
||||
// @formatter:off
|
||||
MockHttpServletRequest request = post("/login")
|
||||
.param("username", "user")
|
||||
.param("password", "password")
|
||||
.buildRequest(servletContext);
|
||||
// @formatter:on
|
||||
request = csrf().postProcessRequest(request);
|
||||
MockHttpServletResponse response = request(request, this.spring.getContext());
|
||||
assertThat(response.getStatus()).isEqualTo(HttpStatus.SC_MOVED_TEMPORARILY);
|
||||
|
@ -194,11 +224,15 @@ public class SessionManagementConfigTests {
|
|||
*/
|
||||
@Test
|
||||
public void requestWhenRejectingUserBasedOnMaxSessionsExceededThenDoesNotCreateSession() throws Exception {
|
||||
this.spring.configLocations(this.xml("Sec1208")).autowire();
|
||||
this.mvc.perform(get("/auth").with(httpBasic("user", "password"))).andExpect(status().isOk())
|
||||
this.spring.configLocations(xml("Sec1208")).autowire();
|
||||
// @formatter:off
|
||||
this.mvc.perform(get("/auth").with(httpBasic("user", "password")))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(session());
|
||||
this.mvc.perform(get("/auth").with(httpBasic("user", "password"))).andExpect(status().isUnauthorized())
|
||||
this.mvc.perform(get("/auth").with(httpBasic("user", "password")))
|
||||
.andExpect(status().isUnauthorized())
|
||||
.andExpect(session().exists(false));
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -207,40 +241,61 @@ public class SessionManagementConfigTests {
|
|||
@Test
|
||||
public void requestWhenSessionFixationProtectionDisabledAndConcurrencyControlEnabledThenSessionNotInvalidated()
|
||||
throws Exception {
|
||||
this.spring.configLocations(this.xml("Sec2137")).autowire();
|
||||
this.spring.configLocations(xml("Sec2137")).autowire();
|
||||
MockHttpSession session = new MockHttpSession();
|
||||
this.mvc.perform(get("/auth").session(session).with(httpBasic("user", "password"))).andExpect(status().isOk())
|
||||
// @formatter:off
|
||||
this.mvc.perform(get("/auth").session(session).with(httpBasic("user", "password")))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(session().id(session.getId()));
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
public void autowireWhenExportingSessionRegistryBeanThenAvailableForWiring() {
|
||||
this.spring.configLocations(this.xml("ConcurrencyControlSessionRegistryAlias")).autowire();
|
||||
this.spring.configLocations(xml("ConcurrencyControlSessionRegistryAlias")).autowire();
|
||||
this.sessionRegistryIsValid();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void requestWhenExpiredUrlIsSetThenInvalidatesSessionAndRedirects() throws Exception {
|
||||
this.spring.configLocations(this.xml("ConcurrencyControlExpiredUrl")).autowire();
|
||||
this.mvc.perform(get("/auth").session(this.expiredSession()).with(httpBasic("user", "password")))
|
||||
.andExpect(redirectedUrl("/expired")).andExpect(session().exists(false));
|
||||
this.spring.configLocations(xml("ConcurrencyControlExpiredUrl")).autowire();
|
||||
// @formatter:off
|
||||
MockHttpServletRequestBuilder request = get("/auth")
|
||||
.session(expiredSession())
|
||||
.with(httpBasic("user", "password"));
|
||||
this.mvc.perform(request)
|
||||
.andExpect(redirectedUrl("/expired"))
|
||||
.andExpect(session().exists(false));
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
public void requestWhenConcurrencyControlAndCustomLogoutHandlersAreSetThenAllAreInvokedWhenSessionExpires()
|
||||
throws Exception {
|
||||
this.spring.configLocations(this.xml("ConcurrencyControlLogoutAndRememberMeHandlers")).autowire();
|
||||
this.mvc.perform(get("/auth").session(this.expiredSession()).with(httpBasic("user", "password")))
|
||||
.andExpect(status().isOk()).andExpect(cookie().maxAge("testCookie", 0))
|
||||
.andExpect(cookie().exists("rememberMeCookie")).andExpect(session().valid(true));
|
||||
this.spring.configLocations(xml("ConcurrencyControlLogoutAndRememberMeHandlers")).autowire();
|
||||
// @formatter:off
|
||||
MockHttpServletRequestBuilder request = get("/auth")
|
||||
.session(expiredSession())
|
||||
.with(httpBasic("user", "password"));
|
||||
this.mvc.perform(request)
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(cookie().maxAge("testCookie", 0))
|
||||
.andExpect(cookie().exists("rememberMeCookie"))
|
||||
.andExpect(session().valid(true));
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
public void requestWhenConcurrencyControlAndRememberMeAreSetThenInvokedWhenSessionExpires() throws Exception {
|
||||
this.spring.configLocations(this.xml("ConcurrencyControlRememberMeHandler")).autowire();
|
||||
this.mvc.perform(get("/auth").session(this.expiredSession()).with(httpBasic("user", "password")))
|
||||
this.spring.configLocations(xml("ConcurrencyControlRememberMeHandler")).autowire();
|
||||
// @formatter:off
|
||||
MockHttpServletRequestBuilder request = get("/auth")
|
||||
.session(expiredSession())
|
||||
.with(httpBasic("user", "password"));
|
||||
this.mvc.perform(request)
|
||||
.andExpect(status().isOk()).andExpect(cookie().exists("rememberMeCookie"))
|
||||
.andExpect(session().exists(false));
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -248,77 +303,104 @@ public class SessionManagementConfigTests {
|
|||
*/
|
||||
@Test
|
||||
public void autowireWhenConcurrencyControlIsSetThenLogoutHandlersGetAuthenticationObject() throws Exception {
|
||||
this.spring.configLocations(this.xml("ConcurrencyControlCustomLogoutHandler")).autowire();
|
||||
MvcResult result = this.mvc.perform(get("/auth").with(httpBasic("user", "password"))).andExpect(session())
|
||||
this.spring.configLocations(xml("ConcurrencyControlCustomLogoutHandler")).autowire();
|
||||
MvcResult result = this.mvc.perform(get("/auth").with(httpBasic("user", "password")))
|
||||
.andExpect(session())
|
||||
.andReturn();
|
||||
MockHttpSession session = (MockHttpSession) result.getRequest().getSession(false);
|
||||
SessionRegistry sessionRegistry = this.spring.getContext().getBean(SessionRegistry.class);
|
||||
sessionRegistry.getSessionInformation(session.getId()).expireNow();
|
||||
this.mvc.perform(get("/auth").session(session)).andExpect(header().string("X-Username", "user"));
|
||||
// @formatter:off
|
||||
this.mvc.perform(get("/auth").session(session))
|
||||
.andExpect(header().string("X-Username", "user"));
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
public void requestWhenConcurrencyControlIsSetThenDefaultsToResponseBodyExpirationResponse() throws Exception {
|
||||
this.spring.configLocations(this.xml("ConcurrencyControlSessionRegistryAlias")).autowire();
|
||||
this.mvc.perform(get("/auth").session(this.expiredSession()).with(httpBasic("user", "password")))
|
||||
this.spring.configLocations(xml("ConcurrencyControlSessionRegistryAlias")).autowire();
|
||||
// @formatter:off
|
||||
MockHttpServletRequestBuilder request = get("/auth")
|
||||
.session(expiredSession())
|
||||
.with(httpBasic("user", "password"));
|
||||
this.mvc.perform(request)
|
||||
.andExpect(content().string("This session has been expired (possibly due to multiple concurrent "
|
||||
+ "logins being attempted as the same user)."));
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
public void requestWhenCustomSessionAuthenticationStrategyThenInvokesOnAuthentication() throws Exception {
|
||||
this.spring.configLocations(this.xml("SessionAuthenticationStrategyRef")).autowire();
|
||||
this.mvc.perform(get("/auth").with(httpBasic("user", "password"))).andExpect(status().isIAmATeapot());
|
||||
this.spring.configLocations(xml("SessionAuthenticationStrategyRef")).autowire();
|
||||
// @formatter:off
|
||||
this.mvc.perform(get("/auth").with(httpBasic("user", "password")))
|
||||
.andExpect(status().isIAmATeapot());
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
public void autowireWhenSessionRegistryRefIsSetThenAvailableForWiring() {
|
||||
this.spring.configLocations(this.xml("ConcurrencyControlSessionRegistryRef")).autowire();
|
||||
this.spring.configLocations(xml("ConcurrencyControlSessionRegistryRef")).autowire();
|
||||
this.sessionRegistryIsValid();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void requestWhenMaxSessionsIsSetThenErrorsWhenExceeded() throws Exception {
|
||||
this.spring.configLocations(this.xml("ConcurrencyControlMaxSessions")).autowire();
|
||||
this.mvc.perform(get("/auth").with(httpBasic("user", "password"))).andExpect(status().isOk());
|
||||
this.mvc.perform(get("/auth").with(httpBasic("user", "password"))).andExpect(status().isOk());
|
||||
this.mvc.perform(get("/auth").with(httpBasic("user", "password"))).andExpect(redirectedUrl("/max-exceeded"));
|
||||
this.spring.configLocations(xml("ConcurrencyControlMaxSessions")).autowire();
|
||||
// @formatter:off
|
||||
this.mvc.perform(get("/auth").with(httpBasic("user", "password")))
|
||||
.andExpect(status().isOk());
|
||||
this.mvc.perform(get("/auth").with(httpBasic("user", "password")))
|
||||
.andExpect(status().isOk());
|
||||
this.mvc.perform(get("/auth").with(httpBasic("user", "password")))
|
||||
.andExpect(redirectedUrl("/max-exceeded"));
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
public void autowireWhenSessionFixationProtectionIsNoneAndCsrfDisabledThenSessionManagementFilterIsNotWired() {
|
||||
this.spring.configLocations(this.xml("NoSessionManagementFilter")).autowire();
|
||||
this.spring.configLocations(xml("NoSessionManagementFilter")).autowire();
|
||||
assertThat(this.getFilter(SessionManagementFilter.class)).isNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void requestWhenSessionFixationProtectionIsNoneThenSessionNotInvalidated() throws Exception {
|
||||
this.spring.configLocations(this.xml("SessionFixationProtectionNone")).autowire();
|
||||
this.spring.configLocations(xml("SessionFixationProtectionNone")).autowire();
|
||||
MockHttpSession session = new MockHttpSession();
|
||||
String sessionId = session.getId();
|
||||
// @formatter:off
|
||||
this.mvc.perform(get("/auth").session(session).with(httpBasic("user", "password")))
|
||||
.andExpect(session().id(sessionId));
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
public void requestWhenSessionFixationProtectionIsMigrateSessionThenSessionIsReplaced() throws Exception {
|
||||
this.spring.configLocations(this.xml("SessionFixationProtectionMigrateSession")).autowire();
|
||||
this.spring.configLocations(xml("SessionFixationProtectionMigrateSession")).autowire();
|
||||
MockHttpSession session = new MockHttpSession();
|
||||
String sessionId = session.getId();
|
||||
// @formatter:off
|
||||
MvcResult result = this.mvc.perform(get("/auth").session(session).with(httpBasic("user", "password")))
|
||||
.andExpect(session()).andReturn();
|
||||
.andExpect(session())
|
||||
.andReturn();
|
||||
// @formatter:on
|
||||
assertThat(result.getRequest().getSession(false).getId()).isNotEqualTo(sessionId);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void requestWhenSessionFixationProtectionIsNoneAndInvalidSessionUrlIsSetThenStillRedirectsOnInvalidSession()
|
||||
throws Exception {
|
||||
this.spring.configLocations(this.xml("SessionFixationProtectionNoneWithInvalidSessionUrl")).autowire();
|
||||
this.mvc.perform(get("/auth").with((request) -> {
|
||||
request.setRequestedSessionId("1");
|
||||
request.setRequestedSessionIdValid(false);
|
||||
return request;
|
||||
})).andExpect(redirectedUrl("/timeoutUrl"));
|
||||
this.spring.configLocations(xml("SessionFixationProtectionNoneWithInvalidSessionUrl")).autowire();
|
||||
// @formatter:off
|
||||
MockHttpServletRequestBuilder request = get("/auth")
|
||||
.with((request) -> {
|
||||
request.setRequestedSessionId("1");
|
||||
request.setRequestedSessionIdValid(false);
|
||||
return request;
|
||||
});
|
||||
this.mvc.perform(request)
|
||||
.andExpect(redirectedUrl("/timeoutUrl"));
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
private void sessionRegistryIsValid() {
|
||||
|
@ -367,7 +449,7 @@ public class SessionManagementConfigTests {
|
|||
*/
|
||||
@Test
|
||||
public void checkConcurrencyAndLogoutFilterHasSameSizeAndHasLogoutSuccessEventPublishingLogoutHandler() {
|
||||
this.spring.configLocations(this.xml("ConcurrencyControlLogoutAndRememberMeHandlers")).autowire();
|
||||
this.spring.configLocations(xml("ConcurrencyControlLogoutAndRememberMeHandlers")).autowire();
|
||||
ConcurrentSessionFilter concurrentSessionFilter = getFilter(ConcurrentSessionFilter.class);
|
||||
LogoutFilter logoutFilter = getFilter(LogoutFilter.class);
|
||||
LogoutHandler csfLogoutHandler = getFieldValue(concurrentSessionFilter, "handlers");
|
||||
|
|
|
@ -75,11 +75,14 @@ public class GlobalMethodSecurityBeanDefinitionParserTests {
|
|||
private BusinessService target;
|
||||
|
||||
public void loadContext() {
|
||||
// @formatter:off
|
||||
setContext("<b:bean id='target' class='org.springframework.security.access.annotation.BusinessServiceImpl'/>"
|
||||
+ "<global-method-security order='1001' proxy-target-class='false' >"
|
||||
+ " <protect-pointcut expression='execution(* *.someUser*(..))' access='ROLE_USER'/>"
|
||||
+ " <protect-pointcut expression='execution(* *.someAdmin*(..))' access='ROLE_ADMIN'/>"
|
||||
+ "</global-method-security>" + ConfigTestUtils.AUTH_PROVIDER_XML);
|
||||
+ "</global-method-security>"
|
||||
+ ConfigTestUtils.AUTH_PROVIDER_XML);
|
||||
// @formatter:on
|
||||
this.target = (BusinessService) this.appContext.getBean("target");
|
||||
}
|
||||
|
||||
|
@ -122,11 +125,14 @@ public class GlobalMethodSecurityBeanDefinitionParserTests {
|
|||
|
||||
@Test
|
||||
public void doesntInterfereWithBeanPostProcessing() {
|
||||
setContext(
|
||||
"<b:bean id='myUserService' class='org.springframework.security.config.PostProcessedMockUserDetailsService'/>"
|
||||
+ "<global-method-security />" + "<authentication-manager>"
|
||||
+ " <authentication-provider user-service-ref='myUserService'/>" + "</authentication-manager>"
|
||||
+ "<b:bean id='beanPostProcessor' class='org.springframework.security.config.MockUserServiceBeanPostProcessor'/>");
|
||||
// @formatter:off
|
||||
setContext("<b:bean id='myUserService' class='org.springframework.security.config.PostProcessedMockUserDetailsService'/>"
|
||||
+ "<global-method-security />"
|
||||
+ "<authentication-manager>"
|
||||
+ " <authentication-provider user-service-ref='myUserService'/>"
|
||||
+ "</authentication-manager>"
|
||||
+ "<b:bean id='beanPostProcessor' class='org.springframework.security.config.MockUserServiceBeanPostProcessor'/>");
|
||||
// @formatter:on
|
||||
PostProcessedMockUserDetailsService service = (PostProcessedMockUserDetailsService) this.appContext
|
||||
.getBean("myUserService");
|
||||
assertThat(service.getPostProcessorWasHere()).isEqualTo("Hello from the post processor!");
|
||||
|
@ -134,12 +140,17 @@ public class GlobalMethodSecurityBeanDefinitionParserTests {
|
|||
|
||||
@Test(expected = AccessDeniedException.class)
|
||||
public void worksWithAspectJAutoproxy() {
|
||||
// @formatter:off
|
||||
setContext("<global-method-security>"
|
||||
+ " <protect-pointcut expression='execution(* org.springframework.security.config.*Service.*(..))'"
|
||||
+ " access='ROLE_SOMETHING' />" + "</global-method-security>"
|
||||
+ " access='ROLE_SOMETHING' />"
|
||||
+ "</global-method-security>"
|
||||
+ "<b:bean id='myUserService' class='org.springframework.security.config.PostProcessedMockUserDetailsService'/>"
|
||||
+ "<aop:aspectj-autoproxy />" + "<authentication-manager>"
|
||||
+ " <authentication-provider user-service-ref='myUserService'/>" + "</authentication-manager>");
|
||||
+ "<aop:aspectj-autoproxy />"
|
||||
+ "<authentication-manager>"
|
||||
+ " <authentication-provider user-service-ref='myUserService'/>"
|
||||
+ "</authentication-manager>");
|
||||
// @formatter:on
|
||||
UserDetailsService service = (UserDetailsService) this.appContext.getBean("myUserService");
|
||||
UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken("Test", "Password",
|
||||
AuthorityUtils.createAuthorityList("ROLE_SOMEOTHERROLE"));
|
||||
|
@ -149,11 +160,14 @@ public class GlobalMethodSecurityBeanDefinitionParserTests {
|
|||
|
||||
@Test
|
||||
public void supportsMethodArgumentsInPointcut() {
|
||||
// @formatter:off
|
||||
setContext("<b:bean id='target' class='org.springframework.security.access.annotation.BusinessServiceImpl'/>"
|
||||
+ "<global-method-security>"
|
||||
+ " <protect-pointcut expression='execution(* org.springframework.security.access.annotation.BusinessService.someOther(String))' access='ROLE_ADMIN'/>"
|
||||
+ " <protect-pointcut expression='execution(* org.springframework.security.access.annotation.BusinessService.*(..))' access='ROLE_USER'/>"
|
||||
+ "</global-method-security>" + ConfigTestUtils.AUTH_PROVIDER_XML);
|
||||
+ "</global-method-security>"
|
||||
+ ConfigTestUtils.AUTH_PROVIDER_XML);
|
||||
// @formatter:on
|
||||
SecurityContextHolder.getContext()
|
||||
.setAuthentication(new UsernamePasswordAuthenticationToken("user", "password"));
|
||||
this.target = (BusinessService) this.appContext.getBean("target");
|
||||
|
@ -171,12 +185,16 @@ public class GlobalMethodSecurityBeanDefinitionParserTests {
|
|||
|
||||
@Test
|
||||
public void supportsBooleanPointcutExpressions() {
|
||||
// @formatter:off
|
||||
setContext("<b:bean id='target' class='org.springframework.security.access.annotation.BusinessServiceImpl'/>"
|
||||
+ "<global-method-security>" + " <protect-pointcut expression="
|
||||
+ "<global-method-security>"
|
||||
+ " <protect-pointcut expression="
|
||||
+ " 'execution(* org.springframework.security.access.annotation.BusinessService.*(..)) "
|
||||
+ " and not execution(* org.springframework.security.access.annotation.BusinessService.someOther(String)))' "
|
||||
+ " access='ROLE_USER'/>" + "</global-method-security>"
|
||||
+ " access='ROLE_USER'/>"
|
||||
+ "</global-method-security>"
|
||||
+ ConfigTestUtils.AUTH_PROVIDER_XML);
|
||||
// @formatter:on
|
||||
this.target = (BusinessService) this.appContext.getBean("target");
|
||||
// String method should not be protected
|
||||
this.target.someOther("somestring");
|
||||
|
@ -200,11 +218,14 @@ public class GlobalMethodSecurityBeanDefinitionParserTests {
|
|||
// SEC-936
|
||||
@Test(expected = AccessDeniedException.class)
|
||||
public void worksWithoutTargetOrClass() {
|
||||
// @formatter:off
|
||||
setContext("<global-method-security secured-annotations='enabled'/>"
|
||||
+ "<b:bean id='businessService' class='org.springframework.remoting.httpinvoker.HttpInvokerProxyFactoryBean'>"
|
||||
+ " <b:property name='serviceUrl' value='http://localhost:8080/SomeService'/>"
|
||||
+ " <b:property name='serviceInterface' value='org.springframework.security.access.annotation.BusinessService'/>"
|
||||
+ "</b:bean>" + ConfigTestUtils.AUTH_PROVIDER_XML);
|
||||
+ "</b:bean>"
|
||||
+ ConfigTestUtils.AUTH_PROVIDER_XML);
|
||||
// @formatter:on
|
||||
UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken("Test", "Password",
|
||||
AuthorityUtils.createAuthorityList("ROLE_SOMEOTHERROLE"));
|
||||
SecurityContextHolder.getContext().setAuthentication(token);
|
||||
|
@ -232,9 +253,11 @@ public class GlobalMethodSecurityBeanDefinitionParserTests {
|
|||
|
||||
@Test(expected = AccessDeniedException.class)
|
||||
public void accessIsDeniedForHasRoleExpression() {
|
||||
// @formatter:off
|
||||
setContext("<global-method-security pre-post-annotations='enabled'/>"
|
||||
+ "<b:bean id='target' class='org.springframework.security.access.annotation.ExpressionProtectedBusinessServiceImpl'/>"
|
||||
+ ConfigTestUtils.AUTH_PROVIDER_XML);
|
||||
// @formatter:on
|
||||
SecurityContextHolder.getContext().setAuthentication(this.bob);
|
||||
this.target = (BusinessService) this.appContext.getBean("target");
|
||||
this.target.someAdminMethod();
|
||||
|
@ -242,11 +265,14 @@ public class GlobalMethodSecurityBeanDefinitionParserTests {
|
|||
|
||||
@Test
|
||||
public void beanNameExpressionPropertyIsSupported() {
|
||||
// @formatter:off
|
||||
setContext("<global-method-security pre-post-annotations='enabled' proxy-target-class='true'/>"
|
||||
+ "<b:bean id='number' class='java.lang.Integer'>" + " <b:constructor-arg value='1294'/>"
|
||||
+ "<b:bean id='number' class='java.lang.Integer'>"
|
||||
+ " <b:constructor-arg value='1294'/>"
|
||||
+ "</b:bean>"
|
||||
+ "<b:bean id='target' class='org.springframework.security.access.annotation.ExpressionProtectedBusinessServiceImpl'/>"
|
||||
+ ConfigTestUtils.AUTH_PROVIDER_XML);
|
||||
// @formatter:on
|
||||
SecurityContextHolder.getContext().setAuthentication(this.bob);
|
||||
ExpressionProtectedBusinessServiceImpl target = (ExpressionProtectedBusinessServiceImpl) this.appContext
|
||||
.getBean("target");
|
||||
|
@ -255,9 +281,11 @@ public class GlobalMethodSecurityBeanDefinitionParserTests {
|
|||
|
||||
@Test
|
||||
public void preAndPostFilterAnnotationsWorkWithLists() {
|
||||
// @formatter:off
|
||||
setContext("<global-method-security pre-post-annotations='enabled'/>"
|
||||
+ "<b:bean id='target' class='org.springframework.security.access.annotation.ExpressionProtectedBusinessServiceImpl'/>"
|
||||
+ ConfigTestUtils.AUTH_PROVIDER_XML);
|
||||
// @formatter:on
|
||||
SecurityContextHolder.getContext().setAuthentication(this.bob);
|
||||
this.target = (BusinessService) this.appContext.getBean("target");
|
||||
List<String> arg = new ArrayList<>();
|
||||
|
@ -274,9 +302,11 @@ public class GlobalMethodSecurityBeanDefinitionParserTests {
|
|||
|
||||
@Test
|
||||
public void prePostFilterAnnotationWorksWithArrays() {
|
||||
// @formatter:off
|
||||
setContext("<global-method-security pre-post-annotations='enabled'/>"
|
||||
+ "<b:bean id='target' class='org.springframework.security.access.annotation.ExpressionProtectedBusinessServiceImpl'/>"
|
||||
+ ConfigTestUtils.AUTH_PROVIDER_XML);
|
||||
// @formatter:on
|
||||
SecurityContextHolder.getContext().setAuthentication(this.bob);
|
||||
this.target = (BusinessService) this.appContext.getBean("target");
|
||||
Object[] arg = new String[] { "joe", "bob", "sam" };
|
||||
|
@ -288,23 +318,30 @@ public class GlobalMethodSecurityBeanDefinitionParserTests {
|
|||
// SEC-1392
|
||||
@Test
|
||||
public void customPermissionEvaluatorIsSupported() {
|
||||
// @formatter:off
|
||||
setContext("<global-method-security pre-post-annotations='enabled'>"
|
||||
+ " <expression-handler ref='expressionHandler'/>" + "</global-method-security>"
|
||||
+ " <expression-handler ref='expressionHandler'/>"
|
||||
+ "</global-method-security>"
|
||||
+ "<b:bean id='expressionHandler' class='org.springframework.security.access.expression.method.DefaultMethodSecurityExpressionHandler'>"
|
||||
+ " <b:property name='permissionEvaluator' ref='myPermissionEvaluator'/>" + "</b:bean>"
|
||||
+ " <b:property name='permissionEvaluator' ref='myPermissionEvaluator'/>"
|
||||
+ "</b:bean>"
|
||||
+ "<b:bean id='myPermissionEvaluator' class='org.springframework.security.config.method.TestPermissionEvaluator'/>"
|
||||
+ ConfigTestUtils.AUTH_PROVIDER_XML);
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
// SEC-1450
|
||||
@Test(expected = AuthenticationException.class)
|
||||
@SuppressWarnings("unchecked")
|
||||
public void genericsAreMatchedByProtectPointcut() {
|
||||
// @formatter:off
|
||||
setContext(
|
||||
"<b:bean id='target' class='org.springframework.security.config.method.GlobalMethodSecurityBeanDefinitionParserTests$ConcreteFoo'/>"
|
||||
+ "<global-method-security>"
|
||||
+ " <protect-pointcut expression='execution(* org..*Foo.foo(..))' access='ROLE_USER'/>"
|
||||
+ "</global-method-security>" + ConfigTestUtils.AUTH_PROVIDER_XML);
|
||||
+ "</global-method-security>"
|
||||
+ ConfigTestUtils.AUTH_PROVIDER_XML);
|
||||
// @formatter:on
|
||||
Foo foo = (Foo) this.appContext.getBean("target");
|
||||
foo.foo(new SecurityConfig("A"));
|
||||
}
|
||||
|
@ -313,8 +350,11 @@ public class GlobalMethodSecurityBeanDefinitionParserTests {
|
|||
@Test
|
||||
@SuppressWarnings("unchecked")
|
||||
public void genericsMethodArgumentNamesAreResolved() {
|
||||
// @formatter:off
|
||||
setContext("<b:bean id='target' class='" + ConcreteFoo.class.getName() + "'/>"
|
||||
+ "<global-method-security pre-post-annotations='enabled'/>" + ConfigTestUtils.AUTH_PROVIDER_XML);
|
||||
+ "<global-method-security pre-post-annotations='enabled'/>"
|
||||
+ ConfigTestUtils.AUTH_PROVIDER_XML);
|
||||
// @formatter:on
|
||||
SecurityContextHolder.getContext().setAuthentication(this.bob);
|
||||
Foo foo = (Foo) this.appContext.getBean("target");
|
||||
foo.foo(new SecurityConfig("A"));
|
||||
|
@ -338,11 +378,14 @@ public class GlobalMethodSecurityBeanDefinitionParserTests {
|
|||
@Test
|
||||
@SuppressWarnings("unchecked")
|
||||
public void supportsExternalMetadataSource() {
|
||||
// @formatter:off
|
||||
setContext("<b:bean id='target' class='" + ConcreteFoo.class.getName() + "'/>"
|
||||
+ "<method-security-metadata-source id='mds'>" + " <protect method='" + Foo.class.getName()
|
||||
+ ".foo' access='ROLE_ADMIN'/>" + "</method-security-metadata-source>"
|
||||
+ "<method-security-metadata-source id='mds'>"
|
||||
+ " <protect method='" + Foo.class.getName() + ".foo' access='ROLE_ADMIN'/>"
|
||||
+ "</method-security-metadata-source>"
|
||||
+ "<global-method-security pre-post-annotations='enabled' metadata-source-ref='mds'/>"
|
||||
+ ConfigTestUtils.AUTH_PROVIDER_XML);
|
||||
// @formatter:on
|
||||
// External MDS should take precedence over PreAuthorize
|
||||
SecurityContextHolder.getContext().setAuthentication(this.bob);
|
||||
Foo foo = (Foo) this.appContext.getBean("target");
|
||||
|
@ -359,12 +402,17 @@ public class GlobalMethodSecurityBeanDefinitionParserTests {
|
|||
|
||||
@Test
|
||||
public void supportsCustomAuthenticationManager() {
|
||||
// @formatter:off
|
||||
setContext("<b:bean id='target' class='" + ConcreteFoo.class.getName() + "'/>"
|
||||
+ "<method-security-metadata-source id='mds'>" + " <protect method='" + Foo.class.getName()
|
||||
+ ".foo' access='ROLE_ADMIN'/>" + "</method-security-metadata-source>"
|
||||
+ "<method-security-metadata-source id='mds'>"
|
||||
+ " <protect method='" + Foo.class.getName() + ".foo' access='ROLE_ADMIN'/>"
|
||||
+ "</method-security-metadata-source>"
|
||||
+ "<global-method-security pre-post-annotations='enabled' metadata-source-ref='mds' authentication-manager-ref='customAuthMgr'/>"
|
||||
+ "<b:bean id='customAuthMgr' class='org.springframework.security.config.method.GlobalMethodSecurityBeanDefinitionParserTests$CustomAuthManager'>"
|
||||
+ " <b:constructor-arg value='authManager'/>" + "</b:bean>" + ConfigTestUtils.AUTH_PROVIDER_XML);
|
||||
+ " <b:constructor-arg value='authManager'/>"
|
||||
+ "</b:bean>"
|
||||
+ ConfigTestUtils.AUTH_PROVIDER_XML);
|
||||
// @formatter:on
|
||||
SecurityContextHolder.getContext().setAuthentication(this.bob);
|
||||
Foo foo = (Foo) this.appContext.getBean("target");
|
||||
try {
|
||||
|
|
|
@ -40,9 +40,12 @@ public class Jsr250AnnotationDrivenBeanDefinitionParserTests {
|
|||
|
||||
@Before
|
||||
public void loadContext() {
|
||||
// @formatter:off
|
||||
this.appContext = new InMemoryXmlApplicationContext(
|
||||
"<b:bean id='target' class='org.springframework.security.access.annotation.Jsr250BusinessServiceImpl'/>"
|
||||
+ "<global-method-security jsr250-annotations='enabled'/>" + ConfigTestUtils.AUTH_PROVIDER_XML);
|
||||
+ "<global-method-security jsr250-annotations='enabled'/>"
|
||||
+ ConfigTestUtils.AUTH_PROVIDER_XML);
|
||||
// @formatter:on
|
||||
this.target = (BusinessService) this.appContext.getBean("target");
|
||||
}
|
||||
|
||||
|
|
|
@ -46,39 +46,80 @@ public class ClientRegistrationsBeanDefinitionParserTests {
|
|||
|
||||
private static final String CONFIG_LOCATION_PREFIX = "classpath:org/springframework/security/config/oauth2/client/ClientRegistrationsBeanDefinitionParserTests";
|
||||
|
||||
// @formatter:off
|
||||
private static final String ISSUER_URI_XML_CONFIG = "<b:beans xmlns:b=\"http://www.springframework.org/schema/beans\"\n"
|
||||
+ "\t\txmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n"
|
||||
+ "\t\txmlns=\"http://www.springframework.org/schema/security\"\n" + "\t\txsi:schemaLocation=\"\n"
|
||||
+ "\t\t\thttp://www.springframework.org/schema/security\n"
|
||||
+ "\t\t\thttps://www.springframework.org/schema/security/spring-security.xsd\n"
|
||||
+ "\t\t\thttp://www.springframework.org/schema/beans\n"
|
||||
+ "\t\t\thttps://www.springframework.org/schema/beans/spring-beans.xsd\">\n" + "\n"
|
||||
+ "\t<client-registrations>\n"
|
||||
+ "\t\t<client-registration registration-id=\"google-login\" client-id=\"google-client-id\" \n"
|
||||
+ "\t\t\t\t\t\t\t client-secret=\"google-client-secret\" provider-id=\"google\"/>\n"
|
||||
+ "\t\t<provider provider-id=\"google\" issuer-uri=\"${issuer-uri}\"/>\n" + "\t</client-registrations>\n"
|
||||
+ "\n" + "</b:beans>\n";
|
||||
+ " xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n"
|
||||
+ " xmlns=\"http://www.springframework.org/schema/security\"\n"
|
||||
+ " xsi:schemaLocation=\"\n"
|
||||
+ " http://www.springframework.org/schema/security\n"
|
||||
+ " https://www.springframework.org/schema/security/spring-security.xsd\n"
|
||||
+ " http://www.springframework.org/schema/beans\n"
|
||||
+ " https://www.springframework.org/schema/beans/spring-beans.xsd\">\n"
|
||||
+ "\n"
|
||||
+ " <client-registrations>\n"
|
||||
+ " <client-registration registration-id=\"google-login\" client-id=\"google-client-id\" \n"
|
||||
+ " client-secret=\"google-client-secret\" provider-id=\"google\"/>\n"
|
||||
+ " <provider provider-id=\"google\" issuer-uri=\"${issuer-uri}\"/>\n"
|
||||
+ " </client-registrations>\n"
|
||||
+ "\n"
|
||||
+ "</b:beans>\n";
|
||||
// @formatter:on
|
||||
|
||||
// @formatter:off
|
||||
private static final String OIDC_DISCOVERY_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\": \"${issuer-uri}\", \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"
|
||||
+ " \"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\": \"${issuer-uri}\", \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" + "}";
|
||||
+ " \"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"
|
||||
+ "}";
|
||||
// @formatter:on
|
||||
|
||||
@Autowired
|
||||
private ClientRegistrationRepository clientRegistrationRepository;
|
||||
|
@ -183,7 +224,10 @@ public class ClientRegistrationsBeanDefinitionParserTests {
|
|||
}
|
||||
|
||||
private static String xml(String configName) {
|
||||
return CONFIG_LOCATION_PREFIX + "-" + configName + ".xml";
|
||||
return CONFIG_LOCATION_PREFIX
|
||||
+ "-"
|
||||
+ configName
|
||||
+ ".xml";
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -129,8 +129,12 @@ public class SpringTestContext implements Closeable {
|
|||
this.context.setServletConfig(new MockServletConfig());
|
||||
this.context.refresh();
|
||||
if (this.context.containsBean(BeanIds.SPRING_SECURITY_FILTER_CHAIN)) {
|
||||
MockMvc mockMvc = MockMvcBuilders.webAppContextSetup(this.context).apply(springSecurity())
|
||||
.apply(new AddFilter()).build();
|
||||
// @formatter:off
|
||||
MockMvc mockMvc = MockMvcBuilders.webAppContextSetup(this.context).
|
||||
apply(springSecurity())
|
||||
.apply(new AddFilter())
|
||||
.build();
|
||||
// @formatter:on
|
||||
this.context.getBeanFactory().registerResolvableDependency(MockMvc.class, mockMvc);
|
||||
}
|
||||
AutowiredAnnotationBeanPostProcessor bpp = new AutowiredAnnotationBeanPostProcessor();
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue