vertx-web
vertx-web copied to clipboard
ChainAuthHandler.any() doesn't work well with multiple JWTAuthHandlers
Version
>=4.5.6
Context
This(https://github.com/vert-x3/vertx-web/pull/2582) pull request broke multiple JWTAuthHandlers hooked with a ChainAuthHandler.any() (Well actually it wasn't checking for scopes before)
So I am using vertx-web-openapi-router and it creates this similar double JWTAuthHandler inside a ChainAuthHandler when a route has security like this
security:
- oauth:
- 'users:read'
- oauth:
- 'users:all'
With the change in referenced PR, ChainAuthHandler now calls postAuthentication for each JWTAuthHandler. But in postAuthentication JWTAuthHandler ends the context while checking for scopes at this line..
https://github.com/vert-x3/vertx-web/blob/a6d16eb0e7f885755527be51d976020a118ea933/vertx-web/src/main/java/io/vertx/ext/web/handler/impl/JWTAuthHandlerImpl.java#L154
Which causes ChainAuthHandler not to continue with the other handlers in the chain. This flow is not expected as its a any() handler and should continue and be successful if one of the handlers are successful.
Do you have a reproducer?
@Test
public void testWithMultipleJWTAuthHandlers() throws Exception {
router.clear();
JWTAuth authProvider = JWTAuth.create(vertx, new JWTAuthOptions()
.setKeyStore(new KeyStoreOptions()
.setType("jceks")
.setPath("keystore.jceks")
.setPassword("secret")));
chain = ChainAuthHandler.any()
.add(JWTAuthHandler.create(authProvider).withScope("users:read"))
.add(JWTAuthHandler.create(authProvider).withScope("users:all"));
router.route()
.handler(chain)
.handler(RoutingContext::end);
final JsonObject payloadA = new JsonObject()
.put("sub", "Paulo")
.put("scope", String.join(" ", Arrays.asList("users:read")));
testRequest(HttpMethod.GET, "/", req -> req.putHeader("Authorization", "Bearer " + authProvider.generateToken(payloadA)), 200, "OK", null);
final JsonObject payloadB = new JsonObject()
.put("sub", "Paulo")
.put("scope", String.join(" ", Arrays.asList("users:read", "users:all")));
testRequest(HttpMethod.GET, "/", req -> req.putHeader("Authorization", "Bearer " + authProvider.generateToken(payloadB)), 200, "OK", null);
final JsonObject payloadC = new JsonObject()
.put("sub", "Paulo")
.put("scope",String.join(" ",Arrays.asList("users:all")));
testRequest(HttpMethod.GET, "/", req -> req.putHeader("Authorization", "Bearer " + authProvider.generateToken(payloadC)), 200, "OK", null);
}
Steps to reproduce
Add this test to ChainAuthHandlerTest class and run.