@dotdo/oauth 0.1.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/README.md +171 -0
- package/dist/index.d.ts +48 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +48 -0
- package/dist/index.js.map +1 -0
- package/dist/pkce.d.ts +103 -0
- package/dist/pkce.d.ts.map +1 -0
- package/dist/pkce.js +186 -0
- package/dist/pkce.js.map +1 -0
- package/dist/server.d.ts +67 -0
- package/dist/server.d.ts.map +1 -0
- package/dist/server.js +579 -0
- package/dist/server.js.map +1 -0
- package/dist/storage.d.ts +204 -0
- package/dist/storage.d.ts.map +1 -0
- package/dist/storage.js +191 -0
- package/dist/storage.js.map +1 -0
- package/dist/types.d.ts +247 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +8 -0
- package/dist/types.js.map +1 -0
- package/package.json +79 -0
package/README.md
ADDED
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
# @dotdo/oauth
|
|
2
|
+
|
|
3
|
+
OAuth 2.1 authorization server for MCP (Model Context Protocol) compatibility.
|
|
4
|
+
|
|
5
|
+
## The Problem
|
|
6
|
+
|
|
7
|
+
You're building an MCP server. Claude and ChatGPT need to authenticate. But OAuth 2.1 is new, the docs are scattered, and you've spent hours debugging `.well-known` endpoints and CORS headers.
|
|
8
|
+
|
|
9
|
+
## The Solution
|
|
10
|
+
|
|
11
|
+
```typescript
|
|
12
|
+
import { createOAuth21Server, MemoryOAuthStorage } from '@dotdo/oauth'
|
|
13
|
+
|
|
14
|
+
const oauth = createOAuth21Server({
|
|
15
|
+
issuer: 'https://your-mcp.do',
|
|
16
|
+
storage: new MemoryOAuthStorage(),
|
|
17
|
+
upstream: {
|
|
18
|
+
provider: 'workos',
|
|
19
|
+
apiKey: process.env.WORKOS_API_KEY,
|
|
20
|
+
clientId: process.env.WORKOS_CLIENT_ID,
|
|
21
|
+
},
|
|
22
|
+
})
|
|
23
|
+
|
|
24
|
+
// Mount it. Done.
|
|
25
|
+
app.route('/', oauth)
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
Your MCP server now speaks OAuth 2.1. Claude can connect.
|
|
29
|
+
|
|
30
|
+
## What This Does
|
|
31
|
+
|
|
32
|
+
This package creates a **federated OAuth 2.1 server**:
|
|
33
|
+
|
|
34
|
+
- It's an OAuth **SERVER** to MCP clients (Claude, ChatGPT)
|
|
35
|
+
- It's an OAuth **CLIENT** to your identity provider (WorkOS, Auth0)
|
|
36
|
+
|
|
37
|
+
```
|
|
38
|
+
┌─────────────────┐ ┌──────────────────┐ ┌─────────────┐
|
|
39
|
+
│ Claude/ChatGPT │ ───> │ Your MCP Server │ ───> │ WorkOS │
|
|
40
|
+
│ (OAuth Client) │ │ (OAuth Server + │ │ (Upstream) │
|
|
41
|
+
│ │ <─── │ OAuth Client) │ <─── │ │
|
|
42
|
+
└─────────────────┘ └──────────────────┘ └─────────────┘
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
## Endpoints
|
|
46
|
+
|
|
47
|
+
Once mounted, your server provides:
|
|
48
|
+
|
|
49
|
+
| Endpoint | Purpose |
|
|
50
|
+
|----------|---------|
|
|
51
|
+
| `/.well-known/oauth-authorization-server` | Server metadata (RFC 8414) |
|
|
52
|
+
| `/.well-known/oauth-protected-resource` | Resource metadata |
|
|
53
|
+
| `/authorize` | Authorization endpoint |
|
|
54
|
+
| `/token` | Token endpoint |
|
|
55
|
+
| `/register` | Dynamic client registration |
|
|
56
|
+
| `/revoke` | Token revocation |
|
|
57
|
+
|
|
58
|
+
## Features
|
|
59
|
+
|
|
60
|
+
- **OAuth 2.1 compliant** - PKCE required, S256 only
|
|
61
|
+
- **MCP compatible** - Works with Claude, ChatGPT, and other MCP clients
|
|
62
|
+
- **Federated auth** - Delegates to WorkOS, Auth0, or custom providers
|
|
63
|
+
- **Storage agnostic** - Bring your own storage backend
|
|
64
|
+
- **Zero dependencies** on `oauth.do` or `@dotdo/do` - this is the leaf package
|
|
65
|
+
|
|
66
|
+
## Storage
|
|
67
|
+
|
|
68
|
+
The package provides `MemoryOAuthStorage` for testing. For production, implement the `OAuthStorage` interface:
|
|
69
|
+
|
|
70
|
+
```typescript
|
|
71
|
+
import type { OAuthStorage } from '@dotdo/oauth'
|
|
72
|
+
|
|
73
|
+
class MyStorage implements OAuthStorage {
|
|
74
|
+
async getUser(id: string) { /* ... */ }
|
|
75
|
+
async saveUser(user: OAuthUser) { /* ... */ }
|
|
76
|
+
async getClient(clientId: string) { /* ... */ }
|
|
77
|
+
// ... other methods
|
|
78
|
+
}
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
If you're using `@dotdo/do`, it provides `DOAuthStorage` that implements this interface using Durable Object SQLite storage.
|
|
82
|
+
|
|
83
|
+
## Configuration
|
|
84
|
+
|
|
85
|
+
```typescript
|
|
86
|
+
createOAuth21Server({
|
|
87
|
+
// Required
|
|
88
|
+
issuer: 'https://your-domain.com', // Your server's URL
|
|
89
|
+
storage: new MemoryOAuthStorage(), // Storage backend
|
|
90
|
+
upstream: { // Identity provider
|
|
91
|
+
provider: 'workos',
|
|
92
|
+
apiKey: 'sk_...',
|
|
93
|
+
clientId: 'client_...',
|
|
94
|
+
},
|
|
95
|
+
|
|
96
|
+
// Optional
|
|
97
|
+
scopes: ['openid', 'profile', 'email'], // Supported scopes
|
|
98
|
+
accessTokenTtl: 3600, // 1 hour (default)
|
|
99
|
+
refreshTokenTtl: 2592000, // 30 days (default)
|
|
100
|
+
authCodeTtl: 600, // 10 minutes (default)
|
|
101
|
+
enableDynamicRegistration: true, // Allow client registration
|
|
102
|
+
debug: false, // Debug logging
|
|
103
|
+
|
|
104
|
+
// Callbacks
|
|
105
|
+
onUserAuthenticated: async (user) => {
|
|
106
|
+
console.log('User logged in:', user.email)
|
|
107
|
+
},
|
|
108
|
+
})
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
## Upstream Providers
|
|
112
|
+
|
|
113
|
+
### WorkOS
|
|
114
|
+
|
|
115
|
+
```typescript
|
|
116
|
+
upstream: {
|
|
117
|
+
provider: 'workos',
|
|
118
|
+
apiKey: process.env.WORKOS_API_KEY,
|
|
119
|
+
clientId: process.env.WORKOS_CLIENT_ID,
|
|
120
|
+
}
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
### Custom Provider
|
|
124
|
+
|
|
125
|
+
```typescript
|
|
126
|
+
upstream: {
|
|
127
|
+
provider: 'custom',
|
|
128
|
+
apiKey: 'your-client-secret',
|
|
129
|
+
clientId: 'your-client-id',
|
|
130
|
+
authorizationEndpoint: 'https://auth.example.com/authorize',
|
|
131
|
+
tokenEndpoint: 'https://auth.example.com/token',
|
|
132
|
+
}
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
## PKCE Utilities
|
|
136
|
+
|
|
137
|
+
The package also exports PKCE utilities:
|
|
138
|
+
|
|
139
|
+
```typescript
|
|
140
|
+
import { generatePkce, verifyCodeChallenge } from '@dotdo/oauth/pkce'
|
|
141
|
+
|
|
142
|
+
// Generate PKCE pair
|
|
143
|
+
const { verifier, challenge } = await generatePkce()
|
|
144
|
+
|
|
145
|
+
// Verify during token exchange
|
|
146
|
+
const valid = await verifyCodeChallenge(verifier, challenge, 'S256')
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
## Architecture
|
|
150
|
+
|
|
151
|
+
This package is the **leaf** in the dependency chain:
|
|
152
|
+
|
|
153
|
+
```
|
|
154
|
+
@dotdo/oauth (this package - pure OAuth 2.1, storage interface)
|
|
155
|
+
↓
|
|
156
|
+
@dotdo/do (depends on @dotdo/oauth, implements DOAuthStorage)
|
|
157
|
+
↓
|
|
158
|
+
oauth.do (depends on @dotdo/do for storage)
|
|
159
|
+
↓
|
|
160
|
+
dotdo (depends on oauth.do for auth)
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
Each layer adds capabilities:
|
|
164
|
+
- **@dotdo/oauth** - OAuth 2.1 primitives, abstract storage interface
|
|
165
|
+
- **@dotdo/do** - Concrete storage using Durable Object SQLite
|
|
166
|
+
- **oauth.do** - High-level auth SDK with session management
|
|
167
|
+
- **dotdo** - Full framework with auth built-in
|
|
168
|
+
|
|
169
|
+
## License
|
|
170
|
+
|
|
171
|
+
MIT
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @dotdo/oauth - OAuth 2.1 Server for MCP
|
|
3
|
+
*
|
|
4
|
+
* A minimal OAuth 2.1 authorization server implementation designed for
|
|
5
|
+
* Model Context Protocol (MCP) compatibility with Claude, ChatGPT, and other AI clients.
|
|
6
|
+
*
|
|
7
|
+
* This package is the "leaf" in the dependency tree - it has no dependencies on
|
|
8
|
+
* oauth.do or @dotdo/do, allowing them to depend on it without circular dependencies.
|
|
9
|
+
*
|
|
10
|
+
* @example Basic usage
|
|
11
|
+
* ```typescript
|
|
12
|
+
* import { createOAuth21Server, MemoryOAuthStorage } from '@dotdo/oauth'
|
|
13
|
+
*
|
|
14
|
+
* const server = createOAuth21Server({
|
|
15
|
+
* issuer: 'https://mcp.do',
|
|
16
|
+
* storage: new MemoryOAuthStorage(),
|
|
17
|
+
* upstream: {
|
|
18
|
+
* provider: 'workos',
|
|
19
|
+
* apiKey: env.WORKOS_API_KEY,
|
|
20
|
+
* clientId: env.WORKOS_CLIENT_ID,
|
|
21
|
+
* },
|
|
22
|
+
* })
|
|
23
|
+
*
|
|
24
|
+
* // Mount on Hono app
|
|
25
|
+
* app.route('/', server)
|
|
26
|
+
* ```
|
|
27
|
+
*
|
|
28
|
+
* @example With DO storage (provided by @dotdo/do)
|
|
29
|
+
* ```typescript
|
|
30
|
+
* import { createOAuth21Server } from '@dotdo/oauth'
|
|
31
|
+
* import { DOAuthStorage } from '@dotdo/do/oauth'
|
|
32
|
+
*
|
|
33
|
+
* const server = createOAuth21Server({
|
|
34
|
+
* issuer: 'https://mcp.do',
|
|
35
|
+
* storage: new DOAuthStorage(digitalObject),
|
|
36
|
+
* upstream: { ... },
|
|
37
|
+
* })
|
|
38
|
+
* ```
|
|
39
|
+
*
|
|
40
|
+
* @packageDocumentation
|
|
41
|
+
*/
|
|
42
|
+
export { createOAuth21Server } from './server';
|
|
43
|
+
export type { OAuth21ServerConfig } from './server';
|
|
44
|
+
export { MemoryOAuthStorage } from './storage';
|
|
45
|
+
export type { OAuthStorage, ListOptions } from './storage';
|
|
46
|
+
export { generateCodeVerifier, generateCodeChallenge, verifyCodeChallenge, generatePkce, generateState, generateToken, generateAuthorizationCode, hashClientSecret, verifyClientSecret, base64UrlEncode, base64UrlDecode, constantTimeEqual, } from './pkce';
|
|
47
|
+
export type { OAuthUser, OAuthOrganization, OAuthClient, OAuthAuthorizationCode, OAuthAccessToken, OAuthRefreshToken, OAuthGrant, OAuthServerMetadata, OAuthResourceMetadata, TokenResponse, OAuthError, UpstreamOAuthConfig, } from './types';
|
|
48
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAwCG;AAGH,OAAO,EAAE,mBAAmB,EAAE,MAAM,UAAU,CAAA;AAC9C,YAAY,EAAE,mBAAmB,EAAE,MAAM,UAAU,CAAA;AAGnD,OAAO,EAAE,kBAAkB,EAAE,MAAM,WAAW,CAAA;AAC9C,YAAY,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,WAAW,CAAA;AAG1D,OAAO,EACL,oBAAoB,EACpB,qBAAqB,EACrB,mBAAmB,EACnB,YAAY,EACZ,aAAa,EACb,aAAa,EACb,yBAAyB,EACzB,gBAAgB,EAChB,kBAAkB,EAClB,eAAe,EACf,eAAe,EACf,iBAAiB,GAClB,MAAM,QAAQ,CAAA;AAGf,YAAY,EACV,SAAS,EACT,iBAAiB,EACjB,WAAW,EACX,sBAAsB,EACtB,gBAAgB,EAChB,iBAAiB,EACjB,UAAU,EACV,mBAAmB,EACnB,qBAAqB,EACrB,aAAa,EACb,UAAU,EACV,mBAAmB,GACpB,MAAM,SAAS,CAAA"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @dotdo/oauth - OAuth 2.1 Server for MCP
|
|
3
|
+
*
|
|
4
|
+
* A minimal OAuth 2.1 authorization server implementation designed for
|
|
5
|
+
* Model Context Protocol (MCP) compatibility with Claude, ChatGPT, and other AI clients.
|
|
6
|
+
*
|
|
7
|
+
* This package is the "leaf" in the dependency tree - it has no dependencies on
|
|
8
|
+
* oauth.do or @dotdo/do, allowing them to depend on it without circular dependencies.
|
|
9
|
+
*
|
|
10
|
+
* @example Basic usage
|
|
11
|
+
* ```typescript
|
|
12
|
+
* import { createOAuth21Server, MemoryOAuthStorage } from '@dotdo/oauth'
|
|
13
|
+
*
|
|
14
|
+
* const server = createOAuth21Server({
|
|
15
|
+
* issuer: 'https://mcp.do',
|
|
16
|
+
* storage: new MemoryOAuthStorage(),
|
|
17
|
+
* upstream: {
|
|
18
|
+
* provider: 'workos',
|
|
19
|
+
* apiKey: env.WORKOS_API_KEY,
|
|
20
|
+
* clientId: env.WORKOS_CLIENT_ID,
|
|
21
|
+
* },
|
|
22
|
+
* })
|
|
23
|
+
*
|
|
24
|
+
* // Mount on Hono app
|
|
25
|
+
* app.route('/', server)
|
|
26
|
+
* ```
|
|
27
|
+
*
|
|
28
|
+
* @example With DO storage (provided by @dotdo/do)
|
|
29
|
+
* ```typescript
|
|
30
|
+
* import { createOAuth21Server } from '@dotdo/oauth'
|
|
31
|
+
* import { DOAuthStorage } from '@dotdo/do/oauth'
|
|
32
|
+
*
|
|
33
|
+
* const server = createOAuth21Server({
|
|
34
|
+
* issuer: 'https://mcp.do',
|
|
35
|
+
* storage: new DOAuthStorage(digitalObject),
|
|
36
|
+
* upstream: { ... },
|
|
37
|
+
* })
|
|
38
|
+
* ```
|
|
39
|
+
*
|
|
40
|
+
* @packageDocumentation
|
|
41
|
+
*/
|
|
42
|
+
// Server
|
|
43
|
+
export { createOAuth21Server } from './server';
|
|
44
|
+
// Storage
|
|
45
|
+
export { MemoryOAuthStorage } from './storage';
|
|
46
|
+
// PKCE
|
|
47
|
+
export { generateCodeVerifier, generateCodeChallenge, verifyCodeChallenge, generatePkce, generateState, generateToken, generateAuthorizationCode, hashClientSecret, verifyClientSecret, base64UrlEncode, base64UrlDecode, constantTimeEqual, } from './pkce';
|
|
48
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAwCG;AAEH,SAAS;AACT,OAAO,EAAE,mBAAmB,EAAE,MAAM,UAAU,CAAA;AAG9C,UAAU;AACV,OAAO,EAAE,kBAAkB,EAAE,MAAM,WAAW,CAAA;AAG9C,OAAO;AACP,OAAO,EACL,oBAAoB,EACpB,qBAAqB,EACrB,mBAAmB,EACnB,YAAY,EACZ,aAAa,EACb,aAAa,EACb,yBAAyB,EACzB,gBAAgB,EAChB,kBAAkB,EAClB,eAAe,EACf,eAAe,EACf,iBAAiB,GAClB,MAAM,QAAQ,CAAA"}
|
package/dist/pkce.d.ts
ADDED
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @dotdo/oauth - PKCE (Proof Key for Code Exchange) utilities
|
|
3
|
+
*
|
|
4
|
+
* OAuth 2.1 requires PKCE for all authorization code flows.
|
|
5
|
+
* Only S256 is supported (plain is deprecated in OAuth 2.1).
|
|
6
|
+
*/
|
|
7
|
+
/**
|
|
8
|
+
* Generate a cryptographically random code verifier
|
|
9
|
+
*
|
|
10
|
+
* Per RFC 7636, the verifier must be:
|
|
11
|
+
* - Between 43 and 128 characters long
|
|
12
|
+
* - Using only unreserved URI characters [A-Z] / [a-z] / [0-9] / "-" / "." / "_" / "~"
|
|
13
|
+
*
|
|
14
|
+
* @param length - Length of the verifier (default: 64)
|
|
15
|
+
* @returns Random code verifier string
|
|
16
|
+
*/
|
|
17
|
+
export declare function generateCodeVerifier(length?: number): string;
|
|
18
|
+
/**
|
|
19
|
+
* Generate a code challenge from a code verifier using S256 method
|
|
20
|
+
*
|
|
21
|
+
* S256: BASE64URL(SHA256(code_verifier))
|
|
22
|
+
*
|
|
23
|
+
* @param verifier - The code verifier
|
|
24
|
+
* @returns Base64URL-encoded SHA-256 hash of the verifier
|
|
25
|
+
*/
|
|
26
|
+
export declare function generateCodeChallenge(verifier: string): Promise<string>;
|
|
27
|
+
/**
|
|
28
|
+
* Verify a code verifier against a code challenge
|
|
29
|
+
*
|
|
30
|
+
* @param verifier - The code verifier from the token request
|
|
31
|
+
* @param challenge - The code challenge from the authorization request
|
|
32
|
+
* @param method - The challenge method (must be 'S256' for OAuth 2.1)
|
|
33
|
+
* @returns True if the verifier matches the challenge
|
|
34
|
+
*/
|
|
35
|
+
export declare function verifyCodeChallenge(verifier: string, challenge: string, method?: string): Promise<boolean>;
|
|
36
|
+
/**
|
|
37
|
+
* Generate a PKCE pair (verifier and challenge)
|
|
38
|
+
*
|
|
39
|
+
* @param length - Length of the verifier (default: 64)
|
|
40
|
+
* @returns Object with verifier and challenge
|
|
41
|
+
*/
|
|
42
|
+
export declare function generatePkce(length?: number): Promise<{
|
|
43
|
+
verifier: string;
|
|
44
|
+
challenge: string;
|
|
45
|
+
}>;
|
|
46
|
+
/**
|
|
47
|
+
* Base64URL encode an ArrayBuffer
|
|
48
|
+
*
|
|
49
|
+
* @param buffer - The buffer to encode
|
|
50
|
+
* @returns Base64URL-encoded string (no padding)
|
|
51
|
+
*/
|
|
52
|
+
export declare function base64UrlEncode(buffer: ArrayBuffer): string;
|
|
53
|
+
/**
|
|
54
|
+
* Base64URL decode a string to ArrayBuffer
|
|
55
|
+
*
|
|
56
|
+
* @param str - Base64URL-encoded string
|
|
57
|
+
* @returns Decoded ArrayBuffer
|
|
58
|
+
*/
|
|
59
|
+
export declare function base64UrlDecode(str: string): ArrayBuffer;
|
|
60
|
+
/**
|
|
61
|
+
* Constant-time string comparison to prevent timing attacks
|
|
62
|
+
*
|
|
63
|
+
* @param a - First string
|
|
64
|
+
* @param b - Second string
|
|
65
|
+
* @returns True if strings are equal
|
|
66
|
+
*/
|
|
67
|
+
export declare function constantTimeEqual(a: string, b: string): boolean;
|
|
68
|
+
/**
|
|
69
|
+
* Generate a random state parameter for CSRF protection
|
|
70
|
+
*
|
|
71
|
+
* @param length - Length of the state (default: 32)
|
|
72
|
+
* @returns Random state string
|
|
73
|
+
*/
|
|
74
|
+
export declare function generateState(length?: number): string;
|
|
75
|
+
/**
|
|
76
|
+
* Generate a random token (for access tokens, refresh tokens, etc.)
|
|
77
|
+
*
|
|
78
|
+
* @param length - Length of the token (default: 32)
|
|
79
|
+
* @returns Random token string
|
|
80
|
+
*/
|
|
81
|
+
export declare function generateToken(length?: number): string;
|
|
82
|
+
/**
|
|
83
|
+
* Generate a unique authorization code
|
|
84
|
+
*
|
|
85
|
+
* @returns Random authorization code
|
|
86
|
+
*/
|
|
87
|
+
export declare function generateAuthorizationCode(): string;
|
|
88
|
+
/**
|
|
89
|
+
* Hash a client secret for storage
|
|
90
|
+
*
|
|
91
|
+
* @param secret - The client secret to hash
|
|
92
|
+
* @returns SHA-256 hash of the secret
|
|
93
|
+
*/
|
|
94
|
+
export declare function hashClientSecret(secret: string): Promise<string>;
|
|
95
|
+
/**
|
|
96
|
+
* Verify a client secret against a hash
|
|
97
|
+
*
|
|
98
|
+
* @param secret - The client secret to verify
|
|
99
|
+
* @param hash - The stored hash
|
|
100
|
+
* @returns True if the secret matches the hash
|
|
101
|
+
*/
|
|
102
|
+
export declare function verifyClientSecret(secret: string, hash: string): Promise<boolean>;
|
|
103
|
+
//# sourceMappingURL=pkce.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pkce.d.ts","sourceRoot":"","sources":["../src/pkce.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH;;;;;;;;;GASG;AACH,wBAAgB,oBAAoB,CAAC,MAAM,GAAE,MAAW,GAAG,MAAM,CAehE;AAED;;;;;;;GAOG;AACH,wBAAsB,qBAAqB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAK7E;AAED;;;;;;;GAOG;AACH,wBAAsB,mBAAmB,CACvC,QAAQ,EAAE,MAAM,EAChB,SAAS,EAAE,MAAM,EACjB,MAAM,GAAE,MAAe,GACtB,OAAO,CAAC,OAAO,CAAC,CAQlB;AAED;;;;;GAKG;AACH,wBAAsB,YAAY,CAAC,MAAM,GAAE,MAAW,GAAG,OAAO,CAAC;IAAE,QAAQ,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,CAAA;CAAE,CAAC,CAIxG;AAED;;;;;GAKG;AACH,wBAAgB,eAAe,CAAC,MAAM,EAAE,WAAW,GAAG,MAAM,CAU3D;AAED;;;;;GAKG;AACH,wBAAgB,eAAe,CAAC,GAAG,EAAE,MAAM,GAAG,WAAW,CAWxD;AAED;;;;;;GAMG;AACH,wBAAgB,iBAAiB,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,GAAG,OAAO,CAW/D;AAED;;;;;GAKG;AACH,wBAAgB,aAAa,CAAC,MAAM,GAAE,MAAW,GAAG,MAAM,CAWzD;AAED;;;;;GAKG;AACH,wBAAgB,aAAa,CAAC,MAAM,GAAE,MAAW,GAAG,MAAM,CAWzD;AAED;;;;GAIG;AACH,wBAAgB,yBAAyB,IAAI,MAAM,CAElD;AAED;;;;;GAKG;AACH,wBAAsB,gBAAgB,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAKtE;AAED;;;;;;GAMG;AACH,wBAAsB,kBAAkB,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAGvF"}
|
package/dist/pkce.js
ADDED
|
@@ -0,0 +1,186 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @dotdo/oauth - PKCE (Proof Key for Code Exchange) utilities
|
|
3
|
+
*
|
|
4
|
+
* OAuth 2.1 requires PKCE for all authorization code flows.
|
|
5
|
+
* Only S256 is supported (plain is deprecated in OAuth 2.1).
|
|
6
|
+
*/
|
|
7
|
+
/**
|
|
8
|
+
* Generate a cryptographically random code verifier
|
|
9
|
+
*
|
|
10
|
+
* Per RFC 7636, the verifier must be:
|
|
11
|
+
* - Between 43 and 128 characters long
|
|
12
|
+
* - Using only unreserved URI characters [A-Z] / [a-z] / [0-9] / "-" / "." / "_" / "~"
|
|
13
|
+
*
|
|
14
|
+
* @param length - Length of the verifier (default: 64)
|
|
15
|
+
* @returns Random code verifier string
|
|
16
|
+
*/
|
|
17
|
+
export function generateCodeVerifier(length = 64) {
|
|
18
|
+
if (length < 43 || length > 128) {
|
|
19
|
+
throw new Error('Code verifier length must be between 43 and 128 characters');
|
|
20
|
+
}
|
|
21
|
+
const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~';
|
|
22
|
+
const randomValues = new Uint8Array(length);
|
|
23
|
+
crypto.getRandomValues(randomValues);
|
|
24
|
+
let verifier = '';
|
|
25
|
+
for (let i = 0; i < length; i++) {
|
|
26
|
+
verifier += chars[randomValues[i] % chars.length];
|
|
27
|
+
}
|
|
28
|
+
return verifier;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Generate a code challenge from a code verifier using S256 method
|
|
32
|
+
*
|
|
33
|
+
* S256: BASE64URL(SHA256(code_verifier))
|
|
34
|
+
*
|
|
35
|
+
* @param verifier - The code verifier
|
|
36
|
+
* @returns Base64URL-encoded SHA-256 hash of the verifier
|
|
37
|
+
*/
|
|
38
|
+
export async function generateCodeChallenge(verifier) {
|
|
39
|
+
const encoder = new TextEncoder();
|
|
40
|
+
const data = encoder.encode(verifier);
|
|
41
|
+
const hashBuffer = await crypto.subtle.digest('SHA-256', data);
|
|
42
|
+
return base64UrlEncode(hashBuffer);
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Verify a code verifier against a code challenge
|
|
46
|
+
*
|
|
47
|
+
* @param verifier - The code verifier from the token request
|
|
48
|
+
* @param challenge - The code challenge from the authorization request
|
|
49
|
+
* @param method - The challenge method (must be 'S256' for OAuth 2.1)
|
|
50
|
+
* @returns True if the verifier matches the challenge
|
|
51
|
+
*/
|
|
52
|
+
export async function verifyCodeChallenge(verifier, challenge, method = 'S256') {
|
|
53
|
+
if (method !== 'S256') {
|
|
54
|
+
// OAuth 2.1 only supports S256
|
|
55
|
+
return false;
|
|
56
|
+
}
|
|
57
|
+
const expectedChallenge = await generateCodeChallenge(verifier);
|
|
58
|
+
return constantTimeEqual(expectedChallenge, challenge);
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Generate a PKCE pair (verifier and challenge)
|
|
62
|
+
*
|
|
63
|
+
* @param length - Length of the verifier (default: 64)
|
|
64
|
+
* @returns Object with verifier and challenge
|
|
65
|
+
*/
|
|
66
|
+
export async function generatePkce(length = 64) {
|
|
67
|
+
const verifier = generateCodeVerifier(length);
|
|
68
|
+
const challenge = await generateCodeChallenge(verifier);
|
|
69
|
+
return { verifier, challenge };
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Base64URL encode an ArrayBuffer
|
|
73
|
+
*
|
|
74
|
+
* @param buffer - The buffer to encode
|
|
75
|
+
* @returns Base64URL-encoded string (no padding)
|
|
76
|
+
*/
|
|
77
|
+
export function base64UrlEncode(buffer) {
|
|
78
|
+
const bytes = new Uint8Array(buffer);
|
|
79
|
+
let binary = '';
|
|
80
|
+
for (let i = 0; i < bytes.length; i++) {
|
|
81
|
+
binary += String.fromCharCode(bytes[i]);
|
|
82
|
+
}
|
|
83
|
+
return btoa(binary)
|
|
84
|
+
.replace(/\+/g, '-')
|
|
85
|
+
.replace(/\//g, '_')
|
|
86
|
+
.replace(/=+$/, '');
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* Base64URL decode a string to ArrayBuffer
|
|
90
|
+
*
|
|
91
|
+
* @param str - Base64URL-encoded string
|
|
92
|
+
* @returns Decoded ArrayBuffer
|
|
93
|
+
*/
|
|
94
|
+
export function base64UrlDecode(str) {
|
|
95
|
+
// Add padding if needed
|
|
96
|
+
const padded = str + '='.repeat((4 - (str.length % 4)) % 4);
|
|
97
|
+
// Convert from base64url to base64
|
|
98
|
+
const base64 = padded.replace(/-/g, '+').replace(/_/g, '/');
|
|
99
|
+
const binary = atob(base64);
|
|
100
|
+
const bytes = new Uint8Array(binary.length);
|
|
101
|
+
for (let i = 0; i < binary.length; i++) {
|
|
102
|
+
bytes[i] = binary.charCodeAt(i);
|
|
103
|
+
}
|
|
104
|
+
return bytes.buffer;
|
|
105
|
+
}
|
|
106
|
+
/**
|
|
107
|
+
* Constant-time string comparison to prevent timing attacks
|
|
108
|
+
*
|
|
109
|
+
* @param a - First string
|
|
110
|
+
* @param b - Second string
|
|
111
|
+
* @returns True if strings are equal
|
|
112
|
+
*/
|
|
113
|
+
export function constantTimeEqual(a, b) {
|
|
114
|
+
if (a.length !== b.length) {
|
|
115
|
+
return false;
|
|
116
|
+
}
|
|
117
|
+
let result = 0;
|
|
118
|
+
for (let i = 0; i < a.length; i++) {
|
|
119
|
+
result |= a.charCodeAt(i) ^ b.charCodeAt(i);
|
|
120
|
+
}
|
|
121
|
+
return result === 0;
|
|
122
|
+
}
|
|
123
|
+
/**
|
|
124
|
+
* Generate a random state parameter for CSRF protection
|
|
125
|
+
*
|
|
126
|
+
* @param length - Length of the state (default: 32)
|
|
127
|
+
* @returns Random state string
|
|
128
|
+
*/
|
|
129
|
+
export function generateState(length = 32) {
|
|
130
|
+
const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
|
|
131
|
+
const randomValues = new Uint8Array(length);
|
|
132
|
+
crypto.getRandomValues(randomValues);
|
|
133
|
+
let state = '';
|
|
134
|
+
for (let i = 0; i < length; i++) {
|
|
135
|
+
state += chars[randomValues[i] % chars.length];
|
|
136
|
+
}
|
|
137
|
+
return state;
|
|
138
|
+
}
|
|
139
|
+
/**
|
|
140
|
+
* Generate a random token (for access tokens, refresh tokens, etc.)
|
|
141
|
+
*
|
|
142
|
+
* @param length - Length of the token (default: 32)
|
|
143
|
+
* @returns Random token string
|
|
144
|
+
*/
|
|
145
|
+
export function generateToken(length = 32) {
|
|
146
|
+
const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
|
|
147
|
+
const randomValues = new Uint8Array(length);
|
|
148
|
+
crypto.getRandomValues(randomValues);
|
|
149
|
+
let token = '';
|
|
150
|
+
for (let i = 0; i < length; i++) {
|
|
151
|
+
token += chars[randomValues[i] % chars.length];
|
|
152
|
+
}
|
|
153
|
+
return token;
|
|
154
|
+
}
|
|
155
|
+
/**
|
|
156
|
+
* Generate a unique authorization code
|
|
157
|
+
*
|
|
158
|
+
* @returns Random authorization code
|
|
159
|
+
*/
|
|
160
|
+
export function generateAuthorizationCode() {
|
|
161
|
+
return generateToken(48);
|
|
162
|
+
}
|
|
163
|
+
/**
|
|
164
|
+
* Hash a client secret for storage
|
|
165
|
+
*
|
|
166
|
+
* @param secret - The client secret to hash
|
|
167
|
+
* @returns SHA-256 hash of the secret
|
|
168
|
+
*/
|
|
169
|
+
export async function hashClientSecret(secret) {
|
|
170
|
+
const encoder = new TextEncoder();
|
|
171
|
+
const data = encoder.encode(secret);
|
|
172
|
+
const hashBuffer = await crypto.subtle.digest('SHA-256', data);
|
|
173
|
+
return base64UrlEncode(hashBuffer);
|
|
174
|
+
}
|
|
175
|
+
/**
|
|
176
|
+
* Verify a client secret against a hash
|
|
177
|
+
*
|
|
178
|
+
* @param secret - The client secret to verify
|
|
179
|
+
* @param hash - The stored hash
|
|
180
|
+
* @returns True if the secret matches the hash
|
|
181
|
+
*/
|
|
182
|
+
export async function verifyClientSecret(secret, hash) {
|
|
183
|
+
const expectedHash = await hashClientSecret(secret);
|
|
184
|
+
return constantTimeEqual(expectedHash, hash);
|
|
185
|
+
}
|
|
186
|
+
//# sourceMappingURL=pkce.js.map
|
package/dist/pkce.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pkce.js","sourceRoot":"","sources":["../src/pkce.ts"],"names":[],"mappings":"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"}
|
package/dist/server.d.ts
ADDED
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @dotdo/oauth - OAuth 2.1 Server Implementation
|
|
3
|
+
*
|
|
4
|
+
* Creates a Hono app that implements OAuth 2.1 authorization server endpoints:
|
|
5
|
+
* - /.well-known/oauth-authorization-server (RFC 8414)
|
|
6
|
+
* - /.well-known/oauth-protected-resource (draft-ietf-oauth-resource-metadata)
|
|
7
|
+
* - /authorize (authorization endpoint)
|
|
8
|
+
* - /callback (upstream OAuth callback)
|
|
9
|
+
* - /token (token endpoint)
|
|
10
|
+
* - /register (dynamic client registration - RFC 7591)
|
|
11
|
+
* - /revoke (token revocation - RFC 7009)
|
|
12
|
+
*
|
|
13
|
+
* This server acts as a federated OAuth 2.1 server:
|
|
14
|
+
* - It is an OAuth SERVER to downstream clients (Claude, ChatGPT, etc.)
|
|
15
|
+
* - It is an OAuth CLIENT to upstream providers (WorkOS, Auth0, etc.)
|
|
16
|
+
*/
|
|
17
|
+
import { Hono } from 'hono';
|
|
18
|
+
import type { OAuthStorage } from './storage';
|
|
19
|
+
import type { OAuthUser, UpstreamOAuthConfig } from './types';
|
|
20
|
+
/**
|
|
21
|
+
* Configuration for the OAuth 2.1 server
|
|
22
|
+
*/
|
|
23
|
+
export interface OAuth21ServerConfig {
|
|
24
|
+
/** Server issuer URL (e.g., https://mcp.do) */
|
|
25
|
+
issuer: string;
|
|
26
|
+
/** Storage backend for users, clients, tokens */
|
|
27
|
+
storage: OAuthStorage;
|
|
28
|
+
/** Upstream OAuth provider configuration */
|
|
29
|
+
upstream: UpstreamOAuthConfig;
|
|
30
|
+
/** Supported scopes */
|
|
31
|
+
scopes?: string[];
|
|
32
|
+
/** Access token lifetime in seconds (default: 3600) */
|
|
33
|
+
accessTokenTtl?: number;
|
|
34
|
+
/** Refresh token lifetime in seconds (default: 2592000 = 30 days) */
|
|
35
|
+
refreshTokenTtl?: number;
|
|
36
|
+
/** Authorization code lifetime in seconds (default: 600 = 10 minutes) */
|
|
37
|
+
authCodeTtl?: number;
|
|
38
|
+
/** Enable dynamic client registration */
|
|
39
|
+
enableDynamicRegistration?: boolean;
|
|
40
|
+
/** Callback after successful user authentication */
|
|
41
|
+
onUserAuthenticated?: (user: OAuthUser) => void | Promise<void>;
|
|
42
|
+
/** Enable debug logging */
|
|
43
|
+
debug?: boolean;
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Create an OAuth 2.1 server as a Hono app
|
|
47
|
+
*
|
|
48
|
+
* @example
|
|
49
|
+
* ```typescript
|
|
50
|
+
* import { createOAuth21Server, MemoryOAuthStorage } from '@dotdo/oauth'
|
|
51
|
+
*
|
|
52
|
+
* const oauthServer = createOAuth21Server({
|
|
53
|
+
* issuer: 'https://mcp.do',
|
|
54
|
+
* storage: new MemoryOAuthStorage(),
|
|
55
|
+
* upstream: {
|
|
56
|
+
* provider: 'workos',
|
|
57
|
+
* apiKey: env.WORKOS_API_KEY,
|
|
58
|
+
* clientId: env.WORKOS_CLIENT_ID,
|
|
59
|
+
* },
|
|
60
|
+
* })
|
|
61
|
+
*
|
|
62
|
+
* // Mount on your main app
|
|
63
|
+
* app.route('/', oauthServer)
|
|
64
|
+
* ```
|
|
65
|
+
*/
|
|
66
|
+
export declare function createOAuth21Server(config: OAuth21ServerConfig): Hono;
|
|
67
|
+
//# sourceMappingURL=server.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAA;AAE3B,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,WAAW,CAAA;AAC7C,OAAO,KAAK,EAIV,SAAS,EAGT,mBAAmB,EACpB,MAAM,SAAS,CAAA;AAShB;;GAEG;AACH,MAAM,WAAW,mBAAmB;IAClC,+CAA+C;IAC/C,MAAM,EAAE,MAAM,CAAA;IACd,iDAAiD;IACjD,OAAO,EAAE,YAAY,CAAA;IACrB,4CAA4C;IAC5C,QAAQ,EAAE,mBAAmB,CAAA;IAC7B,uBAAuB;IACvB,MAAM,CAAC,EAAE,MAAM,EAAE,CAAA;IACjB,uDAAuD;IACvD,cAAc,CAAC,EAAE,MAAM,CAAA;IACvB,qEAAqE;IACrE,eAAe,CAAC,EAAE,MAAM,CAAA;IACxB,yEAAyE;IACzE,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,yCAAyC;IACzC,yBAAyB,CAAC,EAAE,OAAO,CAAA;IACnC,oDAAoD;IACpD,mBAAmB,CAAC,EAAE,CAAC,IAAI,EAAE,SAAS,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;IAC/D,2BAA2B;IAC3B,KAAK,CAAC,EAAE,OAAO,CAAA;CAChB;AAED;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,mBAAmB,GAAG,IAAI,CAuXrE"}
|