Sitemap

The Oracle Database MCP Toolkit — Enabling OAuth 2.0 Authentication in HTTP Streamable Mode

9 min readMay 19, 2026

--

Press enter or click to view image in full size
Oracle Database MCP Toolkit

by Juarez Junior

Key Takeaways

  • Running the Oracle Database MCP Toolkit over HTTPS without authentication is a valid starting point for development. However, a production deployment must restrict access via OAuth 2.0 if possible.
  • The toolkit’s HTTP Streamable mode integrates with any standards-compliant OAuth 2.0 authorization server through two JVM system properties: the issuer URI (used for token discovery) and the JWK Set URI (used for JWT signature verification), and no code changes are required.
  • The OAuth 2.0 flow for machine-to-machine scenarios — the one relevant here — is the Client Credentials grant. Clients obtain a Bearer token from the authorization server and attach it to every MCP request via the Authorization: Bearer <token> header.
  • Once authentication is active, any request that is missing or includes invalid authentication tokens will be rejected with HTTP 401, protecting your Oracle Database tools from unauthorized access.

Introduction

In my previous blog posts, I first introduced the Oracle Database MCP Toolkit and how to run it in local STDIO mode. Then, I explained how to expose the MCP server over a network using HTTPS in HTTP Streamable mode.

Next, I presented how to implement authentication using a static token scheme. This blog post will explore how to use OAuth 2.0 to enforce authentication, which is better aligned with enterprise, production-grade deployments.

We will add OAuth 2.0 authentication to the server we already have running, set up a local authorization server using the Spring Authorization Server, obtain a bearer token, and test it all to confirm if the server correctly rejects unauthenticated requests while accepting authenticated ones.

So without further ado, let’s get started!

Prerequisites

Steps to Enable OAuth 2.0 Authentication

Step 1: Understanding the Authentication Architecture

Before we write a single command, it helps to have a clear picture of what we are building. When authentication is enabled, the Oracle Database MCP Toolkit acts as an OAuth 2.0 Resource Server.

It does not issue tokens — it only validates them. Token issuance is the job of a separate Authorization Server (also called an Identity Provider or IdP).
The flow at runtime looks like this:

Press enter or click to view image in full size
OAuth 2.0-based authentication

The Oracle Database MCP Toolkit needs two additional configuration parameters to perform token validation:

  • -Dauth.issuerUri — The issuer URL of your OAuth 2.0 authorization server.
    The toolkit uses this to discover the server’s OpenID
    Connect metadata (token endpoint, JWK Set URI).
  • -Dauth.jwkSetUri — The URL where the authorization server publishes its public JSON Web Keys. The toolkit fetches these to verify incoming JWT signatures without making a call on every request.

Providing both properties activates OAuth 2.0-based authentication.

Step 2: Test your previous configuration

Before adding authentication, confirm that the HTTPS-only server, from a previous blog post — The Oracle Database MCP Toolkit — HTTP Streamable Mode - still starts cleanly. Open a Windows Command Prompt (CMD) session, navigate to your project directory, and launch the server.

cd C:\oracle-db-mcp-java-toolkit-configs
java -DconfigFile=C:\oracle-db-mcp-java-toolkit-configs\config.yaml -Dtransport=http -Dhttps.port=45450 -DcertificatePath=C:\oracle-db-mcp-java-toolkit-configs\mcp-keystore.p12 -DcertificatePassword=changeit -jar C:\java-projects\mcp\src\oracle-db-mcp-java-toolkit\target\oracle-db-mcp-toolkit-1.0.0.jar

Press Ctrl+C to stop it. You are ready to move on to enable OAuth 2.0-based authentication. So, let’s perform the additional configurations as required.

Step 3: Set Up a Local OAuth 2.0 Authorization Server

For development and testing, we will run a minimal OAuth 2.0 authorization server at localhost:9000, and we’ll use the Spring Authorization Server for this purpose.

You can get a Maven project with the complete code sample on GitHub.

Otherwise, using Spring Initializr, create a new project per your preferences, select the required dependencies, then download the project artifact as usual.

Press enter or click to view image in full size
New Spring project with the required dependencies

Extract the contents of your project, and use your preferred IDE to create a couple of Java classes - AuthServerApplication.java and AuthServerConfig.java.

AuthServerApplication.java

package com.oracle.database.jdbc.oauth2;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class AuthServerApplication {
public static void main(String[] args) {
SpringApplication.run(AuthServerApplication.class, args);
}
}

AuthServerConfig.java

package com.oracle.database.jdbc.oauth2;

