Spring Boot & Swagger UI. Set JWT token

For swagger version 2.9.2

  1. Create a SwaggerConfig class.

    @Bean
    public Docket api() {
        return new Docket(DocumentationType.SWAGGER_2)
                .select()
                .apis(RequestHandlerSelectors.any())
                .paths(PathSelectors.any())
                .build()
                .apiInfo(apiInfo())
                .securitySchemes(Arrays.asList(apiKey()));
    }
    
    private ApiInfo apiInfo() {
        return new ApiInfoBuilder()
                .title("Sig-Predict REST API Document")
                .description("work in progress")
                .termsOfServiceUrl("localhost")
                .version("1.0")
                .build();
    }
    
    private ApiKey apiKey() {
        return new ApiKey("jwtToken", "Authorization", "header");
    }
    
    1. Then annotate each API you would like to send this Authorization header to with:

      @ApiOperation(value = "", authorizations = { @Authorization(value="jwtToken") })
      

Original answer

Support for Authorization: Bearer [JWT_TOKEN] header is working as of version 2.9.2

Added the following dependencies to build.gradle

compile("io.springfox:springfox-swagger2:2.9.2") {
    exclude module: 'mapstruct' // necessary in my case to not end up with multiple mapstruct versions
}
compile "io.springfox:springfox-bean-validators:2.9.2"
compile "io.springfox:springfox-swagger-ui:2.9.2"

Configured Swagger via

@Configuration
@EnableSwagger2
@Import(springfox.bean.validators.configuration.BeanValidatorPluginsConfiguration.class)
public class SwaggerConfiguration {

    public static final String AUTHORIZATION_HEADER = "Authorization";
    public static final String DEFAULT_INCLUDE_PATTERN = "/api/.*";
    private final Logger log = LoggerFactory.getLogger(SwaggerConfiguration.class);

    @Bean
    public Docket swaggerSpringfoxDocket() {
        log.debug("Starting Swagger");
        Contact contact = new Contact(
            "Matyas Albert-Nagy",
            "https://justrocket.de",
            "[email protected]");

        List<VendorExtension> vext = new ArrayList<>();
        ApiInfo apiInfo = new ApiInfo(
            "Backend API",
            "This is the best stuff since sliced bread - API",
            "6.6.6",
            "https://justrocket.de",
            contact,
            "MIT",
            "https://justrocket.de",
            vext);

        Docket docket = new Docket(DocumentationType.SWAGGER_2)
            .apiInfo(apiInfo)
            .pathMapping("/")
            .apiInfo(ApiInfo.DEFAULT)
            .forCodeGeneration(true)
            .genericModelSubstitutes(ResponseEntity.class)
            .ignoredParameterTypes(Pageable.class)
            .ignoredParameterTypes(java.sql.Date.class)
            .directModelSubstitute(java.time.LocalDate.class, java.sql.Date.class)
            .directModelSubstitute(java.time.ZonedDateTime.class, Date.class)
            .directModelSubstitute(java.time.LocalDateTime.class, Date.class)
            .securityContexts(Lists.newArrayList(securityContext()))
            .securitySchemes(Lists.newArrayList(apiKey()))
            .useDefaultResponseMessages(false);

        docket = docket.select()
            .paths(regex(DEFAULT_INCLUDE_PATTERN))
            .build();
        watch.stop();
        log.debug("Started Swagger in {} ms", watch.getTotalTimeMillis());
        return docket;
    }


    private ApiKey apiKey() {
        return new ApiKey("JWT", AUTHORIZATION_HEADER, "header");
    }

    private SecurityContext securityContext() {
        return SecurityContext.builder()
            .securityReferences(defaultAuth())
            .forPaths(PathSelectors.regex(DEFAULT_INCLUDE_PATTERN))
            .build();
    }

