Skip to main content

OAuth Authentication for MCP Servers

Learn how to secure your MCP server with OAuth 2.0 authentication.

Overview

This guide explains how to implement OAuth 2.0 authentication for your MCP server, allowing you to securely integrate with identity providers and restrict access to authorized users.

Prerequisites

Before you begin, you should have:

  • A deployed MCP server
  • Basic understanding of OAuth 2.0 concepts
  • Access to an OAuth provider (Auth0, Okta, Google, etc.)
  • TRMX CLI installed

Setting Up OAuth Provider

Auth0 Setup

  1. Create an Auth0 account or log in to your existing account
  2. Create a new application
    • Name: Your MCP Server
    • Application Type: Regular Web Applications
  3. Configure callback URLs:
    • Add https://your-mcp-server.trmx.ai/auth/callback
  4. Note your Client ID and Client Secret

Google OAuth Setup

  1. Go to the Google Cloud Console
  2. Create a new project or use an existing one
  3. Navigate to "APIs & Services" > "Credentials"
  4. Create an "OAuth client ID"
    • Application type: Web application
    • Name: Your MCP Server
    • Authorized redirect URIs: Add https://your-mcp-server.trmx.ai/auth/callback
  5. Note your Client ID and Client Secret

Configuring Your MCP Server

Step 1: Install Required Dependencies

If you're using the JavaScript/TypeScript template:

npm install passport passport-oauth2

For Python template:

pip install authlib flask-login

Step 2: Update Configuration

Create an auth.js file in your src/config directory:

// src/config/auth.js
export const authConfig = {
oauth: {
enabled: true,
provider: 'auth0', // or 'google', 'okta', etc.
clientId: process.env.OAUTH_CLIENT_ID,
clientSecret: process.env.OAUTH_CLIENT_SECRET,
callbackUrl: process.env.OAUTH_CALLBACK_URL || 'https://your-mcp-server.trmx.ai/auth/callback',
scope: 'openid profile email',
audience: process.env.OAUTH_AUDIENCE, // For Auth0
authorizationURL: process.env.OAUTH_AUTHORIZATION_URL,
tokenURL: process.env.OAUTH_TOKEN_URL,
userInfoURL: process.env.OAUTH_USER_INFO_URL,
},
session: {
secret: process.env.SESSION_SECRET || 'your-secure-session-secret',
cookie: {
maxAge: 24 * 60 * 60 * 1000, // 24 hours
secure: process.env.NODE_ENV === 'production',
},
},
};

Update your .env file with the necessary values:

OAUTH_CLIENT_ID=your-client-id
OAUTH_CLIENT_SECRET=your-client-secret
OAUTH_CALLBACK_URL=https://your-mcp-server.trmx.ai/auth/callback
OAUTH_AUTHORIZATION_URL=https://your-provider.com/authorize
OAUTH_TOKEN_URL=https://your-provider.com/oauth/token
OAUTH_USER_INFO_URL=https://your-provider.com/userinfo
SESSION_SECRET=your-secure-random-string

Step 3: Implement OAuth Middleware

Create an auth.js file in your src/middleware directory:

// src/middleware/auth.js
import passport from 'passport';
import { Strategy as OAuth2Strategy } from 'passport-oauth2';
import session from 'express-session';
import { authConfig } from '../config/auth';

export function configureAuth(app) {
// Configure session
app.use(session({
secret: authConfig.session.secret,
resave: false,
saveUninitialized: false,
cookie: authConfig.session.cookie,
}));

// Initialize Passport
app.use(passport.initialize());
app.use(passport.session());

// Configure OAuth2 strategy
passport.use(new OAuth2Strategy({
authorizationURL: authConfig.oauth.authorizationURL,
tokenURL: authConfig.oauth.tokenURL,
clientID: authConfig.oauth.clientId,
clientSecret: authConfig.oauth.clientSecret,
callbackURL: authConfig.oauth.callbackUrl,
scope: authConfig.oauth.scope,
}, async (accessToken, refreshToken, profile, done) => {
try {
// Fetch user info
const userInfoResponse = await fetch(authConfig.oauth.userInfoURL, {
headers: {
Authorization: `Bearer ${accessToken}`,
},
});

const userInfo = await userInfoResponse.json();

// You can store user info in a database here if needed

return done(null, {
id: userInfo.sub || userInfo.id,
email: userInfo.email,
name: userInfo.name,
accessToken,
});
} catch (error) {
return done(error);
}
}));

// Serialize user to session
passport.serializeUser((user, done) => {
done(null, user);
});

// Deserialize user from session
passport.deserializeUser((user, done) => {
done(null, user);
});

// Define auth routes
app.get('/auth/login', passport.authenticate('oauth2'));

app.get('/auth/callback',
passport.authenticate('oauth2', {
successRedirect: '/auth/success',
failureRedirect: '/auth/failure',
})
);

app.get('/auth/success', (req, res) => {
res.send('Authentication successful! You can close this window.');
});

app.get('/auth/failure', (req, res) => {
res.status(401).send('Authentication failed.');
});

app.get('/auth/logout', (req, res) => {
req.logout();
res.redirect('/');
});

// Middleware to protect routes
return (req, res, next) => {
if (authConfig.oauth.enabled && !req.isAuthenticated() && !req.path.startsWith('/auth/')) {
// Allow public routes if needed
if (['/status', '/health'].includes(req.path)) {
return next();
}

// For API requests, return 401
if (req.headers.accept === 'application/json' || req.path.startsWith('/api/')) {
return res.status(401).json({ error: 'Unauthorized' });
}

// Redirect to login for web requests
return res.redirect('/auth/login');
}

next();
};
}

Step 4: Use the Auth Middleware

Update your server's entry point (src/index.js):

import express from 'express';
import { MCPServer } from '@trmx/server';
import { configureAuth } from './middleware/auth';
import { config } from './config';
import { tools } from './tools';
import { resources } from './resources';

async function main() {
// Create Express app
const app = express();

// Configure and get auth middleware
const authMiddleware = configureAuth(app);

// Apply auth middleware
app.use(authMiddleware);

// Create MCP server with custom Express app
const server = new MCPServer({
app,
port: config.port,
tools,
resources,
});

// Start the server
await server.start();
console.log(`MCP server running on port ${config.port}`);
}

main().catch(console.error);

Client Integration

To connect to an OAuth-protected MCP server from client applications:

import { MCPClient } from '@trmx/client';

// Option 1: Use cookie-based authentication (browser only)
const client = new MCPClient({
serverUrl: 'https://your-mcp-server.trmx.ai',
credentials: 'include', // Includes cookies in requests
});

// Option 2: Pass access token explicitly
const client = new MCPClient({
serverUrl: 'https://your-mcp-server.trmx.ai',
auth: {
type: 'oauth',
token: 'user-access-token',
},
});

Testing OAuth Integration

  1. Deploy your updated MCP server
  2. Navigate to https://your-mcp-server.trmx.ai/auth/login
  3. Complete the OAuth flow with your provider
  4. You should be redirected to the success page

Security Considerations

  • Always use HTTPS in production
  • Keep client secrets secure
  • Implement proper session management
  • Consider token expiration and refresh strategies
  • Implement rate limiting to prevent abuse

Troubleshooting

Authentication flow fails at callback

Verify that your callback URL exactly matches the one configured in your OAuth provider.

Invalid client secret error

Double-check your client secret in the .env file. Make sure there are no spaces or quotation marks.

Session expires too quickly

Adjust the maxAge setting in your session configuration.

Next Steps