@codefox-inc/oauth-provider 0.2.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.
Files changed (113) hide show
  1. package/LICENSE +201 -0
  2. package/README.md +572 -0
  3. package/dist/client/_generated/_ignore.d.ts +1 -0
  4. package/dist/client/_generated/_ignore.d.ts.map +1 -0
  5. package/dist/client/_generated/_ignore.js +3 -0
  6. package/dist/client/_generated/_ignore.js.map +1 -0
  7. package/dist/client/auth-config.d.ts +85 -0
  8. package/dist/client/auth-config.d.ts.map +1 -0
  9. package/dist/client/auth-config.js +81 -0
  10. package/dist/client/auth-config.js.map +1 -0
  11. package/dist/client/auth-helper.d.ts +81 -0
  12. package/dist/client/auth-helper.d.ts.map +1 -0
  13. package/dist/client/auth-helper.js +97 -0
  14. package/dist/client/auth-helper.js.map +1 -0
  15. package/dist/client/index.d.ts +189 -0
  16. package/dist/client/index.d.ts.map +1 -0
  17. package/dist/client/index.js +230 -0
  18. package/dist/client/index.js.map +1 -0
  19. package/dist/client/routes.d.ts +94 -0
  20. package/dist/client/routes.d.ts.map +1 -0
  21. package/dist/client/routes.js +113 -0
  22. package/dist/client/routes.js.map +1 -0
  23. package/dist/component/_generated/api.d.ts +44 -0
  24. package/dist/component/_generated/api.d.ts.map +1 -0
  25. package/dist/component/_generated/api.js +31 -0
  26. package/dist/component/_generated/api.js.map +1 -0
  27. package/dist/component/_generated/component.d.ts +123 -0
  28. package/dist/component/_generated/component.d.ts.map +1 -0
  29. package/dist/component/_generated/component.js +11 -0
  30. package/dist/component/_generated/component.js.map +1 -0
  31. package/dist/component/_generated/dataModel.d.ts +46 -0
  32. package/dist/component/_generated/dataModel.d.ts.map +1 -0
  33. package/dist/component/_generated/dataModel.js +11 -0
  34. package/dist/component/_generated/dataModel.js.map +1 -0
  35. package/dist/component/_generated/server.d.ts +121 -0
  36. package/dist/component/_generated/server.d.ts.map +1 -0
  37. package/dist/component/_generated/server.js +78 -0
  38. package/dist/component/_generated/server.js.map +1 -0
  39. package/dist/component/clientManagement.d.ts +39 -0
  40. package/dist/component/clientManagement.d.ts.map +1 -0
  41. package/dist/component/clientManagement.js +169 -0
  42. package/dist/component/clientManagement.js.map +1 -0
  43. package/dist/component/constants.d.ts +31 -0
  44. package/dist/component/constants.d.ts.map +1 -0
  45. package/dist/component/constants.js +36 -0
  46. package/dist/component/constants.js.map +1 -0
  47. package/dist/component/convex.config.d.ts +3 -0
  48. package/dist/component/convex.config.d.ts.map +1 -0
  49. package/dist/component/convex.config.js +3 -0
  50. package/dist/component/convex.config.js.map +1 -0
  51. package/dist/component/handlers.d.ts +143 -0
  52. package/dist/component/handlers.d.ts.map +1 -0
  53. package/dist/component/handlers.js +624 -0
  54. package/dist/component/handlers.js.map +1 -0
  55. package/dist/component/mutations.d.ts +111 -0
  56. package/dist/component/mutations.d.ts.map +1 -0
  57. package/dist/component/mutations.js +459 -0
  58. package/dist/component/mutations.js.map +1 -0
  59. package/dist/component/queries.d.ts +127 -0
  60. package/dist/component/queries.d.ts.map +1 -0
  61. package/dist/component/queries.js +145 -0
  62. package/dist/component/queries.js.map +1 -0
  63. package/dist/component/schema.d.ts +116 -0
  64. package/dist/component/schema.d.ts.map +1 -0
  65. package/dist/component/schema.js +77 -0
  66. package/dist/component/schema.js.map +1 -0
  67. package/dist/component/token_security.d.ts +53 -0
  68. package/dist/component/token_security.d.ts.map +1 -0
  69. package/dist/component/token_security.js +91 -0
  70. package/dist/component/token_security.js.map +1 -0
  71. package/dist/lib/convex-types.d.ts +21 -0
  72. package/dist/lib/convex-types.d.ts.map +1 -0
  73. package/dist/lib/convex-types.js +2 -0
  74. package/dist/lib/convex-types.js.map +1 -0
  75. package/dist/lib/oauth.d.ts +123 -0
  76. package/dist/lib/oauth.d.ts.map +1 -0
  77. package/dist/lib/oauth.js +295 -0
  78. package/dist/lib/oauth.js.map +1 -0
  79. package/dist/react/index.d.ts +2 -0
  80. package/dist/react/index.d.ts.map +1 -0
  81. package/dist/react/index.js +6 -0
  82. package/dist/react/index.js.map +1 -0
  83. package/package.json +121 -0
  84. package/src/client/__tests__/auth-config.test.ts +244 -0
  85. package/src/client/__tests__/auth-helper.test.ts +273 -0
  86. package/src/client/__tests__/oauth-provider.test.ts +418 -0
  87. package/src/client/__tests__/routes.test.ts +428 -0
  88. package/src/client/_generated/_ignore.ts +1 -0
  89. package/src/client/auth-config.ts +157 -0
  90. package/src/client/auth-helper.ts +201 -0
  91. package/src/client/index.ts +326 -0
  92. package/src/client/routes.ts +251 -0
  93. package/src/component/__tests__/oauth.test.ts +3310 -0
  94. package/src/component/__tests__/rfc-compliance.test.ts +788 -0
  95. package/src/component/__tests__/token-security.test.ts +133 -0
  96. package/src/component/_generated/api.ts +60 -0
  97. package/src/component/_generated/component.ts +201 -0
  98. package/src/component/_generated/dataModel.ts +60 -0
  99. package/src/component/_generated/server.ts +156 -0
  100. package/src/component/clientManagement.ts +189 -0
  101. package/src/component/constants.ts +40 -0
  102. package/src/component/convex.config.ts +3 -0
  103. package/src/component/handlers.ts +964 -0
  104. package/src/component/mutations.ts +531 -0
  105. package/src/component/queries.ts +165 -0
  106. package/src/component/schema.ts +92 -0
  107. package/src/component/token_security.ts +102 -0
  108. package/src/lib/__tests__/oauth-helpers.test.ts +143 -0
  109. package/src/lib/__tests__/oauth-jwt.test.ts +405 -0
  110. package/src/lib/convex-types.ts +37 -0
  111. package/src/lib/oauth.ts +412 -0
  112. package/src/react/index.ts +7 -0
  113. package/src/test.ts +21 -0
