9

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});
}
marc_s
  • 732,580
  • 175
  • 1,330
  • 1,459
wald3
  • 343
  • 1
  • 3
  • 13

2 Answers2

13

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});
}
Andrea Mugnai
  • 311
  • 2
  • 9
  • Yeah, after I edited a decorator the auth header became filled in correctly. I've read a lot about setting up swagger, and I haven't seen or noticed this feature. – wald3 Aug 17 '21 at 16:04
  • is it possible to somehow not explicitly specify this parameter by changing the configuration? – wald3 Aug 17 '21 at 16:07
  • 2
    You can try without set `access-token` in the configuration and using `@ApiBearerAuth()` without parameters. Let me know if works – Andrea Mugnai Aug 18 '21 at 07:06
  • Need to click on the "lock" icon on the top right of the route in swagger api docs. – Calvintwr Jan 13 '22 at 16:21
0

You can ignore the name and param of @ApiBearerAuth()

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'
  }
)
.build();

And in your controller:

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