import java.util.UUID;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.annotation.Order;
import org.springframework.security.config.Customizer;
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.configurers.oauth2.server.authorization.OAuth2AuthorizationServerConfigurer;
import org.springframework.security.oauth2.core.AuthorizationGrantType;
import org.springframework.security.oauth2.core.ClientAuthenticationMethod;
import org.springframework.security.oauth2.server.authorization.client.InMemoryRegisteredClientRepository;
import org.springframework.security.oauth2.server.authorization.client.RegisteredClient;
import org.springframework.security.oauth2.server.authorization.client.RegisteredClientRepository;
import org.springframework.security.oauth2.server.authorization.settings.AuthorizationServerSettings;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.util.matcher.RequestMatcher;

@Configuration
@EnableWebSecurity
public class AuthServerConfig {

@Bean
@Order(1)
public SecurityFilterChain authServerSecurityFilterChain(HttpSecurity http) throws Exception {
OAuth2AuthorizationServerConfigurer authorizationServerConfigurer = new OAuth2AuthorizationServerConfigurer();
RequestMatcher endpointsMatcher = authorizationServerConfigurer.getEndpointsMatcher();

http.securityMatcher(endpointsMatcher).with(authorizationServerConfigurer, Customizer.withDefaults())
.authorizeHttpRequests(auth -> auth.anyRequest().authenticated());

return http.build();
}

@Bean
@Order(2)
public SecurityFilterChain defaultSecurityFilterChain(HttpSecurity http) throws Exception {
http.authorizeHttpRequests(auth -> auth.anyRequest().authenticated()).formLogin(Customizer.withDefaults());
return http.build();
}

@Bean
public RegisteredClientRepository registeredClientRepository() {
RegisteredClient mcpClient = RegisteredClient.withId(UUID.randomUUID().toString()).clientId("mcp-client")
.clientSecret("{noop}mcp-secret") // {noop} means plain-text password for dev use
.clientAuthenticationMethod(ClientAuthenticationMethod.CLIENT_SECRET_BASIC)
.authorizationGrantType(AuthorizationGrantType.CLIENT_CREDENTIALS).scope("mcp.access").build();

return new InMemoryRegisteredClientRepository(mcpClient);
}

@Bean
public AuthorizationServerSettings authorizationServerSettings() {
return AuthorizationServerSettings.builder().issuer("http://localhost:9000").build();
}
}

Create the Application Properties file under src/main/resources as usual:

spring.application.name=oracle-db-mcp-toolkit-oauth2

server.port=9000
spring.security.oauth2.authorizationserver.issuer=http://localhost:9000

spring.security.user.name=user
spring.security.user.password=password

spring.security.oauth2.authorizationserver.client.mcp-client.registration.client-id=mcp-client
spring.security.oauth2.authorizationserver.client.mcp-client.registration.client-secret={noop}mcp-secret
spring.security.oauth2.authorizationserver.client.mcp-client.registration.client-name=MCP Client
spring.security.oauth2.authorizationserver.client.mcp-client.registration.client-authentication-methods=client_secret_basic
spring.security.oauth2.authorizationserver.client.mcp-client.registration.authorization-grant-types=client_credentials
spring.security.oauth2.authorizationserver.client.mcp-client.registration.scopes=mcp.access

Finally, use the Apache Maven tool to build it as usual.

cd C:\java-projects\oracle-db-mcp-toolkit-oauth2
mvn clean package -DskipTests
Press enter or click to view image in full size
mvn clean package

Start the local authorization service:

cd C:\java-projects\oracle-db-mcp-toolkit-oauth2\target

java -jar oracle-db-mcp-toolkit-oauth2-0.0.1-SNAPSHOT.jar
Press enter or click to view image in full size
Local authorization service started successfully

Use this URL to test the endpoint src/main/resources:

Press enter or click to view image in full size
http://localhost:9000/.well-known/oauth-authorization-server

Step 4: Verify if the local Authorization Server is up and running

curl http://localhost:9000/.well-known/openid-configuration

You should receive a JSON response containing the issuer, token_endpoint, jwks_uri, and other standard OpenID Connect metadata. Note the values forissuer and jwks_uri as we’ll use them in the next step. They should be like:

Step 5: Restart the Oracle Database MCP Toolkit with
OAuth 2.0 Authentication Enabled

cd C:\java-projects\mcp\src\oracle-db-mcp-java-toolkit 
java "-DconfigFile=C:\oracle-db-mcp-java-toolkit-configs\config.yaml" "-Dtransport=http" "-Dhttps.port=45450" "-DcertificatePath=C:\oracle-db-mcp-java-toolkit-configs\mcp-keystore.p12" "-DcertificatePassword=changeit" "-DenableAuthentication=true" "-DauthServer=http://localhost:9000" "-DintrospectionEndpoint=http://localhost:9000/oauth2/introspect" "-DclientId=mcp-client" "-DclientSecret=mcp-secret" "-DallowedHosts=http://localhost:6274" -jar "C:\java-projects\mcp\src\oracle-db-mcp-java-toolkit\target\oracle-db-mcp-toolkit-1.0.0.jar"

