@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.
- package/LICENSE +201 -0
- package/README.md +572 -0
- package/dist/client/_generated/_ignore.d.ts +1 -0
- package/dist/client/_generated/_ignore.d.ts.map +1 -0
- package/dist/client/_generated/_ignore.js +3 -0
- package/dist/client/_generated/_ignore.js.map +1 -0
- package/dist/client/auth-config.d.ts +85 -0
- package/dist/client/auth-config.d.ts.map +1 -0
- package/dist/client/auth-config.js +81 -0
- package/dist/client/auth-config.js.map +1 -0
- package/dist/client/auth-helper.d.ts +81 -0
- package/dist/client/auth-helper.d.ts.map +1 -0
- package/dist/client/auth-helper.js +97 -0
- package/dist/client/auth-helper.js.map +1 -0
- package/dist/client/index.d.ts +189 -0
- package/dist/client/index.d.ts.map +1 -0
- package/dist/client/index.js +230 -0
- package/dist/client/index.js.map +1 -0
- package/dist/client/routes.d.ts +94 -0
- package/dist/client/routes.d.ts.map +1 -0
- package/dist/client/routes.js +113 -0
- package/dist/client/routes.js.map +1 -0
- package/dist/component/_generated/api.d.ts +44 -0
- package/dist/component/_generated/api.d.ts.map +1 -0
- package/dist/component/_generated/api.js +31 -0
- package/dist/component/_generated/api.js.map +1 -0
- package/dist/component/_generated/component.d.ts +123 -0
- package/dist/component/_generated/component.d.ts.map +1 -0
- package/dist/component/_generated/component.js +11 -0
- package/dist/component/_generated/component.js.map +1 -0
- package/dist/component/_generated/dataModel.d.ts +46 -0
- package/dist/component/_generated/dataModel.d.ts.map +1 -0
- package/dist/component/_generated/dataModel.js +11 -0
- package/dist/component/_generated/dataModel.js.map +1 -0
- package/dist/component/_generated/server.d.ts +121 -0
- package/dist/component/_generated/server.d.ts.map +1 -0
- package/dist/component/_generated/server.js +78 -0
- package/dist/component/_generated/server.js.map +1 -0
- package/dist/component/clientManagement.d.ts +39 -0
- package/dist/component/clientManagement.d.ts.map +1 -0
- package/dist/component/clientManagement.js +169 -0
- package/dist/component/clientManagement.js.map +1 -0
- package/dist/component/constants.d.ts +31 -0
- package/dist/component/constants.d.ts.map +1 -0
- package/dist/component/constants.js +36 -0
- package/dist/component/constants.js.map +1 -0
- package/dist/component/convex.config.d.ts +3 -0
- package/dist/component/convex.config.d.ts.map +1 -0
- package/dist/component/convex.config.js +3 -0
- package/dist/component/convex.config.js.map +1 -0
- package/dist/component/handlers.d.ts +143 -0
- package/dist/component/handlers.d.ts.map +1 -0
- package/dist/component/handlers.js +624 -0
- package/dist/component/handlers.js.map +1 -0
- package/dist/component/mutations.d.ts +111 -0
- package/dist/component/mutations.d.ts.map +1 -0
- package/dist/component/mutations.js +459 -0
- package/dist/component/mutations.js.map +1 -0
- package/dist/component/queries.d.ts +127 -0
- package/dist/component/queries.d.ts.map +1 -0
- package/dist/component/queries.js +145 -0
- package/dist/component/queries.js.map +1 -0
- package/dist/component/schema.d.ts +116 -0
- package/dist/component/schema.d.ts.map +1 -0
- package/dist/component/schema.js +77 -0
- package/dist/component/schema.js.map +1 -0
- package/dist/component/token_security.d.ts +53 -0
- package/dist/component/token_security.d.ts.map +1 -0
- package/dist/component/token_security.js +91 -0
- package/dist/component/token_security.js.map +1 -0
- package/dist/lib/convex-types.d.ts +21 -0
- package/dist/lib/convex-types.d.ts.map +1 -0
- package/dist/lib/convex-types.js +2 -0
- package/dist/lib/convex-types.js.map +1 -0
- package/dist/lib/oauth.d.ts +123 -0
- package/dist/lib/oauth.d.ts.map +1 -0
- package/dist/lib/oauth.js +295 -0
- package/dist/lib/oauth.js.map +1 -0
- package/dist/react/index.d.ts +2 -0
- package/dist/react/index.d.ts.map +1 -0
- package/dist/react/index.js +6 -0
- package/dist/react/index.js.map +1 -0
- package/package.json +121 -0
- package/src/client/__tests__/auth-config.test.ts +244 -0
- package/src/client/__tests__/auth-helper.test.ts +273 -0
- package/src/client/__tests__/oauth-provider.test.ts +418 -0
- package/src/client/__tests__/routes.test.ts +428 -0
- package/src/client/_generated/_ignore.ts +1 -0
- package/src/client/auth-config.ts +157 -0
- package/src/client/auth-helper.ts +201 -0
- package/src/client/index.ts +326 -0
- package/src/client/routes.ts +251 -0
- package/src/component/__tests__/oauth.test.ts +3310 -0
- package/src/component/__tests__/rfc-compliance.test.ts +788 -0
- package/src/component/__tests__/token-security.test.ts +133 -0
- package/src/component/_generated/api.ts +60 -0
- package/src/component/_generated/component.ts +201 -0
- package/src/component/_generated/dataModel.ts +60 -0
- package/src/component/_generated/server.ts +156 -0
- package/src/component/clientManagement.ts +189 -0
- package/src/component/constants.ts +40 -0
- package/src/component/convex.config.ts +3 -0
- package/src/component/handlers.ts +964 -0
- package/src/component/mutations.ts +531 -0
- package/src/component/queries.ts +165 -0
- package/src/component/schema.ts +92 -0
- package/src/component/token_security.ts +102 -0
- package/src/lib/__tests__/oauth-helpers.test.ts +143 -0
- package/src/lib/__tests__/oauth-jwt.test.ts +405 -0
- package/src/lib/convex-types.ts +37 -0
- package/src/lib/oauth.ts +412 -0
- package/src/react/index.ts +7 -0
- 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":"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"}
|
|
@@ -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"}
|