How to Configure OpenAPI 3 Spec with Basic & JWT Authentication

In the previous article, we implemented user registration and login with OAuth 2.0 bearer token authentication. Now, we are gonna document the API with OpenAPI 3 specification.

Introduction

The OpenAPI Specification (OAS) defines a standard, language-agnostic interface to HTTP APIs that allows both humans and computers to discover and understand the capabilities of the service without access to source code, documentation, or through network traffic inspection. When properly defined, a consumer can understand and interact with the remote service with a minimal amount of implementation logic.

An OpenAPI definition can then be used by documentation generation tools to display the API, code generation tools to generate servers and clients in various programming languages, testing tools, and many other use cases.

What you’ll do?

In a nutshell, we are going to perform the following steps for documenting the REST API that we developed earlier.

  • Add OpenAPI 3.0 dependency
  • Configure OpenAPI 3.0 with Basic and Bearer Security schemes. OpenAPI uses the term security scheme for authentication and authorization schemes.
  • Modify Spring Security to permit the Swagger resource requests without authentication.
  • Test with Swagger UI

What you’ll need?

  • IntelliJ or any other IDE of your choice
  • JDK 17
  • MySQL Server 8

Documenting REST APIs

Adding OpenAPI 3 Dependency

pom.xml

springdoc-openapi java library helps to automate the generation of API documentation using spring boot projects. springdoc-openapi works by examining an application at runtime to infer API semantics based on Spring configurations, class structure, and various annotations.

		<dependency>
			<groupId>org.springdoc</groupId>
			<artifactId>springdoc-openapi-starter-webmvc-ui</artifactId>
			<version>2.0.2</version>
		</dependency>

Configuring OpenAPI

OpenApiConfig.java

OpenAPI can either be configured programmatically or with annotation-based configuration. I chose the latter since that looks neat and simple to me.

package com.javachinna.config;

import io.swagger.v3.oas.annotations.OpenAPIDefinition;
import io.swagger.v3.oas.annotations.enums.SecuritySchemeType;
import io.swagger.v3.oas.annotations.info.Contact;
import io.swagger.v3.oas.annotations.info.Info;
import io.swagger.v3.oas.annotations.security.SecurityRequirement;
import io.swagger.v3.oas.annotations.security.SecurityScheme;
import io.swagger.v3.oas.annotations.security.SecuritySchemes;
import org.springframework.context.annotation.Configuration;

@Configuration
@OpenAPIDefinition(info = @Info(title = "REST API", version = "1.1",
        contact = @Contact(name = "Chinna", email = "[email protected]")),
        security = {@SecurityRequirement(name = "basicAuth"), @SecurityRequirement(name = "bearerToken")}
)
@SecuritySchemes({
        @SecurityScheme(name = "basicAuth", type = SecuritySchemeType.HTTP, scheme = "basic"),
        @SecurityScheme(name = "bearerToken", type = SecuritySchemeType.HTTP, scheme = "bearer", bearerFormat = "JWT")
})
public class OpenApiConfig {
}

Note: We will not be using the basic authentication in this article since we have already disabled in the application. We will explore how we can make use of both basic and JWT authentication together in the next article.

Modifying Spring Security Config

WebConfig.java

When documenting with OpenAPI, there are 4 paths that we need to configure as public paths to allow them without authentication

  • /v3/api-docs.yaml -> This is the default path used to get the swagger definition in YAML format
  • /v3/api-docs -> This is the default path used to get the swagger definition in JSON format
  • /swagger-ui/** -> This is the default root path to Swagger UI which contains all the Swagger UI resources
  • /swagger-ui.html -> This is the default path to Swagger UI itself where we can play with API
@Configuration
public class WebConfig {

    @Value("${jwt.public.key}")
    RSAPublicKey key;

    @Value("${jwt.private.key}")
    RSAPrivateKey privateKey;
    public static final String[] PUBLIC_PATHS = {"/api/auth/**",
            "/v3/api-docs.yaml",
            "/v3/api-docs/**",
            "/swagger-ui/**",
            "/swagger-ui.html"};
    @Bean
    public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
        // @formatter:off
        http
                .authorizeHttpRequests()
                    .requestMatchers(PUBLIC_PATHS).permitAll()
                    .anyRequest().hasAuthority("SCOPE_ROLE_ADMIN").and()
                .csrf().disable()
                .httpBasic().disable()
                .oauth2ResourceServer(OAuth2ResourceServerConfigurer::jwt)
                .sessionManagement((session) -> session.sessionCreationPolicy(SessionCreationPolicy.STATELESS))
                .exceptionHandling((exceptions) -> exceptions
                        .authenticationEntryPoint(new BearerTokenAuthenticationEntryPoint())
                        .accessDeniedHandler(new BearerTokenAccessDeniedHandler())
                )
                // XSS protection
                .headers().xssProtection().and()
                .contentSecurityPolicy("script-src 'self'");
        // @formatter:on
        return http.build();
    }

Configuring Custom Path for Swagger Documentation (Optional)

By default,

  • The Swagger UI page will be available at http://server:port/context-path/swagger-ui.html or http://server:port/context-path/swagger-ui/index.html
  • The OpenAPI description will be available at the following URL in JSON format: http://server:port/context-path/v3/api-docs
    • server: The server name or IP
    • port: The server port
    • context-path: The context path of the application
  • Documentation can be available in yaml format as well, on the following path: /v3/api-docs.yaml
  • For a custom path of the swagger documentation in HTML format and API definition, add the following springdoc properties in your spring-boot configuration file

application.properties

# swagger-ui custom path
springdoc.swagger-ui.path=/docs/swagger-ui.html
# /api-docs endpoint custom path
springdoc.api-docs.path=/docs

We also need to make sure that the custom path is permitted without authentication in the Spring Security configuration.

WebConfig.java

public static final String[] PUBLIC_PATHS = {"/api/auth/**", "/docs/**"};

Accessing Swagger UI with Custom Path

Configuring Custom Swagger UI Path

Accessing API Docs with Custom Path

Custom Api Docs path

Testing

Let’s stick to the default path for Swagger UI and API docs and go to http://localhost:8082/swagger-ui/index.html

OpenAPI 3 Swagger UI REST API documentation.png

Access Token Request

JWT Request

Access Token Response

JWT Response

JWT Authentication

Click on the lock icon on the right side and enter the token in the bearer token field and click on Authorize to login

OpenAPI JWT Authentication

Secured API Request with Access Token

Secured API Request with JWT and Response

User Registration Bad Request and Response

Spring User Registration Request Validation

User Registration Request and Response

Spring User Registration Request and Response

Source Code

https://github.com/JavaChinna/spring-boot-oauth2-jwt

What’s Next?

In this article, we have documented the REST APIs with OpenAPI spec. In the next article, we will explore how we can implement endpoint-specific authentication by configuring multiple httpsecurity in Spring Security.

Leave a Reply