@robelest/convex-auth 0.0.2-preview.2 → 0.0.3-preview
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/dist/bin.cjs +467 -64
- package/dist/client/index.d.ts +127 -0
- package/dist/client/index.d.ts.map +1 -1
- package/dist/client/index.js +424 -1
- package/dist/client/index.js.map +1 -1
- package/dist/component/_generated/api.d.ts +56 -1
- package/dist/component/_generated/api.d.ts.map +1 -1
- package/dist/component/_generated/api.js.map +1 -1
- package/dist/component/_generated/component.d.ts +141 -3
- package/dist/component/_generated/component.d.ts.map +1 -1
- package/dist/component/convex.config.d.ts.map +1 -1
- package/dist/component/convex.config.js +2 -0
- package/dist/component/convex.config.js.map +1 -1
- package/dist/component/index.d.ts +5 -4
- package/dist/component/index.d.ts.map +1 -1
- package/dist/component/index.js +4 -3
- package/dist/component/index.js.map +1 -1
- package/dist/component/portalBridge.d.ts +80 -0
- package/dist/component/portalBridge.d.ts.map +1 -0
- package/dist/component/portalBridge.js +102 -0
- package/dist/component/portalBridge.js.map +1 -0
- package/dist/component/public.d.ts +353 -9
- package/dist/component/public.d.ts.map +1 -1
- package/dist/component/public.js +328 -33
- package/dist/component/public.js.map +1 -1
- package/dist/component/schema.d.ts +168 -9
- package/dist/component/schema.d.ts.map +1 -1
- package/dist/component/schema.js +113 -7
- package/dist/component/schema.js.map +1 -1
- package/dist/providers/passkey.d.ts +20 -0
- package/dist/providers/passkey.d.ts.map +1 -0
- package/dist/providers/passkey.js +32 -0
- package/dist/providers/passkey.js.map +1 -0
- package/dist/providers/totp.d.ts +14 -0
- package/dist/providers/totp.d.ts.map +1 -0
- package/dist/providers/totp.js +23 -0
- package/dist/providers/totp.js.map +1 -0
- package/dist/server/convex-auth.d.ts +296 -0
- package/dist/server/convex-auth.d.ts.map +1 -0
- package/dist/server/convex-auth.js +480 -0
- package/dist/server/convex-auth.js.map +1 -0
- package/dist/server/email-templates.d.ts +18 -0
- package/dist/server/email-templates.d.ts.map +1 -0
- package/dist/server/email-templates.js +74 -0
- package/dist/server/email-templates.js.map +1 -0
- package/dist/server/implementation/apiKey.d.ts +74 -0
- package/dist/server/implementation/apiKey.d.ts.map +1 -0
- package/dist/server/implementation/apiKey.js +140 -0
- package/dist/server/implementation/apiKey.js.map +1 -0
- package/dist/server/implementation/index.d.ts +169 -7
- package/dist/server/implementation/index.d.ts.map +1 -1
- package/dist/server/implementation/index.js +220 -5
- package/dist/server/implementation/index.js.map +1 -1
- package/dist/server/implementation/passkey.d.ts +33 -0
- package/dist/server/implementation/passkey.d.ts.map +1 -0
- package/dist/server/implementation/passkey.js +450 -0
- package/dist/server/implementation/passkey.js.map +1 -0
- package/dist/server/implementation/redirects.d.ts.map +1 -1
- package/dist/server/implementation/redirects.js +4 -9
- package/dist/server/implementation/redirects.js.map +1 -1
- package/dist/server/implementation/signIn.d.ts +13 -0
- package/dist/server/implementation/signIn.d.ts.map +1 -1
- package/dist/server/implementation/signIn.js +29 -15
- package/dist/server/implementation/signIn.js.map +1 -1
- package/dist/server/implementation/totp.d.ts +40 -0
- package/dist/server/implementation/totp.d.ts.map +1 -0
- package/dist/server/implementation/totp.js +211 -0
- package/dist/server/implementation/totp.js.map +1 -0
- package/dist/server/index.d.ts +26 -2
- package/dist/server/index.d.ts.map +1 -1
- package/dist/server/index.js +63 -16
- package/dist/server/index.js.map +1 -1
- package/dist/server/portal-email.d.ts +19 -0
- package/dist/server/portal-email.d.ts.map +1 -0
- package/dist/server/portal-email.js +89 -0
- package/dist/server/portal-email.js.map +1 -0
- package/dist/server/provider_utils.d.ts +3 -1
- package/dist/server/provider_utils.d.ts.map +1 -1
- package/dist/server/provider_utils.js +39 -1
- package/dist/server/provider_utils.js.map +1 -1
- package/dist/server/types.d.ts +263 -4
- package/dist/server/types.d.ts.map +1 -1
- package/dist/server/version.d.ts +2 -0
- package/dist/server/version.d.ts.map +1 -0
- package/dist/server/version.js +3 -0
- package/dist/server/version.js.map +1 -0
- package/package.json +7 -3
- package/src/cli/index.ts +49 -7
- package/src/cli/portal-link.ts +112 -0
- package/src/cli/portal-upload.ts +411 -0
- package/src/cli/utils.ts +248 -0
- package/src/client/index.ts +489 -1
- package/src/component/_generated/api.ts +72 -1
- package/src/component/_generated/component.ts +241 -4
- package/src/component/convex.config.ts +3 -0
- package/src/component/index.ts +8 -3
- package/src/component/portalBridge.ts +116 -0
- package/src/component/public.ts +373 -37
- package/src/component/schema.ts +122 -7
- package/src/providers/passkey.ts +35 -0
- package/src/providers/totp.ts +26 -0
- package/src/server/convex-auth.ts +602 -0
- package/src/server/email-templates.ts +77 -0
- package/src/server/implementation/apiKey.ts +185 -0
- package/src/server/implementation/index.ts +301 -8
- package/src/server/implementation/passkey.ts +650 -0
- package/src/server/implementation/redirects.ts +4 -11
- package/src/server/implementation/signIn.ts +41 -13
- package/src/server/implementation/totp.ts +366 -0
- package/src/server/index.ts +98 -34
- package/src/server/portal-email.ts +95 -0
- package/src/server/provider_utils.ts +42 -1
- package/src/server/types.ts +285 -4
- package/src/server/version.ts +2 -0
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Styled dark-theme magic link email template for the Convex Auth Portal.
|
|
3
|
+
*
|
|
4
|
+
* Matches the portal's design system:
|
|
5
|
+
* - Background: #1e1c1a (body), #2a2825 (card)
|
|
6
|
+
* - Accent: #63a8f8 (Convex blue)
|
|
7
|
+
* - Text: #ffffff (headings), #b9b1aa (secondary), #8f8780 (muted)
|
|
8
|
+
* - Border: #4a4743
|
|
9
|
+
*
|
|
10
|
+
* @module
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
const SHIELD_SVG = `<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 24 24" fill="none" stroke="#63a8f8" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M20 13c0 5-3.5 7.5-7.66 8.95a1 1 0 0 1-.67-.01C7.5 20.5 4 18 4 13V6a1 1 0 0 1 1-1c2 0 4.5-1.2 6.24-2.72a1.17 1.17 0 0 1 1.52 0C14.51 3.81 17 5 19 5a1 1 0 0 1 1 1z"/></svg>`;
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Generate the styled magic link email HTML.
|
|
17
|
+
*
|
|
18
|
+
* @param url - The magic link URL the user clicks to sign in.
|
|
19
|
+
* @param expiresInHours - How long the link is valid (shown in the email).
|
|
20
|
+
*/
|
|
21
|
+
export function portalMagicLinkEmail(
|
|
22
|
+
url: string,
|
|
23
|
+
expiresInHours: number = 24,
|
|
24
|
+
): string {
|
|
25
|
+
const expiryText =
|
|
26
|
+
expiresInHours >= 24
|
|
27
|
+
? `${Math.floor(expiresInHours / 24)} day${Math.floor(expiresInHours / 24) > 1 ? "s" : ""}`
|
|
28
|
+
: `${expiresInHours} hour${expiresInHours > 1 ? "s" : ""}`;
|
|
29
|
+
|
|
30
|
+
return `<!DOCTYPE html>
|
|
31
|
+
<html lang="en">
|
|
32
|
+
<head>
|
|
33
|
+
<meta charset="utf-8" />
|
|
34
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
35
|
+
<meta name="color-scheme" content="dark" />
|
|
36
|
+
<meta name="supported-color-schemes" content="dark" />
|
|
37
|
+
<title>Sign in to Convex Auth Portal</title>
|
|
38
|
+
</head>
|
|
39
|
+
<body style="margin:0;padding:0;background-color:#1e1c1a;font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,'Helvetica Neue',Arial,sans-serif;">
|
|
40
|
+
<table role="presentation" width="100%" cellpadding="0" cellspacing="0" style="background-color:#1e1c1a;padding:40px 16px;">
|
|
41
|
+
<tr>
|
|
42
|
+
<td align="center">
|
|
43
|
+
<table role="presentation" width="480" cellpadding="0" cellspacing="0" style="background-color:#2a2825;border:1px solid #4a4743;border-radius:8px;overflow:hidden;">
|
|
44
|
+
<!-- Header -->
|
|
45
|
+
<tr>
|
|
46
|
+
<td style="padding:32px 32px 0 32px;text-align:center;">
|
|
47
|
+
${SHIELD_SVG}
|
|
48
|
+
<h1 style="margin:16px 0 0 0;font-size:20px;font-weight:600;color:#ffffff;line-height:1.3;">
|
|
49
|
+
Convex Auth Portal
|
|
50
|
+
</h1>
|
|
51
|
+
</td>
|
|
52
|
+
</tr>
|
|
53
|
+
|
|
54
|
+
<!-- Body -->
|
|
55
|
+
<tr>
|
|
56
|
+
<td style="padding:24px 32px;">
|
|
57
|
+
<p style="margin:0 0 20px 0;font-size:15px;line-height:1.6;color:#b9b1aa;">
|
|
58
|
+
Click the button below to sign in to the admin portal. This link will expire in ${expiryText}.
|
|
59
|
+
</p>
|
|
60
|
+
|
|
61
|
+
<!-- CTA Button -->
|
|
62
|
+
<table role="presentation" width="100%" cellpadding="0" cellspacing="0">
|
|
63
|
+
<tr>
|
|
64
|
+
<td align="center" style="padding:8px 0 24px 0;">
|
|
65
|
+
<a href="${url}" target="_blank" style="display:inline-block;background-color:#63a8f8;color:#0a0a0b;font-size:15px;font-weight:600;text-decoration:none;padding:12px 32px;border-radius:6px;line-height:1;">
|
|
66
|
+
Sign in to Portal
|
|
67
|
+
</a>
|
|
68
|
+
</td>
|
|
69
|
+
</tr>
|
|
70
|
+
</table>
|
|
71
|
+
|
|
72
|
+
<p style="margin:0 0 16px 0;font-size:13px;line-height:1.6;color:#8f8780;">
|
|
73
|
+
If the button doesn't work, copy and paste this URL into your browser:
|
|
74
|
+
</p>
|
|
75
|
+
<p style="margin:0;font-size:13px;line-height:1.5;color:#63a8f8;word-break:break-all;">
|
|
76
|
+
${url}
|
|
77
|
+
</p>
|
|
78
|
+
</td>
|
|
79
|
+
</tr>
|
|
80
|
+
|
|
81
|
+
<!-- Footer -->
|
|
82
|
+
<tr>
|
|
83
|
+
<td style="padding:20px 32px;border-top:1px solid #4a4743;">
|
|
84
|
+
<p style="margin:0;font-size:12px;line-height:1.5;color:#8f8780;text-align:center;">
|
|
85
|
+
If you didn't request this email, you can safely ignore it.
|
|
86
|
+
</p>
|
|
87
|
+
</td>
|
|
88
|
+
</tr>
|
|
89
|
+
</table>
|
|
90
|
+
</td>
|
|
91
|
+
</tr>
|
|
92
|
+
</table>
|
|
93
|
+
</body>
|
|
94
|
+
</html>`;
|
|
95
|
+
}
|
|
@@ -79,8 +79,41 @@ function materializeAndDefaultProviders(config_: ConvexAuthConfig) {
|
|
|
79
79
|
);
|
|
80
80
|
const config = { ...config_, providers };
|
|
81
81
|
|
|
82
|
+
// setEnvDefaults is from Auth.js and only works with Auth.js provider types.
|
|
83
|
+
// Filter out passkey and TOTP providers before passing to setEnvDefaults,
|
|
84
|
+
// then reinsert them at their original positions.
|
|
85
|
+
const passkeyIndices: number[] = [];
|
|
86
|
+
const passkeyProviders: AuthProviderMaterializedConfig[] = [];
|
|
87
|
+
const totpIndices: number[] = [];
|
|
88
|
+
const totpProviders: AuthProviderMaterializedConfig[] = [];
|
|
89
|
+
const filteredProviders = config.providers.filter((p, i) => {
|
|
90
|
+
if (p.type === "passkey") {
|
|
91
|
+
passkeyIndices.push(i);
|
|
92
|
+
passkeyProviders.push(p);
|
|
93
|
+
return false;
|
|
94
|
+
}
|
|
95
|
+
if (p.type === "totp") {
|
|
96
|
+
totpIndices.push(i);
|
|
97
|
+
totpProviders.push(p);
|
|
98
|
+
return false;
|
|
99
|
+
}
|
|
100
|
+
return true;
|
|
101
|
+
});
|
|
102
|
+
|
|
82
103
|
// Unfortunately mutates its argument
|
|
83
|
-
|
|
104
|
+
const tempConfig = { ...config, providers: filteredProviders };
|
|
105
|
+
setEnvDefaults(process.env, tempConfig as any);
|
|
106
|
+
|
|
107
|
+
// Reinsert passkey and TOTP providers at their original positions
|
|
108
|
+
const merged = [...tempConfig.providers];
|
|
109
|
+
for (let i = 0; i < passkeyIndices.length; i++) {
|
|
110
|
+
merged.splice(passkeyIndices[i]!, 0, passkeyProviders[i]!);
|
|
111
|
+
}
|
|
112
|
+
for (let i = 0; i < totpIndices.length; i++) {
|
|
113
|
+
merged.splice(totpIndices[i]!, 0, totpProviders[i]!);
|
|
114
|
+
}
|
|
115
|
+
config.providers = merged;
|
|
116
|
+
|
|
84
117
|
// Manually do this for new provider type
|
|
85
118
|
config.providers.forEach((provider) => {
|
|
86
119
|
if (provider.type === "phone") {
|
|
@@ -94,6 +127,14 @@ function materializeAndDefaultProviders(config_: ConvexAuthConfig) {
|
|
|
94
127
|
}
|
|
95
128
|
|
|
96
129
|
function providerDefaults(provider: AuthProviderMaterializedConfig) {
|
|
130
|
+
// Passkey providers don't use Auth.js options merge or OAuth normalization
|
|
131
|
+
if (provider.type === "passkey") {
|
|
132
|
+
return provider;
|
|
133
|
+
}
|
|
134
|
+
// TOTP providers don't use Auth.js options merge or OAuth normalization
|
|
135
|
+
if (provider.type === "totp") {
|
|
136
|
+
return provider;
|
|
137
|
+
}
|
|
97
138
|
// TODO: Add `redirectProxyUrl` to oauth providers
|
|
98
139
|
const merged = merge(
|
|
99
140
|
provider,
|
package/src/server/types.ts
CHANGED
|
@@ -5,7 +5,7 @@ import {
|
|
|
5
5
|
OAuth2Config,
|
|
6
6
|
OIDCConfig,
|
|
7
7
|
} from "@auth/core/providers";
|
|
8
|
-
import { Theme } from "@auth/core/types";
|
|
8
|
+
import { Awaitable, Theme } from "@auth/core/types";
|
|
9
9
|
import {
|
|
10
10
|
AnyDataModel,
|
|
11
11
|
FunctionReference,
|
|
@@ -82,6 +82,60 @@ export type ConvexAuthConfig = {
|
|
|
82
82
|
*/
|
|
83
83
|
maxFailedAttempsPerHour?: number;
|
|
84
84
|
};
|
|
85
|
+
/**
|
|
86
|
+
* API key configuration for programmatic access.
|
|
87
|
+
*
|
|
88
|
+
* Enables `auth.key.*` helpers for creating, verifying, and managing
|
|
89
|
+
* API keys with scoped permissions and optional per-key rate limiting.
|
|
90
|
+
*/
|
|
91
|
+
apiKeys?: ApiKeyConfig;
|
|
92
|
+
/**
|
|
93
|
+
* Email transport configuration.
|
|
94
|
+
*
|
|
95
|
+
* Required for magic link authentication and the admin portal.
|
|
96
|
+
* The library generates email content (subject, styled HTML); you
|
|
97
|
+
* provide the delivery mechanism — Resend, SendGrid, SES, Postmark,
|
|
98
|
+
* or any other provider.
|
|
99
|
+
*
|
|
100
|
+
* When configured, a magic link email provider (`id: "email"`) is
|
|
101
|
+
* auto-registered — no need to add a separate Auth.js email provider
|
|
102
|
+
* to `providers`.
|
|
103
|
+
*
|
|
104
|
+
* Works seamlessly with the `@convex-dev/resend` Convex component:
|
|
105
|
+
*
|
|
106
|
+
* ```ts
|
|
107
|
+
* import { Resend } from "@convex-dev/resend";
|
|
108
|
+
*
|
|
109
|
+
* const resend = new Resend(components.resend, { testMode: false });
|
|
110
|
+
*
|
|
111
|
+
* const auth = new Auth(components.auth, {
|
|
112
|
+
* providers: [google],
|
|
113
|
+
* email: {
|
|
114
|
+
* from: "My App <noreply@example.com>",
|
|
115
|
+
* send: (ctx, params) => resend.sendEmail(ctx, params),
|
|
116
|
+
* },
|
|
117
|
+
* });
|
|
118
|
+
* ```
|
|
119
|
+
*
|
|
120
|
+
* Or with any email API directly:
|
|
121
|
+
*
|
|
122
|
+
* ```ts
|
|
123
|
+
* email: {
|
|
124
|
+
* from: "My App <noreply@example.com>",
|
|
125
|
+
* send: async (_ctx, { from, to, subject, html }) => {
|
|
126
|
+
* await fetch("https://api.resend.com/emails", {
|
|
127
|
+
* method: "POST",
|
|
128
|
+
* headers: {
|
|
129
|
+
* Authorization: `Bearer ${process.env.AUTH_RESEND_KEY}`,
|
|
130
|
+
* "Content-Type": "application/json",
|
|
131
|
+
* },
|
|
132
|
+
* body: JSON.stringify({ from, to, subject, html }),
|
|
133
|
+
* });
|
|
134
|
+
* },
|
|
135
|
+
* },
|
|
136
|
+
* ```
|
|
137
|
+
*/
|
|
138
|
+
email?: EmailTransport;
|
|
85
139
|
callbacks?: {
|
|
86
140
|
/**
|
|
87
141
|
* Control which URLs are allowed as a destination after OAuth sign-in
|
|
@@ -245,7 +299,11 @@ export type AuthProviderConfig =
|
|
|
245
299
|
| ConvexCredentialsConfig
|
|
246
300
|
| ((...args: any) => ConvexCredentialsConfig)
|
|
247
301
|
| PhoneConfig
|
|
248
|
-
| ((...args: any) => PhoneConfig)
|
|
302
|
+
| ((...args: any) => PhoneConfig)
|
|
303
|
+
| PasskeyProviderConfig
|
|
304
|
+
| ((...args: any) => PasskeyProviderConfig)
|
|
305
|
+
| TotpProviderConfig
|
|
306
|
+
| ((...args: any) => TotpProviderConfig);
|
|
249
307
|
|
|
250
308
|
/**
|
|
251
309
|
* Extends the standard Auth.js email provider config
|
|
@@ -254,11 +312,30 @@ export type AuthProviderConfig =
|
|
|
254
312
|
export interface EmailConfig<
|
|
255
313
|
DataModel extends GenericDataModel = GenericDataModel,
|
|
256
314
|
> extends AuthjsEmailConfig {
|
|
315
|
+
/**
|
|
316
|
+
* Send the verification token to the user.
|
|
317
|
+
*
|
|
318
|
+
* Overrides the Auth.js 1-arg signature to accept an optional
|
|
319
|
+
* Convex action context as the second argument. Library-native
|
|
320
|
+
* email providers use `ctx` to call `email.send(ctx, params)`.
|
|
321
|
+
*/
|
|
322
|
+
sendVerificationRequest: (
|
|
323
|
+
params: {
|
|
324
|
+
identifier: string;
|
|
325
|
+
url: string;
|
|
326
|
+
expires: Date;
|
|
327
|
+
provider: AuthjsEmailConfig;
|
|
328
|
+
token: string;
|
|
329
|
+
theme: Theme;
|
|
330
|
+
request: Request;
|
|
331
|
+
},
|
|
332
|
+
ctx?: GenericActionCtx<AnyDataModel>,
|
|
333
|
+
) => Awaitable<void>;
|
|
257
334
|
/**
|
|
258
335
|
* Before the token is verified, check other
|
|
259
336
|
* provided parameters.
|
|
260
337
|
*
|
|
261
|
-
* Used to make sure
|
|
338
|
+
* Used to make sure that OTPs are accompanied
|
|
262
339
|
* with the correct email address.
|
|
263
340
|
*/
|
|
264
341
|
authorize?: (
|
|
@@ -354,6 +431,50 @@ export type ConvexCredentialsConfig = CredentialsUserConfig<any> & {
|
|
|
354
431
|
id: string;
|
|
355
432
|
};
|
|
356
433
|
|
|
434
|
+
/**
|
|
435
|
+
* Configuration for the passkey (WebAuthn) provider.
|
|
436
|
+
*/
|
|
437
|
+
export interface PasskeyProviderConfig {
|
|
438
|
+
id: string;
|
|
439
|
+
type: "passkey";
|
|
440
|
+
options: {
|
|
441
|
+
/** Relying Party display name. Defaults to SITE_URL hostname. */
|
|
442
|
+
rpName?: string;
|
|
443
|
+
/** Relying Party ID (hostname). Defaults to SITE_URL hostname. */
|
|
444
|
+
rpId?: string;
|
|
445
|
+
/** Allowed origins for credential verification. Defaults to SITE_URL. */
|
|
446
|
+
origin?: string | string[];
|
|
447
|
+
/** Attestation conveyance preference. Defaults to "none". */
|
|
448
|
+
attestation?: "none" | "direct";
|
|
449
|
+
/** User verification requirement. Defaults to "required". */
|
|
450
|
+
userVerification?: "required" | "preferred" | "discouraged";
|
|
451
|
+
/** Resident key (discoverable credential) preference. Defaults to "preferred". */
|
|
452
|
+
residentKey?: "required" | "preferred" | "discouraged";
|
|
453
|
+
/** Restrict to platform or cross-platform authenticators. */
|
|
454
|
+
authenticatorAttachment?: "platform" | "cross-platform";
|
|
455
|
+
/** Supported COSE algorithms. Defaults to [-7 (ES256), -257 (RS256)]. */
|
|
456
|
+
algorithms?: number[];
|
|
457
|
+
/** Challenge expiration in ms. Defaults to 300_000 (5 minutes). */
|
|
458
|
+
challengeExpirationMs?: number;
|
|
459
|
+
};
|
|
460
|
+
}
|
|
461
|
+
|
|
462
|
+
/**
|
|
463
|
+
* Configuration for the TOTP two-factor authentication provider.
|
|
464
|
+
*/
|
|
465
|
+
export interface TotpProviderConfig {
|
|
466
|
+
id: string;
|
|
467
|
+
type: "totp";
|
|
468
|
+
options: {
|
|
469
|
+
/** Issuer name shown in authenticator apps (e.g. "My App"). */
|
|
470
|
+
issuer: string;
|
|
471
|
+
/** Number of digits in each code (default: 6). */
|
|
472
|
+
digits: number;
|
|
473
|
+
/** Time period in seconds for code rotation (default: 30). */
|
|
474
|
+
period: number;
|
|
475
|
+
};
|
|
476
|
+
}
|
|
477
|
+
|
|
357
478
|
export type AuthAccountCredentials = {
|
|
358
479
|
id: string;
|
|
359
480
|
secret?: string;
|
|
@@ -472,7 +593,146 @@ export type AuthProviderMaterializedConfig =
|
|
|
472
593
|
| OAuth2Config<any>
|
|
473
594
|
| EmailConfig
|
|
474
595
|
| PhoneConfig
|
|
475
|
-
| ConvexCredentialsConfig
|
|
596
|
+
| ConvexCredentialsConfig
|
|
597
|
+
| PasskeyProviderConfig
|
|
598
|
+
| TotpProviderConfig;
|
|
599
|
+
|
|
600
|
+
// ============================================================================
|
|
601
|
+
// Email transport types
|
|
602
|
+
// ============================================================================
|
|
603
|
+
|
|
604
|
+
/**
|
|
605
|
+
* Email delivery parameters passed to `EmailTransport.send`.
|
|
606
|
+
*/
|
|
607
|
+
export interface EmailMessage {
|
|
608
|
+
/** Sender address (from `email.from` in your Auth config). */
|
|
609
|
+
from: string;
|
|
610
|
+
/** Recipient email address. */
|
|
611
|
+
to: string;
|
|
612
|
+
/** Email subject line. */
|
|
613
|
+
subject: string;
|
|
614
|
+
/** HTML body content. */
|
|
615
|
+
html: string;
|
|
616
|
+
}
|
|
617
|
+
|
|
618
|
+
/**
|
|
619
|
+
* Email transport configuration for the Auth library.
|
|
620
|
+
*
|
|
621
|
+
* Provides a delivery mechanism for library-generated emails
|
|
622
|
+
* (magic links, portal admin sign-in). The library owns the
|
|
623
|
+
* email content; you provide the transport.
|
|
624
|
+
*/
|
|
625
|
+
export interface EmailTransport {
|
|
626
|
+
/** Sender address shown in the From field (e.g. "My App \<noreply@example.com\>"). */
|
|
627
|
+
from: string;
|
|
628
|
+
/**
|
|
629
|
+
* Deliver an email. Called by the library for magic links and portal emails.
|
|
630
|
+
*
|
|
631
|
+
* Receives the Convex action context as the first argument, enabling
|
|
632
|
+
* use with Convex components like `@convex-dev/resend`:
|
|
633
|
+
*
|
|
634
|
+
* ```ts
|
|
635
|
+
* send: (ctx, params) => resend.sendEmail(ctx, params)
|
|
636
|
+
* ```
|
|
637
|
+
*
|
|
638
|
+
* For plain HTTP email APIs, ignore the `ctx` parameter:
|
|
639
|
+
*
|
|
640
|
+
* ```ts
|
|
641
|
+
* send: async (_ctx, { from, to, subject, html }) => {
|
|
642
|
+
* await fetch("https://api.resend.com/emails", { ... });
|
|
643
|
+
* }
|
|
644
|
+
* ```
|
|
645
|
+
*/
|
|
646
|
+
send: (
|
|
647
|
+
ctx: GenericActionCtx<any>,
|
|
648
|
+
params: EmailMessage,
|
|
649
|
+
) => Promise<void>;
|
|
650
|
+
}
|
|
651
|
+
|
|
652
|
+
// ============================================================================
|
|
653
|
+
// API Key types
|
|
654
|
+
// ============================================================================
|
|
655
|
+
|
|
656
|
+
/**
|
|
657
|
+
* A single scope entry stored per API key.
|
|
658
|
+
* Uses a resource:action pattern for structured permissions.
|
|
659
|
+
*
|
|
660
|
+
* ```ts
|
|
661
|
+
* { resource: "users", actions: ["read", "list"] }
|
|
662
|
+
* ```
|
|
663
|
+
*/
|
|
664
|
+
export interface KeyScope {
|
|
665
|
+
resource: string;
|
|
666
|
+
actions: string[];
|
|
667
|
+
}
|
|
668
|
+
|
|
669
|
+
/**
|
|
670
|
+
* Result of scope verification. Provides a `.can()` helper
|
|
671
|
+
* for checking if a key has a specific permission.
|
|
672
|
+
*
|
|
673
|
+
* ```ts
|
|
674
|
+
* const result = await auth.key.verify(ctx, rawKey);
|
|
675
|
+
* if (result.scopes.can("users", "read")) {
|
|
676
|
+
* // authorized
|
|
677
|
+
* }
|
|
678
|
+
* ```
|
|
679
|
+
*/
|
|
680
|
+
export interface ScopeChecker {
|
|
681
|
+
/** Check if the key has permission for a given resource:action. */
|
|
682
|
+
can(resource: string, action: string): boolean;
|
|
683
|
+
/** The raw scope entries from the key. */
|
|
684
|
+
scopes: KeyScope[];
|
|
685
|
+
}
|
|
686
|
+
|
|
687
|
+
/**
|
|
688
|
+
* Configuration for API key support on the Auth class.
|
|
689
|
+
*
|
|
690
|
+
* ```ts
|
|
691
|
+
* const auth = new Auth(components.auth, {
|
|
692
|
+
* providers: [github],
|
|
693
|
+
* apiKeys: {
|
|
694
|
+
* scopes: {
|
|
695
|
+
* users: ["read", "list", "create", "delete"],
|
|
696
|
+
* messages: ["read", "write"],
|
|
697
|
+
* },
|
|
698
|
+
* defaultRateLimit: { maxRequests: 1000, windowMs: 3600000 },
|
|
699
|
+
* },
|
|
700
|
+
* });
|
|
701
|
+
* ```
|
|
702
|
+
*/
|
|
703
|
+
export interface ApiKeyConfig {
|
|
704
|
+
/**
|
|
705
|
+
* Define the available resource:action scopes for your API keys.
|
|
706
|
+
* Keys can only be created with scopes that are a subset of these.
|
|
707
|
+
*/
|
|
708
|
+
scopes?: Record<string, string[]>;
|
|
709
|
+
/**
|
|
710
|
+
* Default rate limit applied to new keys when not specified per-key.
|
|
711
|
+
* Uses a token-bucket algorithm.
|
|
712
|
+
*/
|
|
713
|
+
defaultRateLimit?: { maxRequests: number; windowMs: number };
|
|
714
|
+
/**
|
|
715
|
+
* Key prefix. Defaults to `"sk_live_"`.
|
|
716
|
+
*/
|
|
717
|
+
prefix?: string;
|
|
718
|
+
}
|
|
719
|
+
|
|
720
|
+
/**
|
|
721
|
+
* An API key record as returned by `auth.key.list()` and `auth.key.get()`.
|
|
722
|
+
* Never includes the raw key material — only the display prefix.
|
|
723
|
+
*/
|
|
724
|
+
export interface KeyRecord {
|
|
725
|
+
_id: string;
|
|
726
|
+
userId: string;
|
|
727
|
+
prefix: string;
|
|
728
|
+
name: string;
|
|
729
|
+
scopes: KeyScope[];
|
|
730
|
+
rateLimit?: { maxRequests: number; windowMs: number };
|
|
731
|
+
expiresAt?: number;
|
|
732
|
+
lastUsedAt?: number;
|
|
733
|
+
createdAt: number;
|
|
734
|
+
revoked: boolean;
|
|
735
|
+
}
|
|
476
736
|
|
|
477
737
|
/**
|
|
478
738
|
* Component function references required by core auth runtime.
|
|
@@ -528,8 +788,29 @@ export type AuthComponentApi = {
|
|
|
528
788
|
memberUpdate: FunctionReference<"mutation", "internal">;
|
|
529
789
|
inviteCreate: FunctionReference<"mutation", "internal">;
|
|
530
790
|
inviteGet: FunctionReference<"query", "internal">;
|
|
791
|
+
inviteGetByTokenHash: FunctionReference<"query", "internal">;
|
|
531
792
|
inviteList: FunctionReference<"query", "internal">;
|
|
532
793
|
inviteAccept: FunctionReference<"mutation", "internal">;
|
|
533
794
|
inviteRevoke: FunctionReference<"mutation", "internal">;
|
|
795
|
+
keyInsert: FunctionReference<"mutation", "internal">;
|
|
796
|
+
keyGetByHashedKey: FunctionReference<"query", "internal">;
|
|
797
|
+
keyGetById: FunctionReference<"query", "internal">;
|
|
798
|
+
keyList: FunctionReference<"query", "internal">;
|
|
799
|
+
keyListByUserId: FunctionReference<"query", "internal">;
|
|
800
|
+
keyPatch: FunctionReference<"mutation", "internal">;
|
|
801
|
+
keyDelete: FunctionReference<"mutation", "internal">;
|
|
802
|
+
passkeyInsert: FunctionReference<"mutation", "internal">;
|
|
803
|
+
passkeyGetByCredentialId: FunctionReference<"query", "internal">;
|
|
804
|
+
passkeyListByUserId: FunctionReference<"query", "internal">;
|
|
805
|
+
passkeyUpdateCounter: FunctionReference<"mutation", "internal">;
|
|
806
|
+
passkeyUpdateMeta: FunctionReference<"mutation", "internal">;
|
|
807
|
+
passkeyDelete: FunctionReference<"mutation", "internal">;
|
|
808
|
+
totpInsert: FunctionReference<"mutation", "internal", any, any>;
|
|
809
|
+
totpGetVerifiedByUserId: FunctionReference<"query", "internal", any, any>;
|
|
810
|
+
totpListByUserId: FunctionReference<"query", "internal", any, any>;
|
|
811
|
+
totpGetById: FunctionReference<"query", "internal", any, any>;
|
|
812
|
+
totpMarkVerified: FunctionReference<"mutation", "internal", any, any>;
|
|
813
|
+
totpUpdateLastUsed: FunctionReference<"mutation", "internal", any, any>;
|
|
814
|
+
totpDelete: FunctionReference<"mutation", "internal", any, any>;
|
|
534
815
|
};
|
|
535
816
|
};
|