Spring Boot & Swagger UI. Set JWT token

54,799

Solution 1

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

Solution 2

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") })
      

Solution 3

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.

Share:
54,799
isADon
Author by

isADon

Updated on March 30, 2021

Comments

  • isADon
    isADon about 3 years

    I have a Swagger config like this

    @EnableSwagger2
    @Configuration
    public class SwaggerConfig {
        @Bean
        public Docket api() {
            List<SecurityScheme> schemeList = new ArrayList<>();
            schemeList.add(new ApiKey(HttpHeaders.AUTHORIZATION, "JWT", "header"));
            return new Docket(DocumentationType.SWAGGER_2)
                    .produces(Collections.singleton("application/json"))
                    .consumes(Collections.singleton("application/json"))
                    .ignoredParameterTypes(Authentication.class)
                    .securitySchemes(schemeList)
                    .useDefaultResponseMessages(false)
                    .select()
                    .apis(Predicates.not(RequestHandlerSelectors.basePackage("org.springframework.boot")))
                    .paths(PathSelectors.any())
                    .build();
        }
    }
    

    In the Swagger UI when I click on the Authorize button I enter my JWT token in the value field eyJhbGc..nN84qrBg. Now I expect that any request I do through the Swagger UI will contain the JWT in the header. However, that is not the case. No request contains a Authorization header.

    What am I missing?

  • Ickster
    Ickster over 5 years
    This worked very well. I'm not sure where the AUTHORIZATION_HEADER is imported from, but I just hard-coded it and it worked just as well.
  • Matyas
    Matyas over 5 years
    It is a static variable used across Spring Security / etc. ` public static final String AUTHORIZATION_HEADER = "Authorization";` (added to the answer itself)
  • Ickster
    Ickster over 5 years
    Hmmm. I wonder if that was deprecated in the version of Spring Security I'm using, or if I just missed it. The only import I recall IntelliJ suggesting was from a different package and the String value wasn't what I was looking for.
  • orid
    orid about 4 years
    well done, worked for me, thanks! Just to emphasize that in the UI you need to specify the full header "Bearer <jwt>"
  • moldovean
    moldovean about 4 years
    @orid I am glad I could help. Yes, the standard is to put 'Bearer' in front, however this config is just for Swagger to work and send to back-end a header with name: "Authorization". The value of this header however is up to the developer.
  • webjockey
    webjockey almost 4 years
    I used exact code as above with correct maven dependency, does not show authorize button or does not generate authorization header for the api's
  • Morteza
    Morteza over 3 years
    I did exactly as your answer. but, the token is not sent in request headers. can you tell me what am i doing wrong?
  • Morteza
    Morteza over 3 years
    I wanna smash my monitor. It is about 4 hours that I am searching for why my code is not working, till I faced your answer and figured out that swagger version was my problem too. thanks man. you saved my day :)
  • Adrian B.
    Adrian B. over 3 years
    this worked with version 3.0.0 as well. The only thing that I changes was to use Arrays.asList instead of Lists.newArrayList (as I didn't use Guava) and to switch from Swagger2 to OAS (@EnableOpenApi and DocumentationType.OAS_30)
  • Orkhan Hasanli
    Orkhan Hasanli over 3 years
    @ApiOperation must be added on method level, not to the class. Tried this solution in 3.0.0 version. Thank you)
  • Shashi Ranjan
    Shashi Ranjan almost 2 years
    This code has compilation issue.