    List<SecurityReference> defaultAuth() {
        AuthorizationScope authorizationScope
            = new AuthorizationScope("global", "accessEverything");
        AuthorizationScope[] authorizationScopes = new AuthorizationScope[1];
        authorizationScopes[0] = authorizationScope;
        return Lists.newArrayList(
            new SecurityReference("JWT", authorizationScopes));
    }
}

Access the ui via http://host:port/<context-root>/swagger-ui.html

Press Authorize all requests and enter Bearer [JWT_TOKEN]

Press authorize then enter the Bearer JWT Token

Voila your next requests will have the JWT header

enter image description here

Update 2022-09-24

After a series of newer projects, I started using springdoc-openapi that generates docs based on javadoc, eliminating the need of extra annotations.

Writing this for anyone who is willing to give this library a try. I would recommend it/am a happy user of this lib.

Dependencies

build.gradle

[...]
// swagger ui
implementation 'org.springdoc:springdoc-openapi-ui:1.6.9'
implementation 'org.springdoc:springdoc-openapi-javadoc:1.6.9'
annotationProcessor 'com.github.therapi:therapi-runtime-javadoc-scribe:0.13.0'
implementation 'com.github.therapi:therapi-runtime-javadoc:0.13.0'
[...]

Declare Authentication

Using the project specific SecurityConfiguration.java - define the pattern of the OpenAPI authorization. This case: Bearer in Authorization in the HTTP header.

import static io.swagger.v3.oas.annotations.enums.SecuritySchemeIn.HEADER;
import static io.swagger.v3.oas.annotations.enums.SecuritySchemeType.HTTP;
import io.swagger.v3.oas.annotations.security.SecurityScheme;

 @Component
 @SecurityScheme(name = SecurityConfiguration.SECURITY_CONFIG_NAME, in = HEADER, type = HTTP, scheme = "bearer", bearerFormat = "JWT")
 public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
 [...]
     public static final String SECURITY_CONFIG_NAME = "App Bearer token";
 [...]

Usage in REST controllers

Usage in SomeController.java shall reference the security config

import static com.x.common.security.SecurityConfiguration.SECURITY_CONFIG_NAME;
import io.swagger.v3.oas.annotations.security.SecurityRequirement;

 @RestController
 @RequestMapping("/api/v1/resources")
 @SecurityRequirement(name = SECURITY_CONFIG_NAME)
 public class ConnectionSyncController {
 
     /**
      * Documentation that will be rendered
      * 
      * supports 
      * 
      * 1. markdown
      * 1. list
      */
     @PostMapping("/{id}/sync")
     @DomainAuthorize(permissionType = BasePermissions.PERM_ADMIN_OPERATIONS)
     public void syncConnection(@PathVariable("id") Long id) {

Configure reachability

  1. Configure location of openapi specs (swagger yml) - default /v3/api-docs
  2. Configure where swagger-ui is located/loads config from
  3. Configure which backends swagger-ui can talk with
  4. In case we are behind a proxy, we need to make sure that the calls are proxied with correct headers for everything to work.

/src/main/resources/application.yml

 server:
   port: 80
   # needed for swagger-ui to detect correct proxied paths correctly.
   # Configuration needed for the [Try out] buttons to work
   # this works in combination with the proxied headers
   # proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
   # proxy_set_header X-Forwarded-Prefix /services/impower-facilioo;
   forward-headers-strategy: FRAMEWORK
 
 springdoc:
   swagger-ui:
     # where the UI configuration is located at
     configUrl: /[some/public/path]/v3/api-docs/swagger-config
     filter: true
     deepLinking: true
     # where the server API yml/json files are at (dropdown in top right corner)
     urls[0]:
       url: /[some/public/path]/v3/api-docs
       name: backend

Your code is correct.

There is a bug in springfox-swagger-ui/springfox-swagger2 version 2.8.0 and it seems 2.9.2 as well. I suspect you are using a version effected by this bug.

I simply downgraded to 2.7.0 and it worked perfectly.