Skip to content

Commit 693333e

Browse files
committed
feat(auth): Implement OAuth 2.1 support with gateway and built-in modes
- Added environment configuration for authentication options in .env.example and config.ts. - Introduced GatewayTokenValidator and BuiltinTokenValidator for token validation. - Created OAuthProvider class to handle authorization code flow and token issuance. - Implemented OAuth routes: /authorize, /callback, /token, /introspect, and /revoke. - Added discovery endpoints for OAuth 2.1 compliance. - Updated README.md with detailed authentication setup instructions. - Modified index.ts to conditionally apply authentication middleware based on configuration. - Enhanced error handling and logging throughout the authentication process.
1 parent c21063c commit 693333e

File tree

11 files changed

+1015
-175
lines changed

11 files changed

+1015
-175
lines changed

.env.example

Lines changed: 56 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,64 @@ SERVER_NAME=mcp-typescript-template
55
SERVER_VERSION=1.0.0
66
LOG_LEVEL=info
77

8-
# OAuth Configuration (Optional)
9-
# Set ENABLE_AUTH=true to enable OAuth authentication
8+
# Authentication Configuration (Optional)
9+
# Set ENABLE_AUTH=true to enable authentication
1010
ENABLE_AUTH=false
1111

12-
# Required if ENABLE_AUTH=true
12+
# Authentication mode: "gateway" (recommended) or "builtin" (testing/demos)
13+
AUTH_MODE=gateway
14+
15+
# ============================================================================
16+
# Gateway Mode Configuration (Recommended for Production)
17+
# ============================================================================
18+
# Use when authentication is handled by a reverse proxy/gateway (Pomerium, etc.)
19+
# The MCP server acts as a resource server and only validates tokens
20+
21+
# OAuth issuer URL for token validation (required for gateway mode)
22+
# Examples:
23+
# Auth0: https://your-domain.auth0.com
24+
# Okta: https://your-domain.okta.com
25+
# Google: https://accounts.google.com
26+
OAUTH_ISSUER=https://your-domain.auth0.com
27+
28+
# Expected audience in JWT tokens (optional)
29+
# If set, tokens must have this audience claim
30+
OAUTH_AUDIENCE=your-api-identifier
31+
32+
# ============================================================================
33+
# Built-in Mode Configuration (Testing/Demos Only)
34+
# ============================================================================
35+
# Use when you want the MCP server to handle the OAuth flow directly
36+
# Not recommended for production - use gateway mode instead
37+
38+
# OAuth client credentials (required for built-in mode)
1339
OAUTH_CLIENT_ID=your-client-id
1440
OAUTH_CLIENT_SECRET=your-client-secret
15-
OAUTH_AUTH_ENDPOINT=https://auth.example.com/oauth/authorize
16-
OAUTH_TOKEN_ENDPOINT=https://auth.example.com/oauth/token
41+
42+
# OAuth provider endpoints (required for built-in mode)
43+
OAUTH_AUTH_ENDPOINT=https://your-domain.auth0.com/authorize
44+
OAUTH_TOKEN_ENDPOINT=https://your-domain.auth0.com/oauth/token
45+
46+
# OAuth configuration
1747
OAUTH_SCOPE=read
18-
OAUTH_REDIRECT_URI=http://localhost:3000/oauth/callback
48+
OAUTH_REDIRECT_URI=http://localhost:3000/callback
49+
50+
# ============================================================================
51+
# Example Configurations
52+
# ============================================================================
53+
54+
# Example: Auth0 Gateway Mode
55+
# ENABLE_AUTH=true
56+
# AUTH_MODE=gateway
57+
# OAUTH_ISSUER=https://your-domain.auth0.com
58+
# OAUTH_AUDIENCE=your-api-identifier
59+
60+
# Example: Auth0 Built-in Mode
61+
# ENABLE_AUTH=true
62+
# AUTH_MODE=builtin
63+
# OAUTH_CLIENT_ID=your-auth0-client-id
64+
# OAUTH_CLIENT_SECRET=your-auth0-client-secret
65+
# OAUTH_AUTH_ENDPOINT=https://your-domain.auth0.com/authorize
66+
# OAUTH_TOKEN_ENDPOINT=https://your-domain.auth0.com/oauth/token
67+
# OAUTH_SCOPE=read
68+
# OAUTH_REDIRECT_URI=http://localhost:3000/callback

README.md

