javascriptswaggernestjsnestjs-swaggernestjs-jwt

@nestjs/swagger does not set authorization headers


Can't authorize in a route using @nestjs/swagger@5.0.9 because I dont know how to configure the Document` in a right way and I couldn't find a workable answer in authorization official docs / stackoverflow / github.

I've stumbled upon a problem with JWT authorization in swagger. I'm using "@nestjs/swagger": "^5.0.9" and after I'm getting my access-token from a public route, I'm inserting it into the swagger ui field 'Authorize' which is configured with .addBearerAuth() method, which in this version(5.0.9) has this signature

addBearerAuth(options?: SecuritySchemeObject, name?: string)

as opposed to it lower version.

I've tested my API in Postman and I'm easily get an authorization throw it, I've also created an intersector which is printing headers before route call, but unfortunately it only prints them while I'm calling a public route :/

I only know that Postman is setting a Bearer token and it goes throw the route, and nothing similar is happening with swagger.

I've tried a lot of combinations of this configuration, but I haven't come to a solution in result of which I'm getting authorized in my route method, from swagger I can't reach it because of the swagger auth is not setting an authorization header in case of a bad config or of me doing something completely wrong. And I can't figure it out.

Config of a addBearerAuth is placed lower:

// swagger config
...
const config = new DocumentBuilder()
    .setTitle('SWAGGER API')
    .setVersion('1.0.0')
    .addBearerAuth(
      { 
        // I was also testing it without prefix 'Bearer ' before the JWT
        description: `[just text field] Please enter token in following format: Bearer <JWT>`,
        name: 'Authorization',
        bearerFormat: 'Bearer', // I`ve tested not to use this field, but the result was the same
        scheme: 'Bearer',
        type: 'http', // I`ve attempted type: 'apiKey' too
        in: 'Header'
      },
      'access-token',
    )
    .build();
...

Sample of a route in my controller. Is matched with a @ApiBearerAuth() decorator which is talking to a swagger that that method is cant be reached without an authorization.

@Get('/some-route')
@ApiBearerAuth()
@UseGuards(JwtAuthenticationGuard)
getData(
  @ReqUser() user: User,
): void {
  this.logger.warn({user});
}

Solution

  • If I understood your question you need to specify in your controller which bearer token you are using. In your case:

    // swagger config
    ...
    const config = new DocumentBuilder()
        .setTitle('SWAGGER API')
        .setVersion('1.0.0')
        .addBearerAuth(
          { 
            // I was also testing it without prefix 'Bearer ' before the JWT
            description: `[just text field] Please enter token in following format: Bearer <JWT>`,
            name: 'Authorization',
            bearerFormat: 'Bearer', // I`ve tested not to use this field, but the result was the same
            scheme: 'Bearer',
            type: 'http', // I`ve attempted type: 'apiKey' too
            in: 'Header'
          },
          'access-token', // This name here is important for matching up with @ApiBearerAuth() in your controller!
        )
        .build();
    ...
    

    and in your controller:

    @Get('/some-route')
    @ApiBearerAuth('access-token') //edit here
    @UseGuards(JwtAuthenticationGuard)
    getData(
      @ReqUser() user: User,
    ): void {
      this.logger.warn({user});
    }