Skip to content

Commit

Permalink
Fix for nested ChainAuthHandlers of type "any" (#2644)
Browse files Browse the repository at this point in the history
See #2641

ChainAuthHandlerImpl maintains, for instances of type "any", an index indicating which handler in the list succeeded to authenticate the user.

This index is used in the postAuthentication method to determine which handler int he list should have its postAuthentication method invoked.

When "any" ChainAuthHandlers were nested, the index computed in the top level ChainAuthHandler was used to choose the handlers in the list of nested ChainAuthHandler.

This caused either the wrong handler to be peeked or IndexOutOfBoundsException to be thrown.

With this change, the value put in the RoutingContext is specific to a ChainAuthHandler instance.

Signed-off-by: Thomas Segismont <[email protected]>
  • Loading branch information
tsegismont authored Sep 5, 2024
1 parent 53acdc7 commit ed41309
Show file tree
Hide file tree
Showing 2 changed files with 37 additions and 7 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -15,21 +15,25 @@

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;

public class ChainAuthHandlerImpl extends AuthenticationHandlerImpl<AuthenticationProvider> implements ChainAuthHandler {

private static final Logger LOG = LoggerFactory.getLogger(ChainAuthHandler.class);

private static final String HANDLER_IDX = "__vertx.auth.chain.idx";
private static final String HANDLER_KEY_PREFIX = "__vertx.auth.chain.idx.";
private static final AtomicInteger HANDLER_KEY_SEQ = new AtomicInteger();

private final List<AuthenticationHandlerInternal> handlers = new ArrayList<>();
private final boolean all;
private final String chainAuthHandlerKey;

private int willRedirect = -1;

public ChainAuthHandlerImpl(boolean all) {
super(null);
this.all = all;
this.chainAuthHandlerKey = HANDLER_KEY_PREFIX + HANDLER_KEY_SEQ.getAndIncrement();
}

@Override
Expand Down Expand Up @@ -115,7 +119,7 @@ private void iterate(final int idx, final RoutingContext ctx, User result, Throw
iterate(idx + 1, ctx, user, null, handler);
} else {
// a single success is enough to signal the end of the validation
ctx.put(HANDLER_IDX, idx);
ctx.put(chainAuthHandlerKey, idx);
handler.handle(Future.succeededFuture(user));
}
});
Expand All @@ -139,11 +143,10 @@ public boolean setAuthenticateHeader(RoutingContext ctx) {

@Override
public void postAuthentication(RoutingContext ctx) {
if (all) {
// Can't invoke post-processing for all handlers
Integer idx;
if (all || (idx = ctx.get(chainAuthHandlerKey)) == null) {
ctx.next();
} else {
int idx = ctx.get(HANDLER_IDX);
handlers.get(idx).postAuthentication(ctx);
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,12 @@
import io.vertx.ext.auth.User;
import io.vertx.ext.auth.jwt.JWTAuth;
import io.vertx.ext.auth.jwt.JWTAuthOptions;
import io.vertx.ext.web.RoutingContext;
import io.vertx.ext.web.WebTestBase;
import io.vertx.ext.web.handler.impl.SimpleAuthenticationHandlerImpl;
import io.vertx.ext.web.sstore.LocalSessionStore;
import org.junit.Test;

import java.util.Arrays;

public class ChainAuthMixHandlerTest extends WebTestBase {

private static final User USER = User.create(new JsonObject().put("id", "paulo"));
Expand Down Expand Up @@ -114,4 +114,31 @@ public void testRedirectAndHandlerFail() {
.add(OAuth2AuthHandler.create(vertx, null, "http://server.com/callback"))
.add(BasicAuthHandler.create(null));
}

@Test
public void testNestedAnyChainAuthHandler() throws Exception {
ChainAuthHandler chain =
ChainAuthHandler.any()
.add(failure)
.add(failure)
.add(failure)
.add(failure)
.add(ChainAuthHandler.any()
.add(failure)
.add(failure)
.add(ChainAuthHandler.any()
.add(failure)
.add(new SimpleAuthenticationHandlerImpl() {
@Override
public void postAuthentication(RoutingContext rc) {
rc.response().end("Peekaboo");
}
}.authenticate(ctx -> Future.succeededFuture(USER)))));

router.route().handler(SessionHandler.create(LocalSessionStore.create(vertx)));
router.route().handler(chain);
router.route().handler(ctx -> fail());

testRequest(HttpMethod.GET, "/", 200, "OK", "Peekaboo");
}
}

0 comments on commit ed41309

Please sign in to comment.