Lines changed: 150 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -142,8 +142,19 @@ docker-compose up --build
142142
```
143143
mcp-typescript-template/
144144
├── src/
145+
│ ├── auth/ # Optional OAuth authentication module
146+
│ │ ├── index.ts # Auth initialization and middleware factory
147+
│ │ ├── middleware.ts # Authentication middleware
148+
│ │ ├── oauth-provider.ts # OAuth client implementation
149+
│ │ ├── routes.ts # OAuth routes (/authorize, /callback)
150+
│ │ └── token-validator.ts # Token validation (gateway/builtin)
151+
│ ├── lib/
152+
│ │ └── utils.ts # MCP utility functions
153+
│ ├── config.ts # Environment configuration with validation
154+
│ ├── logger.ts # Structured logging with Pino
145155
│ └── index.ts # Main MCP server entry point
146156
├── dist/ # Built output (generated)
157+
├── .env.example # Environment variables template
147158
├── .eslintrc.js # ESLint configuration
148159
├── .prettierrc # Prettier configuration
149160
├── tsconfig.json # TypeScript configuration
@@ -187,18 +198,150 @@ server.registerTool(
187198

188199
## Authentication & Authorization
189200

190-
### OAuth 2.1 Support
201+
This template provides **optional** OAuth 2.1 authentication with two deployment patterns:
191202

192-
This template supports **optional** OAuth 2.1 authentication with two approaches:
203+
### 🔧 Authentication Modes
193204

194-
1. **External OAuth (Recommended)** - Use Pomerium or similar OAuth proxy to handle authentication externally
195-
2. **Built-in OAuth Server** - Implement OAuth directly in the MCP server using the provided modular implementation
205+
#### Gateway Mode (Enterprise/Multi-Service)
206+
- **Resource Server Pattern**: MCP server only validates tokens from external OAuth providers
207+
- **External OAuth**: Authentication handled by reverse proxy/gateway (Pomerium, nginx, API Gateway)
208+
- **JWT + Introspection**: Supports both JWT validation and token introspection
209+
- **Stateless**: No OAuth routes, sessions, or cookies in MCP server
210+
- **Scalable**: Easy to horizontally scale the MCP server
211+
- **Best for**: Organizations with existing OAuth infrastructure
196212

197-
The OAuth implementation is designed to be easily added or removed without affecting core server functionality.
213+
#### Built-in Mode (Standalone/Simple Deployment)
214+
- **OAuth 2.1 Authorization Server**: MCP server IS the complete OAuth authorization server
215+
- **PKCE Support**: Full PKCE implementation as required by MCP specification
216+
- **MCP Client Compatible**: Works seamlessly with VS Code and other MCP clients
217+
- **Self-contained**: No external OAuth provider needed
218+
- **Discovery Endpoints**: Provides OAuth 2.1 discovery metadata for automatic client configuration
219+
- **Best for**: Solo developers, small teams, or simple deployments wanting OAuth security
198220

199-
### Enabling OAuth
221+
#### No Auth Mode (Default)
222+
- **Completely Optional**: Authentication can be disabled entirely
223+
- **Simple Setup**: Just set `ENABLE_AUTH=false` or omit auth configuration
224+
- **Open Access**: MCP server accepts all requests without authentication
200225

201-
To enable OAuth authentication, see the `src/auth/` directory for a modular OAuth implementation that can be toggled via environment variables.
226+
### 🚀 Quick Setup
227+
228+
#### 1. Gateway Mode (Enterprise)
229+
```bash
230+
# .env
231+
ENABLE_AUTH=true
232+
AUTH_MODE=gateway
233+
OAUTH_ISSUER=https://your-domain.auth0.com
234+
OAUTH_AUDIENCE=your-api-identifier # optional
235+
```
236+
237+
**Setup your gateway (e.g., Pomerium):**
238+
```yaml
239+
# pomerium-config.yaml
240+
routes:
241+
- from: https://mcp.yourdomain.com
242+
to: http://localhost:3000
243+
policies:
244+
- allow:
245+
and:
246+
- authenticated_user: true
247+
```
248+
249+
#### 2. Built-in Mode (Standalone)
250+
```bash
251+
# .env
252+
ENABLE_AUTH=true
253+
AUTH_MODE=builtin
254+
# No external OAuth configuration needed - server acts as OAuth provider
255+
```
256+
257+
**OAuth 2.1 Endpoints (automatically available):**
258+
- `GET /.well-known/oauth-authorization-server` - OAuth server metadata
259+
- `GET /.well-known/oauth-protected-resource` - Resource server metadata
260+
- `GET /authorize` - OAuth authorization endpoint (with PKCE)
261+
- `POST /token` - Token exchange endpoint
262+
- `POST /introspect` - Token introspection endpoint
263+
- `POST /revoke` - Token revocation endpoint
264+
265+
#### 3. No Auth Mode (Default)
266+
```bash
267+
# .env (or just omit ENABLE_AUTH)
268+
ENABLE_AUTH=false
269+
```
270+
Server accepts all requests without authentication.
271+
272+
### 🔐 Token Validation
273+
274+
Both modes validate tokens using the **resource server pattern**:
275+
276+
```bash
277+
# Make authenticated requests
278+
curl -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
279+
http://localhost:3000/mcp
280+
```
281+
282+
### 🏗️ Architecture
283+
284+
```
285+
┌─────── Gateway Mode (Enterprise) ───────┐ ┌────── Built-in Mode (Standalone) ───┐ ┌── No Auth (Default) ──┐
286+
│ │ │ │ │ │
287+
│ MCP Client → Gateway → MCP Server │ │ MCP Client → MCP Server │ │ MCP Client │
288+
│ ↓ │ │ ↓ │ │ ↓ │
289+
│ External OAuth (Auth0) │ │ Built-in OAuth Server │ │ MCP Server │
290+
│ │ │ │ │ (Open Access) │
291+
│ ✅ Enterprise ready │ │ ✅ Production ready │ │ ✅ Simple setup │
292+
│ ✅ Stateless & scalable │ │ ✅ OAuth 2.1 compliant │ │ ✅ No auth overhead │
293+
│ ✅ Security best practices │ │ ✅ PKCE + Discovery │ │ ✅ Perfect for dev │
294+
│ ✅ JWT + Token introspection │ │ ✅ Works with VS Code │ │ │
295+
└─────────────────────────────────────────┘ └─────────────────────────────────────┘ └───────────────────────┘
296+
```
297+
298+
### 🔧 Provider Examples
299+
300+
<details>
301+
<summary><strong>Auth0 Configuration</strong></summary>
302+
303+
**Gateway Mode:**
304+
```bash
305+
OAUTH_ISSUER=https://your-domain.auth0.com
306+
OAUTH_AUDIENCE=your-api-identifier
307+
```
308+
309+
**Built-in Mode:**
310+
```bash
311+
OAUTH_AUTH_ENDPOINT=https://your-domain.auth0.com/authorize
312+
OAUTH_TOKEN_ENDPOINT=https://your-domain.auth0.com/oauth/token
313+
OAUTH_CLIENT_ID=your-client-id
314+
OAUTH_CLIENT_SECRET=your-client-secret
315+
```
316+
</details>
317+
318+
<details>
319+
<summary><strong>Google OAuth Configuration</strong></summary>
320+
321+
**Gateway Mode:**
322+
```bash
323+
OAUTH_ISSUER=https://accounts.google.com
324+
OAUTH_AUDIENCE=your-client-id.apps.googleusercontent.com
325+
```
326+
327+
**Built-in Mode:**
328+
```bash
329+
OAUTH_AUTH_ENDPOINT=https://accounts.google.com/o/oauth2/v2/auth
330+
OAUTH_TOKEN_ENDPOINT=https://oauth2.googleapis.com/token
331+
OAUTH_CLIENT_ID=your-client-id.apps.googleusercontent.com
332+
OAUTH_CLIENT_SECRET=your-client-secret
333+
```
334+
</details>
335+
336+
### 🛠️ Customization
337+
338+
The auth implementation is modular and can be easily:
339+
- Disabled completely (set `ENABLE_AUTH=false`)
340+
- Removed entirely (delete `src/auth/` directory)
341+
- Extended with custom validation logic
342+
- Integrated with other OAuth providers
343+
344+
See `src/auth/` for implementation details.
202345

203346
## Why Express?
204347

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
"main": "dist/index.js",
77
"scripts": {
88
"build": "vite build",
9-
"dev": "node --watch src/index.ts",
9+
"dev": "node --env-file=.env --experimental-strip-types --watch src/index.ts",
1010
"start": "node dist/index.js",
1111
"test": "vitest",
1212
"test:ci": "vitest run --reporter=json --outputFile=test-results.json",

0 commit comments

Comments
 (0)