Search code examples
jakarta-eejerseyjwtswagger-uiopenapi

Add field for bearer token to generated Swagger UI in Java EE / Jersey


I have a Java EE 8 application in which I use OpenAPI annotations to define my REST endpoints and to automatically generate a Swagger UI. For authentication I use JSON Web Tokens (JWT).

Everything works fine when I send my requests from Postman, however, I cannot figure out how to have a field for the bearer token added to my Swagger UI.


I am definining my security scheme with the @SecurityScheme annotation:

@SecurityScheme(
        securitySchemeName = "JWT",
        description = "JWT authentication with bearer token",
        type = SecuritySchemeType.HTTP,
        scheme = "bearer",
        bearerFormat = "Bearer [token]"
)
public class ApplicationConfig extends Application {

}

I have tried adding this scheme as a @SecurityRequirement both to the @OpenAPIDefinition annotation of my resource and directly to my methods.

@Path("/items")
@OpenAPIDefinition(
        info = @Info(title = "Items resource", version = "v1"),
        security = @SecurityRequirement(name = "JWT")
)
@Transactional(value = TxType.REQUIRES_NEW)
@Interceptors({RolesAllowedInterceptor.class})
@SecurityScheme(
        securitySchemeName = "JWT",
        description = "JWT authentication with bearer token",
        type = SecuritySchemeType.HTTP,
        scheme = "bearer",
        bearerFormat = "Bearer [token]"
)
public class ItemsResource {

    (...)

    @GET
    @Operation(description = "Returns the item list overview")
    @APIResponse(responseCode = "200", description = "Valid response")
    @APIResponse(responseCode = "401", description = "Authentication required")
    @APIResponse(responseCode = "500", description = "Unexpected exception")
    @Produces({MediaType.APPLICATION_JSON})
    @SecurityRequirement(name ="JWT", scopes = "write: read")
    @RolesAllowed({Constants.USER_ROLE_EXPERT})
    public Response getItemListOverview() throws TechnicalException {
        ItemListOverviewVO itemListOverviewVO = logic.getItemListOverview();
        return Response.status(Status.OK).entity(itemListOverviewVO).build();
    }

So I now have security information in my OpenAPI JSON file, but still there is no field for the Authorization parameter in the UI.


I also found out that there used to be an @ApiImplicitParameter annotation in the old Swagger API (see Swagger UI passing authentication token to API call in header), but it seems that it was removed from the OpenAPI.

So I tried to use @HeaderParam instead (see Jersey project Swagger-UI doesn't send @HeaderParam while @PathParam is sent):

public Response getItemListOverview(@HeaderParam("Authorization") String bearerToken) throws TechnicalException {

Now there is an Authorization field in my UI, but when I test the endpoints the requests have no Authorization header. I cannot see it in the network analysis of my browser.


The OpenAPI documentation has been of little help so far. Am I missing something here?


Solution

  • The key is to embed the @SecurityScheme annotation in @Components() and pass that as a parameter to the @OpenAPIDefinition annotation:

    @OpenAPIDefinition(
            info = @Info(title = "My application", version = "1.0.0"),
            servers = {@Server(url = "/myapp", description = "localhost") },
            security = @SecurityRequirement(name = "JWT"),
            components = @Components(securitySchemes = @SecurityScheme(
                    securitySchemeName = "JWT",
                    description = "JWT authentication with bearer token",
                    type = SecuritySchemeType.HTTP,
                    scheme = "bearer",
                    bearerFormat = "Bearer [token]"))
    )
    public class ApplicationConfig extends Application {
    
    }