I have simple REST services implemented with Spring MVC. I decided to describe them with Springfox and Swagger 2.0. Everything seemed to be OK until I started adding security schemas and contexts. I use HTTP Basic authentication for certain endpoints and token-based authentication for others. Whatever I do, I cannot see any option to set HTTP Basic authentication credentials or to specify a token in Swagger UI. Below is my configuration. For simplicity's sake I apply both schemas to all endpoints here.
@Configuration
@EnableSwagger2
public class SwaggerConfig {
@Bean
public Docket apiV1() {
return new Docket(DocumentationType.SWAGGER_2)
.select()
.apis(RequestHandlerSelectors.any())
.paths(PathSelectors.any())
.build()
.pathMapping("/api/v1")
.securitySchemes(newArrayList(new BasicAuth("xBasic"),
new ApiKey("X-Auth-Token", "xAuthToken", "header")))
.securityContexts(newArrayList(xBasicSecurityContext(), xAuthTokenSecurityContext()))
}
private SecurityContext xBasicSecurityContext() {
SecurityContext.builder()
.securityReferences(newArrayList(new SecurityReference("xBasic",
new AuthorizationScope[0])))
.build()
}
private SecurityContext xAuthTokenSecurityContext() {
SecurityContext.builder()
.securityReferences(newArrayList(new SecurityReference("xAuthToken",
new AuthorizationScope[0])))
.build()
}
I have tried this approach: to split Docket config. It forced me also to split API into two groups (and packages), but in the end it was a good architectural decision.
@Configuration
@EnableSwagger2
public class SwaggerConfig {
@Bean
public Docket authTokenSecuredApi() {
return new Docket(DocumentationType.SWAGGER_2)
.groupName("authTokenGroup") // 2 Dockets -> need to differ using groupName
.select()
.apis(RequestHandlerSelectors.basePackage("cz.bank.controller.package1"))
.paths(PathSelectors.any())
.build()
.securitySchemes(Collections.singletonList(new ApiKey("X-Auth-Token",
"xAuthToken",
"header")))
.securityContexts(Collections.singletonList(xAuthTokenSecurityContext()));
}
@Bean
public Docket basicAuthSecuredApi() {
return new Docket(DocumentationType.SWAGGER_2)
.groupName("basicAuthGroup") // 2 Dockets -> need to differ using groupName
.select()
.apis(RequestHandlerSelectors.basePackage("cz.bank.controller.package2"))
.paths(PathSelectors.any())
.build()
.securitySchemes(Collections.singletonList(new BasicAuth("xBasic")))
.securityContexts(Collections.singletonList(xBasicSecurityContext()));
}
private SecurityContext xBasicSecurityContext() {
return SecurityContext.builder()
.securityReferences(Collections.singletonList(
new SecurityReference("xBasic",
new AuthorizationScope[0])))
.build();
}
private SecurityContext xAuthTokenSecurityContext() {
return SecurityContext.builder()
.securityReferences(Collections.singletonList(
new SecurityReference("xAuthToken",
new AuthorizationScope[0])))
.build();
}
}
To tell the truth, I would prefer to configure authorization directly in controllers, using authorizations
attribute of @ApiOperation
or @Api
Swagger annotations. But accorging to this springfox "feature", it does not work on @Api
annotation, which causes to copy it to every @ApiOperation
that leads to untidy nasty ugly sinful code :-)