This tutorial is about setting up an OAuth 2.0 Authorization Server and securing microservices with token-based authentication and scope-based authorization using Spring Boot.
Step 1: Setting up the OAuth 2.0 Authorization Server
An OAuth 2.0 Authorization Server centralizes security, issuing access tokens for client applications to authenticate and authorize requests to microservices.
1.1 Adding Dependencies
To begin, include the spring-security-oauth2
and spring-boot-starter-security
dependencies in your pom.xml
. These provide essential libraries for configuring OAuth 2.0 capabilities and securing your Spring Boot application.
<dependency>
<groupId>org.springframework.security.oauth</groupId>
<artifactId>spring-security-oauth2</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
1.2 Configuring Application Properties
Next, configure the server to run on port 8081
by adding a few settings in the application.properties
file. Enabling the OAuth 2.0 Authorization Server is done via spring.security.oauth2.authorizationserver.enabled=true
.
server.port=8081
spring.security.oauth2.authorizationserver.enabled=true
This ensures the application starts on the specified port and sets up the authorization server.
1.3 Implementing the Authorization Server
Create a Java class annotated with @EnableAuthorizationServer
to designate it as an authorization server. Extend AuthorizationServerConfigurerAdapter
to configure clients and supported grant types. In this example, the client details are stored in memory using inMemory()
. The client is identified by "client-id"
, secured with "client-secret"
, and supports the "password"
and "refresh_token"
grant types. It is further scoped to "read"
and "write"
, defining the level of access the client has to resources.
import org.springframework.context.annotation.Configuration;
import org.springframework.security.oauth2.config.annotation.configurers.ClientDetailsServiceConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableAuthorizationServer;
import org.springframework.security.oauth2.config.annotation.web.configuration.AuthorizationServerConfigurerAdapter;
@EnableAuthorizationServer
@Configuration
public class AuthServerConfig extends AuthorizationServerConfigurerAdapter {
@Override
public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
clients.inMemory()
.withClient("client-id")
.secret("{noop}client-secret")
.authorizedGrantTypes("password", "refresh_token")
.scopes("read", "write");
}
}
Step 2: Securing a Microservice as a Resource Server
A Resource Server is a microservice that validates access tokens and enforces access control.
2.1 Adding Dependencies
Include the spring-security-oauth2
dependency in the pom.xml
of your microservice:
<dependency>
<groupId>org.springframework.security.oauth</groupId>
<artifactId>spring-security-oauth2</artifactId>
</dependency>
2.2 Configuring the Resource Server
To secure your microservice, annotate a configuration class with @EnableResourceServer
. Extend ResourceServerConfigurerAdapter
and override the configure(HttpSecurity http)
method. Here, we configure the microservice to permit all requests to /public/**
but require authentication for other endpoints.
import org.springframework.context.annotation.Configuration;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableResourceServer;
import org.springframework.security.oauth2.config.annotation.web.configuration.ResourceServerConfigurerAdapter;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
@EnableResourceServer
@Configuration
public class ResourceServerConfig extends ResourceServerConfigurerAdapter {
@Override
public void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.antMatchers("/public/**").permitAll()
.anyRequest().authenticated();
}
}
2.3 Validating Access Tokens
The resource server must validate the access tokens issued by the authorization server. Specify the token validation endpoint in the application.properties
file:
security.oauth2.resource.token-info-uri=http://localhost:8081/oauth/check_token
This points the resource server to the authorization server’s /check_token
endpoint for token verification.
Step 3: Enforcing Scope-Based Authorization
OAuth 2.0 allows fine-grained access control by using scopes. Scopes represent the level of access permitted to a resource.
Configuring Scope-Based Access
Spring Security annotations like @PreAuthorize
can enforce scope-based access control at the method level. For example, the following OrderController
class uses @PreAuthorize
to allow access to getOrders
only if the token contains the "read"
scope. Similarly, the createOrder
method requires the "write"
scope.
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*;
import java.util.List;
@RestController
@RequestMapping("/orders")
public class OrderController {
@PreAuthorize("hasAuthority('SCOPE_read')")
@GetMapping
public List<Order> getOrders() {
// Logic to fetch orders
return List.of(new Order(1, "Sample Order"));
}
@PreAuthorize("hasAuthority('SCOPE_write')")
@PostMapping
public Order createOrder(@RequestBody Order order) {
// Logic to create order
return order;
}
}
class Order {
private int id;
private String name;
// Constructor, getters, and setters
public Order(int id, String name) {
this.id = id;
this.name = name;
}
}
Ensure that tokens include the required scopes in their payload, as shown below:
{
"scope": ["read", "write"],
"exp": 1700000000,
"client_id": "client-id"
}
Step 4: Testing the Setup
4.1 Obtaining an Access Token
A client can obtain an access token by sending a POST
request to the authorization server’s /oauth/token
endpoint. Use the following curl
command:
curl -X POST \
-d "grant_type=password&username=user&password=pass" \
-u "client-id:client-secret" \
http://localhost:8081/oauth/token
The response includes the access_token
and other token details:
{
"access_token": "abc123",
"token_type": "Bearer",
"expires_in": 3600,
"refresh_token": "xyz789"
}
4.2 Accessing a Secured Endpoint
To access a secured microservice endpoint, include the access token in the Authorization
header:
curl -H "Authorization: Bearer abc123" http://localhost:8080/orders
Conclusion
This tutorial demonstrates how to set up an OAuth 2.0 Authorization Server, secure microservices as resource servers, and enforce scope-based access control. By leveraging token-based authentication, you can centralize security management, improve scalability, and achieve fine-grained access control in a microservices architecture.
Top comments (0)