Skip to content

Commit ec8aa1f

Browse files
committed
Merge branch 'chrispatmore-2557-csrf-reroute-bug'
2 parents 79614a2 + 1c0ae15 commit ec8aa1f

File tree

3 files changed

+59
-0
lines changed

3 files changed

+59
-0
lines changed

vertx-web/src/main/java/io/vertx/ext/web/handler/impl/CSRFHandlerImpl.java

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
import io.vertx.ext.web.handler.CSRFHandler;
3131
import io.vertx.ext.web.handler.SessionHandler;
3232
import io.vertx.ext.web.impl.Origin;
33+
import io.vertx.ext.web.impl.RoutingContextInternal;
3334
import io.vertx.ext.web.impl.Signature;
3435

3536
import java.nio.charset.StandardCharsets;
@@ -292,6 +293,14 @@ private boolean isValidRequest(RoutingContext ctx) {
292293
@Override
293294
public void handle(RoutingContext ctx) {
294295

296+
// we need to keep state since we can be called again on reroute
297+
if (!((RoutingContextInternal) ctx).seenHandler(RoutingContextInternal.CSRF_HANDLER)) {
298+
((RoutingContextInternal) ctx).visitHandler(RoutingContextInternal.CSRF_HANDLER);
299+
} else {
300+
ctx.next();
301+
return;
302+
}
303+
295304
if (nagHttps) {
296305
String uri = ctx.request().absoluteURI();
297306
if (uri != null && !uri.startsWith("https:")) {

vertx-web/src/main/java/io/vertx/ext/web/impl/RoutingContextInternal.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ public interface RoutingContextInternal extends RoutingContext {
3333
int BODY_HANDLER = 1 << 1;
3434
int CORS_HANDLER = 1 << 2;
3535
int SESSION_HANDLER = 1 << 3;
36+
int CSRF_HANDLER = 1 << 4;
3637

3738
/**
3839
* flags the current routing context as having visited the handler with {@code id}.

vertx-web/src/test/java/io/vertx/ext/web/handler/CSRFHandlerTest.java

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -654,4 +654,53 @@ public void simultaneousGetAndPostDoesNotOverrideTokenInSession() throws Excepti
654654
req.putHeader("Cookie", cookieJar.get());
655655
}, null, 200, "OK", null);
656656
}
657+
658+
@Test
659+
public void testRerouteRequest() throws Exception {
660+
final AtomicReference<String> sessionCookieJar = new AtomicReference<>();
661+
final AtomicReference<String> cookieJar = new AtomicReference<>();
662+
663+
router.route().handler(SessionHandler.create(LocalSessionStore.create(vertx)));
664+
router.route("/home").handler(rc -> rc.end("home"));
665+
router.route("/protected/*").handler(CSRFHandler.create(vertx, "Abracadabra"));
666+
router.route("/protected/initial").handler(rc -> rc.reroute("/protected/rerouted"));
667+
router.route("/protected/rerouted").handler(rc -> rc.end("done"));
668+
669+
// get a session, if first request is rerouted we don't get a session because of seenHandler check in SessionHandlerImpl
670+
// and context cleaning in reroute function
671+
testRequest(HttpMethod.GET, "/home", null, resp -> {
672+
List<String> cookies = resp.headers().getAll("set-cookie");
673+
assertEquals(1, cookies.size());
674+
675+
StringBuilder encodedCookie = new StringBuilder();
676+
// save the cookies
677+
for (String cookie : cookies) {
678+
encodedCookie.append(cookie, 0, cookie.indexOf(';'));
679+
encodedCookie.append("; ");
680+
}
681+
sessionCookieJar.set(encodedCookie.toString());
682+
}, 200, "OK", null);
683+
684+
testRequest(HttpMethod.GET, "/protected/initial", req -> req.putHeader("cookie", sessionCookieJar.get()), resp -> {
685+
List<String> cookies = resp.headers().getAll("set-cookie");
686+
assertEquals(1, cookies.size()); // reroute loses session cookie
687+
688+
StringBuilder encodedCookie = new StringBuilder();
689+
// save the cookies
690+
for (String cookie : cookies) {
691+
encodedCookie.append(cookie, 0, cookie.indexOf(';'));
692+
encodedCookie.append("; ");
693+
if (cookie.startsWith(CSRFHandler.DEFAULT_COOKIE_NAME)) {
694+
tmpCookie = cookie.substring(cookie.indexOf('=') + 1, cookie.indexOf(';'));
695+
}
696+
}
697+
cookieJar.set(sessionCookieJar.get() + encodedCookie);
698+
}, 200, "OK", null);
699+
700+
// POST shall be OK as the token and session align
701+
testRequest(HttpMethod.POST, "/protected/rerouted", req -> {
702+
req.putHeader("cookie", cookieJar.get());
703+
req.putHeader(CSRFHandler.DEFAULT_HEADER_NAME, tmpCookie);
704+
}, null, 200, "OK", null);
705+
}
657706
}

0 commit comments

Comments
 (0)