In the previous Part 1 & Part 2 tutorial series, we developed REST APIs, secured them with OAuth2 JWT authentication, and documented them using OpenAPI 3 spec. Now, we are gonna configure multiple HttpSecurity
instances in Spring Security to secure one API with basic authentication and all other APIs with OAuth2 JWT authentication.
Introduction
Sometimes we might need different authentication for different APIs. For instance, in our previous tutorial, we disabled basic auth and enabled only JWT auth. This is because, when the basic auth is enabled, the secured endpoints can then be accessed with either basic auth or JWT auth which is not what we want.
Since we have disabled the basic auth, In the /signin
API, we had to accept the user credentials in plain text format in the request body and perform the authentication manually with the help of AuthenticationManager
. After successful authentication, we had to set the authentication object in the Spring SecurityContextHolder
.
We can avoid this type of manual authentication if we configure basic auth for the token generation API alone and JWT auth for all other APIs.
What you’ll do?
In a nutshell, we are going to perform the following steps:
- Expose a POST API with mapping
/token
. On passing the username and password in the authorization header, it will generate a JSON Web Token (JWT). - Configure Spring Security to enable basic auth only for
/token
API.
What you’ll need?
- IntelliJ or any other IDE of your choice
- JDK 17
- MySQL Server 8
Developing Token API
Modifying Auth Controller
Let’s add a new /token
POST API in AuthController
that returns the access token when the user email/password
is passed in the Authorization header.
AuthController.java
@PostMapping("/token")
public ResponseEntity<?> getToken(Authentication authentication) {
LocalUser localUser = (LocalUser) authentication.getPrincipal();
String jwt = getToken(localUser);
return ResponseEntity.ok(new JwtAuthenticationResponse(jwt));
}
Configuring Spring Security
WebConfig.java
Let’s add one more HttpSecurity
instance for enabling basic authentication only for the new /token
API. Also, we will annotate the new method with @Order(1)
annotation to let Spring Security know that it has the highest precedence over others. Therefore, it will be executed first.
@Bean
@Order(1)
public SecurityFilterChain basicAuthSecurityFilterChain(HttpSecurity http) throws Exception {
// @formatter:off
http
.securityMatcher("/api/auth/token")
.authorizeHttpRequests(authorize -> authorize
.anyRequest().authenticated()
)
.csrf().disable()
.httpBasic(withDefaults());
// @formatter:on
return http.build();
}
Testing
Swagger UI Basic Auth
We need to provide the credentials in the basicAuth
and authorize it.
Accessing Token API with Basic Auth
Accessing Secured API with Basic Auth
If we try to execute a secured API other than /token
API with basic auth, we will get HTTP status 401 Unauthorized.
Accessing Secured API with JWT Auth
If we try to execute a secured API other than /token
API with JWT auth, we will get HTTP 200 response as expected.
Accessing Token API with JWT Auth
If we try to execute a token API with JWT auth, then it will ask for the credentials since JWT will be ignored for this request.
Source Code
https://github.com/JavaChinna/spring-boot-oauth2-jwt
Conclusion
That’s all folks. In this article, we have configured Spring Security to Secure different URLs with different authentication. In the next article, we will see how we can initialize the database with data from a CSV file on application startup.
Thank you for reading.