How access to a security endpoint on OpenAPI with vert.x?

528 views Asked by At

I am playing with the vert.x-openAPI module and I have my petstore.yaml with security like:

/pets/{petId}:
    get:
      summary: Info for a specific pet
      operationId: showPetById
      security:
        - ApiKeyAuth: []

This is the related part of the operationId on my Server side (Verticle) using a JWT Auth Handler (I will ommited the JWT Auth provider creation part from my code) :

 routerBuilder.setOptions(routerBuilderOptions)
      .securityHandler("ApiKeyAuth", JWTAuthHandler.create(jwtAuthProvider))
      .operation("showPetById")
      .handler(routingContext -> {
        RequestParameters params = routingContext.get(ValidationHandler.REQUEST_CONTEXT_KEY);
        Integer id = params.pathParameter("petId").getInteger();
        Optional<JsonObject> pet = getAllPets()
          .stream()
          .filter(p -> p.getInteger("id").equals(id))
          .findFirst();
        if(pet.isPresent()){
          routingContext
            .response()
            .setStatusCode(200)
            .putHeader(HttpHeaders.CONTENT_TYPE,"application/json")
            .end(pet.get().encode());
        }else {
          routingContext.fail(404, new Exception("Pet not found"));
        }

      });

Then, I am trying from my tests access to that endpoint with a successfully (and authorization ok) response :

@Test
  public void breakingTheAuth(Vertx vertx, VertxTestContext vertxTestContext){

    Checkpoint checkFlag = vertxTestContext.checkpoint(2);
    //Checkpoint jwtCheck = vertxTestContext.checkpoint();
    vertxTestContext.verify(()->{
      JWTAuth jwt = loadJWTAuthprovider(vertx);
      checkFlag.flag();
      RouterBuilder.create(vertx,"petstore.yaml")
        .onSuccess(routerBuilder -> {
          routerBuilder.setOptions(FACTORY_OPTIONS)
            .securityHandler("ApiKeyAuth", JWTAuthHandler.create(jwt))
            .operation("showPetById")
            .handler(routingContext -> {
              given()
                .port(8080)
                .get("/pets/2")
                .then()
                .statusCode(200);

            });
          checkFlag.flag();
        }).onFailure(throwable -> {
          vertxTestContext.failNow(throwable);
        });
    });
  }


    I would like to access to this endpoint http://localhost:8080/pets/2 with a 200 status code as a response but I always get the 401 Unauthorized (Maybe a JWTAuth problem, I've read about using oAUTH it could be a better option).
    Maybe I am missing anything, should I use the vertx-webclient to access to that endpoint?
1

There are 1 answers

0
mohamnag On

You can not use RouterBuilder and JWTAuthHandler for the client to inject the auth header for you. I'm afraid that part has to be done by manually setting an auth header on requests. This is normally done in a way like this (using Vertx's WebClient):

WebClient
      .create(vertx, ...) // set params so that this client can reach your API
      .post("/pets/pet123")
      .putHeader("authorization", "Bearer " + token)
      // now make the actual request and use the results

How you get your hands on an auth token, depends. In your case, for the tests, your probably best bet is to use a mock auth service (instead of a real Keycloak). You need to configure your server to use the mock auth instead of real Keycloak for tests only (using configs) and for the client side, in your tests just get the token from it.

This mock auth service is an example of what would work: https://github.com/TNG/keycloak-mock