@@ -0,0 +1,81 @@
1
+ /**
2
+ * Auth Config Generator
3
+ *
4
+ * Generates auth.config.ts configuration for Convex Auth
5
+ * to trust JWTs from the OAuth Provider.
6
+ */
7
+ import { normalizePrefix } from "../lib/oauth.js";
8
+ /**
9
+ * Generate auth.config.ts configuration for OAuth Provider
10
+ *
11
+ * @example
12
+ * ```typescript
13
+ * // convex/auth.config.ts
14
+ * import { generateAuthConfig } from "@codefox-inc/oauth-provider";
15
+ *
16
+ * export default generateAuthConfig({
17
+ * convexSiteUrl: process.env.CONVEX_SITE_URL,
18
+ * localPort: 5173,
19
+ * });
20
+ * ```
21
+ *
22
+ * @example Output
23
+ * ```javascript
24
+ * {
25
+ * providers: [
26
+ * { domain: "https://your-app.convex.site", applicationID: "convex" },
27
+ * { domain: "http://localhost:5173/oauth", applicationID: "convex" },
28
+ * { domain: "https://your-app.convex.site/oauth", applicationID: "convex" },
29
+ * ]
30
+ * }
31
+ * ```
32
+ */
33
+ export function generateAuthConfig(options = {}) {
34
+ const { convexSiteUrl, localPort = 5173, prefix: rawPrefix = "/oauth", applicationID = "convex", additionalProviders = [], includeConvexSiteUrl = true, } = options;
35
+ const prefix = normalizePrefix(rawPrefix);
36
+ const providers = [];
37
+ // 1. CONVEX_SITE_URL for Convex Auth (session-based auth)
38
+ if (includeConvexSiteUrl && convexSiteUrl) {
39
+ providers.push({
40
+ domain: convexSiteUrl,
41
+ applicationID,
42
+ });
43
+ }
44
+ // 2. Local development OAuth issuer
45
+ providers.push({
46
+ domain: `http://localhost:${localPort}${prefix}`,
47
+ applicationID,
48
+ });
49
+ // 3. Production OAuth issuer (CONVEX_SITE_URL + prefix)
50
+ if (convexSiteUrl) {
51
+ providers.push({
52
+ domain: `${convexSiteUrl}${prefix}`,
53
+ applicationID,
54
+ });
55
+ }
56
+ // 4. Additional providers
57
+ providers.push(...additionalProviders);
58
+ return { providers };
59
+ }
60
+ /**
61
+ * Create auth config with validation
62
+ * Throws if required environment variables are missing
63
+ */
64
+ export function createAuthConfig(options = {}) {
65
+ const config = generateAuthConfig(options);
66
+ const prefix = normalizePrefix(options.prefix);
67
+ const localPort = options.localPort ?? 5173;
68
+ // Validate that we have at least one OAuth issuer (with the configured prefix/port)
69
+ const hasOAuthIssuer = config.providers.some(p => {
70
+ if (prefix) {
71
+ return p.domain.includes(prefix) || p.domain.includes(`:${localPort}`);
72
+ }
73
+ return p.domain.includes(`:${localPort}`) || (!!options.convexSiteUrl && p.domain === options.convexSiteUrl);
74
+ });
75
+ if (!hasOAuthIssuer) {
76
+ console.warn("[oauth-provider] Warning: No OAuth issuer found in auth config. " +
77
+ "MCP clients may not be able to authenticate.");
78
+ }
79
+ return config;
80
+ }
81
+ //# sourceMappingURL=auth-config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"auth-config.js","sourceRoot":"","sources":["../../src/client/auth-config.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AAyDlD;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,MAAM,UAAU,kBAAkB,CAAC,UAAqC,EAAE;IACtE,MAAM,EACF,aAAa,EACb,SAAS,GAAG,IAAI,EAChB,MAAM,EAAE,SAAS,GAAG,QAAQ,EAC5B,aAAa,GAAG,QAAQ,EACxB,mBAAmB,GAAG,EAAE,EACxB,oBAAoB,GAAG,IAAI,GAC9B,GAAG,OAAO,CAAC;IACZ,MAAM,MAAM,GAAG,eAAe,CAAC,SAAS,CAAC,CAAC;IAE1C,MAAM,SAAS,GAAmB,EAAE,CAAC;IAErC,0DAA0D;IAC1D,IAAI,oBAAoB,IAAI,aAAa,EAAE,CAAC;QACxC,SAAS,CAAC,IAAI,CAAC;YACX,MAAM,EAAE,aAAa;YACrB,aAAa;SAChB,CAAC,CAAC;IACP,CAAC;IAED,oCAAoC;IACpC,SAAS,CAAC,IAAI,CAAC;QACX,MAAM,EAAE,oBAAoB,SAAS,GAAG,MAAM,EAAE;QAChD,aAAa;KAChB,CAAC,CAAC;IAEH,wDAAwD;IACxD,IAAI,aAAa,EAAE,CAAC;QAChB,SAAS,CAAC,IAAI,CAAC;YACX,MAAM,EAAE,GAAG,aAAa,GAAG,MAAM,EAAE;YACnC,aAAa;SAChB,CAAC,CAAC;IACP,CAAC;IAED,0BAA0B;IAC1B,SAAS,CAAC,IAAI,CAAC,GAAG,mBAAmB,CAAC,CAAC;IAEvC,OAAO,EAAE,SAAS,EAAE,CAAC;AACzB,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,gBAAgB,CAAC,UAAqC,EAAE;IACpE,MAAM,MAAM,GAAG,kBAAkB,CAAC,OAAO,CAAC,CAAC;IAE3C,MAAM,MAAM,GAAG,eAAe,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;IAC/C,MAAM,SAAS,GAAG,OAAO,CAAC,SAAS,IAAI,IAAI,CAAC;IAE5C,oFAAoF;IACpF,MAAM,cAAc,GAAG,MAAM,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE;QAC7C,IAAI,MAAM,EAAE,CAAC;YACT,OAAO,CAAC,CAAC,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,QAAQ,CAAC,IAAI,SAAS,EAAE,CAAC,CAAC;QAC3E,CAAC;QACD,OAAO,CAAC,CAAC,MAAM,CAAC,QAAQ,CAAC,IAAI,SAAS,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC,OAAO,CAAC,aAAa,IAAI,CAAC,CAAC,MAAM,KAAK,OAAO,CAAC,aAAa,CAAC,CAAC;IACjH,CAAC,CAAC,CAAC;IAEH,IAAI,CAAC,cAAc,EAAE,CAAC;QAClB,OAAO,CAAC,IAAI,CACR,kEAAkE;YAClE,8CAA8C,CACjD,CAAC;IACN,CAAC;IAED,OAAO,MAAM,CAAC;AAClB,CAAC"}
@@ -0,0 +1,81 @@
1
+ /**
2
+ * Auth Helper for handling both Convex Auth and OAuth tokens
3
+ *
4
+ * This helper provides a unified way to get the current user
5
+ * regardless of whether they authenticated via Convex Auth (session)
6
+ * or OAuth token (MCP clients).
7
+ */
8
+ /**
9
+ * Context types (simplified for compatibility)
10
+ */
11
+ type QueryCtx = any;
12
+ type MutationCtx = any;
13
+ /**
14
+ * Configuration for the auth helper
15
+ */
16
+ export interface AuthHelperConfig {
17
+ /**
18
+ * Convex Auth provider names to check for subject ID lookup
19
+ * @example ["anonymous", "password", "google"]
20
+ */
21
+ providers?: string[];
22
+ /**
23
+ * Custom function to get auth user ID from Convex Auth
24
+ * If not provided, you must pass it when calling methods
25
+ */
26
+ getAuthUserId?: (ctx: QueryCtx | MutationCtx) => Promise<string | null>;
27
+ /**
28
+ * Function to check if OAuth authorization is still valid
29
+ * Called for OAuth token requests to verify the authorization wasn't revoked
30
+ * @param ctx - Query/Mutation context
31
+ * @param userId - User ID from JWT
32
+ * @param clientId - Client ID from JWT (may be undefined if not in JWT)
33
+ * @returns true if authorization is valid, false if revoked
34
+ */
35
+ checkAuthorization?: (ctx: QueryCtx | MutationCtx, userId: string, clientId?: string) => Promise<boolean>;
36
+ /**
37
+ * OAuth issuer URL pattern to identify OAuth tokens
38
+ * If the token's issuer contains this string, authorization check is enforced
39
+ * @example "/oauth"
40
+ */
41
+ oauthIssuerPattern?: string;
42
+ }
43
+ /**
44
+ * Auth Helper instance
45
+ */
46
+ export interface AuthHelper {
47
+ /**
48
+ * Get the current user ID from either Convex Auth or OAuth token
49
+ * Returns null if not authenticated
50
+ */
51
+ getCurrentUserId: (ctx: QueryCtx | MutationCtx, getAuthUserId?: (ctx: QueryCtx | MutationCtx) => Promise<string | null>) => Promise<string | null>;
52
+ /**
53
+ * Get the current user document from the database
54
+ * Returns null if not authenticated or user not found
55
+ */
56
+ getCurrentUser: <T>(ctx: QueryCtx | MutationCtx, getAuthUserId?: (ctx: QueryCtx | MutationCtx) => Promise<string | null>) => Promise<T | null>;
57
+ /**
58
+ * Require authentication - throws if not authenticated
59
+ */
60
+ requireAuth: (ctx: QueryCtx | MutationCtx, getAuthUserId?: (ctx: QueryCtx | MutationCtx) => Promise<string | null>) => Promise<string>;
61
+ }
62
+ /**
63
+ * Create an auth helper for handling both Convex Auth and OAuth tokens
64
+ *
65
+ * @example
66
+ * ```typescript
67
+ * import { createAuthHelper } from "@codefox-inc/oauth-provider";
68
+ * import { getAuthUserId } from "./auth";
69
+ *
70
+ * const authHelper = createAuthHelper({
71
+ * providers: ["anonymous"],
72
+ * });
73
+ *
74
+ * // In a query/mutation:
75
+ * const userId = await authHelper.getCurrentUserId(ctx, getAuthUserId);
76
+ * const user = await authHelper.getCurrentUser(ctx, getAuthUserId);
77
+ * ```
78
+ */
79
+ export declare function createAuthHelper(config?: AuthHelperConfig): AuthHelper;
80
+ export {};
81
+ //# sourceMappingURL=auth-helper.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"auth-helper.d.ts","sourceRoot":"","sources":["../../src/client/auth-helper.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAQH;;GAEG;AAEH,KAAK,QAAQ,GAAG,GAAG,CAAC;AAEpB,KAAK,WAAW,GAAG,GAAG,CAAC;AAEvB;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC7B;;;OAGG;IACH,SAAS,CAAC,EAAE,MAAM,EAAE,CAAC;IAErB;;;OAGG;IACH,aAAa,CAAC,EAAE,CAAC,GAAG,EAAE,QAAQ,GAAG,WAAW,KAAK,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;IAExE;;;;;;;OAOG;IACH,kBAAkB,CAAC,EAAE,CAAC,GAAG,EAAE,QAAQ,GAAG,WAAW,EAAE,MAAM,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;IAE1G;;;;OAIG;IACH,kBAAkB,CAAC,EAAE,MAAM,CAAC;CAC/B;AAED;;GAEG;AACH,MAAM,WAAW,UAAU;IACvB;;;OAGG;IACH,gBAAgB,EAAE,CACd,GAAG,EAAE,QAAQ,GAAG,WAAW,EAC3B,aAAa,CAAC,EAAE,CAAC,GAAG,EAAE,QAAQ,GAAG,WAAW,KAAK,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,KACtE,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;IAE5B;;;OAGG;IACH,cAAc,EAAE,CAAC,CAAC,EACd,GAAG,EAAE,QAAQ,GAAG,WAAW,EAC3B,aAAa,CAAC,EAAE,CAAC,GAAG,EAAE,QAAQ,GAAG,WAAW,KAAK,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,KACtE,OAAO,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC;IAEvB;;OAEG;IACH,WAAW,EAAE,CACT,GAAG,EAAE,QAAQ,GAAG,WAAW,EAC3B,aAAa,CAAC,EAAE,CAAC,GAAG,EAAE,QAAQ,GAAG,WAAW,KAAK,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,KACtE,OAAO,CAAC,MAAM,CAAC,CAAC;CACxB;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,gBAAgB,CAAC,MAAM,GAAE,gBAAqB,GAAG,UAAU,CAgG1E"}
@@ -0,0 +1,97 @@
1
+ /**
2
+ * Auth Helper for handling both Convex Auth and OAuth tokens
3
+ *
4
+ * This helper provides a unified way to get the current user
5
+ * regardless of whether they authenticated via Convex Auth (session)
6
+ * or OAuth token (MCP clients).
7
+ */
8
+ import { isOAuthToken as checkIsOAuthToken, getOAuthClientId, DEFAULT_OAUTH_ISSUER_PATTERN, } from "../lib/oauth.js";
9
+ /**
10
+ * Create an auth helper for handling both Convex Auth and OAuth tokens
11
+ *
12
+ * @example
13
+ * ```typescript
14
+ * import { createAuthHelper } from "@codefox-inc/oauth-provider";
15
+ * import { getAuthUserId } from "./auth";
16
+ *
17
+ * const authHelper = createAuthHelper({
18
+ * providers: ["anonymous"],
19
+ * });
20
+ *
21
+ * // In a query/mutation:
22
+ * const userId = await authHelper.getCurrentUserId(ctx, getAuthUserId);
23
+ * const user = await authHelper.getCurrentUser(ctx, getAuthUserId);
24
+ * ```
25
+ */
26
+ export function createAuthHelper(config = {}) {
27
+ const { providers = ["anonymous"], getAuthUserId: defaultGetAuthUserId, checkAuthorization, oauthIssuerPattern = DEFAULT_OAUTH_ISSUER_PATTERN, } = config;
28
+ async function getCurrentUserId(ctx, getAuthUserId) {
29
+ const authFn = getAuthUserId ?? defaultGetAuthUserId;
30
+ // First, check if this is an OAuth token by looking at identity issuer
31
+ const identity = await ctx.auth.getUserIdentity();
32
+ const isOAuth = checkIsOAuthToken(identity, oauthIssuerPattern);
33
+ // If this is an OAuth token, skip Convex Auth and enforce authorization check
34
+ if (isOAuth && identity?.subject) {
35
+ const validId = ctx.db.normalizeId("users", identity.subject);
36
+ if (validId) {
37
+ // OAuth tokens MUST pass authorization check
38
+ if (checkAuthorization) {
39
+ const clientId = getOAuthClientId(identity);
40
+ const isValid = await checkAuthorization(ctx, validId, clientId);
41
+ if (!isValid) {
42
+ // Authorization was revoked - reject access
43
+ return null;
44
+ }
45
+ }
46
+ return validId;
47
+ }
48
+ // OAuth token but invalid user ID
49
+ return null;
50
+ }
51
+ // 1. Try Convex Auth (session-based, getAuthUserId)
52
+ if (authFn) {
53
+ const userIdOrSubject = await authFn(ctx);
54
+ if (userIdOrSubject) {
55
+ // Handle "userId|sessionId" format from some Convex Auth versions
56
+ const idToLookup = userIdOrSubject.includes("|")
57
+ ? userIdOrSubject.split("|")[0]
58
+ : userIdOrSubject;
59
+ // Try as Convex ID
60
+ const validId = ctx.db.normalizeId("users", idToLookup);
61
+ if (validId) {
62
+ return validId;
63
+ }
64
+ // Try as Subject ID via authAccounts
65
+ for (const provider of providers) {
66
+ const account = await ctx.db
67
+ .query("authAccounts")
68
+ .withIndex("providerAndAccountId", (q) => q.eq("provider", provider).eq("providerAccountId", idToLookup))
69
+ .unique();
70
+ if (account) {
71
+ return account.userId;
72
+ }
73
+ }
74
+ }
75
+ }
76
+ return null;
77
+ }
78
+ async function getCurrentUser(ctx, getAuthUserId) {
79
+ const userId = await getCurrentUserId(ctx, getAuthUserId);
80
+ if (!userId)
81
+ return null;
82
+ return ctx.db.get(userId);
83
+ }
84
+ async function requireAuth(ctx, getAuthUserId) {
85
+ const userId = await getCurrentUserId(ctx, getAuthUserId);
86
+ if (!userId) {
87
+ throw new Error("Not authenticated");
88
+ }
89
+ return userId;
90
+ }
91
+ return {
92
+ getCurrentUserId,
93
+ getCurrentUser,
94
+ requireAuth,
95
+ };
96
+ }
97
+ //# sourceMappingURL=auth-helper.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"auth-helper.js","sourceRoot":"","sources":["../../src/client/auth-helper.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EACH,YAAY,IAAI,iBAAiB,EACjC,gBAAgB,EAChB,4BAA4B,GAC/B,MAAM,iBAAiB,CAAC;AA2EzB;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,UAAU,gBAAgB,CAAC,SAA2B,EAAE;IAC1D,MAAM,EACF,SAAS,GAAG,CAAC,WAAW,CAAC,EACzB,aAAa,EAAE,oBAAoB,EACnC,kBAAkB,EAClB,kBAAkB,GAAG,4BAA4B,GACpD,GAAG,MAAM,CAAC;IAEX,KAAK,UAAU,gBAAgB,CAC3B,GAA2B,EAC3B,aAAuE;QAEvE,MAAM,MAAM,GAAG,aAAa,IAAI,oBAAoB,CAAC;QAErD,uEAAuE;QACvE,MAAM,QAAQ,GAAG,MAAM,GAAG,CAAC,IAAI,CAAC,eAAe,EAAE,CAAC;QAClD,MAAM,OAAO,GAAG,iBAAiB,CAAC,QAAQ,EAAE,kBAAkB,CAAC,CAAC;QAEhE,8EAA8E;QAC9E,IAAI,OAAO,IAAI,QAAQ,EAAE,OAAO,EAAE,CAAC;YAC/B,MAAM,OAAO,GAAG,GAAG,CAAC,EAAE,CAAC,WAAW,CAAC,OAAO,EAAE,QAAQ,CAAC,OAAO,CAAC,CAAC;YAC9D,IAAI,OAAO,EAAE,CAAC;gBACV,6CAA6C;gBAC7C,IAAI,kBAAkB,EAAE,CAAC;oBACrB,MAAM,QAAQ,GAAG,gBAAgB,CAAC,QAAQ,CAAC,CAAC;oBAC5C,MAAM,OAAO,GAAG,MAAM,kBAAkB,CAAC,GAAG,EAAE,OAAO,EAAE,QAAQ,CAAC,CAAC;oBACjE,IAAI,CAAC,OAAO,EAAE,CAAC;wBACX,4CAA4C;wBAC5C,OAAO,IAAI,CAAC;oBAChB,CAAC;gBACL,CAAC;gBACD,OAAO,OAAO,CAAC;YACnB,CAAC;YACD,kCAAkC;YAClC,OAAO,IAAI,CAAC;QAChB,CAAC;QAED,oDAAoD;QACpD,IAAI,MAAM,EAAE,CAAC;YACT,MAAM,eAAe,GAAG,MAAM,MAAM,CAAC,GAAG,CAAC,CAAC;YAC1C,IAAI,eAAe,EAAE,CAAC;gBAClB,kEAAkE;gBAClE,MAAM,UAAU,GAAG,eAAe,CAAC,QAAQ,CAAC,GAAG,CAAC;oBAC5C,CAAC,CAAC,eAAe,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;oBAC/B,CAAC,CAAC,eAAe,CAAC;gBAEtB,mBAAmB;gBACnB,MAAM,OAAO,GAAG,GAAG,CAAC,EAAE,CAAC,WAAW,CAAC,OAAO,EAAE,UAAU,CAAC,CAAC;gBACxD,IAAI,OAAO,EAAE,CAAC;oBACV,OAAO,OAAO,CAAC;gBACnB,CAAC;gBAED,qCAAqC;gBACrC,KAAK,MAAM,QAAQ,IAAI,SAAS,EAAE,CAAC;oBAE/B,MAAM,OAAO,GAAG,MAAO,GAAG,CAAC,EAAU;yBAChC,KAAK,CAAC,cAAc,CAAC;yBACrB,SAAS,CAAC,sBAAsB,EAAE,CAAC,CAA8F,EAAE,EAAE,CAClI,CAAC,CAAC,EAAE,CAAC,UAAU,EAAE,QAAQ,CAAC,CAAC,EAAE,CAAC,mBAAmB,EAAE,UAAU,CAAC,CACjE;yBACA,MAAM,EAAE,CAAC;oBACd,IAAI,OAAO,EAAE,CAAC;wBACV,OAAO,OAAO,CAAC,MAAM,CAAC;oBAC1B,CAAC;gBACL,CAAC;YACL,CAAC;QACL,CAAC;QAED,OAAO,IAAI,CAAC;IAChB,CAAC;IAED,KAAK,UAAU,cAAc,CACzB,GAA2B,EAC3B,aAAuE;QAEvE,MAAM,MAAM,GAAG,MAAM,gBAAgB,CAAC,GAAG,EAAE,aAAa,CAAC,CAAC;QAC1D,IAAI,CAAC,MAAM;YAAE,OAAO,IAAI,CAAC;QACzB,OAAO,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,MAAM,CAAsB,CAAC;IACnD,CAAC;IAED,KAAK,UAAU,WAAW,CACtB,GAA2B,EAC3B,aAAuE;QAEvE,MAAM,MAAM,GAAG,MAAM,gBAAgB,CAAC,GAAG,EAAE,aAAa,CAAC,CAAC;QAC1D,IAAI,CAAC,MAAM,EAAE,CAAC;YACV,MAAM,IAAI,KAAK,CAAC,mBAAmB,CAAC,CAAC;QACzC,CAAC;QACD,OAAO,MAAM,CAAC;IAClB,CAAC;IAED,OAAO;QACH,gBAAgB;QAChB,cAAc;QACd,WAAW;KACd,CAAC;AACN,CAAC"}
@@ -0,0 +1,189 @@
1
+ import type { OAuthConfig, UserProfile } from "../lib/oauth.js";
2
+ import type { RunQueryCtx, RunMutationCtx, RunActionCtx } from "../lib/convex-types.js";
3
+ export type { OAuthConfig, UserProfile } from "../lib/oauth.js";
4
+ export { OAuthError, verifyAccessToken, isOAuthToken, getOAuthClientId, DEFAULT_OAUTH_ISSUER_PATTERN, } from "../lib/oauth.js";
5
+ export { OAUTH_CONSTANTS, OAUTH_ERROR_CODES } from "../component/constants.js";
6
+ export { createAuthHelper } from "./auth-helper.js";
7
+ export type { AuthHelper, AuthHelperConfig } from "./auth-helper.js";
8
+ export { registerOAuthRoutes } from "./routes.js";
9
+ export type { RegisterOAuthRoutesOptions } from "./routes.js";
10
+ export { generateAuthConfig, createAuthConfig } from "./auth-config.js";
11
+ export type { AuthConfig, AuthProvider, GenerateAuthConfigOptions } from "./auth-config.js";
12
+ /**
13
+ * OAuth Provider Client Configuration
14
+ */
15
+ export type OAuthProviderConfig = OAuthConfig;
16
+ /**
17
+ * OAuth Provider SDK
18
+ *
19
+ * Usage:
20
+ * ```typescript
21
+ * import { OAuthProvider } from "@codefox-inc/oauth-provider";
22
+ * import { components } from "./_generated/api";
23
+ *
24
+ * const oauthProvider = new OAuthProvider(components.oauthProvider, {
25
+ * privateKey: process.env.OAUTH_PRIVATE_KEY!,
26
+ * publicKey: process.env.OAUTH_PUBLIC_KEY!,
27
+ * siteUrl: process.env.SITE_URL!,
28
+ * });
29
+ *
30
+ * // In http.ts
31
+ * http.route({
32
+ * path: "/oauth/.well-known/openid-configuration",
33
+ * method: "GET",
34
+ * handler: httpAction((ctx, req) => oauthProvider.handlers.openIdConfiguration(ctx, req)),
35
+ * });
36
+ * ```
37
+ */
38
+ export declare class OAuthProvider {
39
+ private config;
40
+ private api;
41
+ private component;
42
+ constructor(component: any, config: OAuthProviderConfig);
43
+ getConfig(): OAuthProviderConfig;
44
+ private createAPI;
45
+ /**
46
+ * HTTP Handlers for mounting in http.ts
47
+ *
48
+ * Note: ctx expects Convex ActionCtx (HTTP Action context).
49
+ * RunActionCtx is used as the base type for compatibility.
50
+ */
51
+ get handlers(): {
52
+ /**
53
+ * OpenID Connect Discovery
54
+ * Mount at: /oauth/.well-known/openid-configuration
55
+ */
56
+ openIdConfiguration: (ctx: RunActionCtx, request: Request) => Promise<Response>;
57
+ /**
58
+ * Authorization Endpoint
59
+ * Mount at: /oauth/authorize
60
+ */
61
+ authorize: (ctx: RunActionCtx, request: Request) => Promise<Response>;
62
+ /**
63
+ * JWKS Endpoint
64
+ * Mount at: /oauth/.well-known/jwks.json
65
+ */
66
+ jwks: (ctx: RunActionCtx, request: Request) => Promise<Response>;
67
+ /**
68
+ * Token Endpoint
69
+ * Mount at: /oauth/token
70
+ */
71
+ token: (ctx: RunActionCtx, request: Request) => Promise<Response>;
72
+ /**
73
+ * UserInfo Endpoint
74
+ * Mount at: /oauth/userinfo
75
+ * Requires getUserProfile callback
76
+ */
77
+ userInfo: (ctx: RunActionCtx, request: Request, getUserProfile: (userId: string) => Promise<UserProfile | null>) => Promise<Response>;
78
+ /**
79
+ * Dynamic Client Registration
80
+ * Mount at: /oauth/register
81
+ */
82
+ register: (ctx: RunActionCtx, request: Request) => Promise<Response>;
83
+ /**
84
+ * Protected Resource Metadata
85
+ * Mount at: /.well-known/oauth-protected-resource
86
+ */
87
+ protectedResource: (ctx: RunActionCtx, request: Request) => Promise<Response>;
88
+ };
89
+ /**
90
+ * Issue Authorization Code
91
+ * Called from consent approval mutation
92
+ * Also creates/updates authorization record automatically
93
+ */
94
+ issueAuthorizationCode(ctx: RunMutationCtx, args: {
95
+ userId: string;
96
+ clientId: string;
97
+ scopes: string[];
98
+ redirectUri: string;
99
+ codeChallenge?: string;
100
+ codeChallengeMethod?: string;
101
+ nonce?: string;
102
+ }): Promise<string>;
103
+ /**
104
+ * Get OAuth Client
105
+ */
106
+ getClient(ctx: RunQueryCtx, clientId: string): Promise<{
107
+ clientId: string;
108
+ type: "confidential" | "public";
109
+ redirectUris: string[];
110
+ allowedScopes: string[];
111
+ } | null>;
112
+ /**
113
+ * Register OAuth Client (for admin use)
114
+ */
115
+ registerClient(ctx: RunMutationCtx, args: {
116
+ name: string;
117
+ redirectUris: string[];
118
+ scopes: string[];
119
+ type: "confidential" | "public";
120
+ website?: string;
121
+ logoUrl?: string;
122
+ tosUrl?: string;
123
+ policyUrl?: string;
124
+ }): Promise<{
125
+ clientId: string;
126
+ clientSecret?: string;
127
+ clientIdIssuedAt: number;
128
+ }>;
129
+ /**
130
+ * Get user's active tokens
131
+ */
132
+ getTokensByUser(ctx: RunQueryCtx, userId: string): Promise<{
133
+ _id: string;
134
+ clientId: string;
135
+ userId: string;
136
+ scopes: string[];
137
+ accessTokenExpiresAt: number;
138
+ refreshTokenExpiresAt?: number;
139
+ }[]>;
140
+ /**
141
+ * Get authorization for a specific user-client pair
142
+ * Returns null if user has not authorized this client
143
+ */
144
+ getAuthorization(ctx: RunQueryCtx, userId: string, clientId: string): Promise<any>;
145
+ /**
146
+ * List all authorized apps for a user
147
+ * Returns client info along with authorization details
148
+ */
149
+ listUserAuthorizations(ctx: RunQueryCtx, userId: string): Promise<any>;
150
+ /**
151
+ * Create or update authorization when user grants consent
152
+ * Call this when user approves OAuth consent
153
+ */
154
+ upsertAuthorization(ctx: RunMutationCtx, args: {
155
+ userId: string;
156
+ clientId: string;
157
+ scopes: string[];
158
+ }): Promise<any>;
159
+ /**
160
+ * Revoke authorization and delete all associated tokens
161
+ * Call this when user wants to disconnect an app
162
+ */
163
+ revokeAuthorization(ctx: RunMutationCtx, userId: string, clientId: string): Promise<any>;
164
+ /**
165
+ * Check if user has already authorized this client with sufficient scopes
166
+ * Useful for "skip consent" flow
167
+ */
168
+ hasAuthorization(ctx: RunQueryCtx, userId: string, clientId: string, requiredScopes: string[]): Promise<boolean>;
169
+ /**
170
+ * Check if authorization exists (for revocation check)
171
+ * Use this with createAuthHelper's checkAuthorization option
172
+ */
173
+ checkAuthorizationValid(ctx: RunQueryCtx, userId: string, clientId?: string): Promise<boolean>;
174
+ /**
175
+ * Create a checkAuthorization function for use with createAuthHelper
176
+ * This ensures revoked authorizations are rejected
177
+ *
178
+ * @example
179
+ * ```typescript
180
+ * const oauthProvider = new OAuthProvider(components.oauthProvider, config);
181
+ * const authHelper = createAuthHelper({
182
+ * providers: ["anonymous"],
183
+ * checkAuthorization: oauthProvider.createAuthorizationChecker(),
184
+ * });
185
+ * ```
186
+ */
187
+ createAuthorizationChecker(): (ctx: RunQueryCtx, userId: string, clientId?: string) => Promise<boolean>;
188
+ }
189
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/client/index.ts"],"names":[],"mappings":"AAUA,OAAO,KAAK,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAChE,OAAO,KAAK,EAAE,WAAW,EAAE,cAAc,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;AAGxF,YAAY,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAChE,OAAO,EACH,UAAU,EACV,iBAAiB,EACjB,YAAY,EACZ,gBAAgB,EAChB,4BAA4B,GAC/B,MAAM,iBAAiB,CAAC;AACzB,OAAO,EAAE,eAAe,EAAE,iBAAiB,EAAE,MAAM,2BAA2B,CAAC;AAG/E,OAAO,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AACpD,YAAY,EAAE,UAAU,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AAGrE,OAAO,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AAClD,YAAY,EAAE,0BAA0B,EAAE,MAAM,aAAa,CAAC;AAG9D,OAAO,EAAE,kBAAkB,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AACxE,YAAY,EAAE,UAAU,EAAE,YAAY,EAAE,yBAAyB,EAAE,MAAM,kBAAkB,CAAC;AAE5F;;GAEG;AACH,MAAM,MAAM,mBAAmB,GAAG,WAAW,CAAC;AAE9C;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,qBAAa,aAAa;IACtB,OAAO,CAAC,MAAM,CAAsB;IACpC,OAAO,CAAC,GAAG,CAAoB;IAE/B,OAAO,CAAC,SAAS,CAAM;gBAInB,SAAS,EAAE,GAAG,EACd,MAAM,EAAE,mBAAmB;IAO/B,SAAS,IAAI,mBAAmB;IAKhC,OAAO,CAAC,SAAS;IA8BjB;;;;;OAKG;IACH,IAAI,QAAQ;QAEJ;;;WAGG;mCACwB,YAAY,WAAW,OAAO;QAGzD;;;WAGG;yBACc,YAAY,WAAW,OAAO;QAG/C;;;WAGG;oBACS,YAAY,WAAW,OAAO;QAG1C;;;WAGG;qBACU,YAAY,WAAW,OAAO;QAG3C;;;;WAIG;wBACa,YAAY,WAAW,OAAO,kBAAkB,CAAC,MAAM,EAAE,MAAM,KAAK,OAAO,CAAC,WAAW,GAAG,IAAI,CAAC;QAG/G;;;WAGG;wBACa,YAAY,WAAW,OAAO;QAG9C;;;WAGG;iCACsB,YAAY,WAAW,OAAO;MAG9D;IAED;;;;OAIG;IACG,sBAAsB,CAAC,GAAG,EAAE,cAAc,EAAE,IAAI,EAAE;QACpD,MAAM,EAAE,MAAM,CAAC;QACf,QAAQ,EAAE,MAAM,CAAC;QACjB,MAAM,EAAE,MAAM,EAAE,CAAC;QACjB,WAAW,EAAE,MAAM,CAAC;QACpB,aAAa,CAAC,EAAE,MAAM,CAAC;QACvB,mBAAmB,CAAC,EAAE,MAAM,CAAC;QAC7B,KAAK,CAAC,EAAE,MAAM,CAAC;KAClB,GAAG,OAAO,CAAC,MAAM,CAAC;IAwBnB;;OAEG;IACG,SAAS,CAAC,GAAG,EAAE,WAAW,EAAE,QAAQ,EAAE,MAAM;;;;;;IAIlD;;OAEG;IACG,cAAc,CAAC,GAAG,EAAE,cAAc,EAAE,IAAI,EAAE;QAC5C,IAAI,EAAE,MAAM,CAAC;QACb,YAAY,EAAE,MAAM,EAAE,CAAC;QACvB,MAAM,EAAE,MAAM,EAAE,CAAC;QACjB,IAAI,EAAE,cAAc,GAAG,QAAQ,CAAC;QAChC,OAAO,CAAC,EAAE,MAAM,CAAC;QACjB,OAAO,CAAC,EAAE,MAAM,CAAC;QACjB,MAAM,CAAC,EAAE,MAAM,CAAC;QAChB,SAAS,CAAC,EAAE,MAAM,CAAC;KACtB;;;;;IAID;;OAEG;IACG,eAAe,CAAC,GAAG,EAAE,WAAW,EAAE,MAAM,EAAE,MAAM;;;;;;;;IAQtD;;;OAGG;IACG,gBAAgB,CAAC,GAAG,EAAE,WAAW,EAAE,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM;IAIzE;;;OAGG;IACG,sBAAsB,CAAC,GAAG,EAAE,WAAW,EAAE,MAAM,EAAE,MAAM;IAI7D;;;OAGG;IACG,mBAAmB,CAAC,GAAG,EAAE,cAAc,EAAE,IAAI,EAAE;QACjD,MAAM,EAAE,MAAM,CAAC;QACf,QAAQ,EAAE,MAAM,CAAC;QACjB,MAAM,EAAE,MAAM,EAAE,CAAC;KACpB;IAID;;;OAGG;IACG,mBAAmB,CAAC,GAAG,EAAE,cAAc,EAAE,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM;IAI/E;;;OAGG;IACG,gBAAgB,CAAC,GAAG,EAAE,WAAW,EAAE,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,cAAc,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,OAAO,CAAC;IAQtH;;;OAGG;IACG,uBAAuB,CAAC,GAAG,EAAE,WAAW,EAAE,MAAM,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAUpG;;;;;;;;;;;;OAYG;IACH,0BAA0B,KACR,KAAK,WAAW,EAAE,QAAQ,MAAM,EAAE,WAAW,MAAM,KAAG,OAAO,CAAC,OAAO,CAAC;CAI3F"}