OpenApi 3 custom setup in Spring Boot using springdoc-openapi-ui

OpenApi 3 custom setup in Spring Boot using springdoc-openapi-ui

So I was migrating over our Spring Boot REST API project from Swagger 2 to OpenApi 3. So far it’s been pretty painless. I found a helper library called springdoc-openapi-ui that is for OpenApi 3 what SwaggerFox is for Swagger 2. That said, there are a few changes to the default setup we needed to support:

  • Keycloak OAuth2 authentication
  • API key authenication
  • A Version: header enabled for every API endpoint

I clearly didn’t want to have to add the Version: header manually to every endpoint manually. I found the following solution that does what I need it to do:

@Configuration
public class OpenApi3Config {
    private BuildProperties buildProperties;
    private String authServer;
    private String realm;

    @Autowired
    public OpenApi3Config(BuildProperties buildProperties,
                          @Value("${keycloak.auth-server-url}") String authServer,
                          @Value("${keycloak.realm}") String realm) {
        this.buildProperties = buildProperties;
        this.authServer = authServer;
        this.realm = realm;
    }

    @Bean
    public OpenAPI openAPI() {
        var authUrl = String.format("%s/realms/%s/protocol/openid-connect", this.authServer, this.realm);
        return new OpenAPI()
                .components(new Components()
                        .addSecuritySchemes("spring_oauth", new SecurityScheme()
                                .type(SecurityScheme.Type.OAUTH2)
                                .description("Oauth2 flow")
                                .flows(new OAuthFlows()
                                        .authorizationCode(new OAuthFlow()
                                                .authorizationUrl(authUrl + "/auth")
                                                .refreshUrl(authUrl + "/token")
                                                .tokenUrl(authUrl + "/token")
                                                .scopes(new Scopes())
                                        )))
                        .addSecuritySchemes("api_key", new SecurityScheme()
                                .type(SecurityScheme.Type.APIKEY)
                                .description("Api Key access")
                                .in(SecurityScheme.In.HEADER)
                                .name("API-KEY")
                        )
                        .addParameters("Version", new Parameter()
                                .in("header")
                                .name("Version")
                                .schema(new StringSchema())
                                .required(false)))
                .security(Arrays.asList(
                        new SecurityRequirement().addList("spring_oauth"),
                        new SecurityRequirement().addList("api_key")))

                .info(new Info()
                        .title("Your API")
                        .description("Your API")
                        .version(this.buildProperties.getVersion())
                        .contact(new Contact()
                                .name("Example Inc")
                                .url("https://www.example.com/")
                                .email("developer@example.com")));
    }

    @Bean
    public OpenApiCustomiser openApiCustomiser() {
        return openApi -> openApi.getPaths().values().stream()
                .flatMap(pathItem -> pathItem.readOperations().stream())
                .forEach(operation -> operation.addParametersItem(new HeaderParameter()
                        .$ref("#/components/parameters/Version")));
    }
}

This will get you set up will all three of the requirements, including the Version: header:

Version header input

Keith Miller's Picture

About Keith Miller

Keith is currently the Vice President of Engineering at Mythical Games.

Los Angeles, CA https://keithtmiller.com