@estifanos-sh/convex-auth 0.0.2 → 0.0.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +5 -5
- package/dist/_generated/component.d.ts +130 -61
- package/dist/_generated/component.d.ts.map +1 -1
- package/dist/_generated/dataModel.d.ts +28 -0
- package/dist/_generated/dataModel.d.ts.map +1 -0
- package/dist/bin.js +1 -2
- package/dist/browser/index.d.ts +2 -2
- package/dist/browser/index.d.ts.map +1 -1
- package/dist/browser/index.js.map +1 -1
- package/dist/client/core/types.d.ts +40 -79
- package/dist/client/core/types.d.ts.map +1 -1
- package/dist/client/core/types.js.map +1 -1
- package/dist/client/errors.d.ts +15 -0
- package/dist/client/errors.d.ts.map +1 -0
- package/dist/client/errors.js +8 -1
- package/dist/client/errors.js.map +1 -1
- package/dist/client/index.d.ts +6 -3
- package/dist/client/index.d.ts.map +1 -1
- package/dist/client/index.js +3 -2
- package/dist/client/index.js.map +1 -1
- package/dist/component/_generated/component.d.ts +130 -61
- package/dist/component/_generated/component.d.ts.map +1 -1
- package/dist/component/_generated/dataModel.d.ts +1 -1
- package/dist/component/_generated/server.d.ts +1 -1
- package/dist/component/account.d.ts +43 -37
- package/dist/component/account.d.ts.map +1 -1
- package/dist/component/account.js +14 -16
- package/dist/component/account.js.map +1 -1
- package/dist/component/connection/audit.d.ts +29 -29
- package/dist/component/connection/audit.d.ts.map +1 -1
- package/dist/component/connection/audit.js +2 -1
- package/dist/component/connection/audit.js.map +1 -1
- package/dist/component/connection/cache.d.ts +6 -6
- package/dist/component/connection/domain/verification.d.ts +19 -19
- package/dist/component/connection/domain.d.ts +20 -20
- package/dist/component/connection/saml/assertion.d.ts +4 -4
- package/dist/component/connection/saml/request.d.ts +9 -9
- package/dist/component/connection/saml/request.d.ts.map +1 -1
- package/dist/component/connection/scim/config.d.ts +13 -13
- package/dist/component/connection/scim/identity.d.ts +102 -59
- package/dist/component/connection/scim/identity.d.ts.map +1 -1
- package/dist/component/connection/scim/identity.js +357 -56
- package/dist/component/connection/scim/identity.js.map +1 -1
- package/dist/component/connection/secret.d.ts +15 -15
- package/dist/component/connection/secret.d.ts.map +1 -1
- package/dist/component/connection/webhook/delivery.d.ts +69 -53
- package/dist/component/connection/webhook/delivery.d.ts.map +1 -1
- package/dist/component/connection/webhook/delivery.js +127 -170
- package/dist/component/connection/webhook/delivery.js.map +1 -1
- package/dist/component/connection/webhook/endpoint.d.ts +21 -21
- package/dist/component/connection/webhook/events.d.ts +26 -0
- package/dist/component/connection/webhook/events.d.ts.map +1 -0
- package/dist/component/connection/webhook/events.js +39 -0
- package/dist/component/connection/webhook/events.js.map +1 -0
- package/dist/component/connection.d.ts +38 -38
- package/dist/component/connection.d.ts.map +1 -1
- package/dist/component/context.d.ts +115 -0
- package/dist/component/context.d.ts.map +1 -0
- package/dist/component/context.js +50 -0
- package/dist/component/context.js.map +1 -0
- package/dist/component/convex.config.d.ts +2 -2
- package/dist/component/crons.d.ts +2 -2
- package/dist/component/event.d.ts +134 -138
- package/dist/component/event.d.ts.map +1 -1
- package/dist/component/event.js +88 -117
- package/dist/component/event.js.map +1 -1
- package/dist/component/eventstream.d.ts +30 -0
- package/dist/component/eventstream.d.ts.map +1 -0
- package/dist/component/eventstream.js +51 -0
- package/dist/component/eventstream.js.map +1 -0
- package/dist/component/factor/device.d.ts +25 -24
- package/dist/component/factor/device.d.ts.map +1 -1
- package/dist/component/factor/device.js +5 -2
- package/dist/component/factor/device.js.map +1 -1
- package/dist/component/factor/passkey.d.ts +84 -75
- package/dist/component/factor/passkey.d.ts.map +1 -1
- package/dist/component/factor/passkey.js +6 -6
- package/dist/component/factor/passkey.js.map +1 -1
- package/dist/component/factor/totp.d.ts +54 -49
- package/dist/component/factor/totp.d.ts.map +1 -1
- package/dist/component/factor/totp.js +3 -3
- package/dist/component/factor/totp.js.map +1 -1
- package/dist/component/group/active.d.ts +326 -22
- package/dist/component/group/active.d.ts.map +1 -1
- package/dist/component/group/active.js +21 -11
- package/dist/component/group/active.js.map +1 -1
- package/dist/component/group/invite.d.ts +28 -28
- package/dist/component/group/invite.d.ts.map +1 -1
- package/dist/component/group/member.d.ts +34 -34
- package/dist/component/group.d.ts +47 -62
- package/dist/component/group.d.ts.map +1 -1
- package/dist/component/http.d.ts +2 -2
- package/dist/component/limits.d.ts +4 -4
- package/dist/component/maintenance.d.ts +2 -2
- package/dist/component/model.d.ts +1362 -1027
- package/dist/component/model.d.ts.map +1 -1
- package/dist/component/model.js +23 -6
- package/dist/component/model.js.map +1 -1
- package/dist/component/modules.d.ts +8 -2
- package/dist/component/modules.d.ts.map +1 -1
- package/dist/component/modules.js +3 -0
- package/dist/component/modules.js.map +1 -1
- package/dist/component/oauth/client.d.ts +20 -20
- package/dist/component/oauth/code.d.ts +14 -14
- package/dist/component/oauth/refresh.d.ts +19 -19
- package/dist/component/schema.d.ts +1100 -611
- package/dist/component/schema.d.ts.map +1 -1
- package/dist/component/schema.js +17 -4
- package/dist/component/schema.js.map +1 -1
- package/dist/component/session.d.ts +72 -32
- package/dist/component/session.d.ts.map +1 -1
- package/dist/component/session.js +120 -32
- package/dist/component/session.js.map +1 -1
- package/dist/component/token/continuation.d.ts +40 -18
- package/dist/component/token/continuation.d.ts.map +1 -1
- package/dist/component/token/continuation.js +57 -11
- package/dist/component/token/continuation.js.map +1 -1
- package/dist/component/token/pkce.d.ts +22 -22
- package/dist/component/token/pkce.d.ts.map +1 -1
- package/dist/component/token/refresh.d.ts +39 -35
- package/dist/component/token/refresh.d.ts.map +1 -1
- package/dist/component/token/refresh.js +11 -6
- package/dist/component/token/refresh.js.map +1 -1
- package/dist/component/token/verification.d.ts +36 -32
- package/dist/component/token/verification.d.ts.map +1 -1
- package/dist/component/token/verification.js +3 -3
- package/dist/component/token/verification.js.map +1 -1
- package/dist/component/user/email.d.ts +21 -21
- package/dist/component/user/key.d.ts +35 -35
- package/dist/component/user/key.d.ts.map +1 -1
- package/dist/component/user.d.ts +51 -45
- package/dist/component/user.d.ts.map +1 -1
- package/dist/core/index.d.ts +54 -90
- package/dist/core/index.d.ts.map +1 -1
- package/dist/core/index.js +1 -4
- package/dist/core/index.js.map +1 -1
- package/dist/expo/index.d.ts +3 -3
- package/dist/expo/index.d.ts.map +1 -1
- package/dist/expo/index.js.map +1 -1
- package/dist/model.js.map +1 -1
- package/dist/providers/anonymous.d.ts +11 -5
- package/dist/providers/anonymous.d.ts.map +1 -1
- package/dist/providers/anonymous.js +4 -1
- package/dist/providers/anonymous.js.map +1 -1
- package/dist/providers/apple.d.ts +1 -1
- package/dist/providers/credentials.d.ts +21 -13
- package/dist/providers/credentials.d.ts.map +1 -1
- package/dist/providers/credentials.js +2 -0
- package/dist/providers/credentials.js.map +1 -1
- package/dist/providers/custom.d.ts +3 -3
- package/dist/providers/custom.d.ts.map +1 -1
- package/dist/providers/custom.js.map +1 -1
- package/dist/providers/email.d.ts +3 -3
- package/dist/providers/email.d.ts.map +1 -1
- package/dist/providers/email.js.map +1 -1
- package/dist/providers/github.d.ts +1 -1
- package/dist/providers/google.d.ts +1 -1
- package/dist/providers/microsoft.d.ts +1 -1
- package/dist/providers/password.d.ts +103 -8
- package/dist/providers/password.d.ts.map +1 -1
- package/dist/providers/password.js +71 -26
- package/dist/providers/password.js.map +1 -1
- package/dist/providers/phone.d.ts +4 -3
- package/dist/providers/phone.d.ts.map +1 -1
- package/dist/providers/phone.js.map +1 -1
- package/dist/react/index.d.ts +40 -41
- package/dist/react/index.d.ts.map +1 -1
- package/dist/react/index.js +27 -52
- package/dist/react/index.js.map +1 -1
- package/dist/server/auth.d.ts +157 -117
- package/dist/server/auth.d.ts.map +1 -1
- package/dist/server/auth.js +41 -22
- package/dist/server/auth.js.map +1 -1
- package/dist/server/component/factor/db.js +4 -4
- package/dist/server/component/factor/db.js.map +1 -1
- package/dist/server/config.d.ts +2 -1
- package/dist/server/connection/domain.d.ts +4 -66
- package/dist/server/connection/domain.d.ts.map +1 -1
- package/dist/server/connection/domain.js +22 -4
- package/dist/server/connection/domain.js.map +1 -1
- package/dist/server/connection/group/service.js +6 -4
- package/dist/server/connection/group/service.js.map +1 -1
- package/dist/server/connection/http.js +94 -261
- package/dist/server/connection/http.js.map +1 -1
- package/dist/server/connection/oidc.js +8 -17
- package/dist/server/connection/oidc.js.map +1 -1
- package/dist/server/connection/policy/domain.js +4 -1
- package/dist/server/connection/policy/domain.js.map +1 -1
- package/dist/server/connection/policy.js +14 -13
- package/dist/server/connection/policy.js.map +1 -1
- package/dist/server/connection/provision.js +5 -19
- package/dist/server/connection/provision.js.map +1 -1
- package/dist/server/connection/webhook.js +4 -36
- package/dist/server/connection/webhook.js.map +1 -1
- package/dist/server/context.d.ts +2 -2
- package/dist/server/context.d.ts.map +1 -1
- package/dist/server/context.js +35 -24
- package/dist/server/context.js.map +1 -1
- package/dist/server/contract.d.ts.map +1 -1
- package/dist/server/contract.js +6 -14
- package/dist/server/contract.js.map +1 -1
- package/dist/server/core.js +6 -0
- package/dist/server/core.js.map +1 -1
- package/dist/server/cors.d.ts +2 -2
- package/dist/server/cors.d.ts.map +1 -1
- package/dist/server/crypto.js.map +1 -1
- package/dist/server/db.js +2 -1
- package/dist/server/db.js.map +1 -1
- package/dist/server/domains/context.js +34 -0
- package/dist/server/domains/context.js.map +1 -0
- package/dist/server/domains/factor.d.ts +3 -2
- package/dist/server/domains/factor.d.ts.map +1 -1
- package/dist/server/domains/factor.js.map +1 -1
- package/dist/server/domains/group.js.map +1 -1
- package/dist/server/domains/invite.js.map +1 -1
- package/dist/server/domains/key.js.map +1 -1
- package/dist/server/domains/member.js.map +1 -1
- package/dist/server/domains/session.js.map +1 -1
- package/dist/server/domains/user.js.map +1 -1
- package/dist/server/env.js +2 -22
- package/dist/server/env.js.map +1 -1
- package/dist/server/events.d.ts +0 -1
- package/dist/server/events.d.ts.map +1 -1
- package/dist/server/events.js +6 -6
- package/dist/server/events.js.map +1 -1
- package/dist/server/http.d.ts +1 -0
- package/dist/server/http.d.ts.map +1 -1
- package/dist/server/http.js +4 -4
- package/dist/server/http.js.map +1 -1
- package/dist/server/identity/claims.js +1 -1
- package/dist/server/identity/convex.d.ts +2 -0
- package/dist/server/identity/convex.d.ts.map +1 -1
- package/dist/server/index.d.ts +2 -3
- package/dist/server/index.js +1 -2
- package/dist/server/limits.js +21 -1
- package/dist/server/limits.js.map +1 -1
- package/dist/server/mutations/credentials/signin.js +6 -3
- package/dist/server/mutations/credentials/signin.js.map +1 -1
- package/dist/server/mutations/invalidate.js +5 -10
- package/dist/server/mutations/invalidate.js.map +1 -1
- package/dist/server/mutations/oauth.js +1 -1
- package/dist/server/mutations/oauth.js.map +1 -1
- package/dist/server/mutations/retrieve.js +4 -1
- package/dist/server/mutations/retrieve.js.map +1 -1
- package/dist/server/mutations/signin.js +2 -2
- package/dist/server/mutations/signin.js.map +1 -1
- package/dist/server/mutations/verify.js +4 -3
- package/dist/server/mutations/verify.js.map +1 -1
- package/dist/server/oauth/factory.js.map +1 -1
- package/dist/server/runtime.d.ts +107 -127
- package/dist/server/runtime.d.ts.map +1 -1
- package/dist/server/runtime.js +43 -28
- package/dist/server/runtime.js.map +1 -1
- package/dist/server/session/lifecycle.d.ts.map +1 -1
- package/dist/server/session/lifecycle.js +18 -3
- package/dist/server/session/lifecycle.js.map +1 -1
- package/dist/server/signin/flow.js +1 -1
- package/dist/server/signin/flow.js.map +1 -1
- package/dist/server/tokens.js +1 -0
- package/dist/server/tokens.js.map +1 -1
- package/dist/server/totp.js +3 -3
- package/dist/server/totp.js.map +1 -1
- package/dist/server/types.d.ts +63 -43
- package/dist/server/types.d.ts.map +1 -1
- package/dist/server/user/account.js +0 -1
- package/dist/server/user/account.js.map +1 -1
- package/dist/server/validators.d.ts +874 -917
- package/dist/server/validators.d.ts.map +1 -1
- package/dist/server/validators.js +33 -32
- package/dist/server/validators.js.map +1 -1
- package/dist/server/webauthn.js +4 -4
- package/dist/server/webauthn.js.map +1 -1
- package/dist/shared/brand.d.ts +3 -7
- package/dist/shared/brand.d.ts.map +1 -1
- package/dist/shared/params.d.ts +78 -0
- package/dist/shared/params.d.ts.map +1 -0
- package/dist/shared/results.d.ts +7 -1
- package/dist/shared/results.d.ts.map +1 -1
- package/dist/svelte/context.svelte.d.ts +23 -12
- package/dist/svelte/context.svelte.d.ts.map +1 -1
- package/dist/svelte/context.svelte.js +20 -13
- package/dist/svelte/index.d.ts +1 -4
- package/dist/svelte/index.d.ts.map +1 -1
- package/dist/svelte/index.js +1 -4
- package/dist/test.d.ts +1105 -611
- package/dist/test.d.ts.map +1 -1
- package/package.json +2 -1
- package/dist/server/env.d.ts +0 -28
- package/dist/server/env.d.ts.map +0 -1
- package/dist/svelte/AuthLoading.svelte +0 -13
- package/dist/svelte/AuthLoading.svelte.d.ts +0 -8
- package/dist/svelte/AuthLoading.svelte.d.ts.map +0 -1
- package/dist/svelte/SignedIn.svelte +0 -14
- package/dist/svelte/SignedIn.svelte.d.ts +0 -8
- package/dist/svelte/SignedIn.svelte.d.ts.map +0 -1
- package/dist/svelte/SignedOut.svelte +0 -13
- package/dist/svelte/SignedOut.svelte.d.ts +0 -8
- package/dist/svelte/SignedOut.svelte.d.ts.map +0 -1
package/dist/server/runtime.js
CHANGED
|
@@ -28,13 +28,14 @@ import { wellKnown } from "./wellknown.js";
|
|
|
28
28
|
import { encryptSecret } from "./secret.js";
|
|
29
29
|
import { createGroupService } from "./connection/group/service.js";
|
|
30
30
|
import { createFactorUnlinkHelpers } from "./services/factors.js";
|
|
31
|
-
import { mutateContinuationCreate,
|
|
31
|
+
import { mutateContinuationCreate, queryContinuation } from "./component/factor/db.js";
|
|
32
32
|
import { resolveServerServices } from "./services/resolve.js";
|
|
33
33
|
import { signInImpl } from "./signin/flow.js";
|
|
34
34
|
import { createGroupConnectionDomain } from "./connection/domain.js";
|
|
35
35
|
import { addGroupHttpRuntime } from "./connection/http.js";
|
|
36
36
|
import { ConvexError, v } from "convex/values";
|
|
37
37
|
import { actionGeneric, httpRouter, internalMutationGeneric } from "convex/server";
|
|
38
|
+
import { validate } from "convex-helpers/validators";
|
|
38
39
|
|
|
39
40
|
//#region src/server/runtime.ts
|
|
40
41
|
const GROUP_CONNECTION_OIDC_CLIENT_SECRET_KIND = "oidc_client_secret";
|
|
@@ -90,6 +91,24 @@ function enrichActionCtx(ctx, auth) {
|
|
|
90
91
|
return enriched;
|
|
91
92
|
}
|
|
92
93
|
/**
|
|
94
|
+
* The transport envelope for the public sign-in action.
|
|
95
|
+
*
|
|
96
|
+
* Convex requires every exported function's argument validator to be an
|
|
97
|
+
* object (or `v.any()`), so a provider-discriminated top-level union cannot be
|
|
98
|
+
* exported. The configured provider union remains the public TypeScript
|
|
99
|
+
* contract through {@link AuthSignInAction}; the handler below validates the
|
|
100
|
+
* selected provider's params before starting a sign-in flow.
|
|
101
|
+
*/
|
|
102
|
+
/** @internal */
|
|
103
|
+
const vSignInActionArgs = v.object({
|
|
104
|
+
provider: v.optional(v.string()),
|
|
105
|
+
params: v.optional(v.any()),
|
|
106
|
+
verifier: v.optional(v.string()),
|
|
107
|
+
continuation: v.optional(v.string()),
|
|
108
|
+
refreshToken: v.optional(v.string()),
|
|
109
|
+
calledBy: v.optional(v.string())
|
|
110
|
+
});
|
|
111
|
+
/**
|
|
93
112
|
* Configure the Convex Auth library. Returns an object with
|
|
94
113
|
* functions and `auth` helper. You must export the functions
|
|
95
114
|
* from `convex/auth.ts` to make them callable:
|
|
@@ -133,21 +152,8 @@ function Auth(config_) {
|
|
|
133
152
|
sha256
|
|
134
153
|
});
|
|
135
154
|
const authRequireEnv = (name) => name === "CONVEX_SITE_URL" ? authSiteUrl() : requireEnv(name);
|
|
136
|
-
const
|
|
137
|
-
const
|
|
138
|
-
const enriched = bridgeRuntimeType(enrichCtx(ctx));
|
|
139
|
-
const continuationArgs = {
|
|
140
|
-
userId,
|
|
141
|
-
provider: operation.provider.id,
|
|
142
|
-
operation: operation.operation,
|
|
143
|
-
expirationTime: Date.now() + (operation.provider.options.challengeExpirationMs ?? 3e5)
|
|
144
|
-
};
|
|
145
|
-
const continuation = "commit" in continuationRequest && continuationRequest.commit === "passwordReset" ? await mutatePasswordResetContinuationCreate(enriched, {
|
|
146
|
-
...continuationArgs,
|
|
147
|
-
accountId: continuationRequest.accountId,
|
|
148
|
-
secret: continuationRequest.secret
|
|
149
|
-
}) : await mutateContinuationCreate(enriched, continuationArgs);
|
|
150
|
-
const result = await signInImpl(enriched, operation.provider, {
|
|
155
|
+
const beginProviderContinuation = async (ctx, operation, continuation) => {
|
|
156
|
+
const result = await signInImpl(bridgeRuntimeType(enrichCtx(ctx)), operation.provider, {
|
|
151
157
|
params: { flow: "register" },
|
|
152
158
|
continuation
|
|
153
159
|
}, {
|
|
@@ -157,6 +163,16 @@ function Auth(config_) {
|
|
|
157
163
|
if (result.kind === "signedIn") throw new Error("A provider continuation cannot issue an immediate session.");
|
|
158
164
|
return result;
|
|
159
165
|
};
|
|
166
|
+
const continueWithProvider = async (ctx, args) => {
|
|
167
|
+
const continuation = await mutateContinuationCreate(bridgeRuntimeType(enrichCtx(ctx)), {
|
|
168
|
+
userId: args.userId,
|
|
169
|
+
provider: args.operation.provider.id,
|
|
170
|
+
operation: args.operation.operation,
|
|
171
|
+
expirationTime: Date.now() + (args.operation.provider.options.challengeExpirationMs ?? 3e5)
|
|
172
|
+
});
|
|
173
|
+
return await beginProviderContinuation(ctx, args.operation, continuation);
|
|
174
|
+
};
|
|
175
|
+
const continueRecovery = async (ctx, args) => await beginProviderContinuation(ctx, args.operation, args.continuationId);
|
|
160
176
|
const authBase = {
|
|
161
177
|
...createCoreDomains({
|
|
162
178
|
config,
|
|
@@ -355,24 +371,14 @@ function Auth(config_) {
|
|
|
355
371
|
member: auth.member,
|
|
356
372
|
provider: {
|
|
357
373
|
...auth.provider,
|
|
358
|
-
|
|
359
|
-
...args,
|
|
360
|
-
commit: "passwordReset"
|
|
361
|
-
})
|
|
374
|
+
continueRecovery: async (continuationCtx, args) => await continueRecovery(continuationCtx, args)
|
|
362
375
|
},
|
|
363
376
|
event: auth.event
|
|
364
377
|
});
|
|
365
378
|
return {
|
|
366
379
|
auth,
|
|
367
380
|
signIn: actionGeneric({
|
|
368
|
-
args:
|
|
369
|
-
provider: v.optional(v.string()),
|
|
370
|
-
params: v.optional(vPayloadRecord),
|
|
371
|
-
verifier: v.optional(v.string()),
|
|
372
|
-
continuation: v.optional(v.string()),
|
|
373
|
-
refreshToken: v.optional(v.string()),
|
|
374
|
-
calledBy: v.optional(v.string())
|
|
375
|
-
},
|
|
381
|
+
args: vSignInActionArgs,
|
|
376
382
|
handler: async (ctx, args) => {
|
|
377
383
|
if (args.calledBy !== void 0) log("INFO", `\`auth:signIn\` called by ${args.calledBy}`);
|
|
378
384
|
let provider = null;
|
|
@@ -388,6 +394,15 @@ function Auth(config_) {
|
|
|
388
394
|
message: "The provider continuation does not support this provider."
|
|
389
395
|
});
|
|
390
396
|
} else if (args.provider !== void 0) provider = getProviderOrThrow(args.provider);
|
|
397
|
+
if (provider?.type === "credentials") {
|
|
398
|
+
if (!validate(provider.params, args.params)) throw new ConvexError({
|
|
399
|
+
code: ErrorCode.INVALID_PARAMETERS,
|
|
400
|
+
message: `Invalid parameters for credentials provider ${provider.id}.`
|
|
401
|
+
});
|
|
402
|
+
} else if (!validate(v.optional(vPayloadRecord), args.params)) throw new ConvexError({
|
|
403
|
+
code: ErrorCode.INVALID_PARAMETERS,
|
|
404
|
+
message: "Sign-in parameters must contain only supported payload values."
|
|
405
|
+
});
|
|
391
406
|
const authSiteUrl$1 = provider?.type === "oauth" || provider?.type === "connection" ? getAuthSiteUrl(ctx) : void 0;
|
|
392
407
|
const result = await signInImpl(bridgeRuntimeType(enrichCtx(ctx)), provider, args, {
|
|
393
408
|
generateTokens: true,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"runtime.js","names":["http","request","authSiteUrl"],"sources":["../../src/server/runtime.ts"],"sourcesContent":["import {\n GenericActionCtx,\n GenericDataModel,\n HttpRouter,\n actionGeneric,\n httpRouter,\n internalMutationGeneric,\n} from \"convex/server\";\nimport type { RouteSpec } from \"convex/server\";\nimport { ConvexError, v } from \"convex/values\";\nimport type { GenericValidator } from \"convex/values\";\n\nimport type { AuthTokens, SignInFlowResult } from \"../shared/results\";\nimport { ErrorCode } from \"../shared/codes\";\nimport { createCoreDomains } from \"./core\";\nimport { GetProviderOrThrowFunc } from \"./crypto\";\nimport { requireAuthKey, requireEnv } from \"./env\";\nimport { createAuthEventDomain, emitAuthEvent } from \"./events\";\nimport {\n addAuthRoutes,\n addOAuthProviderRoutes,\n addOpenIdRoutes,\n addWellKnownRoutes,\n createHttpAction,\n createHttpContext,\n createHttpRoute,\n} from \"./http\";\nimport { addMcpRoutes, type McpToolDef } from \"./mcp\";\nimport { createAuthorizeHandler } from \"./oauth/authorize\";\nimport { createOAuthHttpHandlers } from \"./oauth/handlers\";\nimport { createClientManagementHandler } from \"./oauth/manage\";\nimport { createRegisterHandler } from \"./oauth/register\";\nimport type { OAuthCodeRecord } from \"./oauth/code\";\nimport { createTokenHandler } from \"./oauth/token\";\nimport { verifyOAuthToken } from \"./tokens\";\nimport { wellKnown } from \"./wellknown\";\nimport { log } from \"./log\";\nimport {\n callCreateAccountFromCredentials,\n callInvalidateSessions,\n callModifyAccount,\n callRetrieveAccountWithCredentials,\n callSignOut,\n callUserOAuth,\n callVerifierSignature,\n vStoreArgs,\n storeImpl,\n} from \"./mutations/calls\";\nimport { vPayloadRecord } from \"./payloads\";\nimport { generateRandomString, INVITE_TOKEN_ALPHABET, sha256 } from \"./random\";\nimport { extractBearerToken } from \"./utils/bearer\";\nimport { encryptSecret } from \"./secret\";\nimport { createGroupService } from \"./connection/group/service\";\nimport { createFactorUnlinkHelpers } from \"./services/factors\";\nimport {\n mutateContinuationCreate,\n mutatePasswordResetContinuationCreate,\n queryContinuation,\n} from \"./component/factor/db\";\nimport { resolveServerServices } from \"./services/resolve\";\nimport { signInImpl } from \"./signin/flow\";\nimport { createGroupConnectionDomain } from \"./connection/domain\";\nimport { addGroupHttpRuntime } from \"./connection/http\";\nimport { normalizeGroupConnectionPolicy } from \"./connection/policy\";\nimport type {\n AuthProviderContinueArgs,\n ConvexAuthConfig,\n FunctionReferenceFromExport,\n ConnectionProviderConfig,\n} from \"./types\";\nimport { MutationCtx } from \"./types\";\nimport { appUrlFromEnv, authUrlFromEnv } from \"./url\";\n\nconst GROUP_CONNECTION_OIDC_CLIENT_SECRET_KIND = \"oidc_client_secret\" as const;\n\n/**\n * Single sanctioned bridge across an irreducible cross-package ctx/domain\n * family boundary. Several runtime values are structurally equivalent at\n * runtime to a consumer's nominal type but cannot be positively unified by\n * TypeScript — e.g. the {@link enrichCtx}-enriched action ctx versus the\n * sign-in service's `GenericActionCtxWithAuthConfig`, or the assembled\n * `authBase` versus the HTTP context's `HttpContextAuthLike`. This is the one\n * narrow, typed assertion those boundaries route through; callers name the\n * exact target via the `T` type argument so the result stays precisely typed.\n */\nfunction bridgeRuntimeType<T>(value: object): T {\n return value as T;\n}\n\n/**\n * Preserve Convex action context behavior while replacing `ctx.auth`.\n *\n * Convex context methods can be non-enumerable or prototype-backed. A plain\n * `{ ...ctx, auth }` drops those methods in packaged builds, so calls such as\n * `ctx.runQuery(...)` disappear inside provider flows. Forward the call methods\n * bound to the original ctx and preserve the rest of the context descriptors.\n *\n * @internal\n */\nexport function enrichActionCtx<\n DataModel extends GenericDataModel,\n AuthContext extends GenericActionCtx<DataModel>[\"auth\"] & Record<string, unknown>,\n>(\n ctx: GenericActionCtx<DataModel>,\n auth: AuthContext,\n): GenericActionCtx<DataModel> & { auth: AuthContext } {\n const {\n auth: _authDescriptor,\n runAction: _runActionDescriptor,\n runMutation: _runMutationDescriptor,\n runQuery: _runQueryDescriptor,\n ...descriptors\n } = Object.getOwnPropertyDescriptors(ctx);\n\n const enriched = Object.create(\n Object.getPrototypeOf(ctx),\n descriptors,\n ) as GenericActionCtx<DataModel>;\n\n Object.defineProperties(enriched, {\n auth: {\n configurable: true,\n enumerable: true,\n value: auth,\n writable: true,\n },\n runAction: {\n configurable: true,\n value: ctx.runAction.bind(ctx),\n writable: true,\n },\n runMutation: {\n configurable: true,\n value: ctx.runMutation.bind(ctx),\n writable: true,\n },\n runQuery: {\n configurable: true,\n value: ctx.runQuery.bind(ctx),\n writable: true,\n },\n });\n\n return enriched as GenericActionCtx<DataModel> & { auth: AuthContext };\n}\n\n/**\n * The type of the signIn Convex Action returned from the auth() helper.\n *\n * This type is exported for implementors of other client integrations.\n * However it is not stable, and may change until this library reaches 1.0.\n *\n * @internal\n */\nexport type SignInAction = FunctionReferenceFromExport<ReturnType<typeof Auth>[\"signIn\"]>;\n\n/** @internal */\nexport type SignInActionResult = SignInFlowResult<AuthTokens | null>;\n/**\n * The type of the signOut Convex Action returned from the auth() helper.\n *\n * This type is exported for implementors of other client integrations.\n * However it is not stable, and may change until this library reaches 1.0.\n *\n * @internal\n */\nexport type SignOutAction = FunctionReferenceFromExport<ReturnType<typeof Auth>[\"signOut\"]>;\n\n/**\n * Configure the Convex Auth library. Returns an object with\n * functions and `auth` helper. You must export the functions\n * from `convex/auth.ts` to make them callable:\n *\n * ```ts filename=\"convex/auth.ts\"\n * import { defineAuth } from \"@estifanos-sh/convex-auth/component\";\n * import { components } from \"./_generated/api\";\n *\n * export const auth = defineAuth(components.auth, {\n * providers: [],\n * });\n * export const { signIn, signOut, store } = auth;\n * ```\n *\n * Mount the auth HTTP routes from `convex/http.ts`:\n *\n * ```ts filename=\"convex/http.ts\"\n * import { auth } from \"./auth\";\n *\n * export default auth.http();\n * ```\n *\n * @returns An object with fields you should reexport from your\n * `convex/auth.ts` file, plus the `http` router factory.\n */\nexport function Auth(config_: ConvexAuthConfig<any>) {\n const services = resolveServerServices(config_);\n const config = services.config;\n const delegatableGrants: string[] = [...(config.permissions?.grants ?? [])];\n const hasOAuth = config.providers.some((provider) => provider.type === \"oauth\");\n const hasConnection = config.providers.some((provider) => provider.type === \"connection\");\n const ssoProvider = config.providers.find(\n (provider): provider is ConnectionProviderConfig => provider.type === \"connection\",\n );\n const getProviderOrThrow: GetProviderOrThrowFunc = services.providerRegistry.getProviderOrThrow;\n const INVITE_TOKEN_LENGTH = 48;\n\n const GROUP_CONNECTION_ROUTE_BASE = \"/connections\";\n const routePrefix = config.path ?? \"/auth\";\n const authSiteUrl = () => authUrlFromEnv(routePrefix);\n const authCallbackUrl = (providerId: string) => `${authSiteUrl()}/callback/${providerId}`;\n const group = createGroupService({ config, sha256 });\n const authRequireEnv = (name: string) =>\n name === \"CONVEX_SITE_URL\" ? authSiteUrl() : requireEnv(name);\n\n type AuthRuntimeBase = ReturnType<typeof createCoreDomains> & {\n event: ReturnType<typeof createAuthEventDomain>;\n connection: ReturnType<typeof createGroupConnectionDomain>;\n };\n\n type PasswordResetContinuationRequest = AuthProviderContinueArgs & {\n commit: \"passwordReset\";\n accountId: string;\n secret: string;\n };\n\n const continueWithProvider = async <DataModel extends GenericDataModel>(\n ctx: GenericActionCtx<DataModel>,\n continuationRequest: AuthProviderContinueArgs | PasswordResetContinuationRequest,\n ) => {\n const { userId, operation } = continuationRequest;\n const enriched = bridgeRuntimeType<Parameters<typeof signInImpl>[0]>(enrichCtx(ctx));\n const continuationArgs = {\n userId,\n provider: operation.provider.id,\n operation: operation.operation,\n expirationTime: Date.now() + (operation.provider.options.challengeExpirationMs ?? 300_000),\n };\n const continuation =\n \"commit\" in continuationRequest && continuationRequest.commit === \"passwordReset\"\n ? await mutatePasswordResetContinuationCreate(enriched, {\n ...continuationArgs,\n accountId: continuationRequest.accountId,\n secret: continuationRequest.secret,\n })\n : await mutateContinuationCreate(enriched, continuationArgs);\n const result = await signInImpl(\n enriched,\n operation.provider,\n {\n params: { flow: \"register\" },\n continuation,\n },\n {\n generateTokens: true,\n allowExtraProviders: true,\n },\n );\n if (result.kind === \"signedIn\") {\n throw new Error(\"A provider continuation cannot issue an immediate session.\");\n }\n return result;\n };\n\n const authBase: AuthRuntimeBase = {\n ...createCoreDomains({\n config,\n callInvalidateSessions,\n callCreateAccountFromCredentials,\n callRetrieveAccountWithCredentials,\n callModifyAccount,\n getEnrichCtx: () => enrichCtx,\n inviteTokenAlphabet: INVITE_TOKEN_ALPHABET,\n inviteTokenLength: INVITE_TOKEN_LENGTH,\n signInForProvider: async (ctx, providerConfig, args) => {\n const materialized =\n typeof providerConfig === \"function\" ? providerConfig() : providerConfig;\n const result = await signInImpl(\n bridgeRuntimeType<Parameters<typeof signInImpl>[0]>(enrichCtx(ctx)),\n materialized as Parameters<typeof signInImpl>[1],\n args,\n {\n generateTokens: false,\n allowExtraProviders: true,\n },\n );\n if (result.kind === \"signedIn\") {\n const session = result.session as {\n userId?: string;\n sessionId?: string;\n _id?: string;\n } | null;\n if (session === null || session === undefined) {\n return null;\n }\n const userId = session.userId;\n const sessionId = session.sessionId ?? session._id;\n if (userId === undefined || sessionId === undefined) {\n return null;\n }\n return { userId, sessionId };\n }\n return result as Exclude<typeof result, { kind: \"signedIn\" }>;\n },\n continueWithProvider,\n }),\n event: createAuthEventDomain(config),\n /**\n * Connection namespace — group connection management, domain, OIDC,\n * SAML, SCIM, audit, and webhook helpers.\n */\n connection: createGroupConnectionDomain({\n config,\n getGroupConnectionSecret: group.getGroupConnectionSecret,\n loadConnectionOrThrow: group.loadConnectionOrThrow,\n validateGroupConnectionPolicy: group.validateGroupConnectionPolicy,\n emitGroupAuthEvent: group.emitGroupAuthEvent,\n connectionNotFoundError: \"Connection not found.\",\n GROUP_CONNECTION_OIDC_CLIENT_SECRET_KIND,\n requireEnv: authRequireEnv,\n generateRandomString,\n INVITE_TOKEN_ALPHABET,\n sha256,\n encryptSecret,\n loadGroupPolicyOrThrow: group.loadGroupPolicyOrThrow,\n }),\n };\n\n const getDefaultCorsOrigins = () => [new URL(appUrlFromEnv()).origin];\n\n const getAuthSiteUrl = (_ctx: GenericActionCtx<GenericDataModel>) => authSiteUrl();\n\n const oauthHttpHandlers = createOAuthHttpHandlers({\n config,\n getProviderOrThrow,\n authCallbackUrl,\n });\n\n const request = {\n /**\n * Register core HTTP routes for JWT verification and OAuth sign-in.\n *\n * ```ts\n * import { httpRouter } from \"convex/server\";\n * import { auth } from \"./auth\";\n *\n * export default auth.http();\n * ```\n *\n * The following routes are handled always:\n *\n * - `/.well-known/apple-app-site-association`\n * - `/.well-known/assetlinks.json`\n * - `/.well-known/webauthn`\n * - `/.well-known/change-password`\n * - `/.well-known/security.txt`\n * - `<prefix>/.well-known/openid-configuration`\n * - `<prefix>/.well-known/jwks.json`\n *\n * The following routes are handled if OAuth is configured:\n *\n * - `/signin/*`\n * - `/callback/*`\n *\n * @param http your HTTP router\n */\n mount: (http: HttpRouter) => {\n const protocolRequireEnv = (name: string) =>\n name === \"CONVEX_SITE_URL\" ? authSiteUrl() : requireEnv(name);\n\n addOpenIdRoutes(http, {\n routeBase: routePrefix,\n getIssuer: authSiteUrl,\n getJwks: () => JSON.stringify(requireAuthKey(\"jwks\")),\n oauth: config.oauth ? { scopes: delegatableGrants } : undefined,\n });\n\n addWellKnownRoutes(http, {\n getResponse: (endpoint) => wellKnown(endpoint),\n });\n\n addGroupHttpRuntime({\n http,\n hasConnection,\n auth: authBase as Parameters<typeof addGroupHttpRuntime>[0][\"auth\"],\n config,\n routeBase: `${routePrefix}${GROUP_CONNECTION_ROUTE_BASE}`,\n requireEnv: protocolRequireEnv,\n loadActiveConnectionSamlOrThrow: group.loadActiveConnectionSamlOrThrow,\n loadConnectionOidcOrThrow: group.loadConnectionOidcOrThrow,\n getGroupConnectionScimContext: group.getGroupConnectionScimContext,\n loadGroupPolicyOrThrow: group.loadGroupPolicyOrThrow,\n normalizeGroupConnectionPolicy,\n emitGroupAuthEvent: group.emitGroupAuthEvent,\n generateRandomString,\n inviteTokenAlphabet: INVITE_TOKEN_ALPHABET,\n callUserOAuth,\n callVerifierSignature,\n sharedOidcRedirectURI: ssoProvider?.redirectURI,\n });\n\n if (config.oauth) {\n addOAuthProviderRoutes(http, {\n routeBase: routePrefix,\n handleAuthorize: createAuthorizeHandler({\n getClient: (ctx, clientId) => authBase.oauth.client.get(ctx, { clientId }),\n consentPage: config.oauth.pages.consent,\n authSiteUrl,\n }),\n handleToken: createTokenHandler({\n issuer: authSiteUrl,\n getClient: (ctx, clientId) => authBase.oauth.client.get(ctx, { clientId }),\n getCode: async (ctx, codeHash) =>\n (await ctx.runQuery(config.component.oauth.code.get, {\n codeHash,\n })) as OAuthCodeRecord | null,\n verifyClientSecret: (ctx, clientId, clientSecret) =>\n authBase.oauth.client.verify(ctx, { clientId, clientSecret }),\n acceptCode: (ctx, codeHash, clientId, redirectUri, codeChallenge, refresh) =>\n authBase.oauth.code.accept(ctx, {\n codeHash,\n clientId,\n redirectUri,\n codeChallenge,\n refresh,\n }),\n mintRefresh: () => authBase.oauth.refresh.mint(),\n exchangeRefresh: (ctx, args) => authBase.oauth.refresh.exchange(ctx, args),\n emitEvent: async (ctx, event) => await emitAuthEvent(ctx, config, event),\n }),\n handleRegister: createRegisterHandler({\n createClient: (ctx, opts) =>\n authBase.oauth.client.create(ctx, { data: { ...opts, extend: { kind: \"dcr\" } } }),\n allowedScopes: delegatableGrants,\n registrationClientUri: (clientId) => `${authSiteUrl()}/oauth2/register/${clientId}`,\n }),\n handleManage: createClientManagementHandler({\n verifyRegistrationToken: (ctx, args) =>\n authBase.oauth.client.verifyRegistrationToken(ctx, args),\n update: (ctx, args) => authBase.oauth.client.update(ctx, args),\n revoke: (ctx, args) => authBase.oauth.client.revoke(ctx, args),\n allowedScopes: delegatableGrants,\n registrationClientUri: (clientId) => `${authSiteUrl()}/oauth2/register/${clientId}`,\n }),\n });\n }\n\n if (hasOAuth) {\n addAuthRoutes(http, {\n routeBase: routePrefix,\n ...oauthHttpHandlers,\n });\n }\n },\n\n /** Return stable route descriptors for apps that need to wrap auth handlers. */\n routes: (): RouteSpec[] => {\n const http = httpRouter();\n request.mount(http);\n return http\n .getRoutes()\n .map(([path, method, handler]) =>\n path.endsWith(\"*\")\n ? { pathPrefix: path.slice(0, -1), method, handler }\n : { path, method, handler },\n );\n },\n\n /**\n * Resolve mixed HTTP auth for a raw `httpAction`.\n *\n * Checks session auth first, then falls back to `Authorization: Bearer sk_*`\n * API keys. This is the low-level helper for endpoints that intentionally\n * accept either browser sessions or API keys.\n * Use `auth.request.context.optional(ctx, request)` to get a null-shaped\n * auth object instead of a `NOT_SIGNED_IN` error.\n *\n * ```ts\n * http.route({\n * path: \"/api/data\",\n * method: \"GET\",\n * handler: httpAction(async (ctx, request) => {\n * const authContext = await auth.request.context(ctx, request);\n * return Response.json({\n * userId: authContext.userId,\n * source: authContext.source,\n * });\n * }),\n * });\n * ```\n */\n context: createHttpContext(\n bridgeRuntimeType<Parameters<typeof createHttpContext>[0]>(authBase),\n { issuer: authSiteUrl },\n ),\n\n /**\n * Wrap an HTTP action handler with Bearer token authentication.\n *\n * Extracts the `Authorization: Bearer <key>` header, verifies the\n * API key via `auth.key.verify()`, and injects `ctx.key` with the\n * verified key info. Returns structured JSON error responses for\n * missing/invalid/revoked/expired/rate-limited keys.\n *\n * If the handler returns a plain object, it is auto-wrapped in a\n * `200 JSON` response. If it returns a `Response`, CORS headers\n * are merged and the response is passed through.\n *\n * ```ts\n * const handler = auth.request.action(async (ctx, request) => {\n * const data = await ctx.runQuery(api.data.get, { userId: ctx.key.userId });\n * return { data };\n * });\n * http.route({ path: \"/api/data\", method: \"GET\", handler });\n * ```\n *\n * @param handler - Receives enriched `ctx` (with `ctx.key`) and the raw `Request`.\n * @param options.scope - Optional scope check; returns 403 if the key lacks permission.\n * @param options.cors - CORS config; defaults to site URLs from environment.\n */\n action: createHttpAction(\n authBase as Parameters<typeof createHttpAction>[0],\n getDefaultCorsOrigins,\n ),\n\n /**\n * Register a Bearer-authenticated route **and** its OPTIONS preflight\n * in a single call.\n *\n * ```ts\n * auth.request.route(http, {\n * path: \"/api/messages\",\n * method: \"POST\",\n * handler: async (ctx, request) => {\n * const { body } = await request.json();\n * await ctx.runMutation(internal.messages.sendAsUser, {\n * userId: ctx.key.userId,\n * body,\n * });\n * return { success: true };\n * },\n * });\n * ```\n *\n * @param http - The Convex HTTP router.\n * @param routeConfig.path - The URL path to match.\n * @param routeConfig.method - HTTP method (GET, POST, PUT, PATCH, DELETE).\n * @param routeConfig.handler - Receives enriched `ctx` (with `ctx.key`) and the raw `Request`.\n * @param routeConfig.scope - Optional scope check; returns 403 if the key lacks permission.\n * @param routeConfig.cors - CORS config; defaults to site URLs from environment.\n */\n route: createHttpRoute(\n createHttpAction(authBase as Parameters<typeof createHttpAction>[0], getDefaultCorsOrigins),\n getDefaultCorsOrigins,\n ),\n\n /**\n * Mount a remote MCP server (an OAuth-protected resource server) on `http`,\n * next to the other HTTP registrars (`mount`, `route`). Requires `oauth` to be\n * configured in `defineAuth` — the MCP server shares the AS `scopes` and\n * bearer-token verification — and throws at registration time otherwise.\n * Tools are plain `{ description, scope, args, handler }` objects; each\n * handler's `args` are inferred from its Convex validator.\n */\n mcp: <T extends Record<string, GenericValidator>>(\n http: HttpRouter,\n tools: { [K in keyof T]: McpToolDef<T[K]> },\n opts?: { name?: string; version?: string; mcpPath?: string },\n ): void => {\n if (config.oauth === undefined) {\n throw new Error(\n \"`auth.request.mcp(...)` requires `oauth` to be configured in `defineAuth` — the MCP server is protected by the OAuth authorization server.\",\n );\n }\n if (delegatableGrants.length === 0) {\n throw new Error(\n \"`auth.request.mcp(...)` requires `permissions` with at least one grant — MCP tools delegate your app's grants, and none are defined.\",\n );\n }\n const mcpPath = opts?.mcpPath ?? \"/mcp\";\n const canonicalResource = () => requireEnv(\"CONVEX_SITE_URL\").replace(/\\/+$/, \"\") + mcpPath;\n addMcpRoutes(http, {\n tools,\n name: opts?.name,\n version: opts?.version,\n scopes: delegatableGrants,\n mcpPath,\n resource: canonicalResource,\n authorizationServers: () => [authSiteUrl()],\n resolveScopes: async (_ctx, request) => {\n const token = extractBearerToken(request);\n if (token === null) return null;\n const verified = await verifyOAuthToken(token, {\n issuer: authSiteUrl(),\n resource: canonicalResource(),\n });\n return verified ? verified.scopes : null;\n },\n });\n },\n };\n\n const auth = Object.assign(authBase, { request });\n\n /**\n * App-owned HTTP router factory. `auth.http()` returns a Convex `httpRouter()`\n * with every auth protocol route mounted via {@link request.mount}, so there is\n * exactly one route table.\n */\n const http = () => {\n const router = httpRouter();\n request.mount(router);\n return router;\n };\n\n const { accountUnlink, passkeyDelete, totpDelete } = createFactorUnlinkHelpers(config);\n\n const enrichedAccount = Object.assign({}, auth.account, { unlink: accountUnlink });\n const passkeyHelpers = { remove: passkeyDelete };\n const totpHelpers = { remove: totpDelete };\n\n const enrichCtx = <DataModel extends GenericDataModel>(ctx: GenericActionCtx<DataModel>) =>\n enrichActionCtx(ctx, {\n ...ctx.auth,\n getUserIdentity: ctx.auth.getUserIdentity.bind(ctx.auth),\n config,\n account: enrichedAccount,\n passkey: passkeyHelpers,\n totp: totpHelpers,\n session: auth.session,\n member: auth.member,\n provider: {\n ...auth.provider,\n continuePasswordReset: async (\n continuationCtx: GenericActionCtx<DataModel>,\n args: Omit<PasswordResetContinuationRequest, \"commit\">,\n ) => await continueWithProvider(continuationCtx, { ...args, commit: \"passwordReset\" }),\n },\n event: auth.event,\n });\n\n return {\n auth,\n /**\n * Action called by the client to sign the user in.\n *\n * Also used for refreshing the session.\n */\n signIn: actionGeneric({\n args: {\n provider: v.optional(v.string()),\n params: v.optional(vPayloadRecord),\n verifier: v.optional(v.string()),\n continuation: v.optional(v.string()),\n refreshToken: v.optional(v.string()),\n calledBy: v.optional(v.string()),\n },\n handler: async (ctx, args): Promise<SignInActionResult> => {\n if (args.calledBy !== undefined) {\n log(\"INFO\", `\\`auth:signIn\\` called by ${args.calledBy}`);\n }\n let provider = null;\n if (args.provider !== undefined && args.continuation !== undefined) {\n const continuation = await queryContinuation(\n bridgeRuntimeType<Parameters<typeof signInImpl>[0]>(enrichCtx(ctx)),\n args.continuation,\n );\n if (continuation === null || continuation.provider !== args.provider) {\n throw new ConvexError({\n code: ErrorCode.CONTINUATION_INVALID,\n message: \"The provider continuation is invalid or expired.\",\n });\n }\n provider = getProviderOrThrow(args.provider, true);\n if (provider.type !== \"webauthn\") {\n throw new ConvexError({\n code: ErrorCode.CONTINUATION_INVALID,\n message: \"The provider continuation does not support this provider.\",\n });\n }\n } else if (args.provider !== undefined) {\n provider = getProviderOrThrow(args.provider);\n }\n const authSiteUrl =\n provider?.type === \"oauth\" || provider?.type === \"connection\"\n ? getAuthSiteUrl(ctx)\n : undefined;\n const result = await signInImpl(\n bridgeRuntimeType<Parameters<typeof signInImpl>[0]>(enrichCtx(ctx)),\n provider,\n args,\n {\n generateTokens: true,\n allowExtraProviders: false,\n authSiteUrl,\n resolveConnectionProtocol: group.resolveGroupConnectionConnectionProtocolOrThrow,\n },\n );\n const resultKind: string = result.kind;\n /** Exhaustive narrowing dispatch: only `signedIn` reshapes its session into tokens; every other variant passes through unchanged. */\n switch (result.kind) {\n case \"signedIn\":\n return {\n kind: \"signedIn\",\n session: result.session?.tokens ?? null,\n };\n case \"redirect\":\n case \"started\":\n case \"webauthnOptions\":\n case \"totpRequired\":\n case \"totpSetup\":\n case \"deviceCode\":\n return result;\n default:\n throw new Error(`Unexpected sign-in result kind: ${resultKind}`);\n }\n },\n }),\n /**\n * Action called by the client to invalidate the current session.\n */\n signOut: actionGeneric({\n args: {},\n handler: async (ctx) => {\n await callSignOut(ctx);\n },\n }),\n\n /**\n * Internal mutation used by the library to read and write\n * to the database during signin and signout.\n */\n store: internalMutationGeneric({\n args: vStoreArgs,\n handler: async (ctx: MutationCtx, args) => {\n return storeImpl(ctx, args, services);\n },\n }),\n\n /** App-owned HTTP router factory; call `auth.http()` from `convex/http.ts`. */\n http,\n };\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAyEA,MAAM,2CAA2C;;;;;;;;;;;AAYjD,SAAS,kBAAqB,OAAkB;AAC9C,QAAO;;;;;;;;;;;;AAaT,SAAgB,gBAId,KACA,MACqD;CACrD,MAAM,EACJ,MAAM,iBACN,WAAW,sBACX,aAAa,wBACb,UAAU,qBACV,GAAG,gBACD,OAAO,0BAA0B,IAAI;CAEzC,MAAM,WAAW,OAAO,OACtB,OAAO,eAAe,IAAI,EAC1B,YACD;AAED,QAAO,iBAAiB,UAAU;EAChC,MAAM;GACJ,cAAc;GACd,YAAY;GACZ,OAAO;GACP,UAAU;GACX;EACD,WAAW;GACT,cAAc;GACd,OAAO,IAAI,UAAU,KAAK,IAAI;GAC9B,UAAU;GACX;EACD,aAAa;GACX,cAAc;GACd,OAAO,IAAI,YAAY,KAAK,IAAI;GAChC,UAAU;GACX;EACD,UAAU;GACR,cAAc;GACd,OAAO,IAAI,SAAS,KAAK,IAAI;GAC7B,UAAU;GACX;EACF,CAAC;AAEF,QAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAmDT,SAAgB,KAAK,SAAgC;CACnD,MAAM,WAAW,sBAAsB,QAAQ;CAC/C,MAAM,SAAS,SAAS;CACxB,MAAM,oBAA8B,CAAC,GAAI,OAAO,aAAa,UAAU,EAAE,CAAE;CAC3E,MAAM,WAAW,OAAO,UAAU,MAAM,aAAa,SAAS,SAAS,QAAQ;CAC/E,MAAM,gBAAgB,OAAO,UAAU,MAAM,aAAa,SAAS,SAAS,aAAa;CACzF,MAAM,cAAc,OAAO,UAAU,MAClC,aAAmD,SAAS,SAAS,aACvE;CACD,MAAM,qBAA6C,SAAS,iBAAiB;CAC7E,MAAM,sBAAsB;CAE5B,MAAM,8BAA8B;CACpC,MAAM,cAAc,OAAO,QAAQ;CACnC,MAAM,oBAAoB,eAAe,YAAY;CACrD,MAAM,mBAAmB,eAAuB,GAAG,aAAa,CAAC,YAAY;CAC7E,MAAM,QAAQ,mBAAmB;EAAE;EAAQ;EAAQ,CAAC;CACpD,MAAM,kBAAkB,SACtB,SAAS,oBAAoB,aAAa,GAAG,WAAW,KAAK;CAa/D,MAAM,uBAAuB,OAC3B,KACA,wBACG;EACH,MAAM,EAAE,QAAQ,cAAc;EAC9B,MAAM,WAAW,kBAAoD,UAAU,IAAI,CAAC;EACpF,MAAM,mBAAmB;GACvB;GACA,UAAU,UAAU,SAAS;GAC7B,WAAW,UAAU;GACrB,gBAAgB,KAAK,KAAK,IAAI,UAAU,SAAS,QAAQ,yBAAyB;GACnF;EACD,MAAM,eACJ,YAAY,uBAAuB,oBAAoB,WAAW,kBAC9D,MAAM,sCAAsC,UAAU;GACpD,GAAG;GACH,WAAW,oBAAoB;GAC/B,QAAQ,oBAAoB;GAC7B,CAAC,GACF,MAAM,yBAAyB,UAAU,iBAAiB;EAChE,MAAM,SAAS,MAAM,WACnB,UACA,UAAU,UACV;GACE,QAAQ,EAAE,MAAM,YAAY;GAC5B;GACD,EACD;GACE,gBAAgB;GAChB,qBAAqB;GACtB,CACF;AACD,MAAI,OAAO,SAAS,WAClB,OAAM,IAAI,MAAM,6DAA6D;AAE/E,SAAO;;CAGT,MAAM,WAA4B;EAChC,GAAG,kBAAkB;GACnB;GACA;GACA;GACA;GACA;GACA,oBAAoB;GACpB,qBAAqB;GACrB,mBAAmB;GACnB,mBAAmB,OAAO,KAAK,gBAAgB,SAAS;IACtD,MAAM,eACJ,OAAO,mBAAmB,aAAa,gBAAgB,GAAG;IAC5D,MAAM,SAAS,MAAM,WACnB,kBAAoD,UAAU,IAAI,CAAC,EACnE,cACA,MACA;KACE,gBAAgB;KAChB,qBAAqB;KACtB,CACF;AACD,QAAI,OAAO,SAAS,YAAY;KAC9B,MAAM,UAAU,OAAO;AAKvB,SAAI,YAAY,QAAQ,YAAY,OAClC,QAAO;KAET,MAAM,SAAS,QAAQ;KACvB,MAAM,YAAY,QAAQ,aAAa,QAAQ;AAC/C,SAAI,WAAW,UAAa,cAAc,OACxC,QAAO;AAET,YAAO;MAAE;MAAQ;MAAW;;AAE9B,WAAO;;GAET;GACD,CAAC;EACF,OAAO,sBAAsB,OAAO;EAKpC,YAAY,4BAA4B;GACtC;GACA,0BAA0B,MAAM;GAChC,uBAAuB,MAAM;GAC7B,+BAA+B,MAAM;GACrC,oBAAoB,MAAM;GAC1B,yBAAyB;GACzB;GACA,YAAY;GACZ;GACA;GACA;GACA;GACA,wBAAwB,MAAM;GAC/B,CAAC;EACH;CAED,MAAM,8BAA8B,CAAC,IAAI,IAAI,eAAe,CAAC,CAAC,OAAO;CAErE,MAAM,kBAAkB,SAA6C,aAAa;CAElF,MAAM,oBAAoB,wBAAwB;EAChD;EACA;EACA;EACD,CAAC;CAEF,MAAM,UAAU;EA4Bd,QAAQ,WAAqB;GAC3B,MAAM,sBAAsB,SAC1B,SAAS,oBAAoB,aAAa,GAAG,WAAW,KAAK;AAE/D,mBAAgBA,QAAM;IACpB,WAAW;IACX,WAAW;IACX,eAAe,KAAK,UAAU,eAAe,OAAO,CAAC;IACrD,OAAO,OAAO,QAAQ,EAAE,QAAQ,mBAAmB,GAAG;IACvD,CAAC;AAEF,sBAAmBA,QAAM,EACvB,cAAc,aAAa,UAAU,SAAS,EAC/C,CAAC;AAEF,uBAAoB;IAClB;IACA;IACA,MAAM;IACN;IACA,WAAW,GAAG,cAAc;IAC5B,YAAY;IACZ,iCAAiC,MAAM;IACvC,2BAA2B,MAAM;IACjC,+BAA+B,MAAM;IACrC,wBAAwB,MAAM;IAC9B;IACA,oBAAoB,MAAM;IAC1B;IACA,qBAAqB;IACrB;IACA;IACA,uBAAuB,aAAa;IACrC,CAAC;AAEF,OAAI,OAAO,MACT,wBAAuBA,QAAM;IAC3B,WAAW;IACX,iBAAiB,uBAAuB;KACtC,YAAY,KAAK,aAAa,SAAS,MAAM,OAAO,IAAI,KAAK,EAAE,UAAU,CAAC;KAC1E,aAAa,OAAO,MAAM,MAAM;KAChC;KACD,CAAC;IACF,aAAa,mBAAmB;KAC9B,QAAQ;KACR,YAAY,KAAK,aAAa,SAAS,MAAM,OAAO,IAAI,KAAK,EAAE,UAAU,CAAC;KAC1E,SAAS,OAAO,KAAK,aAClB,MAAM,IAAI,SAAS,OAAO,UAAU,MAAM,KAAK,KAAK,EACnD,UACD,CAAC;KACJ,qBAAqB,KAAK,UAAU,iBAClC,SAAS,MAAM,OAAO,OAAO,KAAK;MAAE;MAAU;MAAc,CAAC;KAC/D,aAAa,KAAK,UAAU,UAAU,aAAa,eAAe,YAChE,SAAS,MAAM,KAAK,OAAO,KAAK;MAC9B;MACA;MACA;MACA;MACA;MACD,CAAC;KACJ,mBAAmB,SAAS,MAAM,QAAQ,MAAM;KAChD,kBAAkB,KAAK,SAAS,SAAS,MAAM,QAAQ,SAAS,KAAK,KAAK;KAC1E,WAAW,OAAO,KAAK,UAAU,MAAM,cAAc,KAAK,QAAQ,MAAM;KACzE,CAAC;IACF,gBAAgB,sBAAsB;KACpC,eAAe,KAAK,SAClB,SAAS,MAAM,OAAO,OAAO,KAAK,EAAE,MAAM;MAAE,GAAG;MAAM,QAAQ,EAAE,MAAM,OAAO;MAAE,EAAE,CAAC;KACnF,eAAe;KACf,wBAAwB,aAAa,GAAG,aAAa,CAAC,mBAAmB;KAC1E,CAAC;IACF,cAAc,8BAA8B;KAC1C,0BAA0B,KAAK,SAC7B,SAAS,MAAM,OAAO,wBAAwB,KAAK,KAAK;KAC1D,SAAS,KAAK,SAAS,SAAS,MAAM,OAAO,OAAO,KAAK,KAAK;KAC9D,SAAS,KAAK,SAAS,SAAS,MAAM,OAAO,OAAO,KAAK,KAAK;KAC9D,eAAe;KACf,wBAAwB,aAAa,GAAG,aAAa,CAAC,mBAAmB;KAC1E,CAAC;IACH,CAAC;AAGJ,OAAI,SACF,eAAcA,QAAM;IAClB,WAAW;IACX,GAAG;IACJ,CAAC;;EAKN,cAA2B;GACzB,MAAMA,SAAO,YAAY;AACzB,WAAQ,MAAMA,OAAK;AACnB,UAAOA,OACJ,WAAW,CACX,KAAK,CAAC,MAAM,QAAQ,aACnB,KAAK,SAAS,IAAI,GACd;IAAE,YAAY,KAAK,MAAM,GAAG,GAAG;IAAE;IAAQ;IAAS,GAClD;IAAE;IAAM;IAAQ;IAAS,CAC9B;;EA0BL,SAAS,kBACP,kBAA2D,SAAS,EACpE,EAAE,QAAQ,aAAa,CACxB;EA0BD,QAAQ,iBACN,UACA,sBACD;EA4BD,OAAO,gBACL,iBAAiB,UAAoD,sBAAsB,EAC3F,sBACD;EAUD,MACE,QACA,OACA,SACS;AACT,OAAI,OAAO,UAAU,OACnB,OAAM,IAAI,MACR,6IACD;AAEH,OAAI,kBAAkB,WAAW,EAC/B,OAAM,IAAI,MACR,uIACD;GAEH,MAAM,UAAU,MAAM,WAAW;GACjC,MAAM,0BAA0B,WAAW,kBAAkB,CAAC,QAAQ,QAAQ,GAAG,GAAG;AACpF,gBAAaA,QAAM;IACjB;IACA,MAAM,MAAM;IACZ,SAAS,MAAM;IACf,QAAQ;IACR;IACA,UAAU;IACV,4BAA4B,CAAC,aAAa,CAAC;IAC3C,eAAe,OAAO,MAAM,cAAY;KACtC,MAAM,QAAQ,mBAAmBC,UAAQ;AACzC,SAAI,UAAU,KAAM,QAAO;KAC3B,MAAM,WAAW,MAAM,iBAAiB,OAAO;MAC7C,QAAQ,aAAa;MACrB,UAAU,mBAAmB;MAC9B,CAAC;AACF,YAAO,WAAW,SAAS,SAAS;;IAEvC,CAAC;;EAEL;CAED,MAAM,OAAO,OAAO,OAAO,UAAU,EAAE,SAAS,CAAC;;;;;;CAOjD,MAAM,aAAa;EACjB,MAAM,SAAS,YAAY;AAC3B,UAAQ,MAAM,OAAO;AACrB,SAAO;;CAGT,MAAM,EAAE,eAAe,eAAe,eAAe,0BAA0B,OAAO;CAEtF,MAAM,kBAAkB,OAAO,OAAO,EAAE,EAAE,KAAK,SAAS,EAAE,QAAQ,eAAe,CAAC;CAClF,MAAM,iBAAiB,EAAE,QAAQ,eAAe;CAChD,MAAM,cAAc,EAAE,QAAQ,YAAY;CAE1C,MAAM,aAAiD,QACrD,gBAAgB,KAAK;EACnB,GAAG,IAAI;EACP,iBAAiB,IAAI,KAAK,gBAAgB,KAAK,IAAI,KAAK;EACxD;EACA,SAAS;EACT,SAAS;EACT,MAAM;EACN,SAAS,KAAK;EACd,QAAQ,KAAK;EACb,UAAU;GACR,GAAG,KAAK;GACR,uBAAuB,OACrB,iBACA,SACG,MAAM,qBAAqB,iBAAiB;IAAE,GAAG;IAAM,QAAQ;IAAiB,CAAC;GACvF;EACD,OAAO,KAAK;EACb,CAAC;AAEJ,QAAO;EACL;EAMA,QAAQ,cAAc;GACpB,MAAM;IACJ,UAAU,EAAE,SAAS,EAAE,QAAQ,CAAC;IAChC,QAAQ,EAAE,SAAS,eAAe;IAClC,UAAU,EAAE,SAAS,EAAE,QAAQ,CAAC;IAChC,cAAc,EAAE,SAAS,EAAE,QAAQ,CAAC;IACpC,cAAc,EAAE,SAAS,EAAE,QAAQ,CAAC;IACpC,UAAU,EAAE,SAAS,EAAE,QAAQ,CAAC;IACjC;GACD,SAAS,OAAO,KAAK,SAAsC;AACzD,QAAI,KAAK,aAAa,OACpB,KAAI,QAAQ,6BAA6B,KAAK,WAAW;IAE3D,IAAI,WAAW;AACf,QAAI,KAAK,aAAa,UAAa,KAAK,iBAAiB,QAAW;KAClE,MAAM,eAAe,MAAM,kBACzB,kBAAoD,UAAU,IAAI,CAAC,EACnE,KAAK,aACN;AACD,SAAI,iBAAiB,QAAQ,aAAa,aAAa,KAAK,SAC1D,OAAM,IAAI,YAAY;MACpB,MAAM,UAAU;MAChB,SAAS;MACV,CAAC;AAEJ,gBAAW,mBAAmB,KAAK,UAAU,KAAK;AAClD,SAAI,SAAS,SAAS,WACpB,OAAM,IAAI,YAAY;MACpB,MAAM,UAAU;MAChB,SAAS;MACV,CAAC;eAEK,KAAK,aAAa,OAC3B,YAAW,mBAAmB,KAAK,SAAS;IAE9C,MAAMC,gBACJ,UAAU,SAAS,WAAW,UAAU,SAAS,eAC7C,eAAe,IAAI,GACnB;IACN,MAAM,SAAS,MAAM,WACnB,kBAAoD,UAAU,IAAI,CAAC,EACnE,UACA,MACA;KACE,gBAAgB;KAChB,qBAAqB;KACrB;KACA,2BAA2B,MAAM;KAClC,CACF;IACD,MAAM,aAAqB,OAAO;;AAElC,YAAQ,OAAO,MAAf;KACE,KAAK,WACH,QAAO;MACL,MAAM;MACN,SAAS,OAAO,SAAS,UAAU;MACpC;KACH,KAAK;KACL,KAAK;KACL,KAAK;KACL,KAAK;KACL,KAAK;KACL,KAAK,aACH,QAAO;KACT,QACE,OAAM,IAAI,MAAM,mCAAmC,aAAa;;;GAGvE,CAAC;EAIF,SAAS,cAAc;GACrB,MAAM,EAAE;GACR,SAAS,OAAO,QAAQ;AACtB,UAAM,YAAY,IAAI;;GAEzB,CAAC;EAMF,OAAO,wBAAwB;GAC7B,MAAM;GACN,SAAS,OAAO,KAAkB,SAAS;AACzC,WAAO,UAAU,KAAK,MAAM,SAAS;;GAExC,CAAC;EAGF;EACD"}
|
|
1
|
+
{"version":3,"file":"runtime.js","names":["http","request","authSiteUrl"],"sources":["../../src/server/runtime.ts"],"sourcesContent":["import {\n GenericActionCtx,\n GenericDataModel,\n HttpRouter,\n actionGeneric,\n httpRouter,\n internalMutationGeneric,\n} from \"convex/server\";\nimport type { RouteSpec } from \"convex/server\";\nimport { ConvexError, v } from \"convex/values\";\nimport { validate } from \"convex-helpers/validators\";\nimport type { GenericValidator } from \"convex/values\";\n\nimport type { AuthTokens, SignInFlowResult } from \"../shared/results\";\nimport { ErrorCode } from \"../shared/codes\";\nimport { createCoreDomains } from \"./core\";\nimport { GetProviderOrThrowFunc } from \"./crypto\";\nimport { requireAuthKey, requireEnv } from \"./env\";\nimport { createAuthEventDomain, emitAuthEvent } from \"./events\";\nimport {\n addAuthRoutes,\n addOAuthProviderRoutes,\n addOpenIdRoutes,\n addWellKnownRoutes,\n createHttpAction,\n createHttpContext,\n createHttpRoute,\n} from \"./http\";\nimport { addMcpRoutes, type McpToolDef } from \"./mcp\";\nimport { createAuthorizeHandler } from \"./oauth/authorize\";\nimport { createOAuthHttpHandlers } from \"./oauth/handlers\";\nimport { createClientManagementHandler } from \"./oauth/manage\";\nimport { createRegisterHandler } from \"./oauth/register\";\nimport type { OAuthCodeRecord } from \"./oauth/code\";\nimport { createTokenHandler } from \"./oauth/token\";\nimport { verifyOAuthToken } from \"./tokens\";\nimport { wellKnown } from \"./wellknown\";\nimport { log } from \"./log\";\nimport {\n callCreateAccountFromCredentials,\n callInvalidateSessions,\n callModifyAccount,\n callRetrieveAccountWithCredentials,\n callSignOut,\n callUserOAuth,\n callVerifierSignature,\n vStoreArgs,\n storeImpl,\n} from \"./mutations/calls\";\nimport { vPayloadRecord } from \"./payloads\";\nimport { generateRandomString, INVITE_TOKEN_ALPHABET, sha256 } from \"./random\";\nimport { extractBearerToken } from \"./utils/bearer\";\nimport { encryptSecret } from \"./secret\";\nimport { createGroupService } from \"./connection/group/service\";\nimport { createFactorUnlinkHelpers } from \"./services/factors\";\nimport { mutateContinuationCreate, queryContinuation } from \"./component/factor/db\";\nimport { resolveServerServices } from \"./services/resolve\";\nimport { signInImpl } from \"./signin/flow\";\nimport { createGroupConnectionDomain } from \"./connection/domain\";\nimport { addGroupHttpRuntime } from \"./connection/http\";\nimport { normalizeGroupConnectionPolicy } from \"./connection/policy\";\nimport type {\n AuthProviderContinueArgs,\n ConvexAuthConfig,\n FunctionReferenceFromExport,\n ConnectionProviderConfig,\n} from \"./types\";\nimport { MutationCtx } from \"./types\";\nimport { appUrlFromEnv, authUrlFromEnv } from \"./url\";\n\nconst GROUP_CONNECTION_OIDC_CLIENT_SECRET_KIND = \"oidc_client_secret\" as const;\n\n/**\n * Single sanctioned bridge across an irreducible cross-package ctx/domain\n * family boundary. Several runtime values are structurally equivalent at\n * runtime to a consumer's nominal type but cannot be positively unified by\n * TypeScript — e.g. the {@link enrichCtx}-enriched action ctx versus the\n * sign-in service's `GenericActionCtxWithAuthConfig`, or the assembled\n * `authBase` versus the HTTP context's `HttpContextAuthLike`. This is the one\n * narrow, typed assertion those boundaries route through; callers name the\n * exact target via the `T` type argument so the result stays precisely typed.\n */\nfunction bridgeRuntimeType<T>(value: object): T {\n return value as T;\n}\n\n/**\n * Preserve Convex action context behavior while replacing `ctx.auth`.\n *\n * Convex context methods can be non-enumerable or prototype-backed. A plain\n * `{ ...ctx, auth }` drops those methods in packaged builds, so calls such as\n * `ctx.runQuery(...)` disappear inside provider flows. Forward the call methods\n * bound to the original ctx and preserve the rest of the context descriptors.\n *\n * @internal\n */\nexport function enrichActionCtx<\n DataModel extends GenericDataModel,\n AuthContext extends GenericActionCtx<DataModel>[\"auth\"] & Record<string, unknown>,\n>(\n ctx: GenericActionCtx<DataModel>,\n auth: AuthContext,\n): GenericActionCtx<DataModel> & { auth: AuthContext } {\n const {\n auth: _authDescriptor,\n runAction: _runActionDescriptor,\n runMutation: _runMutationDescriptor,\n runQuery: _runQueryDescriptor,\n ...descriptors\n } = Object.getOwnPropertyDescriptors(ctx);\n\n const enriched = Object.create(\n Object.getPrototypeOf(ctx),\n descriptors,\n ) as GenericActionCtx<DataModel>;\n\n Object.defineProperties(enriched, {\n auth: {\n configurable: true,\n enumerable: true,\n value: auth,\n writable: true,\n },\n runAction: {\n configurable: true,\n value: ctx.runAction.bind(ctx),\n writable: true,\n },\n runMutation: {\n configurable: true,\n value: ctx.runMutation.bind(ctx),\n writable: true,\n },\n runQuery: {\n configurable: true,\n value: ctx.runQuery.bind(ctx),\n writable: true,\n },\n });\n\n return enriched as GenericActionCtx<DataModel> & { auth: AuthContext };\n}\n\n/**\n * The type of the signIn Convex Action returned from the auth() helper.\n *\n * This type is exported for implementors of other client integrations.\n * However it is not stable, and may change until this library reaches 1.0.\n *\n * @internal\n */\nexport type SignInAction = FunctionReferenceFromExport<ReturnType<typeof Auth>[\"signIn\"]>;\n\n/** @internal */\nexport type SignInActionResult = SignInFlowResult<AuthTokens | null>;\n/**\n * The type of the signOut Convex Action returned from the auth() helper.\n *\n * This type is exported for implementors of other client integrations.\n * However it is not stable, and may change until this library reaches 1.0.\n *\n * @internal\n */\nexport type SignOutAction = FunctionReferenceFromExport<ReturnType<typeof Auth>[\"signOut\"]>;\n\n/**\n * The transport envelope for the public sign-in action.\n *\n * Convex requires every exported function's argument validator to be an\n * object (or `v.any()`), so a provider-discriminated top-level union cannot be\n * exported. The configured provider union remains the public TypeScript\n * contract through {@link AuthSignInAction}; the handler below validates the\n * selected provider's params before starting a sign-in flow.\n */\n/** @internal */\nexport const vSignInActionArgs = v.object({\n provider: v.optional(v.string()),\n params: v.optional(v.any()),\n verifier: v.optional(v.string()),\n continuation: v.optional(v.string()),\n refreshToken: v.optional(v.string()),\n calledBy: v.optional(v.string()),\n});\n\n/**\n * Configure the Convex Auth library. Returns an object with\n * functions and `auth` helper. You must export the functions\n * from `convex/auth.ts` to make them callable:\n *\n * ```ts filename=\"convex/auth.ts\"\n * import { defineAuth } from \"@estifanos-sh/convex-auth/component\";\n * import { components } from \"./_generated/api\";\n *\n * export const auth = defineAuth(components.auth, {\n * providers: [],\n * });\n * export const { signIn, signOut, store } = auth;\n * ```\n *\n * Mount the auth HTTP routes from `convex/http.ts`:\n *\n * ```ts filename=\"convex/http.ts\"\n * import { auth } from \"./auth\";\n *\n * export default auth.http();\n * ```\n *\n * @returns An object with fields you should reexport from your\n * `convex/auth.ts` file, plus the `http` router factory.\n */\nexport function Auth(config_: ConvexAuthConfig<any>) {\n const services = resolveServerServices(config_);\n const config = services.config;\n const delegatableGrants: string[] = [...(config.permissions?.grants ?? [])];\n const hasOAuth = config.providers.some((provider) => provider.type === \"oauth\");\n const hasConnection = config.providers.some((provider) => provider.type === \"connection\");\n const ssoProvider = config.providers.find(\n (provider): provider is ConnectionProviderConfig => provider.type === \"connection\",\n );\n const getProviderOrThrow: GetProviderOrThrowFunc = services.providerRegistry.getProviderOrThrow;\n const INVITE_TOKEN_LENGTH = 48;\n\n const GROUP_CONNECTION_ROUTE_BASE = \"/connections\";\n const routePrefix = config.path ?? \"/auth\";\n const authSiteUrl = () => authUrlFromEnv(routePrefix);\n const authCallbackUrl = (providerId: string) => `${authSiteUrl()}/callback/${providerId}`;\n const group = createGroupService({ config, sha256 });\n const authRequireEnv = (name: string) =>\n name === \"CONVEX_SITE_URL\" ? authSiteUrl() : requireEnv(name);\n\n type AuthRuntimeBase = ReturnType<typeof createCoreDomains> & {\n event: ReturnType<typeof createAuthEventDomain>;\n connection: ReturnType<typeof createGroupConnectionDomain>;\n };\n\n type RecoveryContinuationRequest = AuthProviderContinueArgs & { continuationId: string };\n\n const beginProviderContinuation = async <DataModel extends GenericDataModel>(\n ctx: GenericActionCtx<DataModel>,\n operation: AuthProviderContinueArgs[\"operation\"],\n continuation: string,\n ) => {\n const enriched = bridgeRuntimeType<Parameters<typeof signInImpl>[0]>(enrichCtx(ctx));\n const result = await signInImpl(\n enriched,\n operation.provider,\n {\n params: { flow: \"register\" },\n continuation,\n },\n {\n generateTokens: true,\n allowExtraProviders: true,\n },\n );\n if (result.kind === \"signedIn\") {\n throw new Error(\"A provider continuation cannot issue an immediate session.\");\n }\n return result;\n };\n\n const continueWithProvider = async <DataModel extends GenericDataModel>(\n ctx: GenericActionCtx<DataModel>,\n args: AuthProviderContinueArgs,\n ) => {\n const continuation = await mutateContinuationCreate(\n bridgeRuntimeType<Parameters<typeof signInImpl>[0]>(enrichCtx(ctx)),\n {\n userId: args.userId,\n provider: args.operation.provider.id,\n operation: args.operation.operation,\n expirationTime:\n Date.now() + (args.operation.provider.options.challengeExpirationMs ?? 300_000),\n },\n );\n return await beginProviderContinuation(ctx, args.operation, continuation);\n };\n\n const continueRecovery = async <DataModel extends GenericDataModel>(\n ctx: GenericActionCtx<DataModel>,\n args: RecoveryContinuationRequest,\n ) => await beginProviderContinuation(ctx, args.operation, args.continuationId);\n\n const authBase: AuthRuntimeBase = {\n ...createCoreDomains({\n config,\n callInvalidateSessions,\n callCreateAccountFromCredentials,\n callRetrieveAccountWithCredentials,\n callModifyAccount,\n getEnrichCtx: () => enrichCtx,\n inviteTokenAlphabet: INVITE_TOKEN_ALPHABET,\n inviteTokenLength: INVITE_TOKEN_LENGTH,\n signInForProvider: async (ctx, providerConfig, args) => {\n const materialized =\n typeof providerConfig === \"function\" ? providerConfig() : providerConfig;\n const result = await signInImpl(\n bridgeRuntimeType<Parameters<typeof signInImpl>[0]>(enrichCtx(ctx)),\n materialized as Parameters<typeof signInImpl>[1],\n args,\n {\n generateTokens: false,\n allowExtraProviders: true,\n },\n );\n if (result.kind === \"signedIn\") {\n const session = result.session as {\n userId?: string;\n sessionId?: string;\n _id?: string;\n } | null;\n if (session === null || session === undefined) {\n return null;\n }\n const userId = session.userId;\n const sessionId = session.sessionId ?? session._id;\n if (userId === undefined || sessionId === undefined) {\n return null;\n }\n return { userId, sessionId };\n }\n return result as Exclude<typeof result, { kind: \"signedIn\" }>;\n },\n continueWithProvider,\n }),\n event: createAuthEventDomain(config),\n /**\n * Connection namespace — group connection management, domain, OIDC,\n * SAML, SCIM, audit, and webhook helpers.\n */\n connection: createGroupConnectionDomain({\n config,\n getGroupConnectionSecret: group.getGroupConnectionSecret,\n loadConnectionOrThrow: group.loadConnectionOrThrow,\n validateGroupConnectionPolicy: group.validateGroupConnectionPolicy,\n emitGroupAuthEvent: group.emitGroupAuthEvent,\n connectionNotFoundError: \"Connection not found.\",\n GROUP_CONNECTION_OIDC_CLIENT_SECRET_KIND,\n requireEnv: authRequireEnv,\n generateRandomString,\n INVITE_TOKEN_ALPHABET,\n sha256,\n encryptSecret,\n loadGroupPolicyOrThrow: group.loadGroupPolicyOrThrow,\n }),\n };\n\n const getDefaultCorsOrigins = () => [new URL(appUrlFromEnv()).origin];\n\n const getAuthSiteUrl = (_ctx: GenericActionCtx<GenericDataModel>) => authSiteUrl();\n\n const oauthHttpHandlers = createOAuthHttpHandlers({\n config,\n getProviderOrThrow,\n authCallbackUrl,\n });\n\n const request = {\n /**\n * Register core HTTP routes for JWT verification and OAuth sign-in.\n *\n * ```ts\n * import { httpRouter } from \"convex/server\";\n * import { auth } from \"./auth\";\n *\n * export default auth.http();\n * ```\n *\n * The following routes are handled always:\n *\n * - `/.well-known/apple-app-site-association`\n * - `/.well-known/assetlinks.json`\n * - `/.well-known/webauthn`\n * - `/.well-known/change-password`\n * - `/.well-known/security.txt`\n * - `<prefix>/.well-known/openid-configuration`\n * - `<prefix>/.well-known/jwks.json`\n *\n * The following routes are handled if OAuth is configured:\n *\n * - `/signin/*`\n * - `/callback/*`\n *\n * @param http your HTTP router\n */\n mount: (http: HttpRouter) => {\n const protocolRequireEnv = (name: string) =>\n name === \"CONVEX_SITE_URL\" ? authSiteUrl() : requireEnv(name);\n\n addOpenIdRoutes(http, {\n routeBase: routePrefix,\n getIssuer: authSiteUrl,\n getJwks: () => JSON.stringify(requireAuthKey(\"jwks\")),\n oauth: config.oauth ? { scopes: delegatableGrants } : undefined,\n });\n\n addWellKnownRoutes(http, {\n getResponse: (endpoint) => wellKnown(endpoint),\n });\n\n addGroupHttpRuntime({\n http,\n hasConnection,\n auth: authBase as Parameters<typeof addGroupHttpRuntime>[0][\"auth\"],\n config,\n routeBase: `${routePrefix}${GROUP_CONNECTION_ROUTE_BASE}`,\n requireEnv: protocolRequireEnv,\n loadActiveConnectionSamlOrThrow: group.loadActiveConnectionSamlOrThrow,\n loadConnectionOidcOrThrow: group.loadConnectionOidcOrThrow,\n getGroupConnectionScimContext: group.getGroupConnectionScimContext,\n loadGroupPolicyOrThrow: group.loadGroupPolicyOrThrow,\n normalizeGroupConnectionPolicy,\n emitGroupAuthEvent: group.emitGroupAuthEvent,\n generateRandomString,\n inviteTokenAlphabet: INVITE_TOKEN_ALPHABET,\n callUserOAuth,\n callVerifierSignature,\n sharedOidcRedirectURI: ssoProvider?.redirectURI,\n });\n\n if (config.oauth) {\n addOAuthProviderRoutes(http, {\n routeBase: routePrefix,\n handleAuthorize: createAuthorizeHandler({\n getClient: (ctx, clientId) => authBase.oauth.client.get(ctx, { clientId }),\n consentPage: config.oauth.pages.consent,\n authSiteUrl,\n }),\n handleToken: createTokenHandler({\n issuer: authSiteUrl,\n getClient: (ctx, clientId) => authBase.oauth.client.get(ctx, { clientId }),\n getCode: async (ctx, codeHash) =>\n (await ctx.runQuery(config.component.oauth.code.get, {\n codeHash,\n })) as OAuthCodeRecord | null,\n verifyClientSecret: (ctx, clientId, clientSecret) =>\n authBase.oauth.client.verify(ctx, { clientId, clientSecret }),\n acceptCode: (ctx, codeHash, clientId, redirectUri, codeChallenge, refresh) =>\n authBase.oauth.code.accept(ctx, {\n codeHash,\n clientId,\n redirectUri,\n codeChallenge,\n refresh,\n }),\n mintRefresh: () => authBase.oauth.refresh.mint(),\n exchangeRefresh: (ctx, args) => authBase.oauth.refresh.exchange(ctx, args),\n emitEvent: async (ctx, event) => await emitAuthEvent(ctx, config, event),\n }),\n handleRegister: createRegisterHandler({\n createClient: (ctx, opts) =>\n authBase.oauth.client.create(ctx, { data: { ...opts, extend: { kind: \"dcr\" } } }),\n allowedScopes: delegatableGrants,\n registrationClientUri: (clientId) => `${authSiteUrl()}/oauth2/register/${clientId}`,\n }),\n handleManage: createClientManagementHandler({\n verifyRegistrationToken: (ctx, args) =>\n authBase.oauth.client.verifyRegistrationToken(ctx, args),\n update: (ctx, args) => authBase.oauth.client.update(ctx, args),\n revoke: (ctx, args) => authBase.oauth.client.revoke(ctx, args),\n allowedScopes: delegatableGrants,\n registrationClientUri: (clientId) => `${authSiteUrl()}/oauth2/register/${clientId}`,\n }),\n });\n }\n\n if (hasOAuth) {\n addAuthRoutes(http, {\n routeBase: routePrefix,\n ...oauthHttpHandlers,\n });\n }\n },\n\n /** Return stable route descriptors for apps that need to wrap auth handlers. */\n routes: (): RouteSpec[] => {\n const http = httpRouter();\n request.mount(http);\n return http\n .getRoutes()\n .map(([path, method, handler]) =>\n path.endsWith(\"*\")\n ? { pathPrefix: path.slice(0, -1), method, handler }\n : { path, method, handler },\n );\n },\n\n /**\n * Resolve mixed HTTP auth for a raw `httpAction`.\n *\n * Checks session auth first, then falls back to `Authorization: Bearer sk_*`\n * API keys. This is the low-level helper for endpoints that intentionally\n * accept either browser sessions or API keys.\n * Use `auth.request.context.optional(ctx, request)` to get a null-shaped\n * auth object instead of a `NOT_SIGNED_IN` error.\n *\n * ```ts\n * http.route({\n * path: \"/api/data\",\n * method: \"GET\",\n * handler: httpAction(async (ctx, request) => {\n * const authContext = await auth.request.context(ctx, request);\n * return Response.json({\n * userId: authContext.userId,\n * source: authContext.source,\n * });\n * }),\n * });\n * ```\n */\n context: createHttpContext(\n bridgeRuntimeType<Parameters<typeof createHttpContext>[0]>(authBase),\n { issuer: authSiteUrl },\n ),\n\n /**\n * Wrap an HTTP action handler with Bearer token authentication.\n *\n * Extracts the `Authorization: Bearer <key>` header, verifies the\n * API key via `auth.key.verify()`, and injects `ctx.key` with the\n * verified key info. Returns structured JSON error responses for\n * missing/invalid/revoked/expired/rate-limited keys.\n *\n * If the handler returns a plain object, it is auto-wrapped in a\n * `200 JSON` response. If it returns a `Response`, CORS headers\n * are merged and the response is passed through.\n *\n * ```ts\n * const handler = auth.request.action(async (ctx, request) => {\n * const data = await ctx.runQuery(api.data.get, { userId: ctx.key.userId });\n * return { data };\n * });\n * http.route({ path: \"/api/data\", method: \"GET\", handler });\n * ```\n *\n * @param handler - Receives enriched `ctx` (with `ctx.key`) and the raw `Request`.\n * @param options.scope - Optional scope check; returns 403 if the key lacks permission.\n * @param options.cors - CORS config; defaults to site URLs from environment.\n */\n action: createHttpAction(\n authBase as Parameters<typeof createHttpAction>[0],\n getDefaultCorsOrigins,\n ),\n\n /**\n * Register a Bearer-authenticated route **and** its OPTIONS preflight\n * in a single call.\n *\n * ```ts\n * auth.request.route(http, {\n * path: \"/api/messages\",\n * method: \"POST\",\n * handler: async (ctx, request) => {\n * const { body } = await request.json();\n * await ctx.runMutation(internal.messages.sendAsUser, {\n * userId: ctx.key.userId,\n * body,\n * });\n * return { success: true };\n * },\n * });\n * ```\n *\n * @param http - The Convex HTTP router.\n * @param routeConfig.path - The URL path to match.\n * @param routeConfig.method - HTTP method (GET, POST, PUT, PATCH, DELETE).\n * @param routeConfig.handler - Receives enriched `ctx` (with `ctx.key`) and the raw `Request`.\n * @param routeConfig.scope - Optional scope check; returns 403 if the key lacks permission.\n * @param routeConfig.cors - CORS config; defaults to site URLs from environment.\n */\n route: createHttpRoute(\n createHttpAction(authBase as Parameters<typeof createHttpAction>[0], getDefaultCorsOrigins),\n getDefaultCorsOrigins,\n ),\n\n /**\n * Mount a remote MCP server (an OAuth-protected resource server) on `http`,\n * next to the other HTTP registrars (`mount`, `route`). Requires `oauth` to be\n * configured in `defineAuth` — the MCP server shares the AS `scopes` and\n * bearer-token verification — and throws at registration time otherwise.\n * Tools are plain `{ description, scope, args, handler }` objects; each\n * handler's `args` are inferred from its Convex validator.\n */\n mcp: <T extends Record<string, GenericValidator>>(\n http: HttpRouter,\n tools: { [K in keyof T]: McpToolDef<T[K]> },\n opts?: { name?: string; version?: string; mcpPath?: string },\n ): void => {\n if (config.oauth === undefined) {\n throw new Error(\n \"`auth.request.mcp(...)` requires `oauth` to be configured in `defineAuth` — the MCP server is protected by the OAuth authorization server.\",\n );\n }\n if (delegatableGrants.length === 0) {\n throw new Error(\n \"`auth.request.mcp(...)` requires `permissions` with at least one grant — MCP tools delegate your app's grants, and none are defined.\",\n );\n }\n const mcpPath = opts?.mcpPath ?? \"/mcp\";\n const canonicalResource = () => requireEnv(\"CONVEX_SITE_URL\").replace(/\\/+$/, \"\") + mcpPath;\n addMcpRoutes(http, {\n tools,\n name: opts?.name,\n version: opts?.version,\n scopes: delegatableGrants,\n mcpPath,\n resource: canonicalResource,\n authorizationServers: () => [authSiteUrl()],\n resolveScopes: async (_ctx, request) => {\n const token = extractBearerToken(request);\n if (token === null) return null;\n const verified = await verifyOAuthToken(token, {\n issuer: authSiteUrl(),\n resource: canonicalResource(),\n });\n return verified ? verified.scopes : null;\n },\n });\n },\n };\n\n const auth = Object.assign(authBase, { request });\n\n /**\n * App-owned HTTP router factory. `auth.http()` returns a Convex `httpRouter()`\n * with every auth protocol route mounted via {@link request.mount}, so there is\n * exactly one route table.\n */\n const http = () => {\n const router = httpRouter();\n request.mount(router);\n return router;\n };\n\n const { accountUnlink, passkeyDelete, totpDelete } = createFactorUnlinkHelpers(config);\n\n const enrichedAccount = Object.assign({}, auth.account, { unlink: accountUnlink });\n const passkeyHelpers = { remove: passkeyDelete };\n const totpHelpers = { remove: totpDelete };\n\n const enrichCtx = <DataModel extends GenericDataModel>(ctx: GenericActionCtx<DataModel>) =>\n enrichActionCtx(ctx, {\n ...ctx.auth,\n getUserIdentity: ctx.auth.getUserIdentity.bind(ctx.auth),\n config,\n account: enrichedAccount,\n passkey: passkeyHelpers,\n totp: totpHelpers,\n session: auth.session,\n member: auth.member,\n provider: {\n ...auth.provider,\n continueRecovery: async (\n continuationCtx: GenericActionCtx<DataModel>,\n args: RecoveryContinuationRequest,\n ) => await continueRecovery(continuationCtx, args),\n },\n event: auth.event,\n });\n\n return {\n auth,\n /**\n * Action called by the client to sign the user in.\n *\n * Also used for refreshing the session.\n */\n signIn: actionGeneric({\n args: vSignInActionArgs,\n handler: async (ctx, args): Promise<SignInActionResult> => {\n if (args.calledBy !== undefined) {\n log(\"INFO\", `\\`auth:signIn\\` called by ${args.calledBy}`);\n }\n let provider = null;\n if (args.provider !== undefined && args.continuation !== undefined) {\n const continuation = await queryContinuation(\n bridgeRuntimeType<Parameters<typeof signInImpl>[0]>(enrichCtx(ctx)),\n args.continuation,\n );\n if (continuation === null || continuation.provider !== args.provider) {\n throw new ConvexError({\n code: ErrorCode.CONTINUATION_INVALID,\n message: \"The provider continuation is invalid or expired.\",\n });\n }\n provider = getProviderOrThrow(args.provider, true);\n if (provider.type !== \"webauthn\") {\n throw new ConvexError({\n code: ErrorCode.CONTINUATION_INVALID,\n message: \"The provider continuation does not support this provider.\",\n });\n }\n } else if (args.provider !== undefined) {\n provider = getProviderOrThrow(args.provider);\n }\n if (provider?.type === \"credentials\") {\n if (!validate(provider.params, args.params)) {\n throw new ConvexError({\n code: ErrorCode.INVALID_PARAMETERS,\n message: `Invalid parameters for credentials provider ${provider.id}.`,\n });\n }\n } else if (!validate(v.optional(vPayloadRecord), args.params)) {\n throw new ConvexError({\n code: ErrorCode.INVALID_PARAMETERS,\n message: \"Sign-in parameters must contain only supported payload values.\",\n });\n }\n const authSiteUrl =\n provider?.type === \"oauth\" || provider?.type === \"connection\"\n ? getAuthSiteUrl(ctx)\n : undefined;\n const result = await signInImpl(\n bridgeRuntimeType<Parameters<typeof signInImpl>[0]>(enrichCtx(ctx)),\n provider,\n args,\n {\n generateTokens: true,\n allowExtraProviders: false,\n authSiteUrl,\n resolveConnectionProtocol: group.resolveGroupConnectionConnectionProtocolOrThrow,\n },\n );\n const resultKind: string = result.kind;\n /** Exhaustive narrowing dispatch: only `signedIn` reshapes its session into tokens; every other variant passes through unchanged. */\n switch (result.kind) {\n case \"signedIn\":\n return {\n kind: \"signedIn\",\n session: result.session?.tokens ?? null,\n };\n case \"redirect\":\n case \"started\":\n case \"webauthnOptions\":\n case \"totpRequired\":\n case \"totpSetup\":\n case \"deviceCode\":\n return result;\n default:\n throw new Error(`Unexpected sign-in result kind: ${resultKind}`);\n }\n },\n }),\n /**\n * Action called by the client to invalidate the current session.\n */\n signOut: actionGeneric({\n args: {},\n handler: async (ctx) => {\n await callSignOut(ctx);\n },\n }),\n\n /**\n * Internal mutation used by the library to read and write\n * to the database during signin and signout.\n */\n store: internalMutationGeneric({\n args: vStoreArgs,\n handler: async (ctx: MutationCtx, args) => {\n return storeImpl(ctx, args, services);\n },\n }),\n\n /** App-owned HTTP router factory; call `auth.http()` from `convex/http.ts`. */\n http,\n };\n}\n"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"lifecycle.d.ts","names":[],"sources":["../../../src/server/session/lifecycle.ts"],"mappings":";;;;;;;
|
|
1
|
+
{"version":3,"file":"lifecycle.d.ts","names":[],"sources":["../../../src/server/session/lifecycle.ts"],"mappings":";;;;;;;AAyCA;;;KAAY,eAAA;EACV,MAAA,EAAQ,SAAA;EACR,SAAA,EAAW,SAAA;EACX,QAAA,EAAU,0BAAA;EAKgB;;;;EAA1B,YAAA,EAAc,YAAA;AAAA"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { LOG_LEVELS } from "../../shared/log.js";
|
|
2
|
-
import { getAuthenticatedSessionIdOrNull } from "../identity/claims.js";
|
|
2
|
+
import { getAuthenticatedSessionIdOrNull, getUserIdentityOrNull, sessionIdFromIdentity, userIdFromIdentity } from "../identity/claims.js";
|
|
3
3
|
import { queueAuthEvent } from "../events.js";
|
|
4
4
|
import { authDb } from "../db.js";
|
|
5
5
|
import { log, maybeRedact } from "../log.js";
|
|
@@ -29,6 +29,7 @@ function buildSessionIdentity(userId, sessionId, user) {
|
|
|
29
29
|
return {
|
|
30
30
|
subject: userId,
|
|
31
31
|
sessionId,
|
|
32
|
+
sessionEpoch: user?.sessionEpoch ?? 0,
|
|
32
33
|
...typeof user?.name === "string" ? { name: user.name } : null,
|
|
33
34
|
...typeof user?.email === "string" ? { email: user.email } : null,
|
|
34
35
|
...user?.emailVerificationTime !== void 0 ? { emailVerified: true } : user?.email !== void 0 ? { emailVerified: false } : null,
|
|
@@ -77,7 +78,7 @@ async function issueSession(ctx, config, args) {
|
|
|
77
78
|
const issued = await authDb(ctx, config).sessions.create({
|
|
78
79
|
userId: args.userId,
|
|
79
80
|
sessionId: args.existingSessionId,
|
|
80
|
-
|
|
81
|
+
replaceSession: args.replaceSession,
|
|
81
82
|
sessionExpirationTime: sessionExpirationTime(config),
|
|
82
83
|
refreshTokenExpirationTime: args.generateTokens ? refreshTokenExpirationTime(config) : void 0
|
|
83
84
|
});
|
|
@@ -130,7 +131,21 @@ async function deleteSession(ctx, session, config) {
|
|
|
130
131
|
async function getAuthSessionId(ctx) {
|
|
131
132
|
return await getAuthenticatedSessionIdOrNull(ctx);
|
|
132
133
|
}
|
|
134
|
+
/**
|
|
135
|
+
* Return the identity-bound proof needed to replace the caller's current
|
|
136
|
+
* session while issuing a session for any account.
|
|
137
|
+
*
|
|
138
|
+
* @internal
|
|
139
|
+
*/
|
|
140
|
+
async function getAuthSessionReplacement(ctx) {
|
|
141
|
+
const identity = await getUserIdentityOrNull(ctx);
|
|
142
|
+
if (identity === null || typeof identity.sid !== "string" || identity.sid.length === 0) return;
|
|
143
|
+
return {
|
|
144
|
+
sessionId: sessionIdFromIdentity(identity),
|
|
145
|
+
authenticatedUserId: userIdFromIdentity(identity)
|
|
146
|
+
};
|
|
147
|
+
}
|
|
133
148
|
|
|
134
149
|
//#endregion
|
|
135
|
-
export { buildSessionIdentity, deleteSession, finalizeSessionIssuance, getAuthSessionId, issueSession, sessionExpirationTime };
|
|
150
|
+
export { buildSessionIdentity, deleteSession, finalizeSessionIssuance, getAuthSessionId, getAuthSessionReplacement, issueSession, sessionExpirationTime };
|
|
136
151
|
//# sourceMappingURL=lifecycle.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"lifecycle.js","names":[],"sources":["../../../src/server/session/lifecycle.ts"],"sourcesContent":["import { Auth } from \"convex/server\";\nimport { GenericId } from \"convex/values\";\n\nimport type { RefreshToken } from \"../../shared/brand\";\nimport { authDb } from \"../db\";\nimport { queueAuthEvent } from \"../events\";\nimport {
|
|
1
|
+
{"version":3,"file":"lifecycle.js","names":[],"sources":["../../../src/server/session/lifecycle.ts"],"sourcesContent":["import { Auth } from \"convex/server\";\nimport { GenericId } from \"convex/values\";\n\nimport type { RefreshToken } from \"../../shared/brand\";\nimport { authDb } from \"../db\";\nimport { queueAuthEvent } from \"../events\";\nimport {\n getAuthenticatedSessionIdOrNull,\n getUserIdentityOrNull,\n sessionIdFromIdentity,\n userIdFromIdentity,\n} from \"../identity/claims\";\nimport { LOG_LEVELS, log, maybeRedact } from \"../log\";\nimport { encodeRefreshToken, refreshTokenExpirationTime } from \"../token/refresh\";\nimport { generateToken } from \"../tokens\";\nimport {\n ConvexAuthConfig,\n Doc,\n MutationCtx,\n SessionInfo,\n SessionTokenIdentityClaims,\n} from \"../types\";\nimport { withSpan } from \"../utils/span\";\n\nconst DEFAULT_SESSION_TOTAL_DURATION_MS = 1000 * 60 * 60 * 24 * 30;\n\n/**\n * Absolute expiration timestamp (ms) for a new session.\n *\n * Resolved from `config.session.totalDurationMs`, defaulting to 30 days.\n *\n * @internal\n */\nexport const sessionExpirationTime = (config: ConvexAuthConfig, now = Date.now()) =>\n now + (config.session?.totalDurationMs ?? DEFAULT_SESSION_TOTAL_DURATION_MS);\n\n/**\n * Mutation-side session issuance result. The mutation creates the session\n * and refresh-token rows; JWT signing happens on the action side so the\n * transaction commits without paying the signing CPU cost.\n */\nexport type SessionIssuance = {\n userId: GenericId<\"User\">;\n sessionId: GenericId<\"Session\">;\n identity: SessionTokenIdentityClaims;\n /**\n * Encoded refresh token (`${refreshTokenId}|${sessionId}`), or `null` when\n * the caller opted out of refresh-token issuance (e.g. TOTP step-up).\n */\n refreshToken: RefreshToken | null;\n};\n\n/**\n * Proof that a session being replaced belongs to the currently authenticated\n * user. Passing the identity-derived pair lets a sign-in for another account\n * replace only the caller's own current session.\n *\n * @internal\n */\nexport type AuthSessionReplacement = {\n sessionId: GenericId<\"Session\">;\n authenticatedUserId: GenericId<\"User\">;\n};\n\n/**\n * Build the JWT identity-claim set for a session from the user document.\n *\n * Shared by {@link issueSession} and the refresh exchange so both mint\n * identical claims from the same user fields.\n *\n * @internal\n */\nexport function buildSessionIdentity(\n userId: GenericId<\"User\">,\n sessionId: GenericId<\"Session\">,\n user: Doc<\"User\"> | null,\n): SessionTokenIdentityClaims {\n return {\n subject: userId,\n sessionId,\n sessionEpoch: user?.sessionEpoch ?? 0,\n ...(typeof user?.name === \"string\" ? { name: user.name } : null),\n ...(typeof user?.email === \"string\" ? { email: user.email } : null),\n ...(user?.emailVerificationTime !== undefined\n ? { emailVerified: true }\n : user?.email !== undefined\n ? { emailVerified: false }\n : null),\n ...(typeof user?.image === \"string\" ? { picture: user.image } : null),\n ...(typeof user?.phone === \"string\" ? { phoneNumber: user.phone } : null),\n ...(user?.phoneVerificationTime !== undefined\n ? { phoneNumberVerified: true }\n : user?.phone !== undefined\n ? { phoneNumberVerified: false }\n : null),\n };\n}\n\n/**\n * Convert a {@link SessionIssuance} returned from a mutation into the\n * external `SessionInfo` shape by signing the JWT on the action side.\n *\n * Must be called from an action context because `generateToken` performs\n * RSA-2048 JWT signing that would otherwise block the mutation commit.\n *\n * @internal\n */\nexport async function finalizeSessionIssuance(\n config: ConvexAuthConfig,\n issuance: SessionIssuance,\n): Promise<SessionInfo> {\n return withSpan(\n \"convex-auth.session.finalize\",\n { hasRefreshToken: issuance.refreshToken !== null },\n async () => {\n if (issuance.refreshToken === null) {\n return {\n userId: issuance.userId,\n sessionId: issuance.sessionId,\n tokens: null,\n };\n }\n const token = await generateToken({ identity: issuance.identity }, config);\n log(\n LOG_LEVELS.DEBUG,\n `Generated token ${maybeRedact(token)} and refresh token ${maybeRedact(issuance.refreshToken)} for session ${maybeRedact(issuance.sessionId)}`,\n );\n return {\n userId: issuance.userId,\n sessionId: issuance.sessionId,\n tokens: { token, refreshToken: issuance.refreshToken },\n };\n },\n );\n}\n\n/**\n * Create (or extend/replace) a session and its refresh-token row, returning the\n * mutation-side {@link SessionIssuance} for later JWT finalization.\n *\n * @param args.generateTokens - When `false`, no refresh token is issued\n * (e.g. TOTP step-up that defers token issuance to a second factor).\n * @internal\n */\nexport async function issueSession(\n ctx: MutationCtx,\n config: ConvexAuthConfig,\n args: {\n userId: GenericId<\"User\">;\n existingSessionId?: GenericId<\"Session\">;\n replaceSession?: AuthSessionReplacement;\n generateTokens: boolean;\n },\n): Promise<SessionIssuance> {\n const db = authDb(ctx, config);\n const issued = await db.sessions.create({\n userId: args.userId,\n sessionId: args.existingSessionId,\n replaceSession: args.replaceSession,\n sessionExpirationTime: sessionExpirationTime(config),\n refreshTokenExpirationTime: args.generateTokens\n ? refreshTokenExpirationTime(config)\n : undefined,\n });\n const { userId, sessionId, refreshTokenId } = issued;\n if (issued.replacedSessionId !== undefined) {\n const replacedSessionId = issued.replacedSessionId;\n await queueAuthEvent(ctx, config, {\n kind: \"session.invalidated\",\n actor: { type: \"system\" },\n subject: { type: \"session\", id: replacedSessionId },\n targets: [\n { kind: \"user\", id: userId },\n { kind: \"session\", id: replacedSessionId },\n ],\n outcome: \"success\",\n data: { userId, reason: \"replaced\" },\n });\n }\n return {\n userId,\n sessionId,\n identity: buildSessionIdentity(userId, sessionId, issued.user),\n refreshToken:\n args.generateTokens && refreshTokenId !== undefined\n ? encodeRefreshToken(refreshTokenId, sessionId)\n : null,\n };\n}\n\n/**\n * Delete a session and all of its refresh tokens.\n *\n * @internal\n */\nexport async function deleteSession(\n ctx: MutationCtx,\n session: Doc<\"Session\">,\n config: ConvexAuthConfig,\n) {\n const db = authDb(ctx, config);\n await db.sessions.delete(session._id);\n await db.refreshTokens.deleteAll(session._id);\n}\n\n/**\n * Return the current session ID from the auth identity subject.\n *\n * @internal\n */\nexport async function getAuthSessionId(ctx: { auth: Auth }) {\n return await getAuthenticatedSessionIdOrNull(ctx);\n}\n\n/**\n * Return the identity-bound proof needed to replace the caller's current\n * session while issuing a session for any account.\n *\n * @internal\n */\nexport async function getAuthSessionReplacement(ctx: {\n auth: Auth;\n}): Promise<AuthSessionReplacement | undefined> {\n const identity = await getUserIdentityOrNull(ctx);\n if (identity === null || typeof identity.sid !== \"string\" || identity.sid.length === 0) {\n return undefined;\n }\n return {\n sessionId: sessionIdFromIdentity(identity),\n authenticatedUserId: userIdFromIdentity(identity),\n };\n}\n"],"mappings":"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"}
|
|
@@ -190,7 +190,7 @@ async function handleCredentials(ctx, provider, args, options) {
|
|
|
190
190
|
return withSpan("convex-auth.signin.credentials", {}, async () => {
|
|
191
191
|
let result;
|
|
192
192
|
try {
|
|
193
|
-
result = await withSpan("convex-auth.signin.credentials.authorize", { providerId: provider.id }, () => provider.authorize(args.params
|
|
193
|
+
result = await withSpan("convex-auth.signin.credentials.authorize", { providerId: provider.id }, () => provider.authorize(args.params, ctx));
|
|
194
194
|
} catch (error) {
|
|
195
195
|
throw asCredentialsError(error);
|
|
196
196
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"flow.js","names":[],"sources":["../../../src/server/signin/flow.ts"],"sourcesContent":["import { GenericId, ConvexError } from \"convex/values\";\nimport type { CredentialsAuthorizeResult } from \"../../providers/credentials\";\n\nimport { assertNever } from \"../../shared/brand\";\nimport { authFlowError } from \"../../shared/errors\";\nimport type {\n AuthTokens,\n SignInFlowResult,\n SignInRedirectResult,\n SignInSessionResult,\n SignInStartResult,\n} from \"../../shared/results\";\nimport { handleDevice } from \"../device\";\nimport type { AuthErrorData } from \"../errors\";\nimport { toConvexError } from \"../errors\";\nimport { log } from \"../log\";\nimport {\n callCreateVerificationCode,\n callRefreshSession,\n callSignIn,\n callVerifier,\n callVerifyCodeAndSignIn,\n} from \"../mutations/calls\";\nimport { handleWebAuthn } from \"../webauthn\";\nimport type { SignInParams } from \"../payloads\";\nimport { generateRandomString } from \"../random\";\nimport { redirectAbsoluteUrl, setURLSearchParam } from \"../redirects\";\nimport { finalizeSessionIssuance } from \"../session/lifecycle\";\nimport { handleTotp } from \"../totp\";\nimport {\n AuthProviderMaterializedConfig,\n ConvexCredentialsConfig,\n EmailConfig,\n GenericActionCtxWithAuthConfig,\n PhoneConfig,\n} from \"../types\";\nimport { queryTotpVerifiedByUserId } from \"../component/factor/db\";\nimport { AuthDataModel, SessionInfo } from \"../types\";\nimport type { OAuthMaterializedConfig } from \"../types\";\nimport { authUrlFromEnv } from \"../url\";\nimport { withSpan } from \"../utils/span\";\n\nconst DEFAULT_EMAIL_VERIFICATION_CODE_DURATION_S = 60 * 60 * 24;\n\ntype EnrichedActionCtx = GenericActionCtxWithAuthConfig<AuthDataModel>;\n\ntype SignInResult = SignInFlowResult<SessionInfo<AuthTokens | null> | null>;\n\ntype VerificationParams = {\n email?: string;\n phone?: string;\n redirectTo?: unknown;\n connectionId?: unknown;\n loginHint?: unknown;\n protocol?: unknown;\n code?: unknown;\n};\n\nconst normalizeVerificationParams = (params: SignInParams | undefined) => {\n const value = (params ?? {}) as VerificationParams;\n return {\n email: typeof value.email === \"string\" ? value.email : undefined,\n phone: typeof value.phone === \"string\" ? value.phone : undefined,\n redirectTo: value.redirectTo,\n connectionId: value.connectionId,\n loginHint: value.loginHint,\n protocol: value.protocol,\n code: value.code,\n };\n};\n\nconst describeUnknown = (value: unknown) => {\n if (typeof value === \"string\") {\n return JSON.stringify(value);\n }\n if (\n typeof value === \"number\" ||\n typeof value === \"boolean\" ||\n typeof value === \"bigint\" ||\n value === null\n ) {\n return String(value);\n }\n const json = JSON.stringify(value);\n return json ?? Object.prototype.toString.call(value);\n};\n\nconst asConvexError = (\n error: unknown,\n code: string,\n message: string,\n): ConvexError<AuthErrorData> => {\n if (error instanceof ConvexError) {\n return error;\n }\n if (error instanceof Error) {\n return toConvexError(authFlowError(code, error.message || message));\n }\n return toConvexError(authFlowError(code, `${message} ${describeUnknown(error)}`.trim()));\n};\n\nconst asCredentialsError = (error: unknown): ConvexError<AuthErrorData> => {\n if (error instanceof ConvexError) {\n return error as ConvexError<AuthErrorData>;\n }\n if (error instanceof Error) {\n return new ConvexError({\n code: error.message.startsWith(\"Missing `\") ? \"INVALID_PARAMETERS\" : \"INVALID_CREDENTIALS\",\n message: error.message,\n });\n }\n return toConvexError(authFlowError(\"INTERNAL_ERROR\", \"Failed to authorize credentials.\"));\n};\n\n/**\n * Entry point for all sign-in flows.\n *\n * Refreshes a session (when only `refreshToken` is given), verifies a sign-in\n * code (when only `params.code` is given), or dispatches to the matching\n * provider handler based on `provider.type`.\n *\n * @param provider - The resolved provider, or `null` for refresh/code-only calls.\n * @returns The flow result: `signedIn`, `started`, `redirect`, `totpRequired`, etc.\n */\nexport async function signInImpl(\n ctx: EnrichedActionCtx,\n provider: AuthProviderMaterializedConfig | null,\n args: {\n accountId?: GenericId<\"Account\">;\n params?: SignInParams;\n verifier?: string;\n continuation?: string;\n refreshToken?: string;\n calledBy?: string;\n },\n options: {\n generateTokens: boolean;\n allowExtraProviders: boolean;\n authSiteUrl?: string;\n resolveConnectionProtocol?: (\n ctx: EnrichedActionCtx,\n connectionId: string,\n ) => Promise<\"oidc\" | \"saml\">;\n },\n): Promise<SignInResult> {\n return withSpan(\n \"convex-auth.signin\",\n {\n hasProvider: provider !== null,\n hasCode: args.params?.code !== undefined,\n hasRefreshToken: args.refreshToken !== undefined,\n },\n async () => {\n if (provider === null && args.refreshToken) {\n try {\n const session = await callRefreshSession(ctx, { refreshToken: args.refreshToken! });\n if (session === null) {\n return { kind: \"signedIn\" as const, session: null };\n }\n return { kind: \"signedIn\" as const, session };\n } catch (error) {\n throw asConvexError(error, \"INTERNAL_ERROR\", \"Failed to refresh session.\");\n }\n }\n\n if (provider === null && args.params?.code !== undefined) {\n try {\n const result = await callVerifyCodeAndSignIn(ctx, {\n params: args.params as SignInParams,\n verifier: args.verifier,\n createSession: true,\n generateTokens: true,\n allowExtraProviders: options.allowExtraProviders,\n });\n return { kind: \"signedIn\" as const, session: result };\n } catch (error) {\n throw asConvexError(error, \"INTERNAL_ERROR\", \"Failed to verify sign-in code.\");\n }\n }\n\n const resolvedProvider = provider;\n if (resolvedProvider === null) {\n throw toConvexError(\n authFlowError(\n \"SIGN_IN_MISSING_PARAMS\",\n \"Cannot sign in: missing provider, code, or refresh token.\",\n ),\n );\n }\n\n /** Exhaustive narrowing dispatch: each case narrows `resolvedProvider` to its concrete config so the handler receives the typed variant without a cast. */\n switch (resolvedProvider.type) {\n case \"email\":\n case \"phone\":\n return handleEmailAndPhoneProvider(ctx, resolvedProvider, args, options);\n case \"credentials\":\n return handleCredentials(ctx, resolvedProvider, args, options);\n case \"oauth\":\n return handleOAuthProvider(ctx, resolvedProvider, args, options);\n case \"webauthn\":\n return handleWebAuthn(ctx, resolvedProvider, args);\n case \"totp\":\n return handleTotp(ctx, resolvedProvider, args);\n case \"device\":\n return handleDevice(ctx, resolvedProvider, args);\n case \"connection\":\n return handleConnectionProvider(ctx, args, options);\n default:\n return assertNever(resolvedProvider, \"Unknown provider type\");\n }\n },\n );\n}\n\nasync function handleEmailAndPhoneProvider(\n ctx: EnrichedActionCtx,\n provider: EmailConfig | PhoneConfig,\n args: {\n params?: SignInParams;\n accountId?: GenericId<\"Account\">;\n },\n options: {\n generateTokens: boolean;\n allowExtraProviders: boolean;\n },\n): Promise<SignInStartResult | SignInSessionResult<SessionInfo<AuthTokens | null>>> {\n return withSpan(`convex-auth.signin.${provider.type}`, {}, async () => {\n const normalizedParams = normalizeVerificationParams(args.params);\n if (args.params?.code !== undefined) {\n let result;\n try {\n result = await callVerifyCodeAndSignIn(ctx, {\n params: args.params as SignInParams,\n provider: provider.id,\n createSession: true,\n generateTokens: options.generateTokens,\n allowExtraProviders: options.allowExtraProviders,\n });\n } catch (error) {\n throw asConvexError(error, \"INTERNAL_ERROR\", \"Failed to verify email or phone code.\");\n }\n if (result === null) {\n throw toConvexError(\n authFlowError(\"INVALID_VERIFICATION_CODE\", \"Invalid or expired verification code.\"),\n );\n }\n return {\n kind: \"signedIn\" as const,\n session: result,\n };\n }\n\n const alphabet = \"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz\";\n let code: string;\n if (provider.generateVerificationToken) {\n try {\n code = await provider.generateVerificationToken();\n } catch {\n throw toConvexError(\n authFlowError(\"INTERNAL_ERROR\", \"Failed to generate verification token\"),\n );\n }\n } else {\n code = generateRandomString(32, alphabet);\n }\n\n const expirationTime =\n Date.now() + (provider.maxAge ?? DEFAULT_EMAIL_VERIFICATION_CODE_DURATION_S) * 1000;\n\n let identifier: string;\n try {\n identifier = await callCreateVerificationCode(ctx, {\n provider: provider.id,\n accountId: args.accountId,\n email: normalizedParams.email,\n phone: normalizedParams.phone,\n code,\n expirationTime,\n allowExtraProviders: options.allowExtraProviders,\n });\n } catch (error) {\n throw asConvexError(error, \"INTERNAL_ERROR\", \"Failed to create verification code.\");\n }\n\n let destination: string;\n try {\n destination = await redirectAbsoluteUrl(ctx, ctx.auth.config, {\n redirectTo: args.params?.redirectTo,\n });\n } catch (error) {\n throw asConvexError(error, \"INVALID_REDIRECT\", \"Failed to resolve redirect URL.\");\n }\n\n const verificationArgs = {\n identifier,\n url: setURLSearchParam(destination, \"code\", code),\n token: code,\n expires: new Date(expirationTime),\n };\n\n if (provider.type === \"email\") {\n try {\n await provider.sendVerificationRequest(\n {\n ...verificationArgs,\n provider,\n request: new Request(\"http://localhost\"),\n },\n ctx,\n );\n } catch {\n throw toConvexError(authFlowError(\"INTERNAL_ERROR\", \"Failed to send email code\"));\n }\n } else {\n try {\n await provider.sendVerificationRequest({ ...verificationArgs, provider }, ctx);\n } catch {\n throw toConvexError(authFlowError(\"INTERNAL_ERROR\", \"Failed to send phone code\"));\n }\n }\n\n return { kind: \"started\" as const };\n });\n}\n\nasync function handleCredentials(\n ctx: EnrichedActionCtx,\n provider: ConvexCredentialsConfig,\n args: {\n params?: SignInParams;\n },\n options: {\n generateTokens: boolean;\n },\n): Promise<SignInFlowResult<SessionInfo<AuthTokens | null> | null>> {\n return withSpan(\"convex-auth.signin.credentials\", {}, async () => {\n let result: CredentialsAuthorizeResult;\n try {\n result = await withSpan(\n \"convex-auth.signin.credentials.authorize\",\n { providerId: provider.id },\n () => provider.authorize(args.params ?? {}, ctx),\n );\n } catch (error) {\n throw asCredentialsError(error);\n }\n if (result === null) {\n return { kind: \"signedIn\" as const, session: null };\n }\n if (\"kind\" in result) {\n return result;\n }\n\n if (\"provision\" in result) {\n const { provision, hasTotp } = result;\n try {\n const provisioned = await withSpan(\n \"convex-auth.signin.credentials.provision\",\n { providerId: provider.id },\n () =>\n ctx.auth.account.create(ctx, {\n provider: provider.id,\n account: provision.account,\n profile: provision.profile,\n shouldLinkViaEmail: provision.match?.includes(\"email\"),\n shouldLinkViaPhone: provision.match?.includes(\"phone\"),\n }),\n );\n result = {\n userId: provisioned.account.userId,\n hasTotp,\n };\n } catch (error) {\n throw asConvexError(error, \"INTERNAL_ERROR\", \"Failed to provision credentials account.\");\n }\n }\n\n const hintedHasTotp = result.hasTotp;\n const preIssuedIssuance = result.issuance;\n\n let hasTotpEnrolled: boolean;\n if (hintedHasTotp === false) {\n hasTotpEnrolled = false;\n } else if (hintedHasTotp === true) {\n hasTotpEnrolled = true;\n } else if (preIssuedIssuance !== undefined && preIssuedIssuance.refreshToken === null) {\n hasTotpEnrolled = true;\n } else {\n try {\n const totpDoc = await withSpan(\n \"convex-auth.signin.credentials.totp-check\",\n { hinted: hintedHasTotp ?? \"unknown\" },\n () => queryTotpVerifiedByUserId(ctx, result.userId),\n );\n hasTotpEnrolled = totpDoc !== null;\n } catch (error) {\n throw asConvexError(error, \"INTERNAL_ERROR\", \"Failed to load TOTP enrollment.\");\n }\n }\n\n if (hasTotpEnrolled) {\n let verifier: string;\n try {\n verifier = await callVerifier(ctx, JSON.stringify({ userId: result.userId }));\n } catch (error) {\n throw asConvexError(error, \"INTERNAL_ERROR\", \"Failed to create verifier.\");\n }\n return { kind: \"totpRequired\" as const, verifier };\n }\n\n if (preIssuedIssuance !== undefined) {\n try {\n const idsAndTokens = await withSpan(\n \"convex-auth.signin.credentials.finalize\",\n { generateTokens: options.generateTokens, fromAuthorize: true },\n () =>\n finalizeSessionIssuance(ctx.auth.config, {\n ...preIssuedIssuance,\n refreshToken: options.generateTokens ? preIssuedIssuance.refreshToken : null,\n }),\n );\n return { kind: \"signedIn\" as const, session: idsAndTokens };\n } catch (error) {\n throw asConvexError(error, \"INTERNAL_ERROR\", \"Failed to finalize sign-in.\");\n }\n }\n\n let idsAndTokens;\n try {\n idsAndTokens = await withSpan(\n \"convex-auth.signin.credentials.issue-session\",\n { generateTokens: options.generateTokens },\n () =>\n callSignIn(ctx, {\n userId: result.userId,\n sessionId: result.sessionId,\n provider: provider.id,\n generateTokens: options.generateTokens,\n }),\n );\n } catch (error) {\n throw asConvexError(error, \"INTERNAL_ERROR\", \"Failed to complete sign-in.\");\n }\n return { kind: \"signedIn\" as const, session: idsAndTokens };\n });\n}\n\nasync function handleOAuthProvider(\n ctx: EnrichedActionCtx,\n provider: OAuthMaterializedConfig,\n args: {\n params?: SignInParams;\n verifier?: string;\n },\n options: {\n allowExtraProviders: boolean;\n authSiteUrl?: string;\n },\n): Promise<SignInSessionResult<SessionInfo<AuthTokens> | null> | SignInRedirectResult> {\n return withSpan(`convex-auth.signin.oauth`, { provider: provider.id }, async () => {\n if (args.params?.code !== undefined) {\n let result;\n try {\n result = await callVerifyCodeAndSignIn(ctx, {\n params: args.params as SignInParams,\n verifier: args.verifier,\n createSession: true,\n generateTokens: true,\n allowExtraProviders: options.allowExtraProviders,\n });\n } catch (error) {\n throw asConvexError(error, \"INTERNAL_ERROR\", \"Failed to verify OAuth sign-in.\");\n }\n return {\n kind: \"signedIn\" as const,\n session: result,\n };\n }\n\n const authSiteUrl = options.authSiteUrl ?? authUrlFromEnv();\n const redirect = new URL(`${authSiteUrl.replace(/\\/$/, \"\")}/signin/${provider.id}`);\n let verifier: string;\n try {\n verifier = await callVerifier(ctx);\n } catch (error) {\n throw asConvexError(error, \"INTERNAL_ERROR\", \"Failed to create verifier.\");\n }\n redirect.searchParams.set(\"code\", verifier);\n\n if (args.params?.redirectTo !== undefined) {\n if (typeof args.params.redirectTo !== \"string\") {\n throw toConvexError(\n authFlowError(\n \"INVALID_REDIRECT\",\n `Expected \\`redirectTo\\` to be a string, got ${describeUnknown(args.params.redirectTo)}`,\n ),\n );\n }\n redirect.searchParams.set(\"redirectTo\", args.params.redirectTo);\n }\n\n return {\n kind: \"redirect\" as const,\n redirect: redirect.toString(),\n verifier,\n };\n });\n}\n\nasync function handleConnectionProvider(\n ctx: EnrichedActionCtx,\n args: {\n params?: SignInParams;\n },\n options: {\n resolveConnectionProtocol?: (\n ctx: EnrichedActionCtx,\n connectionId: string,\n ) => Promise<\"oidc\" | \"saml\">;\n authSiteUrl?: string;\n },\n): Promise<{ kind: \"redirect\"; redirect: string; verifier: string }> {\n return withSpan(\"convex-auth.signin.connection\", {}, async () => {\n const normalizedParams = normalizeVerificationParams(args.params);\n const connectionId = normalizedParams.connectionId;\n if (!connectionId || typeof connectionId !== \"string\") {\n throw toConvexError(\n authFlowError(\"SIGN_IN_MISSING_PARAMS\", \"connectionId is required for Connection sign-in.\"),\n );\n }\n\n let protocol: \"oidc\" | \"saml\" =\n (normalizedParams.protocol === \"oidc\" || normalizedParams.protocol === \"saml\"\n ? normalizedParams.protocol\n : undefined) ??\n (options.resolveConnectionProtocol\n ? await (async () => {\n try {\n return await options.resolveConnectionProtocol!(ctx, connectionId);\n } catch (error) {\n throw asConvexError(\n error,\n \"INTERNAL_ERROR\",\n \"Failed to resolve Connection protocol.\",\n );\n }\n })()\n : \"oidc\");\n\n log(\"DEBUG\", \"[group-connection] signin:resolved\", {\n connectionId,\n protocol,\n redirectTo: typeof args.params?.redirectTo === \"string\" ? args.params.redirectTo : undefined,\n });\n\n if (protocol !== \"oidc\" && protocol !== \"saml\") {\n throw toConvexError(\n authFlowError(\n \"SIGN_IN_MISSING_PARAMS\",\n `Invalid Connection protocol: ${protocol as string}. Expected \"oidc\" or \"saml\".`,\n ),\n );\n }\n\n let verifier: string;\n try {\n verifier = await callVerifier(ctx);\n } catch (error) {\n throw asConvexError(error, \"INTERNAL_ERROR\", \"Failed to create verifier.\");\n }\n const siteUrl = options.authSiteUrl ?? authUrlFromEnv();\n const redirect = new URL(\n `${siteUrl.replace(/\\/$/, \"\")}/connections/${connectionId}/${protocol}/signin`,\n );\n redirect.searchParams.set(\"code\", verifier);\n\n if (typeof args.params?.redirectTo === \"string\") {\n redirect.searchParams.set(\"redirectTo\", args.params.redirectTo);\n }\n if (typeof normalizedParams.loginHint === \"string\") {\n redirect.searchParams.set(\"loginHint\", normalizedParams.loginHint);\n }\n log(\"DEBUG\", \"[group-connection] signin:redirect\", {\n connectionId,\n protocol,\n redirect: redirect.toString(),\n });\n\n return {\n kind: \"redirect\" as const,\n redirect: redirect.toString(),\n verifier,\n };\n });\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"flow.js","names":[],"sources":["../../../src/server/signin/flow.ts"],"sourcesContent":["import type { GenericDataModel } from \"convex/server\";\nimport { GenericId, ConvexError } from \"convex/values\";\nimport type { GenericValidator } from \"convex/values\";\nimport type { CredentialsAuthorizeResult } from \"../../providers/credentials\";\n\nimport { assertNever } from \"../../shared/brand\";\nimport { authFlowError } from \"../../shared/errors\";\nimport type {\n AuthTokens,\n SignInFlowResult,\n SignInRedirectResult,\n SignInSessionResult,\n SignInStartResult,\n} from \"../../shared/results\";\nimport { handleDevice } from \"../device\";\nimport type { AuthErrorData } from \"../errors\";\nimport { toConvexError } from \"../errors\";\nimport { log } from \"../log\";\nimport {\n callCreateVerificationCode,\n callRefreshSession,\n callSignIn,\n callVerifier,\n callVerifyCodeAndSignIn,\n} from \"../mutations/calls\";\nimport { handleWebAuthn } from \"../webauthn\";\nimport type { SignInParams } from \"../payloads\";\nimport { generateRandomString } from \"../random\";\nimport { redirectAbsoluteUrl, setURLSearchParam } from \"../redirects\";\nimport { finalizeSessionIssuance } from \"../session/lifecycle\";\nimport { handleTotp } from \"../totp\";\nimport {\n AuthProviderMaterializedConfig,\n ConvexCredentialsConfig,\n EmailConfig,\n GenericActionCtxWithAuthConfig,\n PhoneConfig,\n} from \"../types\";\nimport { queryTotpVerifiedByUserId } from \"../component/factor/db\";\nimport { AuthDataModel, SessionInfo } from \"../types\";\nimport type { OAuthMaterializedConfig } from \"../types\";\nimport { authUrlFromEnv } from \"../url\";\nimport { withSpan } from \"../utils/span\";\n\nconst DEFAULT_EMAIL_VERIFICATION_CODE_DURATION_S = 60 * 60 * 24;\n\ntype EnrichedActionCtx = GenericActionCtxWithAuthConfig<AuthDataModel>;\n\ntype SignInResult = SignInFlowResult<SessionInfo<AuthTokens | null> | null>;\n\ntype VerificationParams = {\n email?: string;\n phone?: string;\n redirectTo?: unknown;\n connectionId?: unknown;\n loginHint?: unknown;\n protocol?: unknown;\n code?: unknown;\n};\n\nconst normalizeVerificationParams = (params: SignInParams | undefined) => {\n const value = (params ?? {}) as VerificationParams;\n return {\n email: typeof value.email === \"string\" ? value.email : undefined,\n phone: typeof value.phone === \"string\" ? value.phone : undefined,\n redirectTo: value.redirectTo,\n connectionId: value.connectionId,\n loginHint: value.loginHint,\n protocol: value.protocol,\n code: value.code,\n };\n};\n\nconst describeUnknown = (value: unknown) => {\n if (typeof value === \"string\") {\n return JSON.stringify(value);\n }\n if (\n typeof value === \"number\" ||\n typeof value === \"boolean\" ||\n typeof value === \"bigint\" ||\n value === null\n ) {\n return String(value);\n }\n const json = JSON.stringify(value);\n return json ?? Object.prototype.toString.call(value);\n};\n\nconst asConvexError = (\n error: unknown,\n code: string,\n message: string,\n): ConvexError<AuthErrorData> => {\n if (error instanceof ConvexError) {\n return error;\n }\n if (error instanceof Error) {\n return toConvexError(authFlowError(code, error.message || message));\n }\n return toConvexError(authFlowError(code, `${message} ${describeUnknown(error)}`.trim()));\n};\n\nconst asCredentialsError = (error: unknown): ConvexError<AuthErrorData> => {\n if (error instanceof ConvexError) {\n return error as ConvexError<AuthErrorData>;\n }\n if (error instanceof Error) {\n return new ConvexError({\n code: error.message.startsWith(\"Missing `\") ? \"INVALID_PARAMETERS\" : \"INVALID_CREDENTIALS\",\n message: error.message,\n });\n }\n return toConvexError(authFlowError(\"INTERNAL_ERROR\", \"Failed to authorize credentials.\"));\n};\n\n/**\n * Entry point for all sign-in flows.\n *\n * Refreshes a session (when only `refreshToken` is given), verifies a sign-in\n * code (when only `params.code` is given), or dispatches to the matching\n * provider handler based on `provider.type`.\n *\n * @param provider - The resolved provider, or `null` for refresh/code-only calls.\n * @returns The flow result: `signedIn`, `started`, `redirect`, `totpRequired`, etc.\n */\nexport async function signInImpl(\n ctx: EnrichedActionCtx,\n provider: AuthProviderMaterializedConfig | null,\n args: {\n accountId?: GenericId<\"Account\">;\n params?: SignInParams;\n verifier?: string;\n continuation?: string;\n refreshToken?: string;\n calledBy?: string;\n },\n options: {\n generateTokens: boolean;\n allowExtraProviders: boolean;\n authSiteUrl?: string;\n resolveConnectionProtocol?: (\n ctx: EnrichedActionCtx,\n connectionId: string,\n ) => Promise<\"oidc\" | \"saml\">;\n },\n): Promise<SignInResult> {\n return withSpan(\n \"convex-auth.signin\",\n {\n hasProvider: provider !== null,\n hasCode: args.params?.code !== undefined,\n hasRefreshToken: args.refreshToken !== undefined,\n },\n async () => {\n if (provider === null && args.refreshToken) {\n try {\n const session = await callRefreshSession(ctx, { refreshToken: args.refreshToken! });\n if (session === null) {\n return { kind: \"signedIn\" as const, session: null };\n }\n return { kind: \"signedIn\" as const, session };\n } catch (error) {\n throw asConvexError(error, \"INTERNAL_ERROR\", \"Failed to refresh session.\");\n }\n }\n\n if (provider === null && args.params?.code !== undefined) {\n try {\n const result = await callVerifyCodeAndSignIn(ctx, {\n params: args.params as SignInParams,\n verifier: args.verifier,\n createSession: true,\n generateTokens: true,\n allowExtraProviders: options.allowExtraProviders,\n });\n return { kind: \"signedIn\" as const, session: result };\n } catch (error) {\n throw asConvexError(error, \"INTERNAL_ERROR\", \"Failed to verify sign-in code.\");\n }\n }\n\n const resolvedProvider = provider;\n if (resolvedProvider === null) {\n throw toConvexError(\n authFlowError(\n \"SIGN_IN_MISSING_PARAMS\",\n \"Cannot sign in: missing provider, code, or refresh token.\",\n ),\n );\n }\n\n /** Exhaustive narrowing dispatch: each case narrows `resolvedProvider` to its concrete config so the handler receives the typed variant without a cast. */\n switch (resolvedProvider.type) {\n case \"email\":\n case \"phone\":\n return handleEmailAndPhoneProvider(ctx, resolvedProvider, args, options);\n case \"credentials\":\n return handleCredentials(ctx, resolvedProvider, args, options);\n case \"oauth\":\n return handleOAuthProvider(ctx, resolvedProvider, args, options);\n case \"webauthn\":\n return handleWebAuthn(ctx, resolvedProvider, args);\n case \"totp\":\n return handleTotp(ctx, resolvedProvider, args);\n case \"device\":\n return handleDevice(ctx, resolvedProvider, args);\n case \"connection\":\n return handleConnectionProvider(ctx, args, options);\n default:\n return assertNever(resolvedProvider, \"Unknown provider type\");\n }\n },\n );\n}\n\nasync function handleEmailAndPhoneProvider(\n ctx: EnrichedActionCtx,\n provider: EmailConfig | PhoneConfig,\n args: {\n params?: SignInParams;\n accountId?: GenericId<\"Account\">;\n },\n options: {\n generateTokens: boolean;\n allowExtraProviders: boolean;\n },\n): Promise<SignInStartResult | SignInSessionResult<SessionInfo<AuthTokens | null>>> {\n return withSpan(`convex-auth.signin.${provider.type}`, {}, async () => {\n const normalizedParams = normalizeVerificationParams(args.params);\n if (args.params?.code !== undefined) {\n let result;\n try {\n result = await callVerifyCodeAndSignIn(ctx, {\n params: args.params as SignInParams,\n provider: provider.id,\n createSession: true,\n generateTokens: options.generateTokens,\n allowExtraProviders: options.allowExtraProviders,\n });\n } catch (error) {\n throw asConvexError(error, \"INTERNAL_ERROR\", \"Failed to verify email or phone code.\");\n }\n if (result === null) {\n throw toConvexError(\n authFlowError(\"INVALID_VERIFICATION_CODE\", \"Invalid or expired verification code.\"),\n );\n }\n return {\n kind: \"signedIn\" as const,\n session: result,\n };\n }\n\n const alphabet = \"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz\";\n let code: string;\n if (provider.generateVerificationToken) {\n try {\n code = await provider.generateVerificationToken();\n } catch {\n throw toConvexError(\n authFlowError(\"INTERNAL_ERROR\", \"Failed to generate verification token\"),\n );\n }\n } else {\n code = generateRandomString(32, alphabet);\n }\n\n const expirationTime =\n Date.now() + (provider.maxAge ?? DEFAULT_EMAIL_VERIFICATION_CODE_DURATION_S) * 1000;\n\n let identifier: string;\n try {\n identifier = await callCreateVerificationCode(ctx, {\n provider: provider.id,\n accountId: args.accountId,\n email: normalizedParams.email,\n phone: normalizedParams.phone,\n code,\n expirationTime,\n allowExtraProviders: options.allowExtraProviders,\n });\n } catch (error) {\n throw asConvexError(error, \"INTERNAL_ERROR\", \"Failed to create verification code.\");\n }\n\n let destination: string;\n try {\n destination = await redirectAbsoluteUrl(ctx, ctx.auth.config, {\n redirectTo: args.params?.redirectTo,\n });\n } catch (error) {\n throw asConvexError(error, \"INVALID_REDIRECT\", \"Failed to resolve redirect URL.\");\n }\n\n const verificationArgs = {\n identifier,\n url: setURLSearchParam(destination, \"code\", code),\n token: code,\n expires: new Date(expirationTime),\n };\n\n if (provider.type === \"email\") {\n try {\n await provider.sendVerificationRequest(\n {\n ...verificationArgs,\n provider,\n request: new Request(\"http://localhost\"),\n },\n ctx,\n );\n } catch {\n throw toConvexError(authFlowError(\"INTERNAL_ERROR\", \"Failed to send email code\"));\n }\n } else {\n try {\n await provider.sendVerificationRequest({ ...verificationArgs, provider }, ctx);\n } catch {\n throw toConvexError(authFlowError(\"INTERNAL_ERROR\", \"Failed to send phone code\"));\n }\n }\n\n return { kind: \"started\" as const };\n });\n}\n\nasync function handleCredentials(\n ctx: EnrichedActionCtx,\n provider: ConvexCredentialsConfig<GenericDataModel, GenericValidator, string>,\n args: {\n params?: SignInParams;\n },\n options: {\n generateTokens: boolean;\n },\n): Promise<SignInFlowResult<SessionInfo<AuthTokens | null> | null>> {\n return withSpan(\"convex-auth.signin.credentials\", {}, async () => {\n let result: CredentialsAuthorizeResult;\n try {\n result = await withSpan(\n \"convex-auth.signin.credentials.authorize\",\n { providerId: provider.id },\n () => provider.authorize(args.params, ctx),\n );\n } catch (error) {\n throw asCredentialsError(error);\n }\n if (result === null) {\n return { kind: \"signedIn\" as const, session: null };\n }\n if (\"kind\" in result) {\n return result;\n }\n\n if (\"provision\" in result) {\n const { provision, hasTotp } = result;\n try {\n const provisioned = await withSpan(\n \"convex-auth.signin.credentials.provision\",\n { providerId: provider.id },\n () =>\n ctx.auth.account.create(ctx, {\n provider: provider.id,\n account: provision.account,\n profile: provision.profile,\n shouldLinkViaEmail: provision.match?.includes(\"email\"),\n shouldLinkViaPhone: provision.match?.includes(\"phone\"),\n }),\n );\n result = {\n userId: provisioned.account.userId,\n hasTotp,\n };\n } catch (error) {\n throw asConvexError(error, \"INTERNAL_ERROR\", \"Failed to provision credentials account.\");\n }\n }\n\n const hintedHasTotp = result.hasTotp;\n const preIssuedIssuance = result.issuance;\n\n let hasTotpEnrolled: boolean;\n if (hintedHasTotp === false) {\n hasTotpEnrolled = false;\n } else if (hintedHasTotp === true) {\n hasTotpEnrolled = true;\n } else if (preIssuedIssuance !== undefined && preIssuedIssuance.refreshToken === null) {\n hasTotpEnrolled = true;\n } else {\n try {\n const totpDoc = await withSpan(\n \"convex-auth.signin.credentials.totp-check\",\n { hinted: hintedHasTotp ?? \"unknown\" },\n () => queryTotpVerifiedByUserId(ctx, result.userId),\n );\n hasTotpEnrolled = totpDoc !== null;\n } catch (error) {\n throw asConvexError(error, \"INTERNAL_ERROR\", \"Failed to load TOTP enrollment.\");\n }\n }\n\n if (hasTotpEnrolled) {\n let verifier: string;\n try {\n verifier = await callVerifier(ctx, JSON.stringify({ userId: result.userId }));\n } catch (error) {\n throw asConvexError(error, \"INTERNAL_ERROR\", \"Failed to create verifier.\");\n }\n return { kind: \"totpRequired\" as const, verifier };\n }\n\n if (preIssuedIssuance !== undefined) {\n try {\n const idsAndTokens = await withSpan(\n \"convex-auth.signin.credentials.finalize\",\n { generateTokens: options.generateTokens, fromAuthorize: true },\n () =>\n finalizeSessionIssuance(ctx.auth.config, {\n ...preIssuedIssuance,\n refreshToken: options.generateTokens ? preIssuedIssuance.refreshToken : null,\n }),\n );\n return { kind: \"signedIn\" as const, session: idsAndTokens };\n } catch (error) {\n throw asConvexError(error, \"INTERNAL_ERROR\", \"Failed to finalize sign-in.\");\n }\n }\n\n let idsAndTokens;\n try {\n idsAndTokens = await withSpan(\n \"convex-auth.signin.credentials.issue-session\",\n { generateTokens: options.generateTokens },\n () =>\n callSignIn(ctx, {\n userId: result.userId,\n sessionId: result.sessionId,\n provider: provider.id,\n generateTokens: options.generateTokens,\n }),\n );\n } catch (error) {\n throw asConvexError(error, \"INTERNAL_ERROR\", \"Failed to complete sign-in.\");\n }\n return { kind: \"signedIn\" as const, session: idsAndTokens };\n });\n}\n\nasync function handleOAuthProvider(\n ctx: EnrichedActionCtx,\n provider: OAuthMaterializedConfig,\n args: {\n params?: SignInParams;\n verifier?: string;\n },\n options: {\n allowExtraProviders: boolean;\n authSiteUrl?: string;\n },\n): Promise<SignInSessionResult<SessionInfo<AuthTokens> | null> | SignInRedirectResult> {\n return withSpan(`convex-auth.signin.oauth`, { provider: provider.id }, async () => {\n if (args.params?.code !== undefined) {\n let result;\n try {\n result = await callVerifyCodeAndSignIn(ctx, {\n params: args.params as SignInParams,\n verifier: args.verifier,\n createSession: true,\n generateTokens: true,\n allowExtraProviders: options.allowExtraProviders,\n });\n } catch (error) {\n throw asConvexError(error, \"INTERNAL_ERROR\", \"Failed to verify OAuth sign-in.\");\n }\n return {\n kind: \"signedIn\" as const,\n session: result,\n };\n }\n\n const authSiteUrl = options.authSiteUrl ?? authUrlFromEnv();\n const redirect = new URL(`${authSiteUrl.replace(/\\/$/, \"\")}/signin/${provider.id}`);\n let verifier: string;\n try {\n verifier = await callVerifier(ctx);\n } catch (error) {\n throw asConvexError(error, \"INTERNAL_ERROR\", \"Failed to create verifier.\");\n }\n redirect.searchParams.set(\"code\", verifier);\n\n if (args.params?.redirectTo !== undefined) {\n if (typeof args.params.redirectTo !== \"string\") {\n throw toConvexError(\n authFlowError(\n \"INVALID_REDIRECT\",\n `Expected \\`redirectTo\\` to be a string, got ${describeUnknown(args.params.redirectTo)}`,\n ),\n );\n }\n redirect.searchParams.set(\"redirectTo\", args.params.redirectTo);\n }\n\n return {\n kind: \"redirect\" as const,\n redirect: redirect.toString(),\n verifier,\n };\n });\n}\n\nasync function handleConnectionProvider(\n ctx: EnrichedActionCtx,\n args: {\n params?: SignInParams;\n },\n options: {\n resolveConnectionProtocol?: (\n ctx: EnrichedActionCtx,\n connectionId: string,\n ) => Promise<\"oidc\" | \"saml\">;\n authSiteUrl?: string;\n },\n): Promise<{ kind: \"redirect\"; redirect: string; verifier: string }> {\n return withSpan(\"convex-auth.signin.connection\", {}, async () => {\n const normalizedParams = normalizeVerificationParams(args.params);\n const connectionId = normalizedParams.connectionId;\n if (!connectionId || typeof connectionId !== \"string\") {\n throw toConvexError(\n authFlowError(\"SIGN_IN_MISSING_PARAMS\", \"connectionId is required for Connection sign-in.\"),\n );\n }\n\n let protocol: \"oidc\" | \"saml\" =\n (normalizedParams.protocol === \"oidc\" || normalizedParams.protocol === \"saml\"\n ? normalizedParams.protocol\n : undefined) ??\n (options.resolveConnectionProtocol\n ? await (async () => {\n try {\n return await options.resolveConnectionProtocol!(ctx, connectionId);\n } catch (error) {\n throw asConvexError(\n error,\n \"INTERNAL_ERROR\",\n \"Failed to resolve Connection protocol.\",\n );\n }\n })()\n : \"oidc\");\n\n log(\"DEBUG\", \"[group-connection] signin:resolved\", {\n connectionId,\n protocol,\n redirectTo: typeof args.params?.redirectTo === \"string\" ? args.params.redirectTo : undefined,\n });\n\n if (protocol !== \"oidc\" && protocol !== \"saml\") {\n throw toConvexError(\n authFlowError(\n \"SIGN_IN_MISSING_PARAMS\",\n `Invalid Connection protocol: ${protocol as string}. Expected \"oidc\" or \"saml\".`,\n ),\n );\n }\n\n let verifier: string;\n try {\n verifier = await callVerifier(ctx);\n } catch (error) {\n throw asConvexError(error, \"INTERNAL_ERROR\", \"Failed to create verifier.\");\n }\n const siteUrl = options.authSiteUrl ?? authUrlFromEnv();\n const redirect = new URL(\n `${siteUrl.replace(/\\/$/, \"\")}/connections/${connectionId}/${protocol}/signin`,\n );\n redirect.searchParams.set(\"code\", verifier);\n\n if (typeof args.params?.redirectTo === \"string\") {\n redirect.searchParams.set(\"redirectTo\", args.params.redirectTo);\n }\n if (typeof normalizedParams.loginHint === \"string\") {\n redirect.searchParams.set(\"loginHint\", normalizedParams.loginHint);\n }\n log(\"DEBUG\", \"[group-connection] signin:redirect\", {\n connectionId,\n protocol,\n redirect: redirect.toString(),\n });\n\n return {\n kind: \"redirect\" as const,\n redirect: redirect.toString(),\n verifier,\n };\n });\n}\n"],"mappings":"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"}
|
package/dist/server/tokens.js
CHANGED
|
@@ -149,6 +149,7 @@ async function generateToken(args, config) {
|
|
|
149
149
|
const claims = {
|
|
150
150
|
sub: args.identity.subject,
|
|
151
151
|
sid: args.identity.sessionId,
|
|
152
|
+
session_epoch: args.identity.sessionEpoch,
|
|
152
153
|
...args.identity.name !== void 0 ? { name: args.identity.name } : null,
|
|
153
154
|
...args.identity.email !== void 0 ? { email: args.identity.email } : null,
|
|
154
155
|
...args.identity.emailVerified !== void 0 ? { email_verified: args.identity.emailVerified } : null,
|