Provided that you used the right command as shown above, reflecting your values from the configured local IdP server (from your application.properties file), you will see messages as shown below:

Press enter or click to view image in full size
Oracle Database MCP Toolkit with
OAuth 2.0 authentication enabled started successfully

Step 6: Test it with an unauthenticated HTTP request

First, confirm the server is now enforcing authentication by sending an unauthenticated HTTP request (without a token):

curl -k -i -v "https://localhost:45450/mcp" -H "Content-Type: application/json" -H "Accept: application/json, text/event-stream" -d "{\"jsonrpc\":\"2.0\",\"id\":\"1\",\"method\":\"initialize\",\"params\":{\"protocolVersion\":\"2024-11-05\",\"capabilities\":{},\"clientInfo\":{\"name\":\"curl-test-client\",\"version\":\"1.0\"}}}"

With OAuth 2.0 authentication working as expected, you should now receive:

Press enter or click to view image in full size
Unauthenticated HTTP request — the HTTP response status code is 401 Unauthorized

This confirms the toolkit is rejecting unauthenticated callers.

Step 7: Test it with an authenticated HTTP request (bearer token)

Now that authentication is enabled, every request to the MCP server must include a valid Bearer token. Obtain one from the authorization server using the Client Credentials grant. Open a new Windows CMD session and run the following curl command:

curl -s -X POST http://localhost:9000/oauth2/token -H "Content-Type: application/x-www-form-urlencoded" -u "mcp-client:mcp-secret" -d "grant_type=client_credentials&scope=mcp.access"

A successful response looks like this:

Press enter or click to view image in full size
Bearer Token from the Authorization
Server

Copy the value of access_token. Then, use it to configure an environment variable:

set "ACCESS_TOKEN=YOUR_ACCESS_TOKEN"

Note that Bearer tokens are short-lived (typically 5 minutes for the Spring Authorization Server defaults). If your token expires during testing, re-run this command to obtain a fresh one.

Now repeat the request, this time including the Bearer token you configured above.

curl -k -i -v "https://localhost:45450/mcp" -H "Content-Type: application/json" -H "Accept: application/json, text/event-stream" -H "Authorization: Bearer %ACCESS_TOKEN%" --data-raw "{\"jsonrpc\":\"2.0\",\"id\":\"1\",\"method\":\"initialize\",\"params\":{\"protocolVersion\":\"2024-11-05\",\"capabilities\":{},\"clientInfo\":{\"name\":\"mcp-client\",\"version\":\"1.0\"}}}"

A successful response returns HTTP 200, but is now gated by OAuth 2.0 authentication.

Press enter or click to view image in full size
HTTP request with bearer token — the HTTP response status code is now 200 OK

Your Oracle Database MCP Toolkit is now running over HTTPS with OAuth 2.0 authentication enforced. Only callers with a valid Bearer token issued by your trusted authorization server can reach the database tools.

Wrapping it up

That’s it! An OAuth 2.0-based authentication approach scales cleanly from development to production.

We used Spring for learning purposes on this blog. However, concerning a production deployment, replace the local Spring Authorization Server with your preferred identity provider, such as OCI Identity and Access Management.

I hope you found this blog post useful. Thanks for reading!

Frequently Asked Questions (FAQs)

What is the difference between TLS and OAuth 2.0 authentication in
this context?

TLS (configured via the PKCS12 keystore in a previous blog post) encrypts the communication channel. It protects data in transit against eavesdropping and tampering, but it says nothing about who is allowed to call the server. OAuth 2.0 authentication controls access — it ensures that only clients presenting a valid token from a trusted authorization server can invoke MCP tools. Both layers are necessary for a secure deployment.

Can I use OCI IAM as the authorization server instead
of the local Spring Authorization Server?

Yes, and that is the recommended approach for any shared or production environment. The token acquisition step changes to call the OCI AIM token endpoint with the client ID and secret registered in that identity domain.

How do I customize what the toolkit can do without changing code?

You define data sources and tools in a YAML config file. The server reads this on startup, registers built-in tools, and also exposes any custom SQL-backed tools you define in that configuration.

What happens if the Bearer token expires mid-session?

The toolkit validates the token on every incoming request. Once the token’s exp claim is in the past, the server returns HTTP 401. The MCP client must then obtain a fresh token from the authorization server and retry the request. For long-running sessions, implement a token-refresh loop in your client before the token expires.

--

--

Juarez Junior
Juarez Junior

Written by Juarez Junior

Senior Principal Developer Evangelist @ Oracle ☕️🐍🥑 https://linktr.ee/juarezjunior