OAuth2 is the industry-standard protocol for authorization, enabling secure access to resources without sharing credentials. In MCP (Model Context Protocol) implementations, OAuth2 provides a robust way to authenticate and authorize clients (such as AI agents) to access MCP servers and their tools.
This lesson demonstrates how to implement OAuth2 authentication for MCP servers using Spring Boot, a common pattern for enterprise and production deployments.
By the end of this lesson, you will:
- Understand how OAuth2 integrates with MCP servers
- Implement a Spring Authorization Server for token issuance
- Protect MCP endpoints with JWT-based authentication
- Configure client credentials flow for machine-to-machine communication
- Basic understanding of Java and Spring Boot
- Familiarity with MCP concepts from earlier modules
- Maven or Gradle installed
This project is a minimal Spring Boot application that acts as both:
- a Spring Authorization Server (issuing JWT access tokens via the
client_credentialsflow), and - a Resource Server (protecting its own
/helloendpoint).
It mirrors the setup shown in the Spring blog post (2 Apr 2025).
# build & run
./mvnw spring-boot:run
# obtain a token
curl -u mcp-client:secret -d grant_type=client_credentials \
http://localhost:8081/oauth2/token | jq -r .access_token > token.txt
# call the protected endpoint
curl -H "Authorization: Bearer $(cat token.txt)" http://localhost:8081/helloYou can test the OAuth2 security configuration with the following steps:
# This should return 401 Unauthorized, confirming OAuth2 security is active
curl -v http://localhost:8081/# Get and extract the full token response
curl -v -X POST http://localhost:8081/oauth2/token \
-H "Content-Type: application/x-www-form-urlencoded" \
-H "Authorization: Basic bWNwLWNsaWVudDpzZWNyZXQ=" \
-d "grant_type=client_credentials&scope=mcp.access"
# Or to extract just the token (requires jq)
curl -s -X POST http://localhost:8081/oauth2/token \
-H "Content-Type: application/x-www-form-urlencoded" \
-H "Authorization: Basic bWNwLWNsaWVudDpzZWNyZXQ=" \
-d "grant_type=client_credentials&scope=mcp.access" | jq -r .access_token > token.txtNote: The Basic Authentication header (bWNwLWNsaWVudDpzZWNyZXQ=) is the Base64 encoding of mcp-client:secret.
# Using the saved token
curl -H "Authorization: Bearer $(cat token.txt)" http://localhost:8081/hello
# Or directly with the token value
curl -H "Authorization: Bearer eyJra...token_value...xyz" http://localhost:8081/helloA successful response with "Hello from MCP OAuth2 Demo!" confirms that the OAuth2 configuration is working correctly.
docker build -t mcp-oauth2-demo .
docker run -p 8081:8081 mcp-oauth2-demoaz containerapp up -n mcp-oauth2 \
-g demo-rg -l westeurope \
--image <your-registry>/mcp-oauth2-demo:latest \
--ingress external --target-port 8081The ingress FQDN becomes your issuer (https://<fqdn>).
Azure provides a trusted TLS certificate automatically for *.azurecontainerapps.io.
Add this inbound policy to your API:
<inbound>
<validate-jwt header-name="Authorization">
<openid-config url="https://<fqdn>/.well-known/openid-configuration"/>
<audiences>
<audience>mcp-client</audience>
</audiences>
</validate-jwt>
<base/>
</inbound>APIM will fetch the JWKS and validate every request.