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
- Create an Auth0 account or log in to your existing account
- Create a new application
- Name:
Your MCP Server
- Application Type:
Regular Web Applications
- Name:
- Configure callback URLs:
- Add
https://your-mcp-server.trmx.ai/auth/callback
- Add
- Note your
Client ID
andClient Secret
Google OAuth Setup
- Go to the Google Cloud Console
- Create a new project or use an existing one
- Navigate to "APIs & Services" > "Credentials"
- 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
- Application type:
- Note your
Client ID
andClient 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
- Deploy your updated MCP server
- Navigate to
https://your-mcp-server.trmx.ai/auth/login
- Complete the OAuth flow with your provider
- 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.