Baeldung source format
This commit is contained in:
parent
66d71f0697
commit
26e401b290
|
@ -1,7 +0,0 @@
|
|||
## Spring-Security 6 OAuth2 testing samples
|
||||
|
||||
This module contains articles about testing spring-security 6 access-control with OAuth2
|
||||
|
||||
## Relevant articles:
|
||||
|
||||
- [Testing Spring OAuth2 Access-Control](https://drafts.baeldung.com/?p=154767&preview=true)
|
|
@ -1,32 +1,32 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<artifactId>spring-security-oauth2-testing</artifactId>
|
||||
<name>spring-security-oauth2-testing</name>
|
||||
<packaging>pom</packaging>
|
||||
<description>spring-security 6 oauth testing sample project</description>
|
||||
<parent>
|
||||
<groupId>com.baeldung</groupId>
|
||||
<artifactId>parent-boot-3</artifactId>
|
||||
<version>0.0.1-SNAPSHOT</version>
|
||||
<relativePath>../../parent-boot-3</relativePath>
|
||||
</parent>
|
||||
<properties>
|
||||
<spring-addons.version>6.0.14</spring-addons.version>
|
||||
</properties>
|
||||
<dependencyManagement>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>com.c4-soft.springaddons</groupId>
|
||||
<artifactId>spring-addons-oauth2-test</artifactId>
|
||||
<version>${spring-addons.version}</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</dependencyManagement>
|
||||
<modules>
|
||||
<module>reactive-resource-server</module>
|
||||
<module>servlet-resource-server</module>
|
||||
</modules>
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<artifactId>spring-security-oauth2-testing</artifactId>
|
||||
<name>spring-security-oauth2-testing</name>
|
||||
<packaging>pom</packaging>
|
||||
<description>spring-security 6 oauth testing sample project</description>
|
||||
<parent>
|
||||
<groupId>com.baeldung</groupId>
|
||||
<artifactId>parent-boot-3</artifactId>
|
||||
<version>0.0.1-SNAPSHOT</version>
|
||||
<relativePath>../../parent-boot-3</relativePath>
|
||||
</parent>
|
||||
<properties>
|
||||
<spring-addons.version>6.1.0</spring-addons.version>
|
||||
</properties>
|
||||
<dependencyManagement>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>com.c4-soft.springaddons</groupId>
|
||||
<artifactId>spring-addons-oauth2-test</artifactId>
|
||||
<version>${spring-addons.version}</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</dependencyManagement>
|
||||
<modules>
|
||||
<module>reactive-resource-server</module>
|
||||
<module>servlet-resource-server</module>
|
||||
</modules>
|
||||
</project>
|
|
@ -1,58 +1,58 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<parent>
|
||||
<groupId>com.baeldung</groupId>
|
||||
<artifactId>spring-security-oauth2-testing</artifactId>
|
||||
<version>0.0.1-SNAPSHOT</version>
|
||||
</parent>
|
||||
<groupId>com.baeldung.spring-security-modules.testing</groupId>
|
||||
<artifactId>reactive-resource-server</artifactId>
|
||||
<name>reactive-resource-server</name>
|
||||
<description>Demo project for Spring Boot reactive resource-server</description>
|
||||
<properties>
|
||||
<java.version>17</java.version>
|
||||
</properties>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-oauth2-resource-server</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-webflux</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.projectlombok</groupId>
|
||||
<artifactId>lombok</artifactId>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-test</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.c4-soft.springaddons</groupId>
|
||||
<artifactId>spring-addons-oauth2-test</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-maven-plugin</artifactId>
|
||||
<configuration>
|
||||
<excludes>
|
||||
<exclude>
|
||||
<groupId>org.projectlombok</groupId>
|
||||
<artifactId>lombok</artifactId>
|
||||
</exclude>
|
||||
</excludes>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<parent>
|
||||
<groupId>com.baeldung</groupId>
|
||||
<artifactId>spring-security-oauth2-testing</artifactId>
|
||||
<version>0.0.1-SNAPSHOT</version>
|
||||
</parent>
|
||||
<groupId>com.baeldung.spring-security-modules.testing</groupId>
|
||||
<artifactId>reactive-resource-server</artifactId>
|
||||
<name>reactive-resource-server</name>
|
||||
<description>Demo project for Spring Boot reactive resource-server</description>
|
||||
<properties>
|
||||
<java.version>17</java.version>
|
||||
</properties>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-oauth2-resource-server</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-webflux</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.projectlombok</groupId>
|
||||
<artifactId>lombok</artifactId>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-test</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.c4-soft.springaddons</groupId>
|
||||
<artifactId>spring-addons-oauth2-test</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-maven-plugin</artifactId>
|
||||
<configuration>
|
||||
<excludes>
|
||||
<exclude>
|
||||
<groupId>org.projectlombok</groupId>
|
||||
<artifactId>lombok</artifactId>
|
||||
</exclude>
|
||||
</excludes>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</project>
|
|
@ -49,19 +49,32 @@ public class ReactiveResourceServerApplication {
|
|||
public class SecurityConfig {
|
||||
@Bean
|
||||
SecurityWebFilterChain springSecurityFilterChain(ServerHttpSecurity http, Converter<Jwt, Mono<Collection<GrantedAuthority>>> authoritiesConverter) {
|
||||
http.oauth2ResourceServer().jwt()
|
||||
.jwtAuthenticationConverter(jwt -> authoritiesConverter.convert(jwt).map(authorities -> new JwtAuthenticationToken(jwt, authorities)));
|
||||
http.securityContextRepository(NoOpServerSecurityContextRepository.getInstance()).csrf().disable();
|
||||
http.exceptionHandling().accessDeniedHandler((var exchange, var ex) -> exchange.getPrincipal().flatMap(principal -> {
|
||||
final var response = exchange.getResponse();
|
||||
response.setStatusCode(principal instanceof AnonymousAuthenticationToken ? HttpStatus.UNAUTHORIZED : HttpStatus.FORBIDDEN);
|
||||
response.getHeaders().setContentType(MediaType.TEXT_PLAIN);
|
||||
final var dataBufferFactory = response.bufferFactory();
|
||||
final var buffer = dataBufferFactory.wrap(ex.getMessage().getBytes(Charset.defaultCharset()));
|
||||
return response.writeWith(Mono.just(buffer)).doOnError(error -> DataBufferUtils.release(buffer));
|
||||
}));
|
||||
http.oauth2ResourceServer()
|
||||
.jwt()
|
||||
.jwtAuthenticationConverter(jwt -> authoritiesConverter.convert(jwt)
|
||||
.map(authorities -> new JwtAuthenticationToken(jwt, authorities)));
|
||||
http.securityContextRepository(NoOpServerSecurityContextRepository.getInstance())
|
||||
.csrf()
|
||||
.disable();
|
||||
http.exceptionHandling()
|
||||
.accessDeniedHandler((var exchange, var ex) -> exchange.getPrincipal()
|
||||
.flatMap(principal -> {
|
||||
final var response = exchange.getResponse();
|
||||
response.setStatusCode(principal instanceof AnonymousAuthenticationToken ? HttpStatus.UNAUTHORIZED : HttpStatus.FORBIDDEN);
|
||||
response.getHeaders()
|
||||
.setContentType(MediaType.TEXT_PLAIN);
|
||||
final var dataBufferFactory = response.bufferFactory();
|
||||
final var buffer = dataBufferFactory.wrap(ex.getMessage()
|
||||
.getBytes(Charset.defaultCharset()));
|
||||
return response.writeWith(Mono.just(buffer))
|
||||
.doOnError(error -> DataBufferUtils.release(buffer));
|
||||
}));
|
||||
|
||||
http.authorizeExchange().pathMatchers("/secured-route").hasRole("AUTHORIZED_PERSONNEL").anyExchange().authenticated();
|
||||
http.authorizeExchange()
|
||||
.pathMatchers("/secured-route")
|
||||
.hasRole("AUTHORIZED_PERSONNEL")
|
||||
.anyExchange()
|
||||
.authenticated();
|
||||
|
||||
return http.build();
|
||||
}
|
||||
|
@ -72,10 +85,14 @@ public class ReactiveResourceServerApplication {
|
|||
@Bean
|
||||
AuthoritiesConverter realmRoles2AuthoritiesConverter() {
|
||||
return (Jwt jwt) -> {
|
||||
final var realmRoles = Optional.of(jwt.getClaimAsMap("realm_access")).orElse(Map.of());
|
||||
final var realmRoles = Optional.of(jwt.getClaimAsMap("realm_access"))
|
||||
.orElse(Map.of());
|
||||
@SuppressWarnings("unchecked")
|
||||
final var roles = (List<String>) realmRoles.getOrDefault("roles", List.of());
|
||||
return Mono.just(roles.stream().map(SimpleGrantedAuthority::new).map(GrantedAuthority.class::cast).toList());
|
||||
return Mono.just(roles.stream()
|
||||
.map(SimpleGrantedAuthority::new)
|
||||
.map(GrantedAuthority.class::cast)
|
||||
.toList());
|
||||
};
|
||||
}
|
||||
}
|
||||
|
@ -84,13 +101,13 @@ public class ReactiveResourceServerApplication {
|
|||
public static class MessageService {
|
||||
|
||||
public Mono<String> greet() {
|
||||
return ReactiveSecurityContextHolder.getContext().map(ctx -> {
|
||||
final var who = (JwtAuthenticationToken) ctx.getAuthentication();
|
||||
final var claims = who.getTokenAttributes();
|
||||
return "Hello %s! You are granted with %s.".formatted(
|
||||
claims.getOrDefault(StandardClaimNames.PREFERRED_USERNAME,claims.get(StandardClaimNames.SUB)),
|
||||
who.getAuthorities());
|
||||
}).switchIfEmpty(Mono.error(new AuthenticationCredentialsNotFoundException("Security context is empty")));
|
||||
return ReactiveSecurityContextHolder.getContext()
|
||||
.map(ctx -> {
|
||||
final var who = (JwtAuthenticationToken) ctx.getAuthentication();
|
||||
final var claims = who.getTokenAttributes();
|
||||
return "Hello %s! You are granted with %s.".formatted(claims.getOrDefault(StandardClaimNames.PREFERRED_USERNAME, claims.get(StandardClaimNames.SUB)), who.getAuthorities());
|
||||
})
|
||||
.switchIfEmpty(Mono.error(new AuthenticationCredentialsNotFoundException("Security context is empty")));
|
||||
}
|
||||
|
||||
@PreAuthorize("hasRole('AUTHORIZED_PERSONNEL')")
|
||||
|
@ -106,18 +123,21 @@ public class ReactiveResourceServerApplication {
|
|||
|
||||
@GetMapping("/greet")
|
||||
public Mono<ResponseEntity<String>> greet() {
|
||||
return messageService.greet().map(ResponseEntity::ok);
|
||||
return messageService.greet()
|
||||
.map(ResponseEntity::ok);
|
||||
}
|
||||
|
||||
@GetMapping("/secured-route")
|
||||
public Mono<ResponseEntity<String>> securedRoute() {
|
||||
return messageService.getSecret().map(ResponseEntity::ok);
|
||||
return messageService.getSecret()
|
||||
.map(ResponseEntity::ok);
|
||||
}
|
||||
|
||||
@GetMapping("/secured-method")
|
||||
@PreAuthorize("hasRole('AUTHORIZED_PERSONNEL')")
|
||||
public Mono<ResponseEntity<String>> securedMethod() {
|
||||
return messageService.getSecret().map(ResponseEntity::ok);
|
||||
return messageService.getSecret()
|
||||
.map(ResponseEntity::ok);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -32,25 +32,29 @@ class MessageServiceUnitTest {
|
|||
|
||||
@Test
|
||||
void givenSecurityContextIsEmpty_whenGreet_thenThrowsAuthenticationCredentialsNotFoundException() {
|
||||
assertThrows(AuthenticationCredentialsNotFoundException.class, () -> messageService.greet().block());
|
||||
assertThrows(AuthenticationCredentialsNotFoundException.class, () -> messageService.greet()
|
||||
.block());
|
||||
}
|
||||
|
||||
@Test
|
||||
@WithAnonymousUser
|
||||
void givenUserIsNotAuthenticated_whenGreet_thenThrowsClassCastException() {
|
||||
assertThrows(ClassCastException.class, () -> messageService.greet().block());
|
||||
assertThrows(ClassCastException.class, () -> messageService.greet()
|
||||
.block());
|
||||
}
|
||||
|
||||
@Test
|
||||
@WithMockJwtAuth(authorities = { "admin", "ROLE_AUTHORIZED_PERSONNEL" }, claims = @OpenIdClaims(preferredUsername = "ch4mpy"))
|
||||
void givenSecurityContextIsPopulatedWithJwtAuthenticationToken_whenGreet_thenReturnGreetingWithPreferredUsernameAndAuthorities() {
|
||||
assertEquals("Hello ch4mpy! You are granted with [admin, ROLE_AUTHORIZED_PERSONNEL].", messageService.greet().block());
|
||||
assertEquals("Hello ch4mpy! You are granted with [admin, ROLE_AUTHORIZED_PERSONNEL].", messageService.greet()
|
||||
.block());
|
||||
}
|
||||
|
||||
@Test
|
||||
@WithMockUser(authorities = { "admin", "ROLE_AUTHORIZED_PERSONNEL" }, username = "ch4mpy")
|
||||
void givenSecurityContextIsPopulatedWithUsernamePasswordAuthenticationToken_whenGreet_thenThrowsClassCastException() {
|
||||
assertThrows(ClassCastException.class, () -> messageService.greet().block());
|
||||
assertThrows(ClassCastException.class, () -> messageService.greet()
|
||||
.block());
|
||||
}
|
||||
|
||||
/*--------------------------------------------------------------------*/
|
||||
|
@ -61,19 +65,22 @@ class MessageServiceUnitTest {
|
|||
@Test
|
||||
@WithAnonymousUser
|
||||
void givenUserIsNotAuthenticated_whenGetSecret_thenThrowsAccessDeniedException() {
|
||||
assertThrows(AccessDeniedException.class, () -> messageService.getSecret().block());
|
||||
assertThrows(AccessDeniedException.class, () -> messageService.getSecret()
|
||||
.block());
|
||||
}
|
||||
|
||||
@Test
|
||||
@WithMockJwtAuth(authorities = { "admin", "ROLE_AUTHORIZED_PERSONNEL" }, claims = @OpenIdClaims(preferredUsername = "ch4mpy"))
|
||||
void givenUserIsGrantedWithRoleAuthorizedPersonnel_whenGetSecret_thenReturnSecret() {
|
||||
assertEquals("Only authorized personnel can read that", messageService.getSecret().block());
|
||||
assertEquals("Only authorized personnel can read that", messageService.getSecret()
|
||||
.block());
|
||||
}
|
||||
|
||||
@Test
|
||||
@WithMockJwtAuth(authorities = { "admin" }, claims = @OpenIdClaims(preferredUsername = "ch4mpy"))
|
||||
void givenUserIsNotGrantedWithRoleAuthorizedPersonnel_whenGetSecret_thenThrowsAccessDeniedException() {
|
||||
assertThrows(AccessDeniedException.class, () -> messageService.getSecret().block());
|
||||
assertThrows(AccessDeniedException.class, () -> messageService.getSecret()
|
||||
.block());
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -25,22 +25,23 @@ class ReactiveResourceServerApplicationIntegrationTest {
|
|||
@Test
|
||||
@WithAnonymousUser
|
||||
void givenUserIsAnonymous_whenGetGreet_thenUnauthorized() throws Exception {
|
||||
// @formatter:off
|
||||
api.get().uri("/greet").exchange()
|
||||
.expectStatus().isUnauthorized();
|
||||
// @formatter:on
|
||||
api.get()
|
||||
.uri("/greet")
|
||||
.exchange()
|
||||
.expectStatus()
|
||||
.isUnauthorized();
|
||||
}
|
||||
|
||||
@Test
|
||||
@WithMockJwtAuth(
|
||||
authorities = {"admin", "ROLE_AUTHORIZED_PERSONNEL"},
|
||||
claims = @OpenIdClaims(preferredUsername = "ch4mpy"))
|
||||
@WithMockJwtAuth(authorities = { "admin", "ROLE_AUTHORIZED_PERSONNEL" }, claims = @OpenIdClaims(preferredUsername = "ch4mpy"))
|
||||
void givenUserIsAuthenticated_whenGetGreet_thenOk() throws Exception {
|
||||
// @formatter:off
|
||||
api.get().uri("/greet").exchange()
|
||||
.expectStatus().isOk()
|
||||
.expectBody(String.class).isEqualTo("Hello ch4mpy! You are granted with [admin, ROLE_AUTHORIZED_PERSONNEL].");
|
||||
// @formatter:on
|
||||
api.get()
|
||||
.uri("/greet")
|
||||
.exchange()
|
||||
.expectStatus()
|
||||
.isOk()
|
||||
.expectBody(String.class)
|
||||
.isEqualTo("Hello ch4mpy! You are granted with [admin, ROLE_AUTHORIZED_PERSONNEL].");
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------------------------------------------------*/
|
||||
|
@ -51,31 +52,35 @@ class ReactiveResourceServerApplicationIntegrationTest {
|
|||
@Test
|
||||
@WithAnonymousUser
|
||||
void givenUserIsAnonymous_whenGetSecuredRoute_thenUnauthorized() throws Exception {
|
||||
// @formatter:off
|
||||
api.get().uri("/secured-route").exchange()
|
||||
.expectStatus().isUnauthorized();
|
||||
// @formatter:on
|
||||
api.get()
|
||||
.uri("/secured-route")
|
||||
.exchange()
|
||||
.expectStatus()
|
||||
.isUnauthorized();
|
||||
}
|
||||
|
||||
@Test
|
||||
@WithMockJwtAuth("ROLE_AUTHORIZED_PERSONNEL")
|
||||
void givenUserIsGrantedWithRoleAuthorizedPersonnel_whenGetSecuredRoute_thenOk() throws Exception {
|
||||
// @formatter:off
|
||||
api.get().uri("/secured-route").exchange()
|
||||
.expectStatus().isOk()
|
||||
.expectBody(String.class).isEqualTo("Only authorized personnel can read that");
|
||||
// @formatter:on
|
||||
api.get()
|
||||
.uri("/secured-route")
|
||||
.exchange()
|
||||
.expectStatus()
|
||||
.isOk()
|
||||
.expectBody(String.class)
|
||||
.isEqualTo("Only authorized personnel can read that");
|
||||
}
|
||||
|
||||
@Test
|
||||
@WithMockJwtAuth("admin")
|
||||
void givenUserIsNotGrantedWithRoleAuthorizedPersonnel_whenGetSecuredRoute_thenForbidden() throws Exception {
|
||||
// @formatter:off
|
||||
api.get().uri("/secured-route").exchange()
|
||||
.expectStatus().isForbidden();
|
||||
// @formatter:on
|
||||
api.get()
|
||||
.uri("/secured-route")
|
||||
.exchange()
|
||||
.expectStatus()
|
||||
.isForbidden();
|
||||
}
|
||||
|
||||
|
||||
/*---------------------------------------------------------------------------------------------------------*/
|
||||
/* /secured-method */
|
||||
/* This end-point is secured with "@PreAuthorize("hasRole('AUTHORIZED_PERSONNEL')")" on @Controller method */
|
||||
|
@ -84,28 +89,32 @@ class ReactiveResourceServerApplicationIntegrationTest {
|
|||
@Test
|
||||
@WithAnonymousUser
|
||||
void givenUserIsAnonymous_whenGetSecuredMethod_thenUnauthorized() throws Exception {
|
||||
// @formatter:off
|
||||
api.get().uri("/secured-method").exchange()
|
||||
.expectStatus().isUnauthorized();
|
||||
// @formatter:on
|
||||
api.get()
|
||||
.uri("/secured-method")
|
||||
.exchange()
|
||||
.expectStatus()
|
||||
.isUnauthorized();
|
||||
}
|
||||
|
||||
@Test
|
||||
@WithMockJwtAuth("ROLE_AUTHORIZED_PERSONNEL")
|
||||
void givenUserIsGrantedWithRoleAuthorizedPersonnel_whenGetSecuredMethod_thenOk() throws Exception {
|
||||
// @formatter:off
|
||||
api.get().uri("/secured-method").exchange()
|
||||
.expectStatus().isOk()
|
||||
.expectBody(String.class).isEqualTo("Only authorized personnel can read that");
|
||||
// @formatter:on
|
||||
api.get()
|
||||
.uri("/secured-method")
|
||||
.exchange()
|
||||
.expectStatus()
|
||||
.isOk()
|
||||
.expectBody(String.class)
|
||||
.isEqualTo("Only authorized personnel can read that");
|
||||
}
|
||||
|
||||
@Test
|
||||
@WithMockJwtAuth("admin")
|
||||
void givenUserIsNotGrantedWithRoleAuthorizedPersonnel_whenGetSecuredMethod_thenForbidden() throws Exception {
|
||||
// @formatter:off
|
||||
api.get().uri("/secured-method").exchange()
|
||||
.expectStatus().isForbidden();
|
||||
// @formatter:on
|
||||
api.get()
|
||||
.uri("/secured-method")
|
||||
.exchange()
|
||||
.expectStatus()
|
||||
.isForbidden();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -35,22 +35,26 @@ class SpringAddonsGreetingControllerUnitTest {
|
|||
@Test
|
||||
@WithAnonymousUser
|
||||
void givenUserIsAnonymous_whenGetGreet_thenUnauthorized() throws Exception {
|
||||
api.get().uri("/greet").exchange().expectStatus().isUnauthorized();
|
||||
api.get()
|
||||
.uri("/greet")
|
||||
.exchange()
|
||||
.expectStatus()
|
||||
.isUnauthorized();
|
||||
}
|
||||
|
||||
@Test
|
||||
@WithMockJwtAuth(
|
||||
authorities = {"admin", "ROLE_AUTHORIZED_PERSONNEL"},
|
||||
claims = @OpenIdClaims(preferredUsername = "ch4mpy"))
|
||||
@WithMockJwtAuth(authorities = { "admin", "ROLE_AUTHORIZED_PERSONNEL" }, claims = @OpenIdClaims(preferredUsername = "ch4mpy"))
|
||||
void givenUserIsAuthenticated_whenGetGreet_thenOk() throws Exception {
|
||||
final var greeting = "Whatever the service returns";
|
||||
when(messageService.greet()).thenReturn(Mono.just(greeting));
|
||||
|
||||
// @formatter:off
|
||||
api.get().uri("/greet").exchange()
|
||||
.expectStatus().isOk()
|
||||
.expectBody(String.class).isEqualTo(greeting);
|
||||
// @formatter:on
|
||||
api.get()
|
||||
.uri("/greet")
|
||||
.exchange()
|
||||
.expectStatus()
|
||||
.isOk()
|
||||
.expectBody(String.class)
|
||||
.isEqualTo(greeting);
|
||||
|
||||
verify(messageService, times(1)).greet();
|
||||
}
|
||||
|
@ -63,7 +67,11 @@ class SpringAddonsGreetingControllerUnitTest {
|
|||
@Test
|
||||
@WithAnonymousUser
|
||||
void givenUserIsAnonymous_whenGetSecuredRoute_thenUnauthorized() throws Exception {
|
||||
api.get().uri("/secured-route").exchange().expectStatus().isUnauthorized();
|
||||
api.get()
|
||||
.uri("/secured-route")
|
||||
.exchange()
|
||||
.expectStatus()
|
||||
.isUnauthorized();
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -72,22 +80,25 @@ class SpringAddonsGreetingControllerUnitTest {
|
|||
final var secret = "Secret!";
|
||||
when(messageService.getSecret()).thenReturn(Mono.just(secret));
|
||||
|
||||
// @formatter:off
|
||||
api.get().uri("/secured-route").exchange()
|
||||
.expectStatus().isOk()
|
||||
.expectBody(String.class).isEqualTo(secret);
|
||||
// @formatter:on
|
||||
api.get()
|
||||
.uri("/secured-route")
|
||||
.exchange()
|
||||
.expectStatus()
|
||||
.isOk()
|
||||
.expectBody(String.class)
|
||||
.isEqualTo(secret);
|
||||
}
|
||||
|
||||
@Test
|
||||
@WithMockJwtAuth("admin")
|
||||
void givenUserIsNotGrantedWithRoleAuthorizedPersonnel_whenGetSecuredRoute_thenForbidden() throws Exception {
|
||||
// @formatter:off
|
||||
api.get().uri("/secured-route").exchange()
|
||||
.expectStatus().isForbidden();
|
||||
// @formatter:on
|
||||
api.get()
|
||||
.uri("/secured-route")
|
||||
.exchange()
|
||||
.expectStatus()
|
||||
.isForbidden();
|
||||
}
|
||||
|
||||
|
||||
/*---------------------------------------------------------------------------------------------------------*/
|
||||
/* /secured-method */
|
||||
/* This end-point is secured with "@PreAuthorize("hasRole('AUTHORIZED_PERSONNEL')")" on @Controller method */
|
||||
|
@ -96,7 +107,11 @@ class SpringAddonsGreetingControllerUnitTest {
|
|||
@Test
|
||||
@WithAnonymousUser
|
||||
void givenUserIsAnonymous_whenGetSecuredMethod_thenUnauthorized() throws Exception {
|
||||
api.get().uri("/secured-method").exchange().expectStatus().isUnauthorized();
|
||||
api.get()
|
||||
.uri("/secured-method")
|
||||
.exchange()
|
||||
.expectStatus()
|
||||
.isUnauthorized();
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -105,21 +120,23 @@ class SpringAddonsGreetingControllerUnitTest {
|
|||
final var secret = "Secret!";
|
||||
when(messageService.getSecret()).thenReturn(Mono.just(secret));
|
||||
|
||||
// @formatter:off
|
||||
api.get().uri("/secured-method").exchange()
|
||||
.expectStatus().isOk()
|
||||
.expectBody(String.class).isEqualTo(secret);
|
||||
// @formatter:on
|
||||
api.get()
|
||||
.uri("/secured-method")
|
||||
.exchange()
|
||||
.expectStatus()
|
||||
.isOk()
|
||||
.expectBody(String.class)
|
||||
.isEqualTo(secret);
|
||||
}
|
||||
|
||||
@Test
|
||||
@WithMockJwtAuth("admin")
|
||||
void givenUserIsNotGrantedWithRoleAuthorizedPersonnel_whenGetSecuredMethod_thenForbidden() throws Exception {
|
||||
// @formatter:off
|
||||
api.get().uri("/secured-method").exchange()
|
||||
.expectStatus().isForbidden();
|
||||
// @formatter:on
|
||||
api.get()
|
||||
.uri("/secured-method")
|
||||
.exchange()
|
||||
.expectStatus()
|
||||
.isForbidden();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -25,10 +25,7 @@ import reactor.core.publisher.Mono;
|
|||
|
||||
@WebFluxTest(controllers = GreetingController.class, properties = { "server.ssl.enabled=false" })
|
||||
class SpringSecurityTestGreetingControllerUnitTest {
|
||||
private static final AnonymousAuthenticationToken ANONYMOUS_AUTHENTICATION = new AnonymousAuthenticationToken(
|
||||
"anonymous",
|
||||
"anonymousUser",
|
||||
AuthorityUtils.createAuthorityList("ROLE_ANONYMOUS"));
|
||||
private static final AnonymousAuthenticationToken ANONYMOUS_AUTHENTICATION = new AnonymousAuthenticationToken("anonymous", "anonymousUser", AuthorityUtils.createAuthorityList("ROLE_ANONYMOUS"));
|
||||
|
||||
@MockBean
|
||||
MessageService messageService;
|
||||
|
@ -43,11 +40,12 @@ class SpringSecurityTestGreetingControllerUnitTest {
|
|||
|
||||
@Test
|
||||
void givenUserIsAnonymous_whenGetGreet_thenUnauthorized() throws Exception {
|
||||
// @formatter:off
|
||||
api.mutateWith(mockAuthentication(ANONYMOUS_AUTHENTICATION))
|
||||
.get().uri("/greet").exchange()
|
||||
.expectStatus().isUnauthorized();
|
||||
// @formatter:on
|
||||
.get()
|
||||
.uri("/greet")
|
||||
.exchange()
|
||||
.expectStatus()
|
||||
.isUnauthorized();
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -55,14 +53,15 @@ class SpringSecurityTestGreetingControllerUnitTest {
|
|||
final var greeting = "Whatever the service returns";
|
||||
when(messageService.greet()).thenReturn(Mono.just(greeting));
|
||||
|
||||
// @formatter:off
|
||||
api.mutateWith(mockJwt()
|
||||
.authorities(List.of(new SimpleGrantedAuthority("admin"), new SimpleGrantedAuthority("ROLE_AUTHORIZED_PERSONNEL")))
|
||||
.jwt(jwt -> jwt.claim(StandardClaimNames.PREFERRED_USERNAME, "ch4mpy")))
|
||||
.get().uri("/greet").exchange()
|
||||
.expectStatus().isOk()
|
||||
.expectBody(String.class).isEqualTo(greeting);
|
||||
// @formatter:on
|
||||
api.mutateWith(mockJwt().authorities(List.of(new SimpleGrantedAuthority("admin"), new SimpleGrantedAuthority("ROLE_AUTHORIZED_PERSONNEL")))
|
||||
.jwt(jwt -> jwt.claim(StandardClaimNames.PREFERRED_USERNAME, "ch4mpy")))
|
||||
.get()
|
||||
.uri("/greet")
|
||||
.exchange()
|
||||
.expectStatus()
|
||||
.isOk()
|
||||
.expectBody(String.class)
|
||||
.isEqualTo(greeting);
|
||||
|
||||
verify(messageService, times(1)).greet();
|
||||
}
|
||||
|
@ -74,35 +73,39 @@ class SpringSecurityTestGreetingControllerUnitTest {
|
|||
|
||||
@Test
|
||||
void givenUserIsAnonymous_whenGetSecuredRoute_thenUnauthorized() throws Exception {
|
||||
// @formatter:off
|
||||
api.mutateWith(mockAuthentication(ANONYMOUS_AUTHENTICATION))
|
||||
.get().uri("/secured-route").exchange()
|
||||
.expectStatus().isUnauthorized();
|
||||
// @formatter:on
|
||||
.get()
|
||||
.uri("/secured-route")
|
||||
.exchange()
|
||||
.expectStatus()
|
||||
.isUnauthorized();
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
void givenUserIsGrantedWithRoleAuthorizedPersonnel_whenGetSecuredRoute_thenOk() throws Exception {
|
||||
final var secret = "Secret!";
|
||||
when(messageService.getSecret()).thenReturn(Mono.just(secret));
|
||||
|
||||
// @formatter:off
|
||||
|
||||
api.mutateWith(mockJwt().authorities(new SimpleGrantedAuthority("ROLE_AUTHORIZED_PERSONNEL")))
|
||||
.get().uri("/secured-route").exchange()
|
||||
.expectStatus().isOk()
|
||||
.expectBody(String.class).isEqualTo(secret);
|
||||
// @formatter:on
|
||||
.get()
|
||||
.uri("/secured-route")
|
||||
.exchange()
|
||||
.expectStatus()
|
||||
.isOk()
|
||||
.expectBody(String.class)
|
||||
.isEqualTo(secret);
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
void givenUserIsNotGrantedWithRoleAuthorizedPersonnel_whenGetSecuredRoute_thenForbidden() throws Exception {
|
||||
// @formatter:off
|
||||
api.mutateWith(mockJwt().authorities(new SimpleGrantedAuthority("admin")))
|
||||
.get().uri("/secured-route").exchange()
|
||||
.expectStatus().isForbidden();
|
||||
// @formatter:on
|
||||
.get()
|
||||
.uri("/secured-route")
|
||||
.exchange()
|
||||
.expectStatus()
|
||||
.isForbidden();
|
||||
}
|
||||
|
||||
|
||||
/*---------------------------------------------------------------------------------------------------------*/
|
||||
/* /secured-method */
|
||||
/* This end-point is secured with "@PreAuthorize("hasRole('AUTHORIZED_PERSONNEL')")" on @Controller method */
|
||||
|
@ -110,11 +113,12 @@ class SpringSecurityTestGreetingControllerUnitTest {
|
|||
|
||||
@Test
|
||||
void givenUserIsAnonymous_whenGetSecuredMethod_thenUnauthorized() throws Exception {
|
||||
// @formatter:off
|
||||
api.mutateWith(mockAuthentication(ANONYMOUS_AUTHENTICATION))
|
||||
.get().uri("/secured-method").exchange()
|
||||
.expectStatus().isUnauthorized();
|
||||
// @formatter:on
|
||||
.get()
|
||||
.uri("/secured-method")
|
||||
.exchange()
|
||||
.expectStatus()
|
||||
.isUnauthorized();
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -122,22 +126,24 @@ class SpringSecurityTestGreetingControllerUnitTest {
|
|||
final var secret = "Secret!";
|
||||
when(messageService.getSecret()).thenReturn(Mono.just(secret));
|
||||
|
||||
// @formatter:off
|
||||
api.mutateWith(mockJwt().authorities(new SimpleGrantedAuthority("ROLE_AUTHORIZED_PERSONNEL")))
|
||||
.get().uri("/secured-method").exchange()
|
||||
.expectStatus().isOk()
|
||||
.expectBody(String.class).isEqualTo(secret);
|
||||
// @formatter:on
|
||||
.get()
|
||||
.uri("/secured-method")
|
||||
.exchange()
|
||||
.expectStatus()
|
||||
.isOk()
|
||||
.expectBody(String.class)
|
||||
.isEqualTo(secret);
|
||||
}
|
||||
|
||||
@Test
|
||||
void givenUserIsNotGrantedWithRoleAuthorizedPersonnel_whenGetSecuredMethod_thenForbidden() throws Exception {
|
||||
// @formatter:off
|
||||
api.mutateWith(mockJwt().authorities(new SimpleGrantedAuthority("admin")))
|
||||
.get().uri("/secured-method").exchange()
|
||||
.expectStatus().isForbidden();
|
||||
// @formatter:on
|
||||
.get()
|
||||
.uri("/secured-method")
|
||||
.exchange()
|
||||
.expectStatus()
|
||||
.isForbidden();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -1,58 +1,58 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<parent>
|
||||
<groupId>com.baeldung</groupId>
|
||||
<artifactId>spring-security-oauth2-testing</artifactId>
|
||||
<version>0.0.1-SNAPSHOT</version>
|
||||
</parent>
|
||||
<groupId>com.baeldung.spring-security-modules.testing</groupId>
|
||||
<artifactId>servlet-resource-server</artifactId>
|
||||
<name>servlet-resource-server</name>
|
||||
<description>Demo project for Spring Boot servlet resource-server</description>
|
||||
<properties>
|
||||
<java.version>17</java.version>
|
||||
</properties>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-oauth2-resource-server</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-web</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.projectlombok</groupId>
|
||||
<artifactId>lombok</artifactId>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-test</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.c4-soft.springaddons</groupId>
|
||||
<artifactId>spring-addons-oauth2-test</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-maven-plugin</artifactId>
|
||||
<configuration>
|
||||
<excludes>
|
||||
<exclude>
|
||||
<groupId>org.projectlombok</groupId>
|
||||
<artifactId>lombok</artifactId>
|
||||
</exclude>
|
||||
</excludes>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<parent>
|
||||
<groupId>com.baeldung</groupId>
|
||||
<artifactId>spring-security-oauth2-testing</artifactId>
|
||||
<version>0.0.1-SNAPSHOT</version>
|
||||
</parent>
|
||||
<groupId>com.baeldung.spring-security-modules.testing</groupId>
|
||||
<artifactId>servlet-resource-server</artifactId>
|
||||
<name>servlet-resource-server</name>
|
||||
<description>Demo project for Spring Boot servlet resource-server</description>
|
||||
<properties>
|
||||
<java.version>17</java.version>
|
||||
</properties>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-oauth2-resource-server</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-web</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.projectlombok</groupId>
|
||||
<artifactId>lombok</artifactId>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-test</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.c4-soft.springaddons</groupId>
|
||||
<artifactId>spring-addons-oauth2-test</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-maven-plugin</artifactId>
|
||||
<configuration>
|
||||
<excludes>
|
||||
<exclude>
|
||||
<groupId>org.projectlombok</groupId>
|
||||
<artifactId>lombok</artifactId>
|
||||
</exclude>
|
||||
</excludes>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</project>
|
||||
|
|
|
@ -44,18 +44,25 @@ public class ServletResourceServerApplication {
|
|||
static class SecurityConf {
|
||||
@Bean
|
||||
SecurityFilterChain filterChain(HttpSecurity http, Converter<Jwt, Collection<GrantedAuthority>> authoritiesConverter) throws Exception {
|
||||
// @formatter:off
|
||||
http.oauth2ResourceServer().jwt().jwtAuthenticationConverter(jwt -> new JwtAuthenticationToken(jwt, authoritiesConverter.convert(jwt)));
|
||||
http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS).and().csrf().disable();
|
||||
http.exceptionHandling().authenticationEntryPoint((request, response, authException) -> {
|
||||
response.addHeader(HttpHeaders.WWW_AUTHENTICATE, "Basic realm=\"Restricted Content\"");
|
||||
response.sendError(HttpStatus.UNAUTHORIZED.value(), HttpStatus.UNAUTHORIZED.getReasonPhrase());
|
||||
});
|
||||
|
||||
http.oauth2ResourceServer()
|
||||
.jwt()
|
||||
.jwtAuthenticationConverter(jwt -> new JwtAuthenticationToken(jwt, authoritiesConverter.convert(jwt)));
|
||||
http.sessionManagement()
|
||||
.sessionCreationPolicy(SessionCreationPolicy.STATELESS)
|
||||
.and()
|
||||
.csrf()
|
||||
.disable();
|
||||
http.exceptionHandling()
|
||||
.authenticationEntryPoint((request, response, authException) -> {
|
||||
response.addHeader(HttpHeaders.WWW_AUTHENTICATE, "Basic realm=\"Restricted Content\"");
|
||||
response.sendError(HttpStatus.UNAUTHORIZED.value(), HttpStatus.UNAUTHORIZED.getReasonPhrase());
|
||||
});
|
||||
|
||||
http.authorizeHttpRequests()
|
||||
.requestMatchers("/secured-route").hasRole("AUTHORIZED_PERSONNEL")
|
||||
.anyRequest().authenticated();
|
||||
// @formatter:on
|
||||
.requestMatchers("/secured-route")
|
||||
.hasRole("AUTHORIZED_PERSONNEL")
|
||||
.anyRequest()
|
||||
.authenticated();
|
||||
|
||||
return http.build();
|
||||
}
|
||||
|
@ -66,10 +73,14 @@ public class ServletResourceServerApplication {
|
|||
@Bean
|
||||
AuthoritiesConverter realmRoles2AuthoritiesConverter() {
|
||||
return (Jwt jwt) -> {
|
||||
final var realmRoles = Optional.of(jwt.getClaimAsMap("realm_access")).orElse(Map.of());
|
||||
final var realmRoles = Optional.of(jwt.getClaimAsMap("realm_access"))
|
||||
.orElse(Map.of());
|
||||
@SuppressWarnings("unchecked")
|
||||
final var roles = (List<String>) realmRoles.getOrDefault("roles", List.of());
|
||||
return roles.stream().map(SimpleGrantedAuthority::new).map(GrantedAuthority.class::cast).toList();
|
||||
return roles.stream()
|
||||
.map(SimpleGrantedAuthority::new)
|
||||
.map(GrantedAuthority.class::cast)
|
||||
.toList();
|
||||
};
|
||||
}
|
||||
}
|
||||
|
@ -78,11 +89,10 @@ public class ServletResourceServerApplication {
|
|||
public static class MessageService {
|
||||
|
||||
public String greet() {
|
||||
final var who = (JwtAuthenticationToken) SecurityContextHolder.getContext().getAuthentication();
|
||||
final var who = (JwtAuthenticationToken) SecurityContextHolder.getContext()
|
||||
.getAuthentication();
|
||||
final var claims = who.getTokenAttributes();
|
||||
return "Hello %s! You are granted with %s.".formatted(
|
||||
claims.getOrDefault(StandardClaimNames.PREFERRED_USERNAME, claims.get(StandardClaimNames.SUB)),
|
||||
who.getAuthorities());
|
||||
return "Hello %s! You are granted with %s.".formatted(claims.getOrDefault(StandardClaimNames.PREFERRED_USERNAME, claims.get(StandardClaimNames.SUB)), who.getAuthorities());
|
||||
}
|
||||
|
||||
@PreAuthorize("hasRole('AUTHORIZED_PERSONNEL')")
|
||||
|
|
|
@ -29,22 +29,16 @@ class ServletResourceServerApplicationIntegrationTest {
|
|||
@Test
|
||||
@WithAnonymousUser
|
||||
void givenUserIsNotAuthenticated_whenGetGreet_thenUnauthorized() throws Exception {
|
||||
// @formatter:off
|
||||
api.perform(get("/greet"))
|
||||
.andExpect(status().isUnauthorized());
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
@WithMockJwtAuth(
|
||||
authorities = {"admin", "ROLE_AUTHORIZED_PERSONNEL"},
|
||||
claims = @OpenIdClaims(preferredUsername = "ch4mpy"))
|
||||
@WithMockJwtAuth(authorities = { "admin", "ROLE_AUTHORIZED_PERSONNEL" }, claims = @OpenIdClaims(preferredUsername = "ch4mpy"))
|
||||
void givenUserIsAuthenticated_whenGetGreet_thenOk() throws Exception {
|
||||
// @formatter:off
|
||||
api.perform(get("/greet"))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(content().string("Hello ch4mpy! You are granted with [admin, ROLE_AUTHORIZED_PERSONNEL]."));
|
||||
// @formatter:on
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(content().string("Hello ch4mpy! You are granted with [admin, ROLE_AUTHORIZED_PERSONNEL]."));
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------------------------------------------------*/
|
||||
|
@ -55,31 +49,25 @@ class ServletResourceServerApplicationIntegrationTest {
|
|||
@Test
|
||||
@WithAnonymousUser
|
||||
void givenUserIsNotAuthenticated_whenGetSecuredRoute_thenUnauthorized() throws Exception {
|
||||
// @formatter:off
|
||||
api.perform(get("/secured-route"))
|
||||
.andExpect(status().isUnauthorized());
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
@WithMockJwtAuth("ROLE_AUTHORIZED_PERSONNEL")
|
||||
void givenUserIsGrantedWithRoleAuthorizedPersonnel_whenGetSecuredRoute_thenOk() throws Exception {
|
||||
// @formatter:off
|
||||
api.perform(get("/secured-route"))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(content().string("Only authorized personnel can read that"));
|
||||
// @formatter:on
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(content().string("Only authorized personnel can read that"));
|
||||
}
|
||||
|
||||
@Test
|
||||
@WithMockJwtAuth("admin")
|
||||
void givenUserIsNotGrantedWithRoleAuthorizedPersonnel_whenGetSecuredRoute_thenForbidden() throws Exception {
|
||||
// @formatter:off
|
||||
api.perform(get("/secured-route"))
|
||||
.andExpect(status().isForbidden());
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
|
||||
/*---------------------------------------------------------------------------------------------------------*/
|
||||
/* /secured-method */
|
||||
/* This end-point is secured with "@PreAuthorize("hasRole('AUTHORIZED_PERSONNEL')")" on @Controller method */
|
||||
|
@ -88,29 +76,23 @@ class ServletResourceServerApplicationIntegrationTest {
|
|||
@Test
|
||||
@WithAnonymousUser
|
||||
void givenUserIsNotAuthenticated_whenGetSecuredMethod_thenUnauthorized() throws Exception {
|
||||
// @formatter:off
|
||||
api.perform(get("/secured-method"))
|
||||
.andExpect(status().isUnauthorized());
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
@WithMockJwtAuth("ROLE_AUTHORIZED_PERSONNEL")
|
||||
void givenUserIsGrantedWithRoleAuthorizedPersonnel_whenGetSecuredMethod_thenOk() throws Exception {
|
||||
// @formatter:off
|
||||
api.perform(get("/secured-method"))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(content().string("Only authorized personnel can read that"));
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
@WithMockJwtAuth("admin")
|
||||
void givenUserIsNotGrantedWithRoleAuthorizedPersonnel_whenGetSecuredMethod_thenForbidden() throws Exception {
|
||||
// @formatter:off
|
||||
api.perform(get("/secured-method"))
|
||||
.andExpect(status().isForbidden());
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -36,25 +36,19 @@ class SpringAddonsGreetingControllerUnitTest {
|
|||
@Test
|
||||
@WithAnonymousUser
|
||||
void givenUserIsNotAuthenticated_whenGetGreet_thenUnauthorized() throws Exception {
|
||||
// @formatter:off
|
||||
api.perform(get("/greet"))
|
||||
.andExpect(status().isUnauthorized());
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
@WithMockJwtAuth(
|
||||
authorities = {"admin", "ROLE_AUTHORIZED_PERSONNEL"},
|
||||
claims = @OpenIdClaims(preferredUsername = "ch4mpy"))
|
||||
@WithMockJwtAuth(authorities = { "admin", "ROLE_AUTHORIZED_PERSONNEL" }, claims = @OpenIdClaims(preferredUsername = "ch4mpy"))
|
||||
void givenUserIsAuthenticated_whenGetGreet_thenOk() throws Exception {
|
||||
final var greeting = "Whatever the service returns";
|
||||
when(messageService.greet()).thenReturn(greeting);
|
||||
|
||||
// @formatter:off
|
||||
api.perform(get("/greet"))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(content().string(greeting));
|
||||
// @formatter:on
|
||||
|
||||
verify(messageService, times(1)).greet();
|
||||
}
|
||||
|
@ -67,10 +61,8 @@ class SpringAddonsGreetingControllerUnitTest {
|
|||
@Test
|
||||
@WithAnonymousUser
|
||||
void givenUserIsNotAuthenticated_whenGetSecuredRoute_thenUnauthorized() throws Exception {
|
||||
// @formatter:off
|
||||
api.perform(get("/secured-route"))
|
||||
.andExpect(status().isUnauthorized());
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -79,22 +71,18 @@ class SpringAddonsGreetingControllerUnitTest {
|
|||
final var secret = "Secret!";
|
||||
when(messageService.getSecret()).thenReturn(secret);
|
||||
|
||||
// @formatter:off
|
||||
api.perform(get("/secured-route"))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(content().string(secret));
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
@WithMockJwtAuth({ "admin" })
|
||||
void givenUserIsNotGrantedWithRoleAuthorizedPersonnel_whenGetSecuredRoute_thenForbidden() throws Exception {
|
||||
// @formatter:off
|
||||
api.perform(get("/secured-route"))
|
||||
.andExpect(status().isForbidden());
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
|
||||
/*---------------------------------------------------------------------------------------------------------*/
|
||||
/* /secured-method */
|
||||
/* This end-point is secured with "@PreAuthorize("hasRole('AUTHORIZED_PERSONNEL')")" on @Controller method */
|
||||
|
@ -103,10 +91,8 @@ class SpringAddonsGreetingControllerUnitTest {
|
|||
@Test
|
||||
@WithAnonymousUser
|
||||
void givenUserIsNotAuthenticated_whenGetSecuredMethod_thenUnauthorized() throws Exception {
|
||||
// @formatter:off
|
||||
api.perform(get("/secured-method"))
|
||||
.andExpect(status().isUnauthorized());
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -115,20 +101,16 @@ class SpringAddonsGreetingControllerUnitTest {
|
|||
final var secret = "Secret!";
|
||||
when(messageService.getSecret()).thenReturn(secret);
|
||||
|
||||
// @formatter:off
|
||||
api.perform(get("/secured-method"))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(content().string(secret));
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
@WithMockJwtAuth(authorities = { "admin" })
|
||||
void givenUserIsNotGrantedWithRoleAuthorizedPersonnel_whenGetSecuredMethod_thenForbidden() throws Exception {
|
||||
// @formatter:off
|
||||
api.perform(get("/secured-method"))
|
||||
.andExpect(status().isForbidden());
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -38,10 +38,8 @@ class SpringSecurityTestGreetingControllerUnitTest {
|
|||
|
||||
@Test
|
||||
void givenUserIsNotAuthenticated_whenGetGreet_thenUnauthorized() throws Exception {
|
||||
// @formatter:off
|
||||
api.perform(get("/greet").with(anonymous()))
|
||||
.andExpect(status().isUnauthorized());
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -49,13 +47,10 @@ class SpringSecurityTestGreetingControllerUnitTest {
|
|||
final var greeting = "Whatever the service returns";
|
||||
when(messageService.greet()).thenReturn(greeting);
|
||||
|
||||
// @formatter:off
|
||||
api.perform(get("/greet").with(jwt()
|
||||
.authorities(List.of(new SimpleGrantedAuthority("admin"), new SimpleGrantedAuthority("ROLE_AUTHORIZED_PERSONNEL")))
|
||||
.jwt(jwt -> jwt.claim(StandardClaimNames.PREFERRED_USERNAME, "ch4mpy"))))
|
||||
api.perform(get("/greet").with(jwt().authorities(List.of(new SimpleGrantedAuthority("admin"), new SimpleGrantedAuthority("ROLE_AUTHORIZED_PERSONNEL")))
|
||||
.jwt(jwt -> jwt.claim(StandardClaimNames.PREFERRED_USERNAME, "ch4mpy"))))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(content().string(greeting));
|
||||
// @formatter:on
|
||||
|
||||
verify(messageService, times(1)).greet();
|
||||
}
|
||||
|
@ -67,10 +62,8 @@ class SpringSecurityTestGreetingControllerUnitTest {
|
|||
|
||||
@Test
|
||||
void givenUserIsNotAuthenticated_whenGetSecuredRoute_thenUnauthorized() throws Exception {
|
||||
// @formatter:off
|
||||
api.perform(get("/secured-route").with(anonymous()))
|
||||
.andExpect(status().isUnauthorized());
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -78,21 +71,17 @@ class SpringSecurityTestGreetingControllerUnitTest {
|
|||
final var secret = "Secret!";
|
||||
when(messageService.getSecret()).thenReturn(secret);
|
||||
|
||||
// @formatter:off
|
||||
api.perform(get("/secured-route").with(jwt().authorities(new SimpleGrantedAuthority("ROLE_AUTHORIZED_PERSONNEL"))))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(content().string(secret));
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
void givenUserIsNotGrantedWithRoleAuthorizedPersonnel_whenGetSecuredRoute_thenForbidden() throws Exception {
|
||||
// @formatter:off
|
||||
api.perform(get("/secured-route").with(jwt().authorities(new SimpleGrantedAuthority("admin"))))
|
||||
.andExpect(status().isForbidden());
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
|
||||
/*---------------------------------------------------------------------------------------------------------*/
|
||||
/* /secured-method */
|
||||
/* This end-point is secured with "@PreAuthorize("hasRole('AUTHORIZED_PERSONNEL')")" on @Controller method */
|
||||
|
@ -100,10 +89,8 @@ class SpringSecurityTestGreetingControllerUnitTest {
|
|||
|
||||
@Test
|
||||
void givenUserIsNotAuthenticated_whenGetSecuredMethod_thenUnauthorized() throws Exception {
|
||||
// @formatter:off
|
||||
api.perform(get("/secured-method").with(anonymous()))
|
||||
.andExpect(status().isUnauthorized());
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -111,19 +98,15 @@ class SpringSecurityTestGreetingControllerUnitTest {
|
|||
final var secret = "Secret!";
|
||||
when(messageService.getSecret()).thenReturn(secret);
|
||||
|
||||
// @formatter:off
|
||||
api.perform(get("/secured-method").with(jwt().authorities(new SimpleGrantedAuthority("ROLE_AUTHORIZED_PERSONNEL"))))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(content().string(secret));
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
void givenUserIsNotGrantedWithRoleAuthorizedPersonnel_whenGetSecuredMethod_thenForbidden() throws Exception {
|
||||
// @formatter:off
|
||||
api.perform(get("/secured-method").with(jwt().authorities(new SimpleGrantedAuthority("admin"))))
|
||||
.andExpect(status().isForbidden());
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue