Add Reactive OTT Sample

Closes gh-326
This commit is contained in:
Josh Cummings
2024-10-14 17:05:44 -06:00
parent 371fe2a42d
commit 42831fc9d1
4 changed files with 48 additions and 27 deletions

View File

@@ -11,7 +11,6 @@ java {
}
repositories {
mavenLocal()
mavenCentral()
maven { url "https://repo.spring.io/milestone" }
maven { url "https://repo.spring.io/snapshot" }

View File

@@ -48,13 +48,12 @@ public class MagicLinkOneTimeTokenGenerationSuccessHandler implements ServerOneT
.path("/login/ott")
.queryParam("token", oneTimeToken.getTokenValue());
String magicLink = builder.toUriString();
builder
.replacePath(null)
.replaceQuery(null)
.path("/ott/sent");
builder.replacePath(null).replaceQuery(null).path("/ott/sent");
String redirectLink = builder.toUriString();
return this.mailSender.send("johndoe@example.com", "Your Spring Security One Time Token",
"Use the following link to sign in into the application: " + magicLink)
return this.mailSender
.send("johndoe@example.com", "Your Spring Security One Time Token",
"Use the following link to sign in into the application: " + magicLink)
.then(this.redirectStrategy.sendRedirect(exchange, URI.create(redirectLink)));
}
}

View File

@@ -20,7 +20,6 @@ import org.springframework.boot.autoconfigure.security.reactive.PathRequest;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.Customizer;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.reactive.EnableWebFluxSecurity;
import org.springframework.security.config.web.server.ServerHttpSecurity;
import org.springframework.security.core.userdetails.MapReactiveUserDetailsService;

View File

@@ -24,34 +24,37 @@ import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.RegisterExtension;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
import org.springframework.boot.test.autoconfigure.web.reactive.AutoConfigureWebTestClient;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.reactive.server.WebTestClient;
import org.springframework.web.reactive.function.BodyInserters;
import org.springframework.web.util.UriComponents;
import org.springframework.web.util.UriComponentsBuilder;
import static org.assertj.core.api.Assertions.assertThat;
import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.csrf;
import static org.springframework.security.test.web.servlet.response.SecurityMockMvcResultMatchers.authenticated;
import static org.springframework.security.test.web.servlet.response.SecurityMockMvcResultMatchers.unauthenticated;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.redirectedUrl;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
import static org.springframework.security.test.web.reactive.server.SecurityMockServerConfigurers.csrf;
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
@AutoConfigureMockMvc
@SpringBootTest
@AutoConfigureWebTestClient(timeout = "30s")
class MagicLinkApplicationTests {
@RegisterExtension
static GreenMailExtension greenMail = new GreenMailExtension(ServerSetupTest.SMTP);
@Autowired
MockMvc mockMvc;
WebTestClient web;
@Test
void ottLoginWhenUserExistsThenSendEmailAndAuthenticate() throws Exception {
this.mockMvc.perform(post("/ott/generate").param("username", "user").with(csrf()))
.andExpectAll(status().isFound(), redirectedUrl("/ott/sent"));
this.web.mutateWith(csrf())
.post()
.uri("/ott/generate")
.body(BodyInserters.fromFormData("username", "user"))
.exchange()
.expectStatus()
.isFound()
.expectHeader()
.location("/ott/sent");
greenMail.waitForIncomingEmail(1);
MimeMessage receivedMessage = greenMail.getReceivedMessages()[0];
@@ -62,19 +65,40 @@ class MagicLinkApplicationTests {
assertThat(token).isNotEmpty();
this.mockMvc.perform(post("/login/ott").param("token", token).with(csrf()))
.andExpectAll(status().isFound(), redirectedUrl("/"), authenticated());
this.web.mutateWith(csrf())
.post()
.uri("/login/ott")
.body(BodyInserters.fromFormData("token", token))
.exchange()
.expectStatus()
.isFound()
.expectHeader()
.location("/");
}
@Test
void ottLoginWhenInvalidTokenThenFails() throws Exception {
this.mockMvc.perform(post("/ott/generate").param("username", "user").with(csrf()))
.andExpectAll(status().isFound(), redirectedUrl("/ott/sent"));
this.web.mutateWith(csrf())
.post()
.uri("/ott/generate")
.body(BodyInserters.fromFormData("username", "user"))
.exchange()
.expectStatus()
.isFound()
.expectHeader()
.location("/ott/sent");
String token = "1234;";
this.mockMvc.perform(post("/login/ott").param("token", token).with(csrf()))
.andExpectAll(status().isFound(), redirectedUrl("/login?error"), unauthenticated());
this.web.mutateWith(csrf())
.post()
.uri("/login/ott")
.body(BodyInserters.fromFormData("token", token))
.exchange()
.expectStatus()
.isFound()
.expectHeader()
.location("/login?error");
}
}