@codefox-inc/oauth-provider 0.2.2 → 0.2.3

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 (2) hide show
  1. package/README.md +26 -45
  2. package/package.json +1 -1
package/README.md CHANGED
@@ -6,6 +6,16 @@ OAuth 2.1 / OpenID Connect Provider implemented as a Convex component.
6
6
  > Built for [Convex Auth](https://labs.convex.dev/auth) which is currently in **Beta**.
7
7
  > Expect breaking changes. Production use at your own risk.
8
8
 
9
+ ## Why?
10
+
11
+ Most MCP clients (like Claude Code or ChatGPT) require your app to be an OAuth provider. If you want to connect your Convex app to MCP clients, you need to implement OAuth 2.1.
12
+
13
+ This component turns your Convex Auth app into a fully compliant OAuth 2.1 provider, so you can:
14
+ - Connect to MCP clients out of the box
15
+ - Let clients register automatically via Dynamic Client Registration
16
+ - Let users control what permissions each app gets
17
+ - Focus on your app, not OAuth complexity
18
+
9
19
  ## Installation
10
20
 
11
21
  ```bash
@@ -113,13 +123,7 @@ if (isOAuthToken(identity)) {
113
123
 
114
124
  #### With Convex Auth (Recommended)
115
125
 
116
- If you're using [Convex Auth](https://labs.convex.dev/auth), run the setup command:
117
-
118
- ```bash
119
- npx @convex-dev/auth
120
- ```
121
-
122
- This automatically sets `JWT_PRIVATE_KEY`, `JWKS`, and `SITE_URL`. The OAuth Provider will use these by default.
126
+ If you're using [Convex Auth](https://labs.convex.dev/auth), you already have the required environment variables configured (`JWT_PRIVATE_KEY`, `JWKS`, `SITE_URL`).
123
127
 
124
128
  #### Without Convex Auth
125
129
 
@@ -145,8 +149,8 @@ const privateKey = fs.readFileSync('private.pem', 'utf8');
145
149
  Set environment variables:
146
150
 
147
151
  ```bash
148
- npx convex env set OAUTH_PRIVATE_KEY "-----BEGIN RSA PRIVATE KEY-----\n..."
149
- npx convex env set OAUTH_JWKS '{"keys":[...]}'
152
+ npx convex env set JWT_PRIVATE_KEY "-----BEGIN RSA PRIVATE KEY-----\n..."
153
+ npx convex env set JWKS '{"keys":[...]}'
150
154
  npx convex env set SITE_URL "https://your-app.example.com"
151
155
  ```
152
156
 
@@ -178,23 +182,15 @@ import { api } from "./_generated/api";
178
182
  const http = httpRouter();
179
183
 
180
184
  const oauthProvider = new OAuthProvider(components.oauthProvider, {
181
- privateKey: process.env.OAUTH_PRIVATE_KEY!,
182
- jwks: process.env.OAUTH_JWKS!,
185
+ privateKey: process.env.JWT_PRIVATE_KEY!,
186
+ jwks: process.env.JWKS!,
183
187
  siteUrl: process.env.SITE_URL!,
184
- convexSiteUrl: process.env.CONVEX_SITE_URL,
185
- // OPTIONAL: OAuth endpoint prefix (default: "/oauth")
186
- // Note: This must match the route prefix used below.
187
- // prefix: "/oauth",
188
- allowedScopes: ["openid", "profile", "email", "offline_access"],
189
188
 
190
189
  // REQUIRED: Authenticate user for authorization endpoint
191
190
  getUserId: async (ctx, request) => {
192
191
  const identity = await ctx.auth.getUserIdentity();
193
192
  return identity?.subject ?? null;
194
193
  },
195
-
196
- // OPTIONAL: Enable dynamic client registration (default: false)
197
- allowDynamicClientRegistration: false,
198
194
  });
199
195
 
200
196
  // Register all OAuth routes automatically
@@ -230,14 +226,9 @@ import { components } from "./_generated/api";
230
226
  const http = httpRouter();
231
227
 
232
228
  const oauthProvider = new OAuthProvider(components.oauthProvider, {
233
- privateKey: process.env.OAUTH_PRIVATE_KEY!,
234
- jwks: process.env.OAUTH_JWKS!,
229
+ privateKey: process.env.JWT_PRIVATE_KEY!,
230
+ jwks: process.env.JWKS!,
235
231
  siteUrl: process.env.SITE_URL!,
236
- convexSiteUrl: process.env.CONVEX_SITE_URL,
237
- // OPTIONAL: OAuth endpoint prefix (default: "/oauth")
238
- // Note: This must match the route prefix used below.
239
- // prefix: "/oauth",
240
- allowedScopes: ["openid", "profile", "email", "offline_access"],
241
232
 
242
233
  // REQUIRED: Authenticate user for authorization endpoint
243
234
  getUserId: async (ctx, request) => {
@@ -335,8 +326,8 @@ export const registerOAuthClient = mutation({
335
326
  if (!identity) throw new Error("Unauthorized");
336
327
 
337
328
  const oauthProvider = new OAuthProvider(components.oauthProvider, {
338
- privateKey: process.env.OAUTH_PRIVATE_KEY!,
339
- jwks: process.env.OAUTH_JWKS!,
329
+ privateKey: process.env.JWT_PRIVATE_KEY!,
330
+ jwks: process.env.JWKS!,
340
331
  siteUrl: process.env.SITE_URL!,
341
332
  });
342
333
 
@@ -404,8 +395,8 @@ export const approveAuthorization = mutation({
404
395
  if (!identity) throw new Error("Not authenticated");
405
396
 
406
397
  const oauthProvider = new OAuthProvider(components.oauthProvider, {
407
- privateKey: process.env.OAUTH_PRIVATE_KEY!,
408
- jwks: process.env.OAUTH_JWKS!,
398
+ privateKey: process.env.JWT_PRIVATE_KEY!,
399
+ jwks: process.env.JWKS!,
409
400
  siteUrl: process.env.SITE_URL!,
410
401
  });
411
402
 
@@ -440,8 +431,8 @@ export const listAuthorizedApps = query({
440
431
  if (!identity) return [];
441
432
 
442
433
  const oauthProvider = new OAuthProvider(components.oauthProvider, {
443
- privateKey: process.env.OAUTH_PRIVATE_KEY!,
444
- jwks: process.env.OAUTH_JWKS!,
434
+ privateKey: process.env.JWT_PRIVATE_KEY!,
435
+ jwks: process.env.JWKS!,
445
436
  siteUrl: process.env.SITE_URL!,
446
437
  });
447
438
 
@@ -463,8 +454,8 @@ export const revokeApp = mutation({
463
454
  if (!identity) throw new Error("Not authenticated");
464
455
 
465
456
  const oauthProvider = new OAuthProvider(components.oauthProvider, {
466
- privateKey: process.env.OAUTH_PRIVATE_KEY!,
467
- jwks: process.env.OAUTH_JWKS!,
457
+ privateKey: process.env.JWT_PRIVATE_KEY!,
458
+ jwks: process.env.JWKS!,
468
459
  siteUrl: process.env.SITE_URL!,
469
460
  });
470
461
 
@@ -540,7 +531,7 @@ import { verifyAccessToken } from "@codefox-inc/oauth-provider";
540
531
  const payload = await verifyAccessToken(
541
532
  token,
542
533
  {
543
- jwks: process.env.OAUTH_JWKS!,
534
+ jwks: process.env.JWKS!,
544
535
  siteUrl: process.env.SITE_URL!,
545
536
  },
546
537
  issuerUrl
@@ -551,16 +542,6 @@ console.log("Scopes:", payload.scp);
551
542
  console.log("Client ID:", payload.cid);
552
543
  ```
553
544
 
554
- ## Environment Variables Reference
555
-
556
- | Variable | Required | Description |
557
- |----------|----------|-------------|
558
- | `OAUTH_PRIVATE_KEY` | Yes | RSA private key (PEM format) |
559
- | `OAUTH_JWKS` | Yes | JSON Web Key Set for token verification |
560
- | `SITE_URL` | Yes | Your application's public URL |
561
- | `CONVEX_SITE_URL` | No | Convex deployment URL (used as issuer if set) |
562
- | `ALLOWED_ORIGINS` | No | Comma-separated CORS origins |
563
-
564
545
  ## Testing
565
546
 
566
547
  ```bash
package/package.json CHANGED
@@ -6,7 +6,7 @@
6
6
  "bugs": {
7
7
  "url": "https://github.com/codefox-inc/convex-oauth-provider/issues"
8
8
  },
9
- "version": "0.2.2",
9
+ "version": "0.2.3",
10
10
  "license": "Apache-2.0",
11
11
  "publishConfig": {
12
12
  "access": "public"