@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 @@
|
|
|
1
|
+
{"version":3,"file":"convex-types.d.ts","sourceRoot":"","sources":["../../src/lib/convex-types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACR,iBAAiB,EACjB,kBAAkB,EAClB,YAAY,EACZ,kBAAkB,EACrB,MAAM,eAAe,CAAC;AAEvB;;;;;;;;;GASG;AACH,MAAM,MAAM,WAAW,GAAG;IACtB,QAAQ,CAAC,CAAC,SAAS,iBAAiB,CAAC,OAAO,EAAE,kBAAkB,CAAC,EAC7D,KAAK,EAAE,CAAC,EACR,IAAI,EAAE,YAAY,CAAC,CAAC,CAAC,GACtB,OAAO,CAAC,kBAAkB,CAAC,CAAC,CAAC,CAAC,CAAC;CACrC,CAAC;AAEF,MAAM,MAAM,cAAc,GAAG,WAAW,GAAG;IACvC,WAAW,CAAC,CAAC,SAAS,iBAAiB,CAAC,UAAU,EAAE,kBAAkB,CAAC,EACnE,QAAQ,EAAE,CAAC,EACX,IAAI,EAAE,YAAY,CAAC,CAAC,CAAC,GACtB,OAAO,CAAC,kBAAkB,CAAC,CAAC,CAAC,CAAC,CAAC;CACrC,CAAC;AAEF,MAAM,MAAM,YAAY,GAAG,cAAc,GAAG;IACxC,SAAS,CAAC,CAAC,SAAS,iBAAiB,CAAC,QAAQ,EAAE,kBAAkB,CAAC,EAC/D,MAAM,EAAE,CAAC,EACT,IAAI,EAAE,YAAY,CAAC,CAAC,CAAC,GACtB,OAAO,CAAC,kBAAkB,CAAC,CAAC,CAAC,CAAC,CAAC;CACrC,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"convex-types.js","sourceRoot":"","sources":["../../src/lib/convex-types.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
import { exportJWK } from "jose";
|
|
2
|
+
import type { JWTPayload } from "jose";
|
|
3
|
+
import type { Auth } from "convex/server";
|
|
4
|
+
import type { RunActionCtx } from "./convex-types.js";
|
|
5
|
+
/**
|
|
6
|
+
* OAuth 2.1 Provider Configuration
|
|
7
|
+
*/
|
|
8
|
+
export interface OAuthConfig {
|
|
9
|
+
privateKey: string;
|
|
10
|
+
jwks: string;
|
|
11
|
+
keyId?: string;
|
|
12
|
+
siteUrl: string;
|
|
13
|
+
convexSiteUrl?: string;
|
|
14
|
+
allowedOrigins?: string;
|
|
15
|
+
allowedScopes?: string[];
|
|
16
|
+
getUserId?: (ctx: RunActionCtx & {
|
|
17
|
+
auth: Auth;
|
|
18
|
+
}, request: Request) => Promise<string | null> | string | null;
|
|
19
|
+
checkAuthorization?: (ctx: RunActionCtx & {
|
|
20
|
+
auth: Auth;
|
|
21
|
+
}, userId: string, clientId?: string) => Promise<boolean>;
|
|
22
|
+
allowDynamicClientRegistration?: boolean;
|
|
23
|
+
prefix?: string;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* User Profile for UserInfo endpoint
|
|
27
|
+
*/
|
|
28
|
+
export interface UserProfile {
|
|
29
|
+
sub: string;
|
|
30
|
+
name?: string;
|
|
31
|
+
email?: string;
|
|
32
|
+
picture?: string;
|
|
33
|
+
email_verified?: boolean;
|
|
34
|
+
}
|
|
35
|
+
type JoseJWK = Awaited<ReturnType<typeof exportJWK>>;
|
|
36
|
+
/**
|
|
37
|
+
* Reset key cache (for testing)
|
|
38
|
+
*/
|
|
39
|
+
export declare function resetKeysForTest(): void;
|
|
40
|
+
/**
|
|
41
|
+
* Get Public JWK (for JWKS endpoint)
|
|
42
|
+
* @deprecated Use getJWKS instead
|
|
43
|
+
*/
|
|
44
|
+
export declare function getPublicJWK(publicKeyPEM: string): Promise<JoseJWK>;
|
|
45
|
+
/**
|
|
46
|
+
* Get JWKS for the JWKS endpoint
|
|
47
|
+
* Adds kid: "default-key" to each key if not present (for compatibility with Convex Auth JWKS)
|
|
48
|
+
*/
|
|
49
|
+
export declare function getJWKS(config: OAuthConfig): Promise<{
|
|
50
|
+
keys: JoseJWK[];
|
|
51
|
+
}>;
|
|
52
|
+
export declare function getSigningKeyId(config: OAuthConfig): string;
|
|
53
|
+
/**
|
|
54
|
+
* Sign a JWT using the private key
|
|
55
|
+
*/
|
|
56
|
+
export declare function sign(payload: Record<string, unknown>, subject: string, audience: string, expiresIn: string | number, privateKeyPEM: string, issuer?: string, keyId?: string): Promise<string>;
|
|
57
|
+
/**
|
|
58
|
+
* Verify Access Token using Public Key (PEM) or JWKS
|
|
59
|
+
*/
|
|
60
|
+
export declare function verifyAccessToken(token: string, publicKeyOrConfig: string | OAuthConfig, issuerUrl: string, expectedAudience?: string): Promise<JWTPayload>;
|
|
61
|
+
/**
|
|
62
|
+
* Generate a random code (Authorization Code)
|
|
63
|
+
*/
|
|
64
|
+
export declare function generateCode(length?: number): string;
|
|
65
|
+
/**
|
|
66
|
+
* Generate a cryptographically strong Client Secret (hex string)
|
|
67
|
+
*/
|
|
68
|
+
export declare function generateClientSecret(length?: number): string;
|
|
69
|
+
/**
|
|
70
|
+
* Get Issuer URL helper
|
|
71
|
+
*/
|
|
72
|
+
export declare function getIssuerUrl(config: OAuthConfig): string;
|
|
73
|
+
/**
|
|
74
|
+
* Normalize OAuth prefix for consistent URL building.
|
|
75
|
+
* Ensures a leading slash, trims a trailing slash, and treats "/" as root ("").
|
|
76
|
+
*/
|
|
77
|
+
export declare function normalizePrefix(prefix?: string): string;
|
|
78
|
+
/**
|
|
79
|
+
* CORS Helper - Get allowed origin
|
|
80
|
+
*/
|
|
81
|
+
export declare function getAllowedOrigin(origin: string | null, config: OAuthConfig): string | null;
|
|
82
|
+
/**
|
|
83
|
+
* Create CORS headers
|
|
84
|
+
*/
|
|
85
|
+
export declare function createCorsHeaders(origin: string | null, config: OAuthConfig, methods?: string): Record<string, string>;
|
|
86
|
+
/**
|
|
87
|
+
* Handle CORS preflight OPTIONS request
|
|
88
|
+
*/
|
|
89
|
+
export declare function handleCorsOptions(request: Request, config: OAuthConfig, methods?: string): Response | null;
|
|
90
|
+
/**
|
|
91
|
+
* OAuth Error Class
|
|
92
|
+
*/
|
|
93
|
+
export declare class OAuthError extends Error {
|
|
94
|
+
code: string;
|
|
95
|
+
statusCode: number;
|
|
96
|
+
constructor(code: string, message: string, statusCode?: number);
|
|
97
|
+
toResponse(headers: Record<string, string>): Response;
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* Default OAuth issuer pattern
|
|
101
|
+
* Used to identify OAuth tokens by checking if issuer URL contains this pattern
|
|
102
|
+
*/
|
|
103
|
+
export declare const DEFAULT_OAUTH_ISSUER_PATTERN = "/oauth";
|
|
104
|
+
/**
|
|
105
|
+
* Check if an identity is from an OAuth token
|
|
106
|
+
* @param identity - User identity from ctx.auth.getUserIdentity()
|
|
107
|
+
* @param issuerPattern - Pattern to match in issuer URL (default: "/oauth")
|
|
108
|
+
* @returns true if the identity is from an OAuth token
|
|
109
|
+
*/
|
|
110
|
+
export declare function isOAuthToken(identity: {
|
|
111
|
+
issuer?: string;
|
|
112
|
+
subject?: string;
|
|
113
|
+
} | null | undefined, issuerPattern?: string): boolean;
|
|
114
|
+
/**
|
|
115
|
+
* Extract client ID from an OAuth token identity
|
|
116
|
+
* @param identity - User identity from ctx.auth.getUserIdentity()
|
|
117
|
+
* @returns Client ID if present, undefined otherwise
|
|
118
|
+
*/
|
|
119
|
+
export declare function getOAuthClientId(identity: {
|
|
120
|
+
cid?: string;
|
|
121
|
+
} | null | undefined): string | undefined;
|
|
122
|
+
export {};
|
|
123
|
+
//# sourceMappingURL=oauth.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"oauth.d.ts","sourceRoot":"","sources":["../../src/lib/oauth.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,295 @@
|
|
|
1
|
+
import { SignJWT, importPKCS8, exportJWK, jwtVerify, importSPKI, createLocalJWKSet } from "jose";
|
|
2
|
+
const keyCache = new Map();
|
|
3
|
+
const jwkCache = new Map();
|
|
4
|
+
const jwksKeyCache = new Map();
|
|
5
|
+
const DEFAULT_KEY_ID = "default-key";
|
|
6
|
+
/**
|
|
7
|
+
* Reset key cache (for testing)
|
|
8
|
+
*/
|
|
9
|
+
export function resetKeysForTest() {
|
|
10
|
+
keyCache.clear();
|
|
11
|
+
jwkCache.clear();
|
|
12
|
+
jwksKeyCache.clear();
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Get Private Key from PEM string
|
|
16
|
+
*/
|
|
17
|
+
async function getPrivateKey(privateKeyPEM) {
|
|
18
|
+
const cacheKey = `private:${privateKeyPEM}`;
|
|
19
|
+
const cached = keyCache.get(cacheKey);
|
|
20
|
+
if (cached)
|
|
21
|
+
return cached;
|
|
22
|
+
const key = await importPKCS8(privateKeyPEM, "RS256");
|
|
23
|
+
keyCache.set(cacheKey, key);
|
|
24
|
+
return key;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Get Public Key from PEM string
|
|
28
|
+
*/
|
|
29
|
+
async function getPublicKey(publicKeyPEM) {
|
|
30
|
+
const cacheKey = `public:${publicKeyPEM}`;
|
|
31
|
+
const cached = keyCache.get(cacheKey);
|
|
32
|
+
if (cached)
|
|
33
|
+
return cached;
|
|
34
|
+
const key = await importSPKI(publicKeyPEM, "RS256", { extractable: true });
|
|
35
|
+
keyCache.set(cacheKey, key);
|
|
36
|
+
return key;
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Get Public JWK (for JWKS endpoint)
|
|
40
|
+
* @deprecated Use getJWKS instead
|
|
41
|
+
*/
|
|
42
|
+
export async function getPublicJWK(publicKeyPEM) {
|
|
43
|
+
const cacheKey = `jwk:${publicKeyPEM}`;
|
|
44
|
+
const cached = jwkCache.get(cacheKey);
|
|
45
|
+
if (cached)
|
|
46
|
+
return cached;
|
|
47
|
+
const key = await getPublicKey(publicKeyPEM);
|
|
48
|
+
const jwk = await exportJWK(key);
|
|
49
|
+
// Remove private fields
|
|
50
|
+
const { d: _d, p: _p, q: _q, dp: _dp, dq: _dq, qi: _qi, ...publicKey } = jwk;
|
|
51
|
+
const result = { ...publicKey, use: "sig", alg: "RS256", kid: "default-key" };
|
|
52
|
+
jwkCache.set(cacheKey, result);
|
|
53
|
+
return result;
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Get JWKS for the JWKS endpoint
|
|
57
|
+
* Adds kid: "default-key" to each key if not present (for compatibility with Convex Auth JWKS)
|
|
58
|
+
*/
|
|
59
|
+
export async function getJWKS(config) {
|
|
60
|
+
const jwks = JSON.parse(config.jwks);
|
|
61
|
+
const keyId = getSigningKeyId(config);
|
|
62
|
+
jwks.keys = jwks.keys.map((key) => {
|
|
63
|
+
const { d: _d, p: _p, q: _q, dp: _dp, dq: _dq, qi: _qi, oth: _oth, k: _k, ...publicKey } = key;
|
|
64
|
+
return {
|
|
65
|
+
...publicKey,
|
|
66
|
+
kid: publicKey.kid ?? keyId,
|
|
67
|
+
};
|
|
68
|
+
});
|
|
69
|
+
return jwks;
|
|
70
|
+
}
|
|
71
|
+
function ensureKidOnJwksKeys(keys, keyId) {
|
|
72
|
+
return keys.map((key) => ({
|
|
73
|
+
...key,
|
|
74
|
+
kid: key.kid ?? keyId,
|
|
75
|
+
}));
|
|
76
|
+
}
|
|
77
|
+
export function getSigningKeyId(config) {
|
|
78
|
+
if (config.keyId)
|
|
79
|
+
return config.keyId;
|
|
80
|
+
try {
|
|
81
|
+
const jwks = JSON.parse(config.jwks);
|
|
82
|
+
const kid = jwks.keys?.[0]?.kid;
|
|
83
|
+
if (typeof kid === "string" && kid.length > 0) {
|
|
84
|
+
return kid;
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
catch {
|
|
88
|
+
// Fall through to default when jwks is invalid.
|
|
89
|
+
}
|
|
90
|
+
return DEFAULT_KEY_ID;
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* Sign a JWT using the private key
|
|
94
|
+
*/
|
|
95
|
+
export async function sign(payload, subject, audience, expiresIn, privateKeyPEM, issuer, keyId = DEFAULT_KEY_ID) {
|
|
96
|
+
const privateKey = await getPrivateKey(privateKeyPEM);
|
|
97
|
+
const jwt = new SignJWT(payload)
|
|
98
|
+
.setProtectedHeader({ alg: "RS256", kid: keyId })
|
|
99
|
+
.setIssuedAt()
|
|
100
|
+
.setSubject(subject)
|
|
101
|
+
.setAudience(audience)
|
|
102
|
+
.setExpirationTime(expiresIn);
|
|
103
|
+
if (issuer) {
|
|
104
|
+
jwt.setIssuer(issuer);
|
|
105
|
+
}
|
|
106
|
+
return jwt.sign(privateKey);
|
|
107
|
+
}
|
|
108
|
+
/**
|
|
109
|
+
* Verify Access Token using Public Key (PEM) or JWKS
|
|
110
|
+
*/
|
|
111
|
+
export async function verifyAccessToken(token, publicKeyOrConfig, issuerUrl, expectedAudience = "convex") {
|
|
112
|
+
let publicKey;
|
|
113
|
+
if (typeof publicKeyOrConfig === "string") {
|
|
114
|
+
// Legacy: PEM string
|
|
115
|
+
publicKey = await getPublicKey(publicKeyOrConfig);
|
|
116
|
+
}
|
|
117
|
+
else {
|
|
118
|
+
// New: OAuthConfig - get key from jwks or publicKey
|
|
119
|
+
publicKey = await getVerificationKey(publicKeyOrConfig);
|
|
120
|
+
}
|
|
121
|
+
const options = {
|
|
122
|
+
issuer: issuerUrl,
|
|
123
|
+
audience: expectedAudience,
|
|
124
|
+
};
|
|
125
|
+
const { payload } = typeof publicKey === "function"
|
|
126
|
+
? await jwtVerify(token, publicKey, options)
|
|
127
|
+
: await jwtVerify(token, publicKey, options);
|
|
128
|
+
return payload;
|
|
129
|
+
}
|
|
130
|
+
/**
|
|
131
|
+
* Get verification key from config (JWKS)
|
|
132
|
+
*/
|
|
133
|
+
async function getVerificationKey(config) {
|
|
134
|
+
const cached = jwksKeyCache.get(config.jwks);
|
|
135
|
+
if (cached)
|
|
136
|
+
return cached;
|
|
137
|
+
const jwks = JSON.parse(config.jwks);
|
|
138
|
+
if (!jwks.keys?.length) {
|
|
139
|
+
throw new Error("jwks must include at least one key");
|
|
140
|
+
}
|
|
141
|
+
const normalized = { keys: ensureKidOnJwksKeys(jwks.keys, getSigningKeyId(config)) };
|
|
142
|
+
const localJwks = createLocalJWKSet(normalized);
|
|
143
|
+
jwksKeyCache.set(config.jwks, localJwks);
|
|
144
|
+
return localJwks;
|
|
145
|
+
}
|
|
146
|
+
/**
|
|
147
|
+
* Generate a random code (Authorization Code)
|
|
148
|
+
*/
|
|
149
|
+
export function generateCode(length = 32) {
|
|
150
|
+
const chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~";
|
|
151
|
+
let result = "";
|
|
152
|
+
const randomValues = new Uint32Array(length);
|
|
153
|
+
crypto.getRandomValues(randomValues);
|
|
154
|
+
for (let i = 0; i < length; i++) {
|
|
155
|
+
result += chars[randomValues[i] % chars.length];
|
|
156
|
+
}
|
|
157
|
+
return result;
|
|
158
|
+
}
|
|
159
|
+
/**
|
|
160
|
+
* Generate a cryptographically strong Client Secret (hex string)
|
|
161
|
+
*/
|
|
162
|
+
export function generateClientSecret(length = 64) {
|
|
163
|
+
const array = new Uint8Array(length);
|
|
164
|
+
crypto.getRandomValues(array);
|
|
165
|
+
return Array.from(array, byte => byte.toString(16).padStart(2, '0')).join('');
|
|
166
|
+
}
|
|
167
|
+
/**
|
|
168
|
+
* Get Issuer URL helper
|
|
169
|
+
*/
|
|
170
|
+
export function getIssuerUrl(config) {
|
|
171
|
+
const issuerBaseUrl = config.convexSiteUrl ?? config.siteUrl;
|
|
172
|
+
const prefix = normalizePrefix(config.prefix);
|
|
173
|
+
return issuerBaseUrl + prefix;
|
|
174
|
+
}
|
|
175
|
+
/**
|
|
176
|
+
* Normalize OAuth prefix for consistent URL building.
|
|
177
|
+
* Ensures a leading slash, trims a trailing slash, and treats "/" as root ("").
|
|
178
|
+
*/
|
|
179
|
+
export function normalizePrefix(prefix) {
|
|
180
|
+
const raw = (prefix ?? "/oauth").trim();
|
|
181
|
+
if (!raw || raw === "/")
|
|
182
|
+
return "";
|
|
183
|
+
let normalized = raw.startsWith("/") ? raw : `/${raw}`;
|
|
184
|
+
if (normalized.length > 1 && normalized.endsWith("/")) {
|
|
185
|
+
normalized = normalized.slice(0, -1);
|
|
186
|
+
}
|
|
187
|
+
return normalized;
|
|
188
|
+
}
|
|
189
|
+
/**
|
|
190
|
+
* CORS Helper - Get allowed origin
|
|
191
|
+
*/
|
|
192
|
+
export function getAllowedOrigin(origin, config) {
|
|
193
|
+
// 1. CLI / Non-browser clients (No Origin header)
|
|
194
|
+
if (!origin)
|
|
195
|
+
return null;
|
|
196
|
+
// 2. Browser clients (Verified Origins)
|
|
197
|
+
const toOrigin = (value) => {
|
|
198
|
+
if (!value)
|
|
199
|
+
return null;
|
|
200
|
+
try {
|
|
201
|
+
return new URL(value).origin;
|
|
202
|
+
}
|
|
203
|
+
catch {
|
|
204
|
+
return null;
|
|
205
|
+
}
|
|
206
|
+
};
|
|
207
|
+
const allowedList = (config.allowedOrigins || "")
|
|
208
|
+
.split(",")
|
|
209
|
+
.map((u) => toOrigin(u.trim()))
|
|
210
|
+
.filter((u) => !!u);
|
|
211
|
+
const siteOrigin = toOrigin(config.siteUrl);
|
|
212
|
+
const convexOrigin = toOrigin(config.convexSiteUrl);
|
|
213
|
+
if (allowedList.includes(origin))
|
|
214
|
+
return origin;
|
|
215
|
+
if (siteOrigin && origin === siteOrigin)
|
|
216
|
+
return origin;
|
|
217
|
+
if (convexOrigin && origin === convexOrigin)
|
|
218
|
+
return origin;
|
|
219
|
+
// Allow Localhost (Development tools & Inspectors)
|
|
220
|
+
if (/^http:\/\/localhost(:\d+)?$/.test(origin))
|
|
221
|
+
return origin;
|
|
222
|
+
if (/^http:\/\/127\.0\.0\.1(:\d+)?$/.test(origin))
|
|
223
|
+
return origin;
|
|
224
|
+
return null;
|
|
225
|
+
}
|
|
226
|
+
/**
|
|
227
|
+
* Create CORS headers
|
|
228
|
+
*/
|
|
229
|
+
export function createCorsHeaders(origin, config, methods = "GET, POST, OPTIONS") {
|
|
230
|
+
const headers = {
|
|
231
|
+
"Content-Type": "application/json",
|
|
232
|
+
"Access-Control-Allow-Methods": methods,
|
|
233
|
+
"Access-Control-Allow-Headers": "Content-Type, Authorization, mcp-protocol-version",
|
|
234
|
+
};
|
|
235
|
+
const allowedOrigin = getAllowedOrigin(origin, config);
|
|
236
|
+
if (allowedOrigin) {
|
|
237
|
+
headers["Access-Control-Allow-Origin"] = allowedOrigin;
|
|
238
|
+
}
|
|
239
|
+
return headers;
|
|
240
|
+
}
|
|
241
|
+
/**
|
|
242
|
+
* Handle CORS preflight OPTIONS request
|
|
243
|
+
*/
|
|
244
|
+
export function handleCorsOptions(request, config, methods = "GET, POST, OPTIONS") {
|
|
245
|
+
if (request.method === "OPTIONS") {
|
|
246
|
+
const origin = request.headers.get("Origin");
|
|
247
|
+
return new Response(null, { headers: createCorsHeaders(origin, config, methods) });
|
|
248
|
+
}
|
|
249
|
+
return null;
|
|
250
|
+
}
|
|
251
|
+
/**
|
|
252
|
+
* OAuth Error Class
|
|
253
|
+
*/
|
|
254
|
+
export class OAuthError extends Error {
|
|
255
|
+
code;
|
|
256
|
+
statusCode;
|
|
257
|
+
constructor(code, message, statusCode = 400) {
|
|
258
|
+
super(message);
|
|
259
|
+
this.code = code;
|
|
260
|
+
this.statusCode = statusCode;
|
|
261
|
+
this.name = "OAuthError";
|
|
262
|
+
}
|
|
263
|
+
toResponse(headers) {
|
|
264
|
+
return new Response(JSON.stringify({
|
|
265
|
+
error: this.code,
|
|
266
|
+
error_description: this.message,
|
|
267
|
+
}), { status: this.statusCode, headers });
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
// ============================================================================
|
|
271
|
+
// OAuth Token Detection Helpers
|
|
272
|
+
// ============================================================================
|
|
273
|
+
/**
|
|
274
|
+
* Default OAuth issuer pattern
|
|
275
|
+
* Used to identify OAuth tokens by checking if issuer URL contains this pattern
|
|
276
|
+
*/
|
|
277
|
+
export const DEFAULT_OAUTH_ISSUER_PATTERN = "/oauth";
|
|
278
|
+
/**
|
|
279
|
+
* Check if an identity is from an OAuth token
|
|
280
|
+
* @param identity - User identity from ctx.auth.getUserIdentity()
|
|
281
|
+
* @param issuerPattern - Pattern to match in issuer URL (default: "/oauth")
|
|
282
|
+
* @returns true if the identity is from an OAuth token
|
|
283
|
+
*/
|
|
284
|
+
export function isOAuthToken(identity, issuerPattern = DEFAULT_OAUTH_ISSUER_PATTERN) {
|
|
285
|
+
return !!(identity?.issuer?.includes(issuerPattern) && identity?.subject);
|
|
286
|
+
}
|
|
287
|
+
/**
|
|
288
|
+
* Extract client ID from an OAuth token identity
|
|
289
|
+
* @param identity - User identity from ctx.auth.getUserIdentity()
|
|
290
|
+
* @returns Client ID if present, undefined otherwise
|
|
291
|
+
*/
|
|
292
|
+
export function getOAuthClientId(identity) {
|
|
293
|
+
return identity?.cid;
|
|
294
|
+
}
|
|
295
|
+
//# sourceMappingURL=oauth.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"oauth.js","sourceRoot":"","sources":["../../src/lib/oauth.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/react/index.ts"],"names":[],"mappings":"AAIA,eAAO,MAAM,cAAc,UAE1B,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/react/index.ts"],"names":[],"mappings":"AAAA,YAAY,CAAC;AAEb,6CAA6C;AAE7C,MAAM,CAAC,MAAM,cAAc,GAAG,GAAG,EAAE;IACjC,OAAO,EAAE,CAAC;AACZ,CAAC,CAAC"}
|
package/package.json
ADDED
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@codefox-inc/oauth-provider",
|
|
3
|
+
"description": "OAuth 2.1 / OpenID Connect Provider for Convex Auth (Beta).",
|
|
4
|
+
"repository": "github:codefox-inc/convex-oauth-provider",
|
|
5
|
+
"homepage": "https://github.com/codefox-inc/convex-oauth-provider#readme",
|
|
6
|
+
"bugs": {
|
|
7
|
+
"url": "https://github.com/codefox-inc/convex-oauth-provider/issues"
|
|
8
|
+
},
|
|
9
|
+
"version": "0.2.0",
|
|
10
|
+
"license": "Apache-2.0",
|
|
11
|
+
"publishConfig": {
|
|
12
|
+
"access": "public"
|
|
13
|
+
},
|
|
14
|
+
"keywords": [
|
|
15
|
+
"convex",
|
|
16
|
+
"component",
|
|
17
|
+
"oauth",
|
|
18
|
+
"oauth2",
|
|
19
|
+
"openid-connect",
|
|
20
|
+
"oidc",
|
|
21
|
+
"authentication",
|
|
22
|
+
"authorization"
|
|
23
|
+
],
|
|
24
|
+
"type": "module",
|
|
25
|
+
"scripts": {
|
|
26
|
+
"dev": "run-p -r 'dev:*'",
|
|
27
|
+
"dev:backend": "convex dev --typecheck-components",
|
|
28
|
+
"dev:frontend": "cd example && vite --clearScreen false",
|
|
29
|
+
"dev:build": "chokidar 'tsconfig*.json' 'src/**/*.ts' -i '**/*.test.ts' -c 'npm run build:codegen' --initial",
|
|
30
|
+
"dev:worker": "cd example && wrangler dev --port 8787 2>&1 | cat",
|
|
31
|
+
"predev": "path-exists .env.local dist || (npm run build && convex dev --once)",
|
|
32
|
+
"build": "tsc --project ./tsconfig.build.json",
|
|
33
|
+
"build:codegen": "npx convex codegen --component-dir ./src/component && npm run build",
|
|
34
|
+
"build:clean": "rm -rf dist *.tsbuildinfo && npm run build:codegen",
|
|
35
|
+
"typecheck": "tsc --noEmit && tsc -p example && tsc -p example/convex",
|
|
36
|
+
"lint": "eslint .",
|
|
37
|
+
"all": "run-p -r 'dev:*' 'test:watch'",
|
|
38
|
+
"test": "vitest run --typecheck",
|
|
39
|
+
"test:watch": "vitest --typecheck --clearScreen false",
|
|
40
|
+
"test:debug": "vitest --inspect-brk --no-file-parallelism",
|
|
41
|
+
"test:coverage": "vitest run --coverage --coverage.reporter=text",
|
|
42
|
+
"changeset": "changeset",
|
|
43
|
+
"version": "changeset version && npm install --package-lock-only",
|
|
44
|
+
"release": "npm run build && changeset publish"
|
|
45
|
+
},
|
|
46
|
+
"files": [
|
|
47
|
+
"dist",
|
|
48
|
+
"src"
|
|
49
|
+
],
|
|
50
|
+
"exports": {
|
|
51
|
+
"./package.json": "./package.json",
|
|
52
|
+
".": {
|
|
53
|
+
"types": "./dist/client/index.d.ts",
|
|
54
|
+
"default": "./dist/client/index.js"
|
|
55
|
+
},
|
|
56
|
+
"./react": {
|
|
57
|
+
"types": "./dist/react/index.d.ts",
|
|
58
|
+
"default": "./dist/react/index.js"
|
|
59
|
+
},
|
|
60
|
+
"./test": "./src/test.ts",
|
|
61
|
+
"./_generated/component.js": {
|
|
62
|
+
"types": "./dist/component/_generated/component.d.ts"
|
|
63
|
+
},
|
|
64
|
+
"./convex.config": {
|
|
65
|
+
"types": "./dist/component/convex.config.d.ts",
|
|
66
|
+
"default": "./dist/component/convex.config.js"
|
|
67
|
+
},
|
|
68
|
+
"./convex.config.js": {
|
|
69
|
+
"types": "./dist/component/convex.config.d.ts",
|
|
70
|
+
"default": "./dist/component/convex.config.js"
|
|
71
|
+
}
|
|
72
|
+
},
|
|
73
|
+
"peerDependencies": {
|
|
74
|
+
"convex": "^1.31.6",
|
|
75
|
+
"react": "^18.2.0 || ^19.0.0"
|
|
76
|
+
},
|
|
77
|
+
"dependencies": {
|
|
78
|
+
"bcryptjs": "^2.4.3",
|
|
79
|
+
"jose": "^5.9.6"
|
|
80
|
+
},
|
|
81
|
+
"devDependencies": {
|
|
82
|
+
"@changesets/cli": "^2.27.1",
|
|
83
|
+
"@cloudflare/workers-types": "^4.20260123.0",
|
|
84
|
+
"@convex-dev/auth": "^0.0.88",
|
|
85
|
+
"@convex-dev/eslint-plugin": "^1.1.1",
|
|
86
|
+
"@edge-runtime/vm": "^5.0.0",
|
|
87
|
+
"@eslint/eslintrc": "^3.3.3",
|
|
88
|
+
"@eslint/js": "9.39.2",
|
|
89
|
+
"@modelcontextprotocol/sdk": "^1.25.3",
|
|
90
|
+
"@types/bcryptjs": "^2.4.6",
|
|
91
|
+
"@types/node": "^24.10.9",
|
|
92
|
+
"@types/react": "^19.2.9",
|
|
93
|
+
"@types/react-dom": "^19.2.3",
|
|
94
|
+
"@vitejs/plugin-react": "^5.1.2",
|
|
95
|
+
"@vitest/coverage-v8": "^4.0.17",
|
|
96
|
+
"chokidar-cli": "3.0.0",
|
|
97
|
+
"convex": "1.31.6",
|
|
98
|
+
"convex-test": "0.0.41",
|
|
99
|
+
"cpy-cli": "^6.0.0",
|
|
100
|
+
"eslint": "9.39.2",
|
|
101
|
+
"eslint-plugin-react": "^7.37.5",
|
|
102
|
+
"eslint-plugin-react-hooks": "^7.0.1",
|
|
103
|
+
"eslint-plugin-react-refresh": "^0.4.26",
|
|
104
|
+
"globals": "^17.0.0",
|
|
105
|
+
"hono": "^4.11.5",
|
|
106
|
+
"npm-run-all2": "8.0.4",
|
|
107
|
+
"path-exists-cli": "2.0.0",
|
|
108
|
+
"pkg-pr-new": "^0.0.62",
|
|
109
|
+
"prettier": "3.8.1",
|
|
110
|
+
"react": "^19.2.3",
|
|
111
|
+
"react-dom": "^19.2.3",
|
|
112
|
+
"react-router-dom": "^7.6.2",
|
|
113
|
+
"typescript": "5.9.3",
|
|
114
|
+
"typescript-eslint": "8.53.1",
|
|
115
|
+
"vite": "7.3.1",
|
|
116
|
+
"vitest": "4.0.17",
|
|
117
|
+
"wrangler": "^4.15.2"
|
|
118
|
+
},
|
|
119
|
+
"types": "./dist/client/index.d.ts",
|
|
120
|
+
"module": "./dist/client/index.js"
|
|
121
|
+
}
|