test doesn't go whole cycle of spring security instad mock create Security context also assuming authentication had worked already
authentication , authorization test are seperated
@SpringBootTest
@AutoConfigureMockMvc
class Example1Tests {
@Autowired
private MockMvc mockMvc;
@Test
@DisplayName("When calling the /demo endpoint without authentication we expect to get a 401 Unauthorized.")
void testUnauthenticatedDemoEndpoint() throws Exception {
mockMvc.perform(get("/demo"))
.andExpect(status().isUnauthorized());
}
@Test
@WithMockUser
void testAuthenticatedWithoutProperAuthDemoEndpoint() throws Exception {
mockMvc.perform(get("/demo"))
.andExpect(status().isForbidden());
}
}
mockmvc let you test what client will get if he calls my rest api
here we are simply testing Authorization not Authentication, we assume we are already authenticated somehow.
name of method need to be short , when you wan to tell story abouth this method use @DisplayName
never user network when writing test like database
@Configuration
public class ProjectConfig extends WebSecurityConfigurerAdapter {
@Bean
public UserDetailsService userDetailsService() {
var uds = new InMemoryUserDetailsManager();
var u1 = User.withUsername("john")
.password("12345")
.authorities("read")
.build();
var u2 = User.withUsername("bill")
.password("12345")
.authorities("write")
.build();
uds.createUser(u1);
uds.createUser(u2);
return uds;
}
@Bean
public PasswordEncoder passwordEncoder() {
return NoOpPasswordEncoder.getInstance();
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http.httpBasic();
http.authorizeRequests()
.anyRequest().hasAuthority("read");
}
@Test
@WithMockUser(username = "mary", authorities = "read")
void testAuthenticatedWithProperAuthDemoEndpoint() throws Exception {
mockMvc.perform(get("/demo"))
.andExpect(status().isOk());
}
now we are considering Authorization (read)
notice there is no user mary but still works because we are skipping authentication
@SpringBootTest
@AutoConfigureMockMvc
class Example2Tests {
@Autowired
private MockMvc mockMvc;
@Test
@DisplayName("When calling the /demo endpoint without authentication we expect to get a 401 Unauthorized.")
void testUnauthenticatedDemoEndpoint() throws Exception {
mockMvc.perform(get("/demo"))
.andExpect(status().isUnauthorized());
}
@Test
@WithUserDetails("bill")
void testAuthenticatedWithoutProperAuthDemoEndpoint() throws Exception {
mockMvc.perform(get("/demo"))
.andExpect(status().isForbidden());
}
@Test
@WithUserDetails("john")
void testAuthenticatedWithProperAuthDemoEndpoint() throws Exception {
mockMvc.perform(get("/demo"))
.andExpect(status().isOk());
}
}
we can write test with actual user instead of mock user
public class WithCustomSecurityContextFactory
implements WithSecurityContextFactory<WithCustomUser> {
@Override
public SecurityContext createSecurityContext(WithCustomUser withCustomUser) {
SecurityContext context = SecurityContextHolder.createEmptyContext();
Authentication a =
new UsernamePasswordAuthenticationToken("bill", null,
List.of(() -> withCustomUser.authority()));
context.setAuthentication(a);
return context;
}
}
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
@WithSecurityContext(factory = WithCustomSecurityContextFactory.class)
public @interface WithCustomUser {
String authority();
}
create custom Security Context
WithCustomUser -> name of annotation
CustomSecurityContextFactory gets authority from given annotation.authoirty()
@Test
@WithCustomUser(authority = "read")
void testAuthenticatedWithAProperAuthDemoEndpoint() throws Exception {
mockMvc.perform(get("/demo"))
.andExpect(status().isOk());
}
spring sees @WithCustomUser -> see @WithSecurityContext and know where to get security context from
@Test
void testAuthenticatedWithProperAuthDemoEndpoint() throws Exception {
mockMvc.perform(
get("/demo").with(httpBasic("john", "12345"))
).andExpect(status().isOk());
}
test for authentication -> here we used basic auth(httpBasic)
but we can also use jwt() for jwt validation or opaqueToken()
'WEB > Security' 카테고리의 다른 글
Spring Security Fundamentals (0) | 2022.11.16 |
---|---|
앱 설명 (0) | 2022.06.08 |
Lesson 29 - Using permissions (0) | 2022.05.20 |
Lesson 27 - Method authorization configurations (0) | 2022.05.16 |
Lesson 26 - Endpoint authorization rules for an OAuth 2 resource server (0) | 2022.05.14 |