nitrostack 1.0.74 → 1.0.75

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (52) hide show
  1. package/dist/auth/__tests__/pkce.test.js +53 -4
  2. package/dist/auth/__tests__/pkce.test.js.map +1 -1
  3. package/dist/auth/__tests__/simple-jwt.test.js +153 -2
  4. package/dist/auth/__tests__/simple-jwt.test.js.map +1 -1
  5. package/dist/cli/commands/install.d.ts +10 -0
  6. package/dist/cli/commands/install.d.ts.map +1 -0
  7. package/dist/cli/commands/install.js +79 -0
  8. package/dist/cli/commands/install.js.map +1 -0
  9. package/dist/cli/index.d.ts.map +1 -1
  10. package/dist/cli/index.js +8 -0
  11. package/dist/cli/index.js.map +1 -1
  12. package/dist/core/__tests__/errors.test.d.ts +2 -0
  13. package/dist/core/__tests__/errors.test.d.ts.map +1 -0
  14. package/dist/core/__tests__/errors.test.js +109 -0
  15. package/dist/core/__tests__/errors.test.js.map +1 -0
  16. package/dist/core/__tests__/logger.test.d.ts +2 -0
  17. package/dist/core/__tests__/logger.test.d.ts.map +1 -0
  18. package/dist/core/__tests__/logger.test.js +83 -0
  19. package/dist/core/__tests__/logger.test.js.map +1 -0
  20. package/dist/core/__tests__/prompt.test.d.ts +2 -0
  21. package/dist/core/__tests__/prompt.test.d.ts.map +1 -0
  22. package/dist/core/__tests__/prompt.test.js +126 -0
  23. package/dist/core/__tests__/prompt.test.js.map +1 -0
  24. package/dist/core/__tests__/resource.test.d.ts +2 -0
  25. package/dist/core/__tests__/resource.test.d.ts.map +1 -0
  26. package/dist/core/__tests__/resource.test.js +173 -0
  27. package/dist/core/__tests__/resource.test.js.map +1 -0
  28. package/dist/core/pipes/__tests__/pipes.test.js +113 -1
  29. package/dist/core/pipes/__tests__/pipes.test.js.map +1 -1
  30. package/dist/widgets/hooks/__tests__/hooks.test.d.ts +2 -0
  31. package/dist/widgets/hooks/__tests__/hooks.test.d.ts.map +1 -0
  32. package/dist/widgets/hooks/__tests__/hooks.test.js +129 -0
  33. package/dist/widgets/hooks/__tests__/hooks.test.js.map +1 -0
  34. package/dist/widgets/hooks/__tests__/use-widget-state.test.d.ts +2 -0
  35. package/dist/widgets/hooks/__tests__/use-widget-state.test.d.ts.map +1 -0
  36. package/dist/widgets/hooks/__tests__/use-widget-state.test.js +66 -0
  37. package/dist/widgets/hooks/__tests__/use-widget-state.test.js.map +1 -0
  38. package/dist/widgets/runtime/__tests__/widget-polyfill.test.d.ts +2 -0
  39. package/dist/widgets/runtime/__tests__/widget-polyfill.test.d.ts.map +1 -0
  40. package/dist/widgets/runtime/__tests__/widget-polyfill.test.js +66 -0
  41. package/dist/widgets/runtime/__tests__/widget-polyfill.test.js.map +1 -0
  42. package/package.json +6 -2
  43. package/src/studio/app/chat/page.tsx +21 -0
  44. package/src/studio/lib/llm-service.ts +77 -10
  45. package/templates/typescript-oauth/OAUTH_SETUP.md +592 -0
  46. package/templates/typescript-oauth/README.md +186 -235
  47. package/templates/typescript-oauth/package.json +5 -3
  48. package/templates/typescript-pizzaz/README.md +78 -57
  49. package/templates/typescript-pizzaz/package.json +32 -30
  50. package/templates/typescript-starter/README.md +22 -14
  51. package/templates/typescript-starter/package.json +4 -1
  52. package/templates/typescript-starter/package-lock.json +0 -4112
