nitrostack 1.0.0
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.
- package/CHANGELOG.md +227 -0
- package/CONTRIBUTING.md +182 -0
- package/LICENSE +201 -0
- package/LICENSE_URLS_UPDATE_COMPLETE.md +388 -0
- package/NOTICE +153 -0
- package/README.md +571 -0
- package/dist/auth/api-key.d.ts +118 -0
- package/dist/auth/api-key.d.ts.map +1 -0
- package/dist/auth/api-key.js +168 -0
- package/dist/auth/api-key.js.map +1 -0
- package/dist/auth/client.d.ts +151 -0
- package/dist/auth/client.d.ts.map +1 -0
- package/dist/auth/client.js +330 -0
- package/dist/auth/client.js.map +1 -0
- package/dist/auth/index.d.ts +30 -0
- package/dist/auth/index.d.ts.map +1 -0
- package/dist/auth/index.js +43 -0
- package/dist/auth/index.js.map +1 -0
- package/dist/auth/middleware.d.ts +95 -0
- package/dist/auth/middleware.d.ts.map +1 -0
- package/dist/auth/middleware.js +260 -0
- package/dist/auth/middleware.js.map +1 -0
- package/dist/auth/pkce.d.ts +53 -0
- package/dist/auth/pkce.d.ts.map +1 -0
- package/dist/auth/pkce.js +105 -0
- package/dist/auth/pkce.js.map +1 -0
- package/dist/auth/quick-setup.d.ts +94 -0
- package/dist/auth/quick-setup.d.ts.map +1 -0
- package/dist/auth/quick-setup.js +210 -0
- package/dist/auth/quick-setup.js.map +1 -0
- package/dist/auth/server-integration.d.ts +97 -0
- package/dist/auth/server-integration.d.ts.map +1 -0
- package/dist/auth/server-integration.js +182 -0
- package/dist/auth/server-integration.js.map +1 -0
- package/dist/auth/server-metadata.d.ts +51 -0
- package/dist/auth/server-metadata.d.ts.map +1 -0
- package/dist/auth/server-metadata.js +106 -0
- package/dist/auth/server-metadata.js.map +1 -0
- package/dist/auth/simple-jwt.d.ts +88 -0
- package/dist/auth/simple-jwt.d.ts.map +1 -0
- package/dist/auth/simple-jwt.js +152 -0
- package/dist/auth/simple-jwt.js.map +1 -0
- package/dist/auth/token-store.d.ts +104 -0
- package/dist/auth/token-store.d.ts.map +1 -0
- package/dist/auth/token-store.js +205 -0
- package/dist/auth/token-store.js.map +1 -0
- package/dist/auth/token-validation.d.ts +47 -0
- package/dist/auth/token-validation.d.ts.map +1 -0
- package/dist/auth/token-validation.js +237 -0
- package/dist/auth/token-validation.js.map +1 -0
- package/dist/auth/types.d.ts +215 -0
- package/dist/auth/types.d.ts.map +1 -0
- package/dist/auth/types.js +6 -0
- package/dist/auth/types.js.map +1 -0
- package/dist/cli/commands/build.d.ts +6 -0
- package/dist/cli/commands/build.d.ts.map +1 -0
- package/dist/cli/commands/build.js +104 -0
- package/dist/cli/commands/build.js.map +1 -0
- package/dist/cli/commands/dev.d.ts +7 -0
- package/dist/cli/commands/dev.d.ts.map +1 -0
- package/dist/cli/commands/dev.js +312 -0
- package/dist/cli/commands/dev.js.map +1 -0
- package/dist/cli/commands/generate-types.d.ts +8 -0
- package/dist/cli/commands/generate-types.d.ts.map +1 -0
- package/dist/cli/commands/generate-types.js +220 -0
- package/dist/cli/commands/generate-types.js.map +1 -0
- package/dist/cli/commands/generate.d.ts +5 -0
- package/dist/cli/commands/generate.d.ts.map +1 -0
- package/dist/cli/commands/generate.js +365 -0
- package/dist/cli/commands/generate.js.map +1 -0
- package/dist/cli/commands/init.d.ts +7 -0
- package/dist/cli/commands/init.d.ts.map +1 -0
- package/dist/cli/commands/init.js +365 -0
- package/dist/cli/commands/init.js.map +1 -0
- package/dist/cli/commands/start.d.ts +6 -0
- package/dist/cli/commands/start.d.ts.map +1 -0
- package/dist/cli/commands/start.js +61 -0
- package/dist/cli/commands/start.js.map +1 -0
- package/dist/cli/index.d.ts +3 -0
- package/dist/cli/index.d.ts.map +1 -0
- package/dist/cli/index.js +47 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/cli/mcp-dev-wrapper.d.ts +3 -0
- package/dist/cli/mcp-dev-wrapper.d.ts.map +1 -0
- package/dist/cli/mcp-dev-wrapper.js +116 -0
- package/dist/cli/mcp-dev-wrapper.js.map +1 -0
- package/dist/core/apikey-module.d.ts +69 -0
- package/dist/core/apikey-module.d.ts.map +1 -0
- package/dist/core/apikey-module.js +114 -0
- package/dist/core/apikey-module.js.map +1 -0
- package/dist/core/app-decorator.d.ts +58 -0
- package/dist/core/app-decorator.d.ts.map +1 -0
- package/dist/core/app-decorator.js +261 -0
- package/dist/core/app-decorator.js.map +1 -0
- package/dist/core/builders.d.ts +38 -0
- package/dist/core/builders.d.ts.map +1 -0
- package/dist/core/builders.js +129 -0
- package/dist/core/builders.js.map +1 -0
- package/dist/core/component.d.ts +105 -0
- package/dist/core/component.d.ts.map +1 -0
- package/dist/core/component.js +182 -0
- package/dist/core/component.js.map +1 -0
- package/dist/core/config-module.d.ts +55 -0
- package/dist/core/config-module.d.ts.map +1 -0
- package/dist/core/config-module.js +94 -0
- package/dist/core/config-module.js.map +1 -0
- package/dist/core/decorators/cache.decorator.d.ts +61 -0
- package/dist/core/decorators/cache.decorator.d.ts.map +1 -0
- package/dist/core/decorators/cache.decorator.js +115 -0
- package/dist/core/decorators/cache.decorator.js.map +1 -0
- package/dist/core/decorators/health-check.decorator.d.ts +80 -0
- package/dist/core/decorators/health-check.decorator.d.ts.map +1 -0
- package/dist/core/decorators/health-check.decorator.js +153 -0
- package/dist/core/decorators/health-check.decorator.js.map +1 -0
- package/dist/core/decorators/rate-limit.decorator.d.ts +62 -0
- package/dist/core/decorators/rate-limit.decorator.d.ts.map +1 -0
- package/dist/core/decorators/rate-limit.decorator.js +129 -0
- package/dist/core/decorators/rate-limit.decorator.js.map +1 -0
- package/dist/core/decorators.d.ts +151 -0
- package/dist/core/decorators.d.ts.map +1 -0
- package/dist/core/decorators.js +142 -0
- package/dist/core/decorators.js.map +1 -0
- package/dist/core/di/container.d.ts +42 -0
- package/dist/core/di/container.d.ts.map +1 -0
- package/dist/core/di/container.js +76 -0
- package/dist/core/di/container.js.map +1 -0
- package/dist/core/di/injectable.decorator.d.ts +35 -0
- package/dist/core/di/injectable.decorator.d.ts.map +1 -0
- package/dist/core/di/injectable.decorator.js +57 -0
- package/dist/core/di/injectable.decorator.js.map +1 -0
- package/dist/core/errors.d.ts +54 -0
- package/dist/core/errors.d.ts.map +1 -0
- package/dist/core/errors.js +87 -0
- package/dist/core/errors.js.map +1 -0
- package/dist/core/events/event-emitter.d.ts +50 -0
- package/dist/core/events/event-emitter.d.ts.map +1 -0
- package/dist/core/events/event-emitter.js +94 -0
- package/dist/core/events/event-emitter.js.map +1 -0
- package/dist/core/events/event.decorator.d.ts +48 -0
- package/dist/core/events/event.decorator.d.ts.map +1 -0
- package/dist/core/events/event.decorator.js +68 -0
- package/dist/core/events/event.decorator.js.map +1 -0
- package/dist/core/filters/exception-filter.decorator.d.ts +40 -0
- package/dist/core/filters/exception-filter.decorator.d.ts.map +1 -0
- package/dist/core/filters/exception-filter.decorator.js +54 -0
- package/dist/core/filters/exception-filter.decorator.js.map +1 -0
- package/dist/core/filters/exception-filter.interface.d.ts +30 -0
- package/dist/core/filters/exception-filter.interface.d.ts.map +1 -0
- package/dist/core/filters/exception-filter.interface.js +2 -0
- package/dist/core/filters/exception-filter.interface.js.map +1 -0
- package/dist/core/guards/apikey.guard.d.ts +22 -0
- package/dist/core/guards/apikey.guard.d.ts.map +1 -0
- package/dist/core/guards/apikey.guard.js +11 -0
- package/dist/core/guards/apikey.guard.js.map +1 -0
- package/dist/core/guards/guard.interface.d.ts +18 -0
- package/dist/core/guards/guard.interface.d.ts.map +1 -0
- package/dist/core/guards/guard.interface.js +2 -0
- package/dist/core/guards/guard.interface.js.map +1 -0
- package/dist/core/guards/jwt.guard.d.ts +18 -0
- package/dist/core/guards/jwt.guard.d.ts.map +1 -0
- package/dist/core/guards/jwt.guard.js +2 -0
- package/dist/core/guards/jwt.guard.js.map +1 -0
- package/dist/core/guards/oauth.guard.d.ts +35 -0
- package/dist/core/guards/oauth.guard.d.ts.map +1 -0
- package/dist/core/guards/oauth.guard.js +2 -0
- package/dist/core/guards/oauth.guard.js.map +1 -0
- package/dist/core/guards/use-guards.decorator.d.ts +25 -0
- package/dist/core/guards/use-guards.decorator.d.ts.map +1 -0
- package/dist/core/guards/use-guards.decorator.js +32 -0
- package/dist/core/guards/use-guards.decorator.js.map +1 -0
- package/dist/core/health/health-checks.resource.d.ts +14 -0
- package/dist/core/health/health-checks.resource.d.ts.map +1 -0
- package/dist/core/health/health-checks.resource.js +29 -0
- package/dist/core/health/health-checks.resource.js.map +1 -0
- package/dist/core/index.d.ts +55 -0
- package/dist/core/index.d.ts.map +1 -0
- package/dist/core/index.js +57 -0
- package/dist/core/index.js.map +1 -0
- package/dist/core/interceptors/interceptor.decorator.d.ts +37 -0
- package/dist/core/interceptors/interceptor.decorator.d.ts.map +1 -0
- package/dist/core/interceptors/interceptor.decorator.js +51 -0
- package/dist/core/interceptors/interceptor.decorator.js.map +1 -0
- package/dist/core/interceptors/interceptor.interface.d.ts +31 -0
- package/dist/core/interceptors/interceptor.interface.d.ts.map +1 -0
- package/dist/core/interceptors/interceptor.interface.js +2 -0
- package/dist/core/interceptors/interceptor.interface.js.map +1 -0
- package/dist/core/jwt-module.d.ts +51 -0
- package/dist/core/jwt-module.d.ts.map +1 -0
- package/dist/core/jwt-module.js +52 -0
- package/dist/core/jwt-module.js.map +1 -0
- package/dist/core/logger.d.ts +18 -0
- package/dist/core/logger.d.ts.map +1 -0
- package/dist/core/logger.js +51 -0
- package/dist/core/logger.js.map +1 -0
- package/dist/core/middleware/middleware.decorator.d.ts +39 -0
- package/dist/core/middleware/middleware.decorator.d.ts.map +1 -0
- package/dist/core/middleware/middleware.decorator.js +53 -0
- package/dist/core/middleware/middleware.decorator.js.map +1 -0
- package/dist/core/middleware/middleware.interface.d.ts +29 -0
- package/dist/core/middleware/middleware.interface.d.ts.map +1 -0
- package/dist/core/middleware/middleware.interface.js +2 -0
- package/dist/core/middleware/middleware.interface.js.map +1 -0
- package/dist/core/module.d.ts +74 -0
- package/dist/core/module.d.ts.map +1 -0
- package/dist/core/module.js +82 -0
- package/dist/core/module.js.map +1 -0
- package/dist/core/oauth-module.d.ts +144 -0
- package/dist/core/oauth-module.d.ts.map +1 -0
- package/dist/core/oauth-module.js +190 -0
- package/dist/core/oauth-module.js.map +1 -0
- package/dist/core/pipes/pipe.decorator.d.ts +55 -0
- package/dist/core/pipes/pipe.decorator.d.ts.map +1 -0
- package/dist/core/pipes/pipe.decorator.js +85 -0
- package/dist/core/pipes/pipe.decorator.js.map +1 -0
- package/dist/core/pipes/pipe.interface.d.ts +36 -0
- package/dist/core/pipes/pipe.interface.d.ts.map +1 -0
- package/dist/core/pipes/pipe.interface.js +2 -0
- package/dist/core/pipes/pipe.interface.js.map +1 -0
- package/dist/core/prompt.d.ts +37 -0
- package/dist/core/prompt.d.ts.map +1 -0
- package/dist/core/prompt.js +76 -0
- package/dist/core/prompt.js.map +1 -0
- package/dist/core/resource.d.ts +42 -0
- package/dist/core/resource.d.ts.map +1 -0
- package/dist/core/resource.js +90 -0
- package/dist/core/resource.js.map +1 -0
- package/dist/core/server.d.ts +72 -0
- package/dist/core/server.d.ts.map +1 -0
- package/dist/core/server.js +406 -0
- package/dist/core/server.js.map +1 -0
- package/dist/core/tool.d.ts +78 -0
- package/dist/core/tool.d.ts.map +1 -0
- package/dist/core/tool.js +190 -0
- package/dist/core/tool.js.map +1 -0
- package/dist/core/transports/http-server.d.ts +102 -0
- package/dist/core/transports/http-server.d.ts.map +1 -0
- package/dist/core/transports/http-server.js +265 -0
- package/dist/core/transports/http-server.js.map +1 -0
- package/dist/core/types.d.ts +123 -0
- package/dist/core/types.d.ts.map +1 -0
- package/dist/core/types.js +2 -0
- package/dist/core/types.js.map +1 -0
- package/dist/core/widgets/widget-examples.resource.d.ts +17 -0
- package/dist/core/widgets/widget-examples.resource.d.ts.map +1 -0
- package/dist/core/widgets/widget-examples.resource.js +28 -0
- package/dist/core/widgets/widget-examples.resource.js.map +1 -0
- package/dist/core/widgets/widget-registry.d.ts +56 -0
- package/dist/core/widgets/widget-registry.d.ts.map +1 -0
- package/dist/core/widgets/widget-registry.js +75 -0
- package/dist/core/widgets/widget-registry.js.map +1 -0
- package/dist/testing/index.d.ts +82 -0
- package/dist/testing/index.d.ts.map +1 -0
- package/dist/testing/index.js +164 -0
- package/dist/testing/index.js.map +1 -0
- package/dist/ui-next/index.d.ts +31 -0
- package/dist/ui-next/index.d.ts.map +1 -0
- package/dist/ui-next/index.js +687 -0
- package/dist/ui-next/index.js.map +1 -0
- package/dist/widgets/index.d.ts +9 -0
- package/dist/widgets/index.d.ts.map +1 -0
- package/dist/widgets/index.js +9 -0
- package/dist/widgets/index.js.map +1 -0
- package/dist/widgets/metadata.d.ts +53 -0
- package/dist/widgets/metadata.d.ts.map +1 -0
- package/dist/widgets/metadata.js +29 -0
- package/dist/widgets/metadata.js.map +1 -0
- package/dist/widgets/withToolData.d.ts +19 -0
- package/dist/widgets/withToolData.d.ts.map +1 -0
- package/dist/widgets/withToolData.js +240 -0
- package/dist/widgets/withToolData.js.map +1 -0
- package/jest.config.js +21 -0
- package/package.json +108 -0
- package/templates/typescript-auth/AI_AGENT_CLI_REFERENCE.md +702 -0
- package/templates/typescript-auth/AI_AGENT_SDK_REFERENCE.md +1260 -0
- package/templates/typescript-auth/README.md +400 -0
- package/templates/typescript-auth/package.json +44 -0
- package/templates/typescript-auth-api-key/AI_AGENT_CLI_REFERENCE.md +701 -0
- package/templates/typescript-auth-api-key/AI_AGENT_SDK_REFERENCE.md +1260 -0
- package/templates/typescript-auth-api-key/README.md +483 -0
- package/templates/typescript-auth-api-key/package-lock.json +124 -0
- package/templates/typescript-auth-api-key/package.json +29 -0
- package/templates/typescript-oauth/AI_AGENT_CLI_REFERENCE.md +701 -0
- package/templates/typescript-oauth/AI_AGENT_SDK_REFERENCE.md +1260 -0
- package/templates/typescript-oauth/OAUTH_SETUP.md +406 -0
- package/templates/typescript-oauth/README.md +350 -0
- package/templates/typescript-oauth/package.json +30 -0
- package/templates/typescript-starter/AI_AGENT_CLI_REFERENCE.md +701 -0
- package/templates/typescript-starter/AI_AGENT_SDK_REFERENCE.md +1260 -0
- package/templates/typescript-starter/README.md +312 -0
- package/templates/typescript-starter/package.json +32 -0
|
@@ -0,0 +1,350 @@
|
|
|
1
|
+
# OAuth 2.1 MCP Server Template
|
|
2
|
+
|
|
3
|
+
Complete OAuth 2.1 authentication implementation for Model Context Protocol servers.
|
|
4
|
+
|
|
5
|
+
## ๐ฏ What This Template Demonstrates
|
|
6
|
+
|
|
7
|
+
- โ
**OAuth 2.1** authentication (MCP & OpenAI Apps SDK compliant)
|
|
8
|
+
- โ
**Token Audience Binding** (RFC 8707) - Critical security feature
|
|
9
|
+
- โ
**Protected Resource Metadata** (RFC 9728) - Auto-discovery
|
|
10
|
+
- โ
**PKCE Support** (RFC 7636) - Already handled by NitroStack Studio
|
|
11
|
+
- โ
**Scope-based Access Control** - Fine-grained permissions
|
|
12
|
+
- โ
**Multi-Provider Support** - Works with Auth0, Okta, Keycloak, etc.
|
|
13
|
+
|
|
14
|
+
## ๐ Quick Start
|
|
15
|
+
|
|
16
|
+
### 1. Install Dependencies
|
|
17
|
+
|
|
18
|
+
```bash
|
|
19
|
+
npm install
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
### 2. Setup Auth0 (Recommended for Quick Testing)
|
|
23
|
+
|
|
24
|
+
#### Create Auth0 Application
|
|
25
|
+
|
|
26
|
+
1. Go to [Auth0 Dashboard](https://manage.auth0.com/)
|
|
27
|
+
2. **Applications** โ **Create Application**
|
|
28
|
+
3. Choose **"Regular Web Application"**
|
|
29
|
+
4. **Application Settings:**
|
|
30
|
+
- **Name**: `NitroStack OAuth Server`
|
|
31
|
+
- **Allowed Callback URLs**: `http://localhost:3000/auth/callback`
|
|
32
|
+
- **Allowed Logout URLs**: `http://localhost:3000`
|
|
33
|
+
- **Allowed Web Origins**: `http://localhost:3000`
|
|
34
|
+
- **Grant Types**: Authorization Code, Refresh Token
|
|
35
|
+
5. **Save** and copy:
|
|
36
|
+
- **Domain** (e.g., `dev-xxx.us.auth0.com`)
|
|
37
|
+
- **Client ID**
|
|
38
|
+
- **Client Secret**
|
|
39
|
+
|
|
40
|
+
#### Create Auth0 API
|
|
41
|
+
|
|
42
|
+
1. Auth0 Dashboard โ **Applications** โ **APIs** โ **Create API**
|
|
43
|
+
2. **Settings:**
|
|
44
|
+
- **Name**: `NitroStack MCP API`
|
|
45
|
+
- **Identifier**: `http://localhost:3002` (your RESOURCE_URI)
|
|
46
|
+
- **Signing Algorithm**: RS256
|
|
47
|
+
3. **Permissions** tab โ **Add Scopes:**
|
|
48
|
+
- `read` - Read access to resources
|
|
49
|
+
- `write` - Write/modify resources
|
|
50
|
+
- `admin` - Administrative operations
|
|
51
|
+
4. **Save**
|
|
52
|
+
|
|
53
|
+
### 3. Configure Environment Variables
|
|
54
|
+
|
|
55
|
+
Edit `.env` with your Auth0 settings:
|
|
56
|
+
|
|
57
|
+
```bash
|
|
58
|
+
# Your MCP server's resource URI (matches API Identifier in Auth0)
|
|
59
|
+
RESOURCE_URI=http://localhost:3002
|
|
60
|
+
|
|
61
|
+
# Your Auth0 domain (with https://)
|
|
62
|
+
AUTH_SERVER_URL=https://YOUR-TENANT.auth0.com
|
|
63
|
+
|
|
64
|
+
# Token audience (same as RESOURCE_URI)
|
|
65
|
+
TOKEN_AUDIENCE=http://localhost:3002
|
|
66
|
+
|
|
67
|
+
# Token issuer (Auth0 domain with trailing slash)
|
|
68
|
+
TOKEN_ISSUER=https://YOUR-TENANT.auth0.com/
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
**See `OAUTH_SETUP.md` for other providers** (Okta, Keycloak, Azure AD).
|
|
72
|
+
|
|
73
|
+
### 4. Start the Server
|
|
74
|
+
|
|
75
|
+
```bash
|
|
76
|
+
npm run dev
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
You should see:
|
|
80
|
+
```
|
|
81
|
+
๐ HTTP MCP Server listening on http://0.0.0.0:3002/mcp
|
|
82
|
+
๐ OAuth 2.1 enabled
|
|
83
|
+
๐ Server started successfully (DUAL: STDIO + HTTP)
|
|
84
|
+
๐ก MCP Protocol: STDIO (for Studio/Claude)
|
|
85
|
+
๐ OAuth Metadata: HTTP (port 3002)
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
**Note:** The server runs in **DUAL mode** - STDIO for MCP protocol + HTTP for OAuth metadata!
|
|
89
|
+
|
|
90
|
+
### 5. Complete OAuth Flow in Studio
|
|
91
|
+
|
|
92
|
+
#### Open NitroStack Studio
|
|
93
|
+
Navigate to `http://localhost:3000`
|
|
94
|
+
|
|
95
|
+
#### Step 1: Discover OAuth Server
|
|
96
|
+
1. Go to **Auth โ OAuth 2.1** tab
|
|
97
|
+
2. Enter Server URL: `http://localhost:3002`
|
|
98
|
+
3. Click **"Discover Auth Config"**
|
|
99
|
+
4. โ
Should show: **Discovery Successful**
|
|
100
|
+
5. You'll see the discovered metadata (resource URI, auth server, scopes)
|
|
101
|
+
|
|
102
|
+
#### Step 2: Enter Client Credentials
|
|
103
|
+
1. Scroll to **"2a. Use Existing Client"** section
|
|
104
|
+
2. **Client ID**: Paste your Auth0 Client ID
|
|
105
|
+
3. **Client Secret**: Paste your Auth0 Client Secret
|
|
106
|
+
4. Click **"Save Client Credentials"**
|
|
107
|
+
5. โ
Should show: **Client credentials saved!**
|
|
108
|
+
|
|
109
|
+
#### Step 3: Start OAuth Flow
|
|
110
|
+
1. Click **"Start Authorization Flow"**
|
|
111
|
+
2. โ
You'll be redirected to Auth0 login page
|
|
112
|
+
3. **Login** with your Auth0 account
|
|
113
|
+
4. **Authorize** the application (grant requested scopes)
|
|
114
|
+
5. โ
You'll be redirected back to Studio with a JWT token!
|
|
115
|
+
6. โ
Token is automatically saved and ready to use
|
|
116
|
+
|
|
117
|
+
#### Step 4: Test Protected Tools
|
|
118
|
+
1. Go to **Tools** tab
|
|
119
|
+
2. Try any protected tool (e.g., `get_user_profile`, `list_resources`)
|
|
120
|
+
3. โ
Your JWT token is automatically included in requests!
|
|
121
|
+
4. Tools will show your authenticated user info
|
|
122
|
+
|
|
123
|
+
**Congratulations! ๐** Your OAuth 2.1 server is working!
|
|
124
|
+
|
|
125
|
+
## ๐ Available Tools
|
|
126
|
+
|
|
127
|
+
### Public Tools (No Auth)
|
|
128
|
+
|
|
129
|
+
| Tool | Description |
|
|
130
|
+
|------|-------------|
|
|
131
|
+
| `get_server_info` | Get server information |
|
|
132
|
+
|
|
133
|
+
### Protected Tools (OAuth Required)
|
|
134
|
+
|
|
135
|
+
| Tool | Required Scopes | Description |
|
|
136
|
+
|------|-----------------|-------------|
|
|
137
|
+
| `get_user_profile` | _(any valid token)_ | Get authenticated user info |
|
|
138
|
+
| `list_resources` | `read` | List available resources |
|
|
139
|
+
| `create_resource` | `write` | Create a new resource |
|
|
140
|
+
| `admin_statistics` | `read`, `admin` | Get admin statistics |
|
|
141
|
+
|
|
142
|
+
## ๐๏ธ Project Structure
|
|
143
|
+
|
|
144
|
+
```
|
|
145
|
+
typescript-oauth/
|
|
146
|
+
โโโ src/
|
|
147
|
+
โ โโโ guards/
|
|
148
|
+
โ โ โโโ oauth.guard.ts # OAuth token validation
|
|
149
|
+
โ โโโ modules/demo/
|
|
150
|
+
โ โ โโโ demo.module.ts
|
|
151
|
+
โ โ โโโ demo.tools.ts # Example tools
|
|
152
|
+
โ โโโ app.module.ts # OAuthModule configuration
|
|
153
|
+
โ โโโ index.ts # Entry point
|
|
154
|
+
โโโ .env.example # Environment template
|
|
155
|
+
โโโ OAUTH_SETUP.md # Provider setup guides
|
|
156
|
+
โโโ README.md
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
## ๐ OAuth 2.1 Implementation
|
|
160
|
+
|
|
161
|
+
### OAuthModule Configuration
|
|
162
|
+
|
|
163
|
+
```typescript
|
|
164
|
+
// src/app.module.ts
|
|
165
|
+
OAuthModule.forRoot({
|
|
166
|
+
resourceUri: process.env.RESOURCE_URI!,
|
|
167
|
+
authorizationServers: [process.env.AUTH_SERVER_URL!],
|
|
168
|
+
scopesSupported: ['read', 'write', 'admin'],
|
|
169
|
+
tokenIntrospectionEndpoint: process.env.INTROSPECTION_ENDPOINT,
|
|
170
|
+
audience: process.env.TOKEN_AUDIENCE,
|
|
171
|
+
issuer: process.env.TOKEN_ISSUER,
|
|
172
|
+
})
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
### OAuth Guard
|
|
176
|
+
|
|
177
|
+
```typescript
|
|
178
|
+
// Protect a tool with OAuth
|
|
179
|
+
@Tool({ name: 'protected_tool' })
|
|
180
|
+
@UseGuards(OAuthGuard)
|
|
181
|
+
async protectedTool() {
|
|
182
|
+
// Only accessible with valid OAuth token
|
|
183
|
+
}
|
|
184
|
+
```
|
|
185
|
+
|
|
186
|
+
### Scope-Based Access
|
|
187
|
+
|
|
188
|
+
```typescript
|
|
189
|
+
// Require specific scopes
|
|
190
|
+
@Tool({ name: 'admin_tool' })
|
|
191
|
+
@UseGuards(OAuthGuard, createScopeGuard(['admin']))
|
|
192
|
+
async adminTool() {
|
|
193
|
+
// Requires 'admin' scope
|
|
194
|
+
}
|
|
195
|
+
```
|
|
196
|
+
|
|
197
|
+
## ๐ Key Security Features
|
|
198
|
+
|
|
199
|
+
### 1. Token Audience Binding (RFC 8707)
|
|
200
|
+
|
|
201
|
+
**Critical for security!** Tokens are validated to ensure they were issued **specifically for your MCP server**.
|
|
202
|
+
|
|
203
|
+
```typescript
|
|
204
|
+
// Tokens MUST include your RESOURCE_URI in the audience claim
|
|
205
|
+
{
|
|
206
|
+
"aud": "https://mcp.yourapp.com", // โ Must match RESOURCE_URI
|
|
207
|
+
"sub": "user123",
|
|
208
|
+
"scope": "read write"
|
|
209
|
+
}
|
|
210
|
+
```
|
|
211
|
+
|
|
212
|
+
### 2. No Token Passthrough
|
|
213
|
+
|
|
214
|
+
**Never forward OAuth tokens to other services!** Each service must have its own token.
|
|
215
|
+
|
|
216
|
+
```typescript
|
|
217
|
+
// โ WRONG - Don't do this
|
|
218
|
+
await upstreamAPI.call(headers: { Authorization: clientToken });
|
|
219
|
+
|
|
220
|
+
// โ
CORRECT - Use separate token
|
|
221
|
+
const upstreamToken = await getTokenForUpstream();
|
|
222
|
+
await upstreamAPI.call(headers: { Authorization: upstreamToken });
|
|
223
|
+
```
|
|
224
|
+
|
|
225
|
+
### 3. Scope Validation
|
|
226
|
+
|
|
227
|
+
Fine-grained access control based on OAuth scopes:
|
|
228
|
+
|
|
229
|
+
```typescript
|
|
230
|
+
// Automatically validates scopes
|
|
231
|
+
@UseGuards(OAuthGuard, createScopeGuard(['read', 'write']))
|
|
232
|
+
```
|
|
233
|
+
|
|
234
|
+
## ๐งช Testing with Studio
|
|
235
|
+
|
|
236
|
+
### Step 1: Start OAuth Flow
|
|
237
|
+
|
|
238
|
+
1. **Auth Tab** โ **OAuth 2.1**
|
|
239
|
+
2. Enter your MCP server URL
|
|
240
|
+
3. Click **"Discover & Register"**
|
|
241
|
+
|
|
242
|
+
### Step 2: Complete Authorization
|
|
243
|
+
|
|
244
|
+
1. Studio redirects to your OAuth provider
|
|
245
|
+
2. Login with your credentials
|
|
246
|
+
3. Grant requested scopes
|
|
247
|
+
4. Studio receives and stores the token
|
|
248
|
+
|
|
249
|
+
### Step 3: Test Tools
|
|
250
|
+
|
|
251
|
+
1. **Tools Tab** โ Select a protected tool
|
|
252
|
+
2. Execute - Token is automatically included!
|
|
253
|
+
3. Try tools with different scope requirements
|
|
254
|
+
|
|
255
|
+
## ๐ Standards Compliance
|
|
256
|
+
|
|
257
|
+
This template implements:
|
|
258
|
+
|
|
259
|
+
- โ
**OAuth 2.1** ([draft-ietf-oauth-v2-1-13](https://datatracker.ietf.org/doc/html/draft-ietf-oauth-v2-1-13))
|
|
260
|
+
- โ
**RFC 9728** - Protected Resource Metadata
|
|
261
|
+
- โ
**RFC 8414** - Authorization Server Metadata
|
|
262
|
+
- โ
**RFC 7591** - Dynamic Client Registration
|
|
263
|
+
- โ
**RFC 8707** - Resource Indicators (Token Audience Binding)
|
|
264
|
+
- โ
**RFC 7636** - PKCE
|
|
265
|
+
- โ
**RFC 7662** - Token Introspection
|
|
266
|
+
|
|
267
|
+
Compatible with:
|
|
268
|
+
- โ
[MCP Specification](https://modelcontextprotocol.io/specification/draft/basic/authorization)
|
|
269
|
+
- โ
[OpenAI Apps SDK](https://developers.openai.com/apps-sdk/build/auth)
|
|
270
|
+
|
|
271
|
+
## ๐ง Configuration Options
|
|
272
|
+
|
|
273
|
+
### Required
|
|
274
|
+
|
|
275
|
+
- `RESOURCE_URI` - Your MCP server's public URL
|
|
276
|
+
- `AUTH_SERVER_URL` - Your OAuth provider's base URL
|
|
277
|
+
|
|
278
|
+
### Optional
|
|
279
|
+
|
|
280
|
+
- `TOKEN_AUDIENCE` - Expected audience (defaults to RESOURCE_URI)
|
|
281
|
+
- `TOKEN_ISSUER` - Expected issuer (recommended for security)
|
|
282
|
+
- `INTROSPECTION_ENDPOINT` - For opaque token validation
|
|
283
|
+
- `INTROSPECTION_CLIENT_ID` - Introspection client credentials
|
|
284
|
+
- `INTROSPECTION_CLIENT_SECRET` - Introspection client secret
|
|
285
|
+
|
|
286
|
+
## ๐ Supported OAuth Providers
|
|
287
|
+
|
|
288
|
+
This template works with any RFC-compliant OAuth 2.1 provider:
|
|
289
|
+
|
|
290
|
+
- โ
**Auth0** - Easiest for testing
|
|
291
|
+
- โ
**Okta** - Enterprise-ready
|
|
292
|
+
- โ
**Keycloak** - Self-hosted
|
|
293
|
+
- โ
**Azure AD / Entra ID**
|
|
294
|
+
- โ
**Google Identity Platform**
|
|
295
|
+
- โ
**Custom OAuth servers**
|
|
296
|
+
|
|
297
|
+
**See `OAUTH_SETUP.md` for provider-specific configuration guides.**
|
|
298
|
+
|
|
299
|
+
## ๐จ Common Issues
|
|
300
|
+
|
|
301
|
+
### "OAuth token validation failed: Token audience mismatch"
|
|
302
|
+
|
|
303
|
+
**Fix:** Ensure `TOKEN_AUDIENCE` in `.env` matches the audience claim in your tokens.
|
|
304
|
+
|
|
305
|
+
```bash
|
|
306
|
+
# .env
|
|
307
|
+
TOKEN_AUDIENCE=https://mcp.yourapp.com
|
|
308
|
+
|
|
309
|
+
# Token must have:
|
|
310
|
+
{
|
|
311
|
+
"aud": "https://mcp.yourapp.com" # โ Must match
|
|
312
|
+
}
|
|
313
|
+
```
|
|
314
|
+
|
|
315
|
+
### "Missing required environment variables"
|
|
316
|
+
|
|
317
|
+
**Fix:** Copy `.env.example` to `.env` and configure all required variables.
|
|
318
|
+
|
|
319
|
+
```bash
|
|
320
|
+
cp .env.example .env
|
|
321
|
+
# Edit .env with your OAuth provider settings
|
|
322
|
+
```
|
|
323
|
+
|
|
324
|
+
### "Insufficient scope"
|
|
325
|
+
|
|
326
|
+
**Fix:** Request the required scopes when authorizing in Studio:
|
|
327
|
+
|
|
328
|
+
1. Auth Tab โ OAuth 2.1
|
|
329
|
+
2. Check required scopes for the tool
|
|
330
|
+
3. Re-authorize with correct scopes
|
|
331
|
+
|
|
332
|
+
## ๐ Learn More
|
|
333
|
+
|
|
334
|
+
- [MCP OAuth Specification](https://modelcontextprotocol.io/specification/draft/basic/authorization)
|
|
335
|
+
- [OpenAI Apps SDK Auth](https://developers.openai.com/apps-sdk/build/auth)
|
|
336
|
+
- [OAuth 2.1 Draft](https://datatracker.ietf.org/doc/html/draft-ietf-oauth-v2-1-13)
|
|
337
|
+
- [RFC 8707 - Resource Indicators](https://datatracker.ietf.org/doc/html/rfc8707)
|
|
338
|
+
- [OAUTH_SETUP.md](./OAUTH_SETUP.md) - Provider setup guides
|
|
339
|
+
|
|
340
|
+
## ๐ Ready to Build!
|
|
341
|
+
|
|
342
|
+
This template provides a production-ready OAuth 2.1 implementation. Customize it for your needs:
|
|
343
|
+
|
|
344
|
+
1. Add your own tools with appropriate scopes
|
|
345
|
+
2. Integrate with your user database
|
|
346
|
+
3. Add custom token validation logic
|
|
347
|
+
4. Deploy with your chosen OAuth provider
|
|
348
|
+
|
|
349
|
+
**Happy coding! ๐**
|
|
350
|
+
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "oauth-mcp-server",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "NitroStack server demonstrating OAuth 2.1 authentication",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "dist/index.js",
|
|
7
|
+
"scripts": {
|
|
8
|
+
"dev": "nitrostack dev",
|
|
9
|
+
"build": "nitrostack build",
|
|
10
|
+
"start": "nitrostack start",
|
|
11
|
+
"widget": "npm --prefix src/widgets"
|
|
12
|
+
},
|
|
13
|
+
"keywords": [
|
|
14
|
+
"mcp",
|
|
15
|
+
"nitrostack",
|
|
16
|
+
"oauth",
|
|
17
|
+
"oauth2.1",
|
|
18
|
+
"authentication"
|
|
19
|
+
],
|
|
20
|
+
"author": "",
|
|
21
|
+
"license": "MIT",
|
|
22
|
+
"dependencies": {
|
|
23
|
+
"nitrostack": "^1.0.0",
|
|
24
|
+
"zod": "^3.23.8"
|
|
25
|
+
},
|
|
26
|
+
"devDependencies": {
|
|
27
|
+
"@types/node": "^20",
|
|
28
|
+
"typescript": "^5"
|
|
29
|
+
}
|
|
30
|
+
}
|