Spring Boot + Swagger 3 (OpenAPI 3) + Security Example(Basic Authentication)
Join the DZone community and get the full member experience.
In a previous tutorial, we implemented Spring Boot + Swagger 3 (OpenAPI 3) Hello World Example. Also previously, we had implemented Understand Spring Security Architecture and implement Spring Boot Security Example. In this tutorial, we will be implementing Spring Boot Basic Security for the Spring Boot Swagger example. So when using Swagger to access the endpoints, Swagger also allows us to configure the Spring Security user name and password.
Watch the YouTube Video below for the tutorial.
Let’s Begin
We will be modifying the Spring Boot + Swagger 3 (OpenAPI 3) Hello World Example project we had implemented in the previous tutorial.
Download the project and import the maven project in eclipse. Start the project. If we go to http://localhost:8080/swagger-ui/index.html#/ we see the following:
The final maven project we will be developing is as follows:
Modify the pom.xml to add the spring security dependency:
4.0.0 org.springframework.boot spring-boot-starter-parent 2.3.0.RELEASE com.javainuse boot-swagger-3-fin 0.0.1-SNAPSHOT boot-swagger-3 1.8 org.springdoc springdoc-openapi-ui 1.2.32 org.springframework.boot spring-boot-starter-web org.springframework.boot spring-boot-starter-security org.springframework.boot spring-boot-maven-plugin
Next, we will be adding the Spring Security configuration.
- We annotate the SecurityConfiguration class with @EnableWebSecurity to apply the class to the global WebSecurity.
- Also, we extend WebSecurityConfigurerAdapter to define rules to specify what URIs to protect or pass through. This provides us a configuration method.
- Extending WebSecurityConfiguration allows customizing Spring Security by overriding methods.
package com.javainuse.configuration; import org.springframework.context.annotation.Bean; import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; import org.springframework.security.crypto.password.PasswordEncoder; @EnableWebSecurity public class SecurityConfiguration extends WebSecurityConfigurerAdapter < @Override protected void configure(HttpSecurity http) throws Exception < http.authorizeRequests() .antMatchers("/swagger-ui/**", "/javainuse-openapi/**").permitAll() .anyRequest().authenticated() .and() .httpBasic(); >@Override protected void configure(AuthenticationManagerBuilder auth) throws Exception < auth.inMemoryAuthentication() .withUser("javainuse") .password(passwordEncoder().encode("javainuse")) .authorities("ADMIN"); >@Bean public PasswordEncoder passwordEncoder() < return new BCryptPasswordEncoder(); >>
Start the project using Swagger UI if we do not try to test the REST endpoints it asks for the username and password. If we enter these, Swagger is able to successfully interact with the endpoints.
Let us now configure Swagger for Spring Security. In the SwaggerSpringDemoApplication class, specify SecurityScheme. OpenAPI uses the term security scheme for authentication and authorization schemes. OpenAPI 3.0 lets you describe APIs protected using the following security schemes:
- HTTP authentication schemes (they use the Authorization header):
- Basic
- Bearer
- other HTTP schemes as defined by RFC 7235 and HTTP Authentication Scheme Registry
- Cookie authentication
package com.javainuse; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import io.swagger.v3.oas.annotations.OpenAPIDefinition; import io.swagger.v3.oas.annotations.enums.SecuritySchemeIn; import io.swagger.v3.oas.annotations.enums.SecuritySchemeType; import io.swagger.v3.oas.annotations.info.Info; import io.swagger.v3.oas.annotations.security.SecurityScheme; @SpringBootApplication @OpenAPIDefinition(info = @Info(title = "Employees API", version = "2.0", description = "Employees Information")) @SecurityScheme(name = "javainuseapi", scheme = "basic", type = SecuritySchemeType.HTTP, in = SecuritySchemeIn.HEADER) public class SwaggerSpringDemoApplication < public static void main(String[] args) < SpringApplication.run(SwaggerSpringDemoApplication.class, args); >>
Finally, in the controller class, use SecurityRequirement to define security requirements for the single operation (when applied at method level) or for all operations of a class (when applied at class level).
package com.javainuse.controllers; import java.util.ArrayList; import java.util.List; import org.springframework.web.bind.annotation.DeleteMapping; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RestController; import com.javainuse.model.Employee; import io.swagger.v3.oas.annotations.security.SecurityRequirement; @RestController @SecurityRequirement(name = "javainuseapi") public class EmployeeController < private Listemployees = createList(); @RequestMapping(value = "/employees", method = RequestMethod.GET, produces = "application/json") public List firstPage() < return employees; >@DeleteMapping(path = < "/" >) public Employee delete(@PathVariable("id") int id) < Employee deletedEmp = null; for (Employee emp : employees) < if (emp.getEmpId().equals(id)) < employees.remove(emp); deletedEmp = emp; break; >> return deletedEmp; > @PostMapping public Employee create(@RequestBody Employee user) < employees.add(user); System.out.println(employees); return user; >private static List createList() < ListtempEmployees = new ArrayList<>(); Employee emp1 = new Employee(); emp1.setName("emp1"); emp1.setDesignation("manager"); emp1.setEmpId("1"); emp1.setSalary(3000); Employee emp2 = new Employee(); emp2.setName("emp2"); emp2.setDesignation("developer"); emp2.setEmpId("2"); emp2.setSalary(3000); tempEmployees.add(emp1); tempEmployees.add(emp2); return tempEmployees; > >
Start the project. We can now see the lock symbol.
If we click on it, it asks for the credentials. On entering it, we can successfully access the REST enfpoints using Swagger.
Published at DZone with permission of Rida Shaikh . See the original article here.
Opinions expressed by DZone contributors are their own.
Swagger/OpenAPI and Spring Security
If your project uses Spring Security and you have added Swagger/OpenAPI to it, there is a little additional configuration you need to do in order to make your /v3/api-docs and swagger-ui.html pages work.
Enable Swagger URLs in Spring Security Project
To enable Swagger URLs in a RESTful Web Services project built with Spring Boot and Spring Security Framework, make the following configuration to your WebSecurity Java class which is annotated with @EnableWebSecurity annotation:
http .authorizeHttpRequests() .requestMatchers("/swagger-ui/**") .permitAll();
Below is an example of my WebSecurity Java class with the needed configuration to enable Swagger URLs.
package com.appsdeveloperblog.webapp.security; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; import org.springframework.security.config.annotation.web.configuration.WebSecurityCustomizer; import org.springframework.security.web.SecurityFilterChain; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @Configuration @EnableWebSecurity public class WebSecurity < @Bean public SecurityFilterChain configure(HttpSecurity http) throws Exception < http .authorizeHttpRequests() .requestMatchers("/swagger-ui/**") .permitAll(); return http.build(); >@Bean public WebSecurityCustomizer webSecurityCustomizer() < return (web) ->web.ignoring().requestMatchers("/v3/api-docs/**"); > >
Once you add the above-mentioned configuration to your WebSecurity Java class, it should help you get the /v3/api-docs and swagger-ui.html pages to start working. Do not forget to specify the path of the OpenAPI documentation and the Swagger UI in your application.properties file like this:
springdoc.api-docs.path=/v3/api-docs springdoc.swagger-ui.path=/swagger-ui.html
Best Practices for Documenting REST APIs with Swagger
- Use descriptive path and operation names – Path and operation names should accurately describe the resource and the action being performed. Use nouns for paths and verbs for operations.
- Provide detailed descriptions – Use the “description” field to provide a detailed explanation of the operation, including any input parameters and their types, possible response codes, and any other relevant details.
- Use common response codes – Use the HTTP response codes that are most commonly used for each operation. For example, use 200 for a successful operation, 400 for a bad request, 401 for unauthorized access, and so on.
- Use examples – Use examples to show how to use the API and what kind of response to expect. Examples can be included in the “examples” field of the Swagger specification.
- Validate input parameters – Use the “schema” field to validate input parameters. This ensures that the parameters meet the expected data type and format.
- Group related operations – Group related operations together under a single path. This makes the API easier to navigate and understand.
- Version your API – Version your API using the URL path. This ensures that changes to the API do not break existing clients.
- Update documentation regularly – Keep the documentation up-to-date with any changes to the API. This ensures that clients always have accurate and relevant information.
Conclusion
In conclusion, documenting your RESTful APIs with Swagger/OpenAPI is an essential aspect of software development that can help streamline the API design and development process. With this tutorial, you have learned how to configure Swagger/OpenAPI with Spring Security to enable Swagger URLs. If you’re unsure about how to add Swagger/OpenAPI to your Spring Boot application, this tutorial Document Spring REST API with OpenAPI 3(Swagger) can help you out. Additionally, there are some video courses available below that can teach you more about Swagger/OpenAPI and how to use it.
Frequently asked questions
- What is Swagger, and why do I need it in my Spring Boot project?
Swagger is a tool that helps developers design, document, and test APIs. It’s useful in Spring Boot projects to provide a user-friendly interface to interact with APIs. - Why am I getting a 404 error when I try to access the /v2/api-docs or swagger-ui.html pages?
A 404 error may occur if the requestMatchers() for Swagger URLs are not added correctly in the WebSecurity Java class. - How can I customize the appearance of my Swagger documentation?
You can customize the appearance of your Swagger documentation by modifying the configuration settings in the Docket bean of your Swagger configuration. - What are the benefits of using Swagger in my Spring Boot project?
Using Swagger in a Spring Boot project can save time by automating API documentation and testing, as well as providing a more intuitive interface for interacting with APIs.
Related Posts: