ch4mpy
2023-02-16 08:47:54 -10:00
parent 416dc0492d
commit b4d18fd227
17 changed files with 1300 additions and 0 deletions
@@ -0,0 +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>
</project>
@@ -0,0 +1,124 @@
package com.baeldung;
import java.nio.charset.Charset;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.convert.converter.Converter;
import org.springframework.core.io.buffer.DataBufferUtils;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.security.authentication.AnonymousAuthenticationToken;
import org.springframework.security.authentication.AuthenticationCredentialsNotFoundException;
import org.springframework.security.config.annotation.method.configuration.EnableReactiveMethodSecurity;
import org.springframework.security.config.annotation.web.reactive.EnableWebFluxSecurity;
import org.springframework.security.config.web.server.ServerHttpSecurity;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.context.ReactiveSecurityContextHolder;
import org.springframework.security.oauth2.core.oidc.StandardClaimNames;
import org.springframework.security.oauth2.jwt.Jwt;
import org.springframework.security.oauth2.server.resource.authentication.JwtAuthenticationToken;
import org.springframework.security.web.server.SecurityWebFilterChain;
import org.springframework.security.web.server.context.NoOpServerSecurityContextRepository;
import org.springframework.stereotype.Service;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import lombok.RequiredArgsConstructor;
import reactor.core.publisher.Mono;
@SpringBootApplication
public class ReactiveResourceServerApplication {
public static void main(String[] args) {
SpringApplication.run(ReactiveResourceServerApplication.class, args);
}
@Configuration
@EnableWebFluxSecurity
@EnableReactiveMethodSecurity
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.authorizeExchange().pathMatchers("/secured-route").hasRole("AUTHORIZED_PERSONNEL").anyExchange().authenticated();
return http.build();
}
static interface AuthoritiesConverter extends Converter<Jwt, Mono<Collection<GrantedAuthority>>> {
}
@Bean
AuthoritiesConverter realmRoles2AuthoritiesConverter() {
return (Jwt jwt) -> {
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());
};
}
}
@Service
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")));
}
@PreAuthorize("hasRole('AUTHORIZED_PERSONNEL')")
public Mono<String> getSecret() {
return Mono.just("Only authorized personnel can read that");
}
}
@RestController
@RequiredArgsConstructor
public class GreetingController {
private final MessageService messageService;
@GetMapping("/greet")
public Mono<ResponseEntity<String>> greet() {
return messageService.greet().map(ResponseEntity::ok);
}
@GetMapping("/secured-route")
public Mono<ResponseEntity<String>> securedRoute() {
return messageService.getSecret().map(ResponseEntity::ok);
}
@GetMapping("/secured-method")
@PreAuthorize("hasRole('AUTHORIZED_PERSONNEL')")
public Mono<ResponseEntity<String>> securedMethod() {
return messageService.getSecret().map(ResponseEntity::ok);
}
}
}
@@ -0,0 +1,6 @@
spring:
security:
oauth2:
resourceserver:
jwt:
issuer-uri: https://localhost:8443/realms/master
@@ -0,0 +1,79 @@
package com.baeldung;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertThrows;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Import;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.security.authentication.AuthenticationCredentialsNotFoundException;
import org.springframework.security.config.annotation.method.configuration.EnableReactiveMethodSecurity;
import org.springframework.security.test.context.support.WithAnonymousUser;
import org.springframework.security.test.context.support.WithMockUser;
import org.springframework.test.context.junit.jupiter.SpringExtension;
import com.baeldung.ReactiveResourceServerApplication.MessageService;
import com.c4_soft.springaddons.security.oauth2.test.annotations.OpenIdClaims;
import com.c4_soft.springaddons.security.oauth2.test.annotations.WithMockJwtAuth;
@Import({ MessageService.class })
@ExtendWith(SpringExtension.class)
@EnableReactiveMethodSecurity
class MessageServiceUnitTest {
@Autowired
MessageService messageService;
/*----------------------------------------------------------------------------*/
/* greet() */
/* Expects a JwtAuthenticationToken to be retrieved from the security-context */
/*----------------------------------------------------------------------------*/
@Test
void givenSecurityContextIsEmpty_whenGreet_thenThrowsAuthenticationCredentialsNotFoundException() {
assertThrows(AuthenticationCredentialsNotFoundException.class, () -> messageService.greet().block());
}
@Test
@WithAnonymousUser
void givenUserIsNotAuthenticated_whenGreet_thenThrowsClassCastException() {
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());
}
@Test
@WithMockUser(authorities = { "admin", "ROLE_AUTHORIZED_PERSONNEL" }, username = "ch4mpy")
void givenSecurityContextIsPopulatedWithUsernamePasswordAuthenticationToken_whenGreet_thenThrowsClassCastException() {
assertThrows(ClassCastException.class, () -> messageService.greet().block());
}
/*--------------------------------------------------------------------*/
/* getSecret() */
/* is secured with "@PreAuthorize("hasRole('AUTHORIZED_PERSONNEL')")" */
/*--------------------------------------------------------------------*/
@Test
@WithAnonymousUser
void givenUserIsNotAuthenticated_whenGetSecret_thenThrowsAccessDeniedException() {
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());
}
@Test
@WithMockJwtAuth(authorities = { "admin" }, claims = @OpenIdClaims(preferredUsername = "ch4mpy"))
void givenUserIsNotGrantedWithRoleAuthorizedPersonnel_whenGetSecret_thenThrowsAccessDeniedException() {
assertThrows(AccessDeniedException.class, () -> messageService.getSecret().block());
}
}
@@ -0,0 +1,109 @@
package com.baeldung;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.reactive.AutoConfigureWebTestClient;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.context.SpringBootTest.WebEnvironment;
import org.springframework.security.test.context.support.WithAnonymousUser;
import org.springframework.test.web.reactive.server.WebTestClient;
import com.c4_soft.springaddons.security.oauth2.test.annotations.OpenIdClaims;
import com.c4_soft.springaddons.security.oauth2.test.annotations.WithMockJwtAuth;
@SpringBootTest(webEnvironment = WebEnvironment.MOCK)
@AutoConfigureWebTestClient
class ReactiveResourceServerApplicationIntegrationTest {
@Autowired
WebTestClient api;
/*-----------------------------------------------------------------------------*/
/* /greet */
/* This end-point secured with ".anyRequest().authenticated()" in SecurityConf */
/*-----------------------------------------------------------------------------*/
@Test
@WithAnonymousUser
void givenUserIsNotAuthenticated_whenGetGreet_thenUnauthorized() throws Exception {
// @formatter:off
api.get().uri("/greet").exchange()
.expectStatus().isUnauthorized();
// @formatter:on
}
@Test
@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
}
/*---------------------------------------------------------------------------------------------------------------------*/
/* /secured-route */
/* This end-point is secured with ".requestMatchers("/secured-route").hasRole("AUTHORIZED_PERSONNEL")" in SecurityConf */
/*---------------------------------------------------------------------------------------------------------------------*/
@Test
@WithAnonymousUser
void givenUserIsNotAuthenticated_whenGetSecuredRoute_thenUnauthorized() throws Exception {
// @formatter:off
api.get().uri("/secured-route").exchange()
.expectStatus().isUnauthorized();
// @formatter:on
}
@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
}
@Test
@WithMockJwtAuth("admin")
void givenUserIsNotGrantedWithRoleAuthorizedPersonnel_whenGetSecuredRoute_thenForbidden() throws Exception {
// @formatter:off
api.get().uri("/secured-route").exchange()
.expectStatus().isForbidden();
// @formatter:on
}
/*---------------------------------------------------------------------------------------------------------*/
/* /secured-method */
/* This end-point is secured with "@PreAuthorize("hasRole('AUTHORIZED_PERSONNEL')")" on @Controller method */
/*---------------------------------------------------------------------------------------------------------*/
@Test
@WithAnonymousUser
void givenUserIsNotAuthenticated_whenGetSecuredMethod_thenUnauthorized() throws Exception {
// @formatter:off
api.get().uri("/secured-method").exchange()
.expectStatus().isUnauthorized();
// @formatter:on
}
@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
}
@Test
@WithMockJwtAuth("admin")
void givenUserIsNotGrantedWithRoleAuthorizedPersonnel_whenGetSecuredMethod_thenForbidden() throws Exception {
// @formatter:off
api.get().uri("/secured-method").exchange()
.expectStatus().isForbidden();
// @formatter:on
}
}
@@ -0,0 +1,123 @@
package com.baeldung;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.reactive.WebFluxTest;
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.security.test.context.support.WithAnonymousUser;
import org.springframework.test.web.reactive.server.WebTestClient;
import com.baeldung.ReactiveResourceServerApplication.GreetingController;
import com.baeldung.ReactiveResourceServerApplication.MessageService;
import com.c4_soft.springaddons.security.oauth2.test.annotations.OpenIdClaims;
import com.c4_soft.springaddons.security.oauth2.test.annotations.WithMockJwtAuth;
import reactor.core.publisher.Mono;
@WebFluxTest(controllers = GreetingController.class, properties = { "server.ssl.enabled=false" })
class SpringAddonsGreetingControllerUnitTest {
@MockBean
MessageService messageService;
@Autowired
WebTestClient api;
/*-----------------------------------------------------------------------------*/
/* /greet */
/* This end-point secured with ".anyRequest().authenticated()" in SecurityConf */
/*-----------------------------------------------------------------------------*/
@Test
@WithAnonymousUser
void givenUserIsNotAuthenticated_whenGetGreet_thenUnauthorized() throws Exception {
api.get().uri("/greet").exchange().expectStatus().isUnauthorized();
}
@Test
@WithMockJwtAuth(claims = @OpenIdClaims(preferredUsername = "Tonton Pirate"))
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
verify(messageService, times(1)).greet();
}
/*---------------------------------------------------------------------------------------------------------------------*/
/* /secured-route */
/* This end-point is secured with ".requestMatchers("/secured-route").hasRole("AUTHORIZED_PERSONNEL")" in SecurityConf */
/*---------------------------------------------------------------------------------------------------------------------*/
@Test
@WithAnonymousUser
void givenUserIsNotAuthenticated_whenGetSecuredRoute_thenUnauthorized() throws Exception {
api.get().uri("/secured-route").exchange().expectStatus().isUnauthorized();
}
@Test
@WithMockJwtAuth("ROLE_AUTHORIZED_PERSONNEL")
void givenUserIsGrantedWithRoleAuthorizedPersonnel_whenGetSecuredRoute_thenOk() throws Exception {
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
}
@Test
@WithMockJwtAuth("admin")
void givenUserIsNotGrantedWithRoleAuthorizedPersonnel_whenGetSecuredRoute_thenForbidden() throws Exception {
// @formatter:off
api.get().uri("/secured-route").exchange()
.expectStatus().isForbidden();
// @formatter:on
}
/*---------------------------------------------------------------------------------------------------------*/
/* /secured-method */
/* This end-point is secured with "@PreAuthorize("hasRole('AUTHORIZED_PERSONNEL')")" on @Controller method */
/*---------------------------------------------------------------------------------------------------------*/
@Test
@WithAnonymousUser
void givenUserIsNotAuthenticated_whenGetSecuredMethod_thenUnauthorized() throws Exception {
api.get().uri("/secured-method").exchange().expectStatus().isUnauthorized();
}
@Test
@WithMockJwtAuth("ROLE_AUTHORIZED_PERSONNEL")
void givenUserIsGrantedWithRoleAuthorizedPersonnel_whenGetSecuredMethod_thenOk() throws Exception {
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
}
@Test
@WithMockJwtAuth("admin")
void givenUserIsNotGrantedWithRoleAuthorizedPersonnel_whenGetSecuredMethod_thenForbidden() throws Exception {
// @formatter:off
api.get().uri("/secured-method").exchange()
.expectStatus().isForbidden();
// @formatter:on
}
}
@@ -0,0 +1,138 @@
package com.baeldung;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import static org.springframework.security.test.web.reactive.server.SecurityMockServerConfigurers.mockAuthentication;
import static org.springframework.security.test.web.reactive.server.SecurityMockServerConfigurers.mockJwt;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.reactive.WebFluxTest;
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.security.authentication.AnonymousAuthenticationToken;
import org.springframework.security.core.authority.AuthorityUtils;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.test.web.reactive.server.WebTestClient;
import com.baeldung.ReactiveResourceServerApplication.GreetingController;
import com.baeldung.ReactiveResourceServerApplication.MessageService;
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"));
@MockBean
MessageService messageService;
@Autowired
WebTestClient api;
/*-----------------------------------------------------------------------------*/
/* /greet */
/* This end-point secured with ".anyRequest().authenticated()" in SecurityConf */
/*-----------------------------------------------------------------------------*/
@Test
void givenUserIsNotAuthenticated_whenGetGreet_thenUnauthorized() throws Exception {
// @formatter:off
api.mutateWith(mockAuthentication(ANONYMOUS_AUTHENTICATION))
.get().uri("/greet").exchange()
.expectStatus().isUnauthorized();
// @formatter:on
}
@Test
void givenUserIsAuthenticated_whenGetGreet_thenOk() throws Exception {
final var greeting = "Whatever the service returns";
when(messageService.greet()).thenReturn(Mono.just(greeting));
// @formatter:off
api.mutateWith(mockJwt())
.get().uri("/greet").exchange()
.expectStatus().isOk()
.expectBody(String.class).isEqualTo(greeting);
// @formatter:on
verify(messageService, times(1)).greet();
}
/*---------------------------------------------------------------------------------------------------------------------*/
/* /secured-route */
/* This end-point is secured with ".requestMatchers("/secured-route").hasRole("AUTHORIZED_PERSONNEL")" in SecurityConf */
/*---------------------------------------------------------------------------------------------------------------------*/
@Test
void givenUserIsNotAuthenticated_whenGetSecuredRoute_thenUnauthorized() throws Exception {
// @formatter:off
api.mutateWith(mockAuthentication(ANONYMOUS_AUTHENTICATION))
.get().uri("/secured-route").exchange()
.expectStatus().isUnauthorized();
// @formatter:on
}
@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
}
@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
}
/*---------------------------------------------------------------------------------------------------------*/
/* /secured-method */
/* This end-point is secured with "@PreAuthorize("hasRole('AUTHORIZED_PERSONNEL')")" on @Controller method */
/*---------------------------------------------------------------------------------------------------------*/
@Test
void givenUserIsNotAuthenticated_whenGetSecuredMethod_thenUnauthorized() throws Exception {
// @formatter:off
api.mutateWith(mockAuthentication(ANONYMOUS_AUTHENTICATION))
.get().uri("/secured-method").exchange()
.expectStatus().isUnauthorized();
// @formatter:on
}
@Test
void givenUserIsGrantedWithRoleAuthorizedPersonnel_whenGetSecuredMethod_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-method").exchange()
.expectStatus().isOk()
.expectBody(String.class).isEqualTo(secret);
// @formatter:on
}
@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
}
}