@@ -0,0 +1,592 @@
1
+ # Complete OAuth 2.1 Setup Guide for NitroStack
2
+
3
+ This guide shows you **exactly** how to set up OAuth 2.1 authentication from scratch with **zero issues**.
4
+
5
+ ## 🎯 What You'll Learn
6
+
7
+ - ✅ How to configure Auth0 correctly (avoiding common pitfalls)
8
+ - ✅ How to set up your MCP server environment
9
+ - ✅ How to test the complete OAuth flow in Studio
10
+ - ✅ How to troubleshoot common issues
11
+
12
+ ---
13
+
14
+ ## 🚀 Quick Start with Auth0 (10 Minutes)
15
+
16
+ ### Why Auth0?
17
+ - ✅ **Free tier** (7,000 active users, no credit card)
18
+ - ✅ **Fastest setup** (10 minutes)
19
+ - ✅ **Best for testing** and learning
20
+ - ✅ **Production-ready** when you need it
21
+
22
+ ---
23
+
24
+ ## Step 1: Create Auth0 Account
25
+
26
+ 1. Go to **[auth0.com/signup](https://auth0.com/signup)**
27
+ 2. Sign up for free (choose "Personal" plan)
28
+ 3. Complete email verification
29
+
30
+ ---
31
+
32
+ ## Step 2: Create Auth0 API (Protected Resource)
33
+
34
+ **⚠️ DO THIS FIRST!** The API represents your MCP server as a protected resource.
35
+
36
+ 1. Go to **Applications** → **APIs** in Auth0 Dashboard
37
+ 2. Click **"Create API"**
38
+ 3. **Settings:**
39
+ ```
40
+ Name: MCP Server API
41
+ Identifier: https://mcplocal
42
+ Signing Algorithm: RS256
43
+ ```
44
+
45
+ **⚠️ CRITICAL NOTES:**
46
+ - The **Identifier** can be any unique URI (doesn't need to be a real URL)
47
+ - For development, use `https://mcplocal` (simple and clear)
48
+ - For production, use your actual domain like `https://api.yourapp.com`
49
+ - This **MUST** match your `RESOURCE_URI` in `.env` **EXACTLY**
50
+ - **JWT Profile**: Select **RFC 9068** (OAuth 2.0 Access Token JWT Profile)
51
+ - **RBAC**: You can leave this **disabled** for basic OAuth (only needed for role-based permissions)
52
+
53
+ 4. Click **"Create"**
54
+
55
+ 5. Go to **Permissions** tab
56
+ 6. Add these scopes:
57
+ ```
58
+ Scope Description
59
+ ----- -----------
60
+ read Read access to resources
61
+ write Write/modify resources
62
+ admin Administrative operations
63
+ ```
64
+
65
+ 7. Click **"Add"** for each scope
66
+ 8. **Save Changes**
67
+
68
+ ---
69
+
70
+ ## Step 3: Create Auth0 Application (OAuth Client)
71
+
72
+ **⚠️ Application Type Matters!** This is where many users get stuck.
73
+
74
+ 1. Go to **Applications** → **Applications**
75
+ 2. Click **"Create Application"**
76
+ 3. **Settings:**
77
+ ```
78
+ Name: MCP Server OAuth
79
+ Application Type: Regular Web Application ← CRITICAL!
80
+ ```
81
+
82
+ **⚠️ WHY "Regular Web Application"?**
83
+ - ❌ **NOT** "Single Page Application" (SPA) - Won't show in API authorization
84
+ - ❌ **NOT** "Machine to Machine" - Different auth flow, not compatible with OpenAI Studio
85
+ - ✅ **YES** "Regular Web Application" - Supports confidential clients with client secret
86
+
87
+ 4. Click **"Create"**
88
+
89
+ 5. Go to **Settings** tab and configure:
90
+
91
+ **Allowed Callback URLs** (supports both dev and prod):
92
+ ```
93
+ http://localhost:3005/auth/callback,http://localhost:3000/auth/callback
94
+ ```
95
+
96
+ **Why both ports?**
97
+ - `3005`: Dev mode (DiscoveryHttpServer handles OAuth callbacks)
98
+ - `3000`: Prod mode (HttpServerTransport handles OAuth callbacks)
99
+
100
+ **Allowed Logout URLs**:
101
+ ```
102
+ http://localhost:3005,http://localhost:3000
103
+ ```
104
+
105
+ **Allowed Web Origins**:
106
+ ```
107
+ http://localhost:3005,http://localhost:3000
108
+ ```
109
+
110
+ 6. Scroll down to **Advanced Settings**
111
+ 7. Go to **Grant Types** tab:
112
+ ```
113
+ ✅ Authorization Code
114
+ ✅ Refresh Token
115
+ ❌ Implicit (disable - deprecated in OAuth 2.1)
116
+ ❌ Client Credentials (not needed for this use case)
117
+ ```
118
+
119
+ 8. Go to **OAuth** tab:
120
+ ```
121
+ ✅ OIDC Conformant: ON (enabled)
122
+ JsonWebToken Signature Algorithm: RS256
123
+ ```
124
+
125
+ 9. Go to **ID Token** tab:
126
+ ```
127
+ ❌ ID Token Encryption: NONE/Disabled
128
+ ```
129
+
130
+ **⚠️ CRITICAL:** If encryption is enabled, you'll receive JWE (encrypted) tokens instead of JWT tokens, which will fail validation!
131
+
132
+ 10. **Save Changes**
133
+
134
+ 11. **Copy these values** (you'll need them later):
135
+ - **Domain** (e.g., `dev-abc123.us.auth0.com`)
136
+ - **Client ID** (e.g., `aBc123XyZ...`)
137
+ - **Client Secret** (click "Show" to reveal it)
138
+
139
+ ---
140
+
141
+ ## Step 4: Link Application to API
142
+
143
+ **⚠️ REQUIRED STEP!** Many users miss this.
144
+
145
+ 1. Go back to **Applications** → **APIs**
146
+ 2. Click on your **"MCP Server API"** (created in Step 2)
147
+ 3. Click the **"Machine to Machine Applications"** tab
148
+
149
+ **Note:** Despite the confusing name, this tab shows which applications can access your API
150
+
151
+ 4. Find your **"MCP Server OAuth"** application in the list
152
+ 5. **Toggle the switch to "Authorized"** (should turn green)
153
+ 6. Click the **dropdown arrow** to expand permissions
154
+ 7. **Select all scopes** you want to grant (`read`, `write`, `admin`)
155
+ 8. Click **"Update"**
156
+
157
+ **✅ Verification:** Your application should now show as "Authorized" with selected scopes
158
+
159
+ ---
160
+
161
+ ## Step 5: Configure Your MCP Server
162
+
163
+ ### Copy and Edit `.env` File
164
+
165
+ ```bash
166
+ cp .env.example .env
167
+ ```
168
+
169
+ Edit `.env` with your Auth0 settings:
170
+
171
+ ```bash
172
+ # =============================================================================
173
+ # REQUIRED: Server Configuration
174
+ # =============================================================================
175
+
176
+ # ⚠️ MUST match Auth0 API Identifier from Step 2 EXACTLY
177
+ RESOURCE_URI=https://mcplocal
178
+
179
+ # Your Auth0 domain from Step 3 (with https://)
180
+ AUTH_SERVER_URL=https://dev-abc123.us.auth0.com
181
+
182
+ # =============================================================================
183
+ # OPTIONAL: Token Configuration
184
+ # =============================================================================
185
+
186
+ # Must match RESOURCE_URI
187
+ TOKEN_AUDIENCE=https://mcplocal
188
+
189
+ # Auth0 domain with trailing slash!
190
+ TOKEN_ISSUER=https://dev-abc123.us.auth0.com/
191
+ ```
192
+
193
+ **⚠️ Important:**
194
+ - Replace `dev-abc123` with YOUR actual Auth0 domain
195
+ - `RESOURCE_URI` must match Auth0 API Identifier **EXACTLY** (case-sensitive!)
196
+ - `TOKEN_ISSUER` must have trailing slash `/`
197
+
198
+ ---
199
+
200
+ ## Step 6: Start Your MCP Server
201
+
202
+ ```bash
203
+ npm install
204
+ npm run dev
205
+ ```
206
+
207
+ **Expected Output:**
208
+ ```
209
+ 🚀 OAuth discovery server running at http://localhost:3005
210
+ NITRO_LOG::{"level":"info","message":"OAuthModule: Running in STDIO mode, starting DiscoveryHttpServer on port 3005"}
211
+ NITRO_LOG::{"level":"info","message":"🔐 OAuth 2.1 enabled"}
212
+ NITRO_LOG::{"level":"info","message":" Resource URI: https://mcplocal"}
213
+ NITRO_LOG::{"level":"info","message":" Auth Servers: https://dev-abc123.us.auth0.com"}
214
+ 🚀 Server started successfully (DUAL: STDIO + HTTP)
215
+ 📡 MCP Protocol: STDIO (for Studio/Claude)
216
+ 🌐 OAuth Metadata: HTTP (port 3005)
217
+ ```
218
+
219
+ **✅ Success!** Your server is running in DUAL mode:
220
+ - **STDIO**: For MCP protocol communication (tools, chat)
221
+ - **HTTP (3005)**: For OAuth metadata and discovery in dev mode
222
+
223
+ ---
224
+
225
+ ## Step 7: Test OAuth Flow in NitroStack Studio
226
+
227
+ ### Open Studio
228
+
229
+ Navigate to **http://localhost:3000** in your browser
230
+
231
+ ### 7.1 Discover OAuth Server
232
+
233
+ 1. Go to **Auth** → **OAuth 2.1** tab
234
+ 2. In the **"1. Discover Server Auth"** section:
235
+ ```
236
+ Server URL: http://localhost:3005
237
+ ```
238
+ **Note:** Port 3005 in dev mode (discovery server)
239
+
240
+ 3. Click **"Discover Auth Config"**
241
+
242
+ **Expected Result:**
243
+ ```
244
+ ✅ Discovery successful!
245
+
246
+ Resource: https://mcplocal
247
+ Authorization Servers: https://dev-abc123.us.auth0.com
248
+ Scopes: read, write, admin
249
+ ```
250
+
251
+ **✅ In Console, you should see:**
252
+ ```
253
+ 🎯 Setting audience parameter: https://mcplocal
254
+ ```
255
+
256
+ **⚠️ This is CRITICAL!** The audience parameter tells Auth0 to issue a proper JWT access token for your API.
257
+
258
+ ### 7.2 Enter Client Credentials
259
+
260
+ 1. Scroll to **"2a. Use Existing Client"** section
261
+ 2. Enter your credentials from Step 3:
262
+ ```
263
+ Client ID: [Your Auth0 Client ID]
264
+ Client Secret: [Your Auth0 Client Secret]
265
+ ```
266
+ 3. Click **"Save Client Credentials"**
267
+
268
+ **Expected Result:**
269
+ ```
270
+ ✅ Client credentials saved!
271
+ ```
272
+
273
+ ### 7.3 Start OAuth Flow
274
+
275
+ 1. Scroll to **"3. Start OAuth Flow"** section
276
+ 2. Click **"Start Authorization Flow"**
277
+
278
+ **What Happens:**
279
+ 1. ✅ You're redirected to Auth0 login page
280
+ 2. ✅ Login with your Auth0 account (or test user)
281
+ 3. ✅ You're asked to authorize the application
282
+ 4. ✅ After authorization, you're redirected back to Studio
283
+ 5. ✅ Studio exchanges the code for a JWT token
284
+ 6. ✅ Token is automatically saved!
285
+
286
+ **Expected Result:**
287
+ ```
288
+ ✅ Authorization successful! Redirecting...
289
+ ```
290
+
291
+ ### 7.4 Verify Token Type (Debug Check)
292
+
293
+ **In your MCP server logs, you should see:**
294
+ ```
295
+ [DEBUG] Token header: {"alg":"RS256","typ":"at+jwt","kid":"..."}
296
+ [DEBUG] Decoded payload: SUCCESS
297
+ [DEBUG] Payload audience: https://mcplocal
298
+ [DEBUG] Expected audience: https://mcplocal
299
+ ```
300
+
301
+ **✅ Perfect!** You're getting **RS256 JWT tokens** (not encrypted JWE tokens)
302
+
303
+ **❌ If you see this instead:**
304
+ ```
305
+ [DEBUG] Token header: {"alg":"dir","enc":"A256GCM",...}
306
+ [ERROR] Received JWE (encrypted) token instead of JWT!
307
+ ```
308
+
309
+ **Fix:** Go back to Step 3 and disable ID Token Encryption in Application settings
310
+
311
+ ### 7.5 Test Protected Tools
312
+
313
+ 1. Go to **Tools** tab
314
+ 2. Try a protected tool (e.g., `get_user_profile`, `list_resources`)
315
+ 3. Click **"Execute"**
316
+
317
+ **Expected Result:**
318
+ ```json
319
+ {
320
+ "success": true,
321
+ "user": {
322
+ "sub": "auth0|xxx",
323
+ "scopes": ["read", "write", "admin"],
324
+ "clientId": "..."
325
+ }
326
+ }
327
+ ```
328
+
329
+ **🎉 Congratulations!** Your OAuth 2.1 server is fully working!
330
+
331
+ ---
332
+
333
+ ## 🔍 How It Works
334
+
335
+ ### Dual Transport Architecture
336
+
337
+ NitroStack automatically runs **two transports simultaneously** when OAuth is enabled:
338
+
339
+ ```
340
+ Development Mode:
341
+ ┌─────────────────────────────────────┐
342
+ │ Your OAuth 2.1 MCP Server │
343
+ ├─────────────────────────────────────┤
344
+ │ │
345
+ │ 📡 STDIO Transport │
346
+ │ ├─ MCP Protocol (tools, chat) │
347
+ │ ├─ Connected to Studio/Claude │
348
+ │ └─ stdin/stdout communication │
349
+ │ │
350
+ │ 🌐 DiscoveryHttpServer (Port 3005) │
351
+ │ ├─ OAuth Metadata Endpoints │
352
+ │ ├─ /.well-known/oauth-protected- │
353
+ │ │ resource │
354
+ │ ├─ /auth/callback │
355
+ │ └─ Discovery & Token Validation │
356
+ │ │
357
+ └─────────────────────────────────────┘
358
+
359
+ Production Mode:
360
+ ┌─────────────────────────────────────┐
361
+ │ Your OAuth 2.1 MCP Server │
362
+ ├─────────────────────────────────────┤
363
+ │ │
364
+ │ 🌐 HttpServerTransport (Port 3000) │
365
+ │ ├─ MCP Protocol (SSE) │
366
+ │ ├─ OAuth Metadata Endpoints │
367
+ │ ├─ /.well-known/oauth-protected- │
368
+ │ │ resource │
369
+ │ ├─ /auth/callback │
370
+ │ └─ All-in-one HTTP server │
371
+ │ │
372
+ └─────────────────────────────────────┘
373
+ ```
374
+
375
+ ### OAuth Flow Sequence
376
+
377
+ ```
378
+ 1. Studio → Discover → Your MCP Server (HTTP :3005 in dev)
379
+
380
+ Returns OAuth metadata
381
+ (includes resource URI for audience)
382
+
383
+ 2. Studio → Authorize → Auth0 Login Page
384
+ (with audience param) ↓
385
+ User logs in
386
+
387
+ 3. Auth0 → Redirect → Studio Callback (/auth/callback)
388
+
389
+ 4. Studio → Exchange → Auth0 Token Endpoint
390
+ (code for token) ↓
391
+ Receives RS256 JWT access token
392
+ (NOT encrypted JWE token!)
393
+
394
+ 5. Studio → Execute Tool → Your MCP Server (STDIO)
395
+ (with JWT) ↓
396
+ Tool validates token & executes
397
+ ```
398
+
399
+ **Key Point:** Studio now automatically includes the `audience` parameter when starting the OAuth flow, which ensures Auth0 issues proper JWT tokens.
400
+
401
+ ---
402
+
403
+ ## 🚨 Troubleshooting
404
+
405
+ ### Issue: "Received JWE (encrypted) token instead of JWT!"
406
+
407
+ **Symptoms:**
408
+ ```
409
+ [DEBUG] Token header: {"alg":"dir","enc":"A256GCM",...}
410
+ [ERROR] Received JWE (encrypted) token instead of JWT!
411
+ ```
412
+
413
+ **Root Cause:** One of these:
414
+ 1. ID Token Encryption is enabled in Application settings
415
+ 2. Application type is wrong (SPA instead of Regular Web App)
416
+ 3. Audience parameter not being sent (fixed in latest Studio version)
417
+
418
+ **Fix:**
419
+ 1. Go to Applications → Your Application → Settings → Advanced Settings
420
+ 2. Click **"ID Token"** tab
421
+ 3. Ensure **"ID Token Encryption"** is **Disabled** or **None**
422
+ 4. Click **"OAuth"** tab
423
+ 5. Ensure **"OIDC Conformant"** is **ON**
424
+ 6. **Save Changes**
425
+ 7. Clear Studio's saved token and re-authorize
426
+
427
+ ### Issue: "Application doesn't show in API's Machine to Machine tab"
428
+
429
+ **Root Cause:** Application type is "Single Page Application" instead of "Regular Web Application"
430
+
431
+ **Fix:**
432
+ 1. Delete the current application
433
+ 2. Create a new one with type **"Regular Web Application"**
434
+ 3. Follow Step 3 again
435
+
436
+ ### Issue: "Token audience mismatch"
437
+
438
+ **Symptoms:**
439
+ ```
440
+ OAuth token validation failed: Token audience mismatch.
441
+ Expected: https://mcplocal, Got: https://dev-abc123.us.auth0.com/api/v2/
442
+ ```
443
+
444
+ **Root Cause:** `RESOURCE_URI` in `.env` doesn't match Auth0 API Identifier
445
+
446
+ **Fix:**
447
+ 1. In Auth0: Applications → APIs → Your API → Settings → **Identifier**
448
+ 2. Copy the exact identifier (e.g., `https://mcplocal`)
449
+ 3. In `.env`: Set `RESOURCE_URI` to match **EXACTLY** (case-sensitive)
450
+ 4. In `.env`: Set `TOKEN_AUDIENCE` to match **EXACTLY**
451
+ 5. Restart your MCP server
452
+
453
+ ### Issue: "Discovery failed" or "Cannot read properties of undefined"
454
+
455
+ **Root Cause:** Server URL is incorrect or server isn't running
456
+
457
+ **Fix:**
458
+ 1. Verify server is running: Check for "🚀 OAuth discovery server running" in logs
459
+ 2. Check URL is exactly: `http://localhost:3005` (dev mode)
460
+ 3. Test metadata endpoint:
461
+ ```bash
462
+ curl http://localhost:3005/.well-known/oauth-protected-resource
463
+ ```
464
+ Should return:
465
+ ```json
466
+ {
467
+ "resource": "https://mcplocal",
468
+ "authorization_servers": ["https://dev-abc123.us.auth0.com"],
469
+ "scopes_supported": ["read", "write", "admin"]
470
+ }
471
+ ```
472
+
473
+ ### Issue: "Invalid token issuer"
474
+
475
+ **Root Cause:** `TOKEN_ISSUER` doesn't match token's `iss` claim
476
+
477
+ **Fix:**
478
+ 1. Check Auth0 domain in dashboard
479
+ 2. Add `https://` prefix
480
+ 3. Add trailing `/`
481
+ 4. Example: `https://dev-abc123.us.auth0.com/` (note the slash!)
482
+
483
+ ### Issue: "Insufficient scope"
484
+
485
+ **Root Cause:** Token doesn't have required scopes for the tool
486
+
487
+ **Fix:**
488
+ 1. In Auth0: Applications → APIs → Your API → Machine to Machine Applications
489
+ 2. Find your application and ensure it's **Authorized**
490
+ 3. Click the dropdown and **select all required scopes**
491
+ 4. Click **"Update"**
492
+ 5. In Studio: Clear the saved token and re-authorize
493
+ 6. New token will have updated scopes
494
+
495
+ ### Issue: "Port 3005 already in use"
496
+
497
+ **Root Cause:** Previous server instance still running
498
+
499
+ **Fix:**
500
+ ```bash
501
+ # Kill process on port 3005
502
+ lsof -ti :3005 | xargs kill -9
503
+
504
+ # Restart server
505
+ npm run dev
506
+ ```
507
+
508
+ ---
509
+
510
+ ## 🌐 Other OAuth Providers
511
+
512
+ ### Okta
513
+
514
+ ```bash
515
+ RESOURCE_URI=https://mcp.yourapp.com
516
+ AUTH_SERVER_URL=https://your-domain.okta.com/oauth2/default
517
+ TOKEN_AUDIENCE=api://mcp.yourapp.com
518
+ TOKEN_ISSUER=https://your-domain.okta.com/oauth2/default
519
+ ```
520
+
521
+ ### Keycloak
522
+
523
+ ```bash
524
+ RESOURCE_URI=https://mcp.yourapp.com
525
+ AUTH_SERVER_URL=https://keycloak.yourapp.com/realms/your-realm
526
+ TOKEN_AUDIENCE=mcp-server
527
+ TOKEN_ISSUER=https://keycloak.yourapp.com/realms/your-realm
528
+ ```
529
+
530
+ ### Azure AD / Entra ID
531
+
532
+ ```bash
533
+ RESOURCE_URI=https://mcp.yourapp.com
534
+ AUTH_SERVER_URL=https://login.microsoftonline.com/YOUR-TENANT-ID/v2.0
535
+ TOKEN_AUDIENCE=api://YOUR-APP-ID
536
+ TOKEN_ISSUER=https://login.microsoftonline.com/YOUR-TENANT-ID/v2.0
537
+ ```
538
+
539
+ ---
540
+
541
+ ## 📚 Learn More
542
+
543
+ - [MCP OAuth Specification](https://modelcontextprotocol.io/specification/draft/basic/authorization)
544
+ - [OAuth 2.1 Draft](https://datatracker.ietf.org/doc/html/draft-ietf-oauth-v2-1-13)
545
+ - [RFC 8707 - Resource Indicators](https://datatracker.ietf.org/doc/html/rfc8707)
546
+ - [RFC 9728 - Protected Resource Metadata](https://datatracker.ietf.org/doc/html/rfc9728)
547
+ - [OpenAI Apps SDK - Auth](https://developers.openai.com/apps-sdk/build/auth)
548
+
549
+ ---
550
+
551
+ ## ✅ Pre-Flight Checklist
552
+
553
+ Before asking for help, verify:
554
+
555
+ - [ ] Auth0 API created with **RS256** signing algorithm
556
+ - [ ] Auth0 API **JWT Profile** set to **RFC 9068**
557
+ - [ ] Auth0 Application type is **"Regular Web Application"** (not SPA or M2M)
558
+ - [ ] Application has correct **callback URLs** (`http://localhost:3005/auth/callback`)
559
+ - [ ] Application **Grant Types** include "Authorization Code" and "Refresh Token"
560
+ - [ ] Application **ID Token Encryption** is **DISABLED**
561
+ - [ ] Application is **Authorized** to access the API (Machine to Machine Applications tab)
562
+ - [ ] Required **scopes** are granted to the application
563
+ - [ ] `.env` file has `RESOURCE_URI` matching Auth0 API Identifier **EXACTLY**
564
+ - [ ] `.env` file has `TOKEN_ISSUER` with **trailing slash** `/`
565
+ - [ ] Server starts successfully (check logs for "🚀 OAuth discovery server running")
566
+ - [ ] Discovery endpoint is accessible: `curl http://localhost:3005/.well-known/oauth-protected-resource`
567
+ - [ ] Discovery works in Studio (shows resource, auth servers, scopes)
568
+ - [ ] Client credentials saved in Studio
569
+ - [ ] OAuth flow completes successfully
570
+ - [ ] Server logs show **RS256 JWT tokens** (not JWE encrypted tokens)
571
+ - [ ] JWT token stored in Studio (check Auth tab)
572
+ - [ ] Protected tools execute successfully
573
+
574
+ **If all checkboxes are ✅ and it still doesn't work,** check the troubleshooting section above!
575
+
576
+ ---
577
+
578
+ ## 🎓 What We Learned (Common Pitfalls)
579
+
580
+ 1. **Application Type Matters:** Must be "Regular Web Application", not SPA or M2M
581
+ 2. **Audience Parameter is Critical:** Without it, Auth0 returns encrypted tokens (fixed in Studio)
582
+ 3. **API Identifier Must Match:** `RESOURCE_URI` must **exactly** match Auth0 API Identifier
583
+ 4. **Encryption Must Be Disabled:** ID Token encryption breaks JWT validation
584
+ 5. **Trailing Slash Matters:** `TOKEN_ISSUER` must have trailing `/` for Auth0
585
+ 6. **Authorization Required:** Application must be explicitly authorized to access the API
586
+ 7. **Port Awareness:** Dev mode uses 3005, prod mode uses 3000
587
+
588
+ ---
589
+
590
+ **Happy coding! 🚀**
591
+
592
+ If you have issues, check the troubleshooting section above. Most problems are solved by verifying the checklist!