@robelest/convex-auth 0.0.4-preview.2 → 0.0.4-preview.21
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 +67 -26
- package/dist/authorization/index.d.ts +63 -0
- package/dist/authorization/index.d.ts.map +1 -0
- package/dist/authorization/index.js +63 -0
- package/dist/authorization/index.js.map +1 -0
- package/dist/bin.js +6185 -0
- package/dist/client/core/types.d.ts +20 -0
- package/dist/client/core/types.d.ts.map +1 -0
- package/dist/client/index.d.ts +2 -299
- package/dist/client/index.d.ts.map +1 -1
- package/dist/client/index.js +407 -534
- package/dist/client/index.js.map +1 -1
- package/dist/component/_generated/api.d.ts +42 -0
- package/dist/component/_generated/api.d.ts.map +1 -1
- package/dist/component/_generated/api.js.map +1 -1
- package/dist/component/_generated/component.d.ts +2546 -90
- package/dist/component/_generated/component.d.ts.map +1 -1
- package/dist/component/client/core/types.d.ts +2 -0
- package/dist/component/client/index.d.ts +2 -0
- package/dist/component/convex.config.d.ts +2 -2
- package/dist/component/functions.d.ts +11 -9
- package/dist/component/functions.d.ts.map +1 -1
- package/dist/component/functions.js.map +1 -1
- package/dist/component/index.d.ts +7 -11
- package/dist/component/index.js +2 -3
- package/dist/component/model.d.ts +153 -0
- package/dist/component/model.d.ts.map +1 -0
- package/dist/component/model.js +349 -0
- package/dist/component/model.js.map +1 -0
- package/dist/component/providers/anonymous.d.ts +54 -0
- package/dist/component/providers/anonymous.d.ts.map +1 -0
- package/dist/component/providers/credentials.d.ts +5 -5
- package/dist/component/providers/credentials.d.ts.map +1 -1
- package/dist/component/providers/device.d.ts +67 -0
- package/dist/component/providers/device.d.ts.map +1 -0
- package/dist/component/providers/email.d.ts +62 -0
- package/dist/component/providers/email.d.ts.map +1 -0
- package/dist/component/providers/oauth.d.ts.map +1 -1
- package/dist/component/providers/oauth.js.map +1 -1
- package/dist/component/providers/passkey.d.ts +57 -0
- package/dist/component/providers/passkey.d.ts.map +1 -0
- package/dist/component/providers/password.d.ts +88 -0
- package/dist/component/providers/password.d.ts.map +1 -0
- package/dist/component/providers/phone.d.ts +48 -0
- package/dist/component/providers/phone.d.ts.map +1 -0
- package/dist/component/providers/sso.d.ts +50 -0
- package/dist/component/providers/sso.d.ts.map +1 -0
- package/dist/component/providers/totp.d.ts +45 -0
- package/dist/component/providers/totp.d.ts.map +1 -0
- package/dist/component/public/enterprise/audit.d.ts +73 -0
- package/dist/component/public/enterprise/audit.d.ts.map +1 -0
- package/dist/component/public/enterprise/audit.js +108 -0
- package/dist/component/public/enterprise/audit.js.map +1 -0
- package/dist/component/public/enterprise/core.d.ts +176 -0
- package/dist/component/public/enterprise/core.d.ts.map +1 -0
- package/dist/component/public/enterprise/core.js +292 -0
- package/dist/component/public/enterprise/core.js.map +1 -0
- package/dist/component/public/enterprise/domains.d.ts +174 -0
- package/dist/component/public/enterprise/domains.d.ts.map +1 -0
- package/dist/component/public/enterprise/domains.js +271 -0
- package/dist/component/public/enterprise/domains.js.map +1 -0
- package/dist/component/public/enterprise/scim.d.ts +245 -0
- package/dist/component/public/enterprise/scim.d.ts.map +1 -0
- package/dist/component/public/enterprise/scim.js +344 -0
- package/dist/component/public/enterprise/scim.js.map +1 -0
- package/dist/component/public/enterprise/secrets.d.ts +78 -0
- package/dist/component/public/enterprise/secrets.d.ts.map +1 -0
- package/dist/component/public/enterprise/secrets.js +118 -0
- package/dist/component/public/enterprise/secrets.js.map +1 -0
- package/dist/component/public/enterprise/webhooks.d.ts +211 -0
- package/dist/component/public/enterprise/webhooks.d.ts.map +1 -0
- package/dist/component/public/enterprise/webhooks.js +300 -0
- package/dist/component/public/enterprise/webhooks.js.map +1 -0
- package/dist/component/public/factors/devices.d.ts +157 -0
- package/dist/component/public/factors/devices.d.ts.map +1 -0
- package/dist/component/public/factors/devices.js +216 -0
- package/dist/component/public/factors/devices.js.map +1 -0
- package/dist/component/public/factors/passkeys.d.ts +175 -0
- package/dist/component/public/factors/passkeys.d.ts.map +1 -0
- package/dist/component/public/factors/passkeys.js +238 -0
- package/dist/component/public/factors/passkeys.js.map +1 -0
- package/dist/component/public/factors/totp.d.ts +189 -0
- package/dist/component/public/factors/totp.d.ts.map +1 -0
- package/dist/component/public/factors/totp.js +254 -0
- package/dist/component/public/factors/totp.js.map +1 -0
- package/dist/component/public/groups/core.d.ts +137 -0
- package/dist/component/public/groups/core.d.ts.map +1 -0
- package/dist/component/public/groups/core.js +321 -0
- package/dist/component/public/groups/core.js.map +1 -0
- package/dist/component/public/groups/invites.d.ts +217 -0
- package/dist/component/public/groups/invites.d.ts.map +1 -0
- package/dist/component/public/groups/invites.js +457 -0
- package/dist/component/public/groups/invites.js.map +1 -0
- package/dist/component/public/groups/members.d.ts +204 -0
- package/dist/component/public/groups/members.d.ts.map +1 -0
- package/dist/component/public/groups/members.js +355 -0
- package/dist/component/public/groups/members.js.map +1 -0
- package/dist/component/public/identity/accounts.d.ts +147 -0
- package/dist/component/public/identity/accounts.d.ts.map +1 -0
- package/dist/component/public/identity/accounts.js +200 -0
- package/dist/component/public/identity/accounts.js.map +1 -0
- package/dist/component/public/identity/codes.d.ts +104 -0
- package/dist/component/public/identity/codes.d.ts.map +1 -0
- package/dist/component/public/identity/codes.js +140 -0
- package/dist/component/public/identity/codes.js.map +1 -0
- package/dist/component/public/identity/sessions.d.ts +128 -0
- package/dist/component/public/identity/sessions.d.ts.map +1 -0
- package/dist/component/public/identity/sessions.js +192 -0
- package/dist/component/public/identity/sessions.js.map +1 -0
- package/dist/component/public/identity/tokens.d.ts +169 -0
- package/dist/component/public/identity/tokens.d.ts.map +1 -0
- package/dist/component/public/identity/tokens.js +227 -0
- package/dist/component/public/identity/tokens.js.map +1 -0
- package/dist/component/public/identity/users.d.ts +212 -0
- package/dist/component/public/identity/users.d.ts.map +1 -0
- package/dist/component/public/identity/users.js +311 -0
- package/dist/component/public/identity/users.js.map +1 -0
- package/dist/component/public/identity/verifiers.d.ts +116 -0
- package/dist/component/public/identity/verifiers.d.ts.map +1 -0
- package/dist/component/public/identity/verifiers.js +154 -0
- package/dist/component/public/identity/verifiers.js.map +1 -0
- package/dist/component/public/security/keys.d.ts +209 -0
- package/dist/component/public/security/keys.d.ts.map +1 -0
- package/dist/component/public/security/keys.js +319 -0
- package/dist/component/public/security/keys.js.map +1 -0
- package/dist/component/public/security/limits.d.ts +114 -0
- package/dist/component/public/security/limits.d.ts.map +1 -0
- package/dist/component/public/security/limits.js +169 -0
- package/dist/component/public/security/limits.js.map +1 -0
- package/dist/component/public.d.ts +24 -271
- package/dist/component/public.d.ts.map +1 -1
- package/dist/component/public.js +21 -1229
- package/dist/component/schema.d.ts +473 -110
- package/dist/component/schema.js +162 -73
- package/dist/component/schema.js.map +1 -1
- package/dist/component/server/auth.d.ts +318 -373
- package/dist/component/server/auth.d.ts.map +1 -1
- package/dist/component/server/auth.js +204 -123
- package/dist/component/server/auth.js.map +1 -1
- package/dist/component/server/authError.js +34 -0
- package/dist/component/server/authError.js.map +1 -0
- package/dist/component/server/{providers.js → config.js} +43 -12
- package/dist/component/server/config.js.map +1 -0
- package/dist/component/server/cookies.js +3 -0
- package/dist/component/server/cookies.js.map +1 -1
- package/dist/component/server/core.js +713 -0
- package/dist/component/server/core.js.map +1 -0
- package/dist/component/server/crypto.js +38 -0
- package/dist/component/server/crypto.js.map +1 -0
- package/dist/component/server/{implementation/db.js → db.js} +2 -1
- package/dist/component/server/db.js.map +1 -0
- package/dist/component/server/device.js +109 -0
- package/dist/component/server/device.js.map +1 -0
- package/dist/component/server/enterprise/config.js +46 -0
- package/dist/component/server/enterprise/config.js.map +1 -0
- package/dist/component/server/enterprise/domain.js +885 -0
- package/dist/component/server/enterprise/domain.js.map +1 -0
- package/dist/component/server/enterprise/http.js +766 -0
- package/dist/component/server/enterprise/http.js.map +1 -0
- package/dist/component/server/enterprise/oidc.js +248 -0
- package/dist/component/server/enterprise/oidc.js.map +1 -0
- package/dist/component/server/enterprise/policy.js +85 -0
- package/dist/component/server/enterprise/policy.js.map +1 -0
- package/dist/component/server/enterprise/saml.js +338 -0
- package/dist/component/server/enterprise/saml.js.map +1 -0
- package/dist/component/server/enterprise/scim.js +97 -0
- package/dist/component/server/enterprise/scim.js.map +1 -0
- package/dist/component/server/enterprise/shared.js +51 -0
- package/dist/component/server/enterprise/shared.js.map +1 -0
- package/dist/component/server/errors.d.ts +1 -0
- package/dist/component/server/errors.js +24 -16
- package/dist/component/server/errors.js.map +1 -1
- package/dist/component/server/http.js +288 -0
- package/dist/component/server/http.js.map +1 -0
- package/dist/component/server/identity.js +13 -0
- package/dist/component/server/identity.js.map +1 -0
- package/dist/{server/implementation → component/server}/keys.js +9 -31
- package/dist/component/server/keys.js.map +1 -0
- package/dist/component/server/limits.js +61 -0
- package/dist/component/server/limits.js.map +1 -0
- package/dist/component/server/mutations/account.js +44 -0
- package/dist/component/server/mutations/account.js.map +1 -0
- package/dist/component/server/{implementation/mutations → mutations}/code.js +7 -4
- package/dist/component/server/mutations/code.js.map +1 -0
- package/dist/component/server/mutations/invalidate.js +32 -0
- package/dist/component/server/mutations/invalidate.js.map +1 -0
- package/dist/component/server/mutations/oauth.js +110 -0
- package/dist/component/server/mutations/oauth.js.map +1 -0
- package/dist/component/server/mutations/refresh.js +119 -0
- package/dist/component/server/mutations/refresh.js.map +1 -0
- package/dist/component/server/mutations/register.js +83 -0
- package/dist/component/server/mutations/register.js.map +1 -0
- package/dist/component/server/mutations/retrieve.js +65 -0
- package/dist/component/server/mutations/retrieve.js.map +1 -0
- package/dist/component/server/mutations/signature.js +32 -0
- package/dist/component/server/mutations/signature.js.map +1 -0
- package/dist/component/server/{implementation/mutations → mutations}/signin.js +2 -2
- package/dist/component/server/mutations/signin.js.map +1 -0
- package/dist/component/server/mutations/signout.js +27 -0
- package/dist/component/server/mutations/signout.js.map +1 -0
- package/dist/component/server/mutations/store/refs.js +15 -0
- package/dist/component/server/mutations/store/refs.js.map +1 -0
- package/dist/component/server/mutations/store.js +85 -0
- package/dist/component/server/mutations/store.js.map +1 -0
- package/dist/component/server/mutations/verifier.js +18 -0
- package/dist/component/server/mutations/verifier.js.map +1 -0
- package/dist/component/server/mutations/verify.js +98 -0
- package/dist/component/server/mutations/verify.js.map +1 -0
- package/dist/component/server/oauth.js +106 -60
- package/dist/component/server/oauth.js.map +1 -1
- package/dist/component/server/passkey.js +328 -0
- package/dist/component/server/passkey.js.map +1 -0
- package/dist/{server/implementation → component/server}/redirects.js +13 -11
- package/dist/component/server/redirects.js.map +1 -0
- package/dist/component/server/refresh.js +96 -0
- package/dist/component/server/refresh.js.map +1 -0
- package/dist/component/server/runtime.d.ts +136 -0
- package/dist/component/server/runtime.d.ts.map +1 -0
- package/dist/component/server/runtime.js +413 -0
- package/dist/component/server/runtime.js.map +1 -0
- package/dist/{server/implementation → component/server}/sessions.js +14 -8
- package/dist/component/server/sessions.js.map +1 -0
- package/dist/component/server/signin.js +201 -0
- package/dist/component/server/signin.js.map +1 -0
- package/dist/component/server/tokens.js +17 -0
- package/dist/component/server/tokens.js.map +1 -0
- package/dist/component/server/totp.js +148 -0
- package/dist/component/server/totp.js.map +1 -0
- package/dist/component/server/types.d.ts +387 -298
- package/dist/component/server/types.d.ts.map +1 -1
- package/dist/component/server/{implementation/types.js → types.js} +1 -1
- package/dist/component/server/types.js.map +1 -0
- package/dist/component/server/{implementation/users.js → users.js} +54 -35
- package/dist/component/server/users.js.map +1 -0
- package/dist/component/server/utils.js +110 -4
- package/dist/component/server/utils.js.map +1 -1
- package/dist/core/types.d.ts +369 -0
- package/dist/core/types.d.ts.map +1 -0
- package/dist/factors/device.js +105 -0
- package/dist/factors/device.js.map +1 -0
- package/dist/factors/passkey.js +181 -0
- package/dist/factors/passkey.js.map +1 -0
- package/dist/factors/totp.js +122 -0
- package/dist/factors/totp.js.map +1 -0
- package/dist/providers/anonymous.d.ts +3 -9
- package/dist/providers/anonymous.d.ts.map +1 -1
- package/dist/providers/anonymous.js +1 -18
- package/dist/providers/anonymous.js.map +1 -1
- package/dist/providers/credentials.d.ts +8 -10
- package/dist/providers/credentials.d.ts.map +1 -1
- package/dist/providers/credentials.js +3 -5
- package/dist/providers/credentials.js.map +1 -1
- package/dist/providers/device.d.ts +18 -10
- package/dist/providers/device.d.ts.map +1 -1
- package/dist/providers/device.js +4 -8
- package/dist/providers/device.js.map +1 -1
- package/dist/providers/email.d.ts +50 -23
- package/dist/providers/email.d.ts.map +1 -1
- package/dist/providers/email.js +58 -34
- package/dist/providers/email.js.map +1 -1
- package/dist/providers/index.d.ts +7 -3
- package/dist/providers/index.js +4 -1
- package/dist/providers/oauth.d.ts.map +1 -1
- package/dist/providers/oauth.js.map +1 -1
- package/dist/providers/passkey.d.ts +12 -9
- package/dist/providers/passkey.d.ts.map +1 -1
- package/dist/providers/passkey.js +1 -7
- package/dist/providers/passkey.js.map +1 -1
- package/dist/providers/password.d.ts +6 -12
- package/dist/providers/password.d.ts.map +1 -1
- package/dist/providers/password.js +189 -89
- package/dist/providers/password.js.map +1 -1
- package/dist/providers/phone.d.ts +40 -11
- package/dist/providers/phone.d.ts.map +1 -1
- package/dist/providers/phone.js +52 -21
- package/dist/providers/phone.js.map +1 -1
- package/dist/providers/sso.d.ts +50 -0
- package/dist/providers/sso.d.ts.map +1 -0
- package/dist/providers/sso.js +34 -0
- package/dist/providers/sso.js.map +1 -0
- package/dist/providers/totp.d.ts +12 -9
- package/dist/providers/totp.d.ts.map +1 -1
- package/dist/providers/totp.js +1 -7
- package/dist/providers/totp.js.map +1 -1
- package/dist/runtime/browser.js +68 -0
- package/dist/runtime/browser.js.map +1 -0
- package/dist/runtime/invite.js +51 -0
- package/dist/runtime/invite.js.map +1 -0
- package/dist/runtime/proxy.js +70 -0
- package/dist/runtime/proxy.js.map +1 -0
- package/dist/runtime/storage.js +37 -0
- package/dist/runtime/storage.js.map +1 -0
- package/dist/server/auth.d.ts +335 -370
- package/dist/server/auth.d.ts.map +1 -1
- package/dist/server/auth.js +204 -123
- package/dist/server/auth.js.map +1 -1
- package/dist/server/authError.d.ts +46 -0
- package/dist/server/authError.d.ts.map +1 -0
- package/dist/server/authError.js +34 -0
- package/dist/server/authError.js.map +1 -0
- package/dist/server/config.d.ts +1 -0
- package/dist/server/{providers.js → config.js} +43 -12
- package/dist/server/config.js.map +1 -0
- package/dist/server/cookies.d.ts +1 -38
- package/dist/server/cookies.js +3 -0
- package/dist/server/cookies.js.map +1 -1
- package/dist/server/core.d.ts +1436 -0
- package/dist/server/core.d.ts.map +1 -0
- package/dist/server/core.js +713 -0
- package/dist/server/core.js.map +1 -0
- package/dist/server/crypto.d.ts +8 -0
- package/dist/server/crypto.d.ts.map +1 -0
- package/dist/server/crypto.js +38 -0
- package/dist/server/crypto.js.map +1 -0
- package/dist/server/db.d.ts +1 -0
- package/dist/server/{implementation/db.js → db.js} +2 -1
- package/dist/server/db.js.map +1 -0
- package/dist/server/device.d.ts +1 -0
- package/dist/server/device.js +109 -0
- package/dist/server/device.js.map +1 -0
- package/dist/server/enterprise/config.d.ts +1 -0
- package/dist/server/enterprise/config.js +46 -0
- package/dist/server/enterprise/config.js.map +1 -0
- package/dist/server/enterprise/domain.d.ts +409 -0
- package/dist/server/enterprise/domain.d.ts.map +1 -0
- package/dist/server/enterprise/domain.js +885 -0
- package/dist/server/enterprise/domain.js.map +1 -0
- package/dist/server/enterprise/http.d.ts +26 -0
- package/dist/server/enterprise/http.d.ts.map +1 -0
- package/dist/server/enterprise/http.js +766 -0
- package/dist/server/enterprise/http.js.map +1 -0
- package/dist/server/enterprise/oidc.d.ts +1 -0
- package/dist/server/enterprise/oidc.js +248 -0
- package/dist/server/enterprise/oidc.js.map +1 -0
- package/dist/server/enterprise/policy.d.ts +1 -0
- package/dist/server/enterprise/policy.js +85 -0
- package/dist/server/enterprise/policy.js.map +1 -0
- package/dist/server/enterprise/saml.d.ts +1 -0
- package/dist/server/enterprise/saml.js +338 -0
- package/dist/server/enterprise/saml.js.map +1 -0
- package/dist/server/enterprise/scim.d.ts +1 -0
- package/dist/server/enterprise/scim.js +97 -0
- package/dist/server/enterprise/scim.js.map +1 -0
- package/dist/server/enterprise/shared.d.ts +5 -0
- package/dist/server/enterprise/shared.d.ts.map +1 -0
- package/dist/server/enterprise/shared.js +51 -0
- package/dist/server/enterprise/shared.js.map +1 -0
- package/dist/server/enterprise/validators.d.ts +1 -0
- package/dist/server/enterprise/validators.js +60 -0
- package/dist/server/enterprise/validators.js.map +1 -0
- package/dist/server/errors.d.ts +33 -1
- package/dist/server/errors.d.ts.map +1 -1
- package/dist/server/errors.js +44 -1
- package/dist/server/errors.js.map +1 -1
- package/dist/server/http.d.ts +59 -0
- package/dist/server/http.d.ts.map +1 -0
- package/dist/server/http.js +288 -0
- package/dist/server/http.js.map +1 -0
- package/dist/server/identity.d.ts +1 -0
- package/dist/server/identity.js +13 -0
- package/dist/server/identity.js.map +1 -0
- package/dist/server/index.d.ts +4 -182
- package/dist/server/index.js +4 -376
- package/dist/server/keys.d.ts +1 -0
- package/dist/{component/server/implementation → server}/keys.js +9 -31
- package/dist/server/keys.js.map +1 -0
- package/dist/server/limits.d.ts +1 -0
- package/dist/server/limits.js +61 -0
- package/dist/server/limits.js.map +1 -0
- package/dist/server/mounts.d.ts +647 -0
- package/dist/server/mounts.d.ts.map +1 -0
- package/dist/server/mounts.js +643 -0
- package/dist/server/mounts.js.map +1 -0
- package/dist/server/mutations/account.d.ts +30 -0
- package/dist/server/mutations/account.d.ts.map +1 -0
- package/dist/server/mutations/account.js +44 -0
- package/dist/server/mutations/account.js.map +1 -0
- package/dist/server/mutations/code.d.ts +30 -0
- package/dist/server/mutations/code.d.ts.map +1 -0
- package/dist/server/{implementation/mutations → mutations}/code.js +7 -4
- package/dist/server/mutations/code.js.map +1 -0
- package/dist/server/mutations/index.d.ts +14 -0
- package/dist/server/mutations/index.js +15 -0
- package/dist/server/mutations/invalidate.d.ts +20 -0
- package/dist/server/mutations/invalidate.d.ts.map +1 -0
- package/dist/server/mutations/invalidate.js +32 -0
- package/dist/server/mutations/invalidate.js.map +1 -0
- package/dist/server/mutations/oauth.d.ts +28 -0
- package/dist/server/mutations/oauth.d.ts.map +1 -0
- package/dist/server/mutations/oauth.js +110 -0
- package/dist/server/mutations/oauth.js.map +1 -0
- package/dist/server/mutations/refresh.d.ts +21 -0
- package/dist/server/mutations/refresh.d.ts.map +1 -0
- package/dist/server/mutations/refresh.js +119 -0
- package/dist/server/mutations/refresh.js.map +1 -0
- package/dist/server/mutations/register.d.ts +38 -0
- package/dist/server/mutations/register.d.ts.map +1 -0
- package/dist/server/mutations/register.js +83 -0
- package/dist/server/mutations/register.js.map +1 -0
- package/dist/server/mutations/retrieve.d.ts +33 -0
- package/dist/server/mutations/retrieve.d.ts.map +1 -0
- package/dist/server/mutations/retrieve.js +65 -0
- package/dist/server/mutations/retrieve.js.map +1 -0
- package/dist/server/mutations/signature.d.ts +22 -0
- package/dist/server/mutations/signature.d.ts.map +1 -0
- package/dist/server/mutations/signature.js +32 -0
- package/dist/server/mutations/signature.js.map +1 -0
- package/dist/server/mutations/signin.d.ts +22 -0
- package/dist/server/mutations/signin.d.ts.map +1 -0
- package/dist/server/{implementation/mutations → mutations}/signin.js +2 -2
- package/dist/server/mutations/signin.js.map +1 -0
- package/dist/server/mutations/signout.d.ts +16 -0
- package/dist/server/mutations/signout.d.ts.map +1 -0
- package/dist/server/mutations/signout.js +27 -0
- package/dist/server/mutations/signout.js.map +1 -0
- package/dist/server/mutations/store/refs.d.ts +12 -0
- package/dist/server/mutations/store/refs.d.ts.map +1 -0
- package/dist/server/mutations/store/refs.js +15 -0
- package/dist/server/mutations/store/refs.js.map +1 -0
- package/dist/server/mutations/store.d.ts +306 -0
- package/dist/server/mutations/store.d.ts.map +1 -0
- package/dist/server/mutations/store.js +85 -0
- package/dist/server/mutations/store.js.map +1 -0
- package/dist/server/mutations/verifier.d.ts +13 -0
- package/dist/server/mutations/verifier.d.ts.map +1 -0
- package/dist/server/mutations/verifier.js +18 -0
- package/dist/server/mutations/verifier.js.map +1 -0
- package/dist/server/mutations/verify.d.ts +26 -0
- package/dist/server/mutations/verify.d.ts.map +1 -0
- package/dist/server/mutations/verify.js +98 -0
- package/dist/server/mutations/verify.js.map +1 -0
- package/dist/server/oauth.d.ts +1 -48
- package/dist/server/oauth.js +107 -64
- package/dist/server/oauth.js.map +1 -1
- package/dist/server/passkey.d.ts +27 -0
- package/dist/server/passkey.d.ts.map +1 -0
- package/dist/server/passkey.js +328 -0
- package/dist/server/passkey.js.map +1 -0
- package/dist/server/redirects.d.ts +1 -0
- package/dist/{component/server/implementation → server}/redirects.js +13 -11
- package/dist/server/redirects.js.map +1 -0
- package/dist/server/refresh.d.ts +1 -0
- package/dist/server/refresh.js +96 -0
- package/dist/server/refresh.js.map +1 -0
- package/dist/server/runtime.d.ts +136 -0
- package/dist/server/runtime.d.ts.map +1 -0
- package/dist/server/runtime.js +413 -0
- package/dist/server/runtime.js.map +1 -0
- package/dist/server/sessions.d.ts +1 -0
- package/dist/{component/server/implementation → server}/sessions.js +14 -8
- package/dist/server/sessions.js.map +1 -0
- package/dist/server/signin.d.ts +1 -0
- package/dist/server/signin.js +201 -0
- package/dist/server/signin.js.map +1 -0
- package/dist/server/ssr.d.ts +226 -0
- package/dist/server/ssr.d.ts.map +1 -0
- package/dist/server/ssr.js +786 -0
- package/dist/server/ssr.js.map +1 -0
- package/dist/server/templates.d.ts +1 -21
- package/dist/server/templates.js +2 -1
- package/dist/server/templates.js.map +1 -1
- package/dist/server/tokens.d.ts +1 -0
- package/dist/server/tokens.js +17 -0
- package/dist/server/tokens.js.map +1 -0
- package/dist/server/totp.d.ts +1 -0
- package/dist/server/totp.js +148 -0
- package/dist/server/totp.js.map +1 -0
- package/dist/server/types.d.ts +498 -306
- package/dist/server/types.d.ts.map +1 -1
- package/dist/server/types.js +108 -1
- package/dist/server/types.js.map +1 -0
- package/dist/server/users.d.ts +1 -0
- package/dist/server/{implementation/users.js → users.js} +54 -35
- package/dist/server/users.js.map +1 -0
- package/dist/server/utils.d.ts +1 -6
- package/dist/server/utils.js +110 -4
- package/dist/server/utils.js.map +1 -1
- package/package.json +49 -46
- package/src/authorization/index.ts +83 -0
- package/src/cli/bin.ts +5 -0
- package/src/cli/command.ts +6 -5
- package/src/cli/index.ts +456 -248
- package/src/cli/keys.ts +3 -0
- package/src/client/core/types.ts +437 -0
- package/src/client/factors/device.ts +160 -0
- package/src/client/factors/passkey.ts +282 -0
- package/src/client/factors/totp.ts +150 -0
- package/src/client/index.ts +745 -989
- package/src/client/runtime/browser.ts +112 -0
- package/src/client/runtime/invite.ts +65 -0
- package/src/client/runtime/proxy.ts +111 -0
- package/src/client/runtime/storage.ts +79 -0
- package/src/component/_generated/api.ts +42 -0
- package/src/component/_generated/component.ts +3123 -102
- package/src/component/functions.ts +38 -22
- package/src/component/index.ts +10 -20
- package/src/component/model.ts +449 -0
- package/src/component/public/enterprise/audit.ts +120 -0
- package/src/component/public/enterprise/core.ts +354 -0
- package/src/component/public/enterprise/domains.ts +323 -0
- package/src/component/public/enterprise/scim.ts +396 -0
- package/src/component/public/enterprise/secrets.ts +132 -0
- package/src/component/public/enterprise/webhooks.ts +306 -0
- package/src/component/public/factors/devices.ts +223 -0
- package/src/component/public/factors/passkeys.ts +242 -0
- package/src/component/public/factors/totp.ts +258 -0
- package/src/component/public/groups/core.ts +481 -0
- package/src/component/public/groups/invites.ts +602 -0
- package/src/component/public/groups/members.ts +409 -0
- package/src/component/public/identity/accounts.ts +206 -0
- package/src/component/public/identity/codes.ts +148 -0
- package/src/component/public/identity/sessions.ts +209 -0
- package/src/component/public/identity/tokens.ts +250 -0
- package/src/component/public/identity/users.ts +354 -0
- package/src/component/public/identity/verifiers.ts +157 -0
- package/src/component/public/security/keys.ts +365 -0
- package/src/component/public/security/limits.ts +173 -0
- package/src/component/public.ts +26 -1766
- package/src/component/schema.ts +273 -100
- package/src/providers/anonymous.ts +10 -20
- package/src/providers/credentials.ts +14 -22
- package/src/providers/device.ts +3 -14
- package/src/providers/email.ts +83 -47
- package/src/providers/index.ts +7 -0
- package/src/providers/oauth.ts +5 -3
- package/src/providers/passkey.ts +0 -13
- package/src/providers/password.ts +307 -130
- package/src/providers/phone.ts +81 -37
- package/src/providers/sso.ts +54 -0
- package/src/providers/totp.ts +0 -13
- package/src/samlify.d.ts +53 -0
- package/src/server/auth.ts +701 -247
- package/src/server/authError.ts +44 -0
- package/src/server/{providers.ts → config.ts} +84 -15
- package/src/server/cookies.ts +8 -1
- package/src/server/core.ts +2095 -0
- package/src/server/crypto.ts +88 -0
- package/src/server/{implementation/db.ts → db.ts} +90 -15
- package/src/server/device.ts +221 -0
- package/src/server/enterprise/config.ts +51 -0
- package/src/server/enterprise/domain.ts +1751 -0
- package/src/server/enterprise/http.ts +1324 -0
- package/src/server/enterprise/oidc.ts +500 -0
- package/src/server/enterprise/policy.ts +128 -0
- package/src/server/enterprise/saml.ts +578 -0
- package/src/server/enterprise/scim.ts +135 -0
- package/src/server/enterprise/shared.ts +134 -0
- package/src/server/enterprise/validators.ts +93 -0
- package/src/server/errors.ts +130 -119
- package/src/server/http.ts +531 -0
- package/src/server/identity.ts +18 -0
- package/src/server/index.ts +32 -650
- package/src/server/{implementation/keys.ts → keys.ts} +16 -44
- package/src/server/limits.ts +134 -0
- package/src/server/mounts.ts +948 -0
- package/src/server/mutations/account.ts +76 -0
- package/src/server/{implementation/mutations → mutations}/code.ts +22 -11
- package/src/server/mutations/index.ts +13 -0
- package/src/server/mutations/invalidate.ts +50 -0
- package/src/server/mutations/oauth.ts +237 -0
- package/src/server/mutations/refresh.ts +298 -0
- package/src/server/mutations/register.ts +200 -0
- package/src/server/mutations/retrieve.ts +109 -0
- package/src/server/mutations/signature.ts +50 -0
- package/src/server/{implementation/mutations → mutations}/signin.ts +9 -7
- package/src/server/mutations/signout.ts +43 -0
- package/src/server/mutations/store/refs.ts +10 -0
- package/src/server/mutations/store.ts +138 -0
- package/src/server/mutations/verifier.ts +34 -0
- package/src/server/mutations/verify.ts +202 -0
- package/src/server/oauth.ts +243 -131
- package/src/server/passkey.ts +784 -0
- package/src/server/{implementation/redirects.ts → redirects.ts} +21 -16
- package/src/server/refresh.ts +222 -0
- package/src/server/runtime.ts +880 -0
- package/src/server/{implementation/sessions.ts → sessions.ts} +33 -25
- package/src/server/signin.ts +438 -0
- package/src/server/ssr.ts +1764 -0
- package/src/server/templates.ts +8 -3
- package/src/server/{implementation/tokens.ts → tokens.ts} +11 -5
- package/src/server/totp.ts +349 -0
- package/src/server/types.ts +972 -207
- package/src/server/{implementation/users.ts → users.ts} +129 -75
- package/src/server/utils.ts +192 -5
- package/src/test.ts +28 -4
- package/dist/bin.cjs +0 -27757
- package/dist/component/providers/email.js +0 -47
- package/dist/component/providers/email.js.map +0 -1
- package/dist/component/public.js.map +0 -1
- package/dist/component/server/implementation/db.js.map +0 -1
- package/dist/component/server/implementation/device.js +0 -135
- package/dist/component/server/implementation/device.js.map +0 -1
- package/dist/component/server/implementation/index.d.ts +0 -870
- package/dist/component/server/implementation/index.d.ts.map +0 -1
- package/dist/component/server/implementation/index.js +0 -610
- package/dist/component/server/implementation/index.js.map +0 -1
- package/dist/component/server/implementation/keys.js.map +0 -1
- package/dist/component/server/implementation/mutations/account.js +0 -39
- package/dist/component/server/implementation/mutations/account.js.map +0 -1
- package/dist/component/server/implementation/mutations/code.js.map +0 -1
- package/dist/component/server/implementation/mutations/index.js +0 -70
- package/dist/component/server/implementation/mutations/index.js.map +0 -1
- package/dist/component/server/implementation/mutations/invalidate.js +0 -29
- package/dist/component/server/implementation/mutations/invalidate.js.map +0 -1
- package/dist/component/server/implementation/mutations/oauth.js +0 -51
- package/dist/component/server/implementation/mutations/oauth.js.map +0 -1
- package/dist/component/server/implementation/mutations/refresh.js +0 -85
- package/dist/component/server/implementation/mutations/refresh.js.map +0 -1
- package/dist/component/server/implementation/mutations/register.js +0 -65
- package/dist/component/server/implementation/mutations/register.js.map +0 -1
- package/dist/component/server/implementation/mutations/retrieve.js +0 -50
- package/dist/component/server/implementation/mutations/retrieve.js.map +0 -1
- package/dist/component/server/implementation/mutations/signature.js +0 -27
- package/dist/component/server/implementation/mutations/signature.js.map +0 -1
- package/dist/component/server/implementation/mutations/signin.js.map +0 -1
- package/dist/component/server/implementation/mutations/signout.js +0 -27
- package/dist/component/server/implementation/mutations/signout.js.map +0 -1
- package/dist/component/server/implementation/mutations/store.js +0 -12
- package/dist/component/server/implementation/mutations/store.js.map +0 -1
- package/dist/component/server/implementation/mutations/verifier.js +0 -16
- package/dist/component/server/implementation/mutations/verifier.js.map +0 -1
- package/dist/component/server/implementation/mutations/verify.js +0 -105
- package/dist/component/server/implementation/mutations/verify.js.map +0 -1
- package/dist/component/server/implementation/passkey.js +0 -307
- package/dist/component/server/implementation/passkey.js.map +0 -1
- package/dist/component/server/implementation/provider.js +0 -19
- package/dist/component/server/implementation/provider.js.map +0 -1
- package/dist/component/server/implementation/ratelimit.js +0 -48
- package/dist/component/server/implementation/ratelimit.js.map +0 -1
- package/dist/component/server/implementation/redirects.js.map +0 -1
- package/dist/component/server/implementation/refresh.js +0 -109
- package/dist/component/server/implementation/refresh.js.map +0 -1
- package/dist/component/server/implementation/sessions.js.map +0 -1
- package/dist/component/server/implementation/signin.js +0 -148
- package/dist/component/server/implementation/signin.js.map +0 -1
- package/dist/component/server/implementation/tokens.js +0 -15
- package/dist/component/server/implementation/tokens.js.map +0 -1
- package/dist/component/server/implementation/totp.js +0 -142
- package/dist/component/server/implementation/totp.js.map +0 -1
- package/dist/component/server/implementation/types.d.ts +0 -42
- package/dist/component/server/implementation/types.d.ts.map +0 -1
- package/dist/component/server/implementation/types.js.map +0 -1
- package/dist/component/server/implementation/users.js.map +0 -1
- package/dist/component/server/implementation/utils.js +0 -56
- package/dist/component/server/implementation/utils.js.map +0 -1
- package/dist/component/server/providers.js.map +0 -1
- package/dist/component/server/templates.js +0 -84
- package/dist/component/server/templates.js.map +0 -1
- package/dist/server/cookies.d.ts.map +0 -1
- package/dist/server/implementation/db.d.ts +0 -86
- package/dist/server/implementation/db.d.ts.map +0 -1
- package/dist/server/implementation/db.js.map +0 -1
- package/dist/server/implementation/device.d.ts +0 -30
- package/dist/server/implementation/device.d.ts.map +0 -1
- package/dist/server/implementation/device.js +0 -135
- package/dist/server/implementation/device.js.map +0 -1
- package/dist/server/implementation/index.d.ts +0 -870
- package/dist/server/implementation/index.d.ts.map +0 -1
- package/dist/server/implementation/index.js +0 -610
- package/dist/server/implementation/index.js.map +0 -1
- package/dist/server/implementation/keys.d.ts +0 -66
- package/dist/server/implementation/keys.d.ts.map +0 -1
- package/dist/server/implementation/keys.js.map +0 -1
- package/dist/server/implementation/mutations/account.d.ts +0 -27
- package/dist/server/implementation/mutations/account.d.ts.map +0 -1
- package/dist/server/implementation/mutations/account.js +0 -39
- package/dist/server/implementation/mutations/account.js.map +0 -1
- package/dist/server/implementation/mutations/code.d.ts +0 -29
- package/dist/server/implementation/mutations/code.d.ts.map +0 -1
- package/dist/server/implementation/mutations/code.js.map +0 -1
- package/dist/server/implementation/mutations/index.d.ts +0 -310
- package/dist/server/implementation/mutations/index.d.ts.map +0 -1
- package/dist/server/implementation/mutations/index.js +0 -70
- package/dist/server/implementation/mutations/index.js.map +0 -1
- package/dist/server/implementation/mutations/invalidate.d.ts +0 -18
- package/dist/server/implementation/mutations/invalidate.d.ts.map +0 -1
- package/dist/server/implementation/mutations/invalidate.js +0 -29
- package/dist/server/implementation/mutations/invalidate.js.map +0 -1
- package/dist/server/implementation/mutations/oauth.d.ts +0 -23
- package/dist/server/implementation/mutations/oauth.d.ts.map +0 -1
- package/dist/server/implementation/mutations/oauth.js +0 -51
- package/dist/server/implementation/mutations/oauth.js.map +0 -1
- package/dist/server/implementation/mutations/refresh.d.ts +0 -20
- package/dist/server/implementation/mutations/refresh.d.ts.map +0 -1
- package/dist/server/implementation/mutations/refresh.js +0 -85
- package/dist/server/implementation/mutations/refresh.js.map +0 -1
- package/dist/server/implementation/mutations/register.d.ts +0 -37
- package/dist/server/implementation/mutations/register.d.ts.map +0 -1
- package/dist/server/implementation/mutations/register.js +0 -65
- package/dist/server/implementation/mutations/register.js.map +0 -1
- package/dist/server/implementation/mutations/retrieve.d.ts +0 -31
- package/dist/server/implementation/mutations/retrieve.d.ts.map +0 -1
- package/dist/server/implementation/mutations/retrieve.js +0 -50
- package/dist/server/implementation/mutations/retrieve.js.map +0 -1
- package/dist/server/implementation/mutations/signature.d.ts +0 -19
- package/dist/server/implementation/mutations/signature.d.ts.map +0 -1
- package/dist/server/implementation/mutations/signature.js +0 -27
- package/dist/server/implementation/mutations/signature.js.map +0 -1
- package/dist/server/implementation/mutations/signin.d.ts +0 -21
- package/dist/server/implementation/mutations/signin.d.ts.map +0 -1
- package/dist/server/implementation/mutations/signin.js.map +0 -1
- package/dist/server/implementation/mutations/signout.d.ts +0 -14
- package/dist/server/implementation/mutations/signout.d.ts.map +0 -1
- package/dist/server/implementation/mutations/signout.js +0 -27
- package/dist/server/implementation/mutations/signout.js.map +0 -1
- package/dist/server/implementation/mutations/store.d.ts +0 -11
- package/dist/server/implementation/mutations/store.d.ts.map +0 -1
- package/dist/server/implementation/mutations/store.js +0 -12
- package/dist/server/implementation/mutations/store.js.map +0 -1
- package/dist/server/implementation/mutations/verifier.d.ts +0 -11
- package/dist/server/implementation/mutations/verifier.d.ts.map +0 -1
- package/dist/server/implementation/mutations/verifier.js +0 -16
- package/dist/server/implementation/mutations/verifier.js.map +0 -1
- package/dist/server/implementation/mutations/verify.d.ts +0 -25
- package/dist/server/implementation/mutations/verify.d.ts.map +0 -1
- package/dist/server/implementation/mutations/verify.js +0 -105
- package/dist/server/implementation/mutations/verify.js.map +0 -1
- package/dist/server/implementation/passkey.d.ts +0 -24
- package/dist/server/implementation/passkey.d.ts.map +0 -1
- package/dist/server/implementation/passkey.js +0 -307
- package/dist/server/implementation/passkey.js.map +0 -1
- package/dist/server/implementation/provider.d.ts +0 -10
- package/dist/server/implementation/provider.d.ts.map +0 -1
- package/dist/server/implementation/provider.js +0 -19
- package/dist/server/implementation/provider.js.map +0 -1
- package/dist/server/implementation/ratelimit.d.ts +0 -10
- package/dist/server/implementation/ratelimit.d.ts.map +0 -1
- package/dist/server/implementation/ratelimit.js +0 -48
- package/dist/server/implementation/ratelimit.js.map +0 -1
- package/dist/server/implementation/redirects.d.ts +0 -10
- package/dist/server/implementation/redirects.d.ts.map +0 -1
- package/dist/server/implementation/redirects.js.map +0 -1
- package/dist/server/implementation/refresh.d.ts +0 -37
- package/dist/server/implementation/refresh.d.ts.map +0 -1
- package/dist/server/implementation/refresh.js +0 -109
- package/dist/server/implementation/refresh.js.map +0 -1
- package/dist/server/implementation/sessions.d.ts +0 -29
- package/dist/server/implementation/sessions.d.ts.map +0 -1
- package/dist/server/implementation/sessions.js.map +0 -1
- package/dist/server/implementation/signin.d.ts +0 -55
- package/dist/server/implementation/signin.d.ts.map +0 -1
- package/dist/server/implementation/signin.js +0 -148
- package/dist/server/implementation/signin.js.map +0 -1
- package/dist/server/implementation/tokens.d.ts +0 -11
- package/dist/server/implementation/tokens.d.ts.map +0 -1
- package/dist/server/implementation/tokens.js +0 -15
- package/dist/server/implementation/tokens.js.map +0 -1
- package/dist/server/implementation/totp.d.ts +0 -31
- package/dist/server/implementation/totp.d.ts.map +0 -1
- package/dist/server/implementation/totp.js +0 -142
- package/dist/server/implementation/totp.js.map +0 -1
- package/dist/server/implementation/types.d.ts +0 -189
- package/dist/server/implementation/types.d.ts.map +0 -1
- package/dist/server/implementation/types.js +0 -97
- package/dist/server/implementation/types.js.map +0 -1
- package/dist/server/implementation/users.d.ts +0 -30
- package/dist/server/implementation/users.d.ts.map +0 -1
- package/dist/server/implementation/users.js.map +0 -1
- package/dist/server/implementation/utils.d.ts +0 -19
- package/dist/server/implementation/utils.d.ts.map +0 -1
- package/dist/server/implementation/utils.js +0 -56
- package/dist/server/implementation/utils.js.map +0 -1
- package/dist/server/index.d.ts.map +0 -1
- package/dist/server/index.js.map +0 -1
- package/dist/server/oauth.d.ts.map +0 -1
- package/dist/server/providers.d.ts +0 -72
- package/dist/server/providers.d.ts.map +0 -1
- package/dist/server/providers.js.map +0 -1
- package/dist/server/templates.d.ts.map +0 -1
- package/dist/server/utils.d.ts.map +0 -1
- package/dist/server/version.d.ts +0 -5
- package/dist/server/version.d.ts.map +0 -1
- package/dist/server/version.js +0 -6
- package/dist/server/version.js.map +0 -1
- package/src/cli/utils.ts +0 -248
- package/src/server/implementation/device.ts +0 -307
- package/src/server/implementation/index.ts +0 -1583
- package/src/server/implementation/mutations/account.ts +0 -50
- package/src/server/implementation/mutations/index.ts +0 -157
- package/src/server/implementation/mutations/invalidate.ts +0 -42
- package/src/server/implementation/mutations/oauth.ts +0 -73
- package/src/server/implementation/mutations/refresh.ts +0 -175
- package/src/server/implementation/mutations/register.ts +0 -100
- package/src/server/implementation/mutations/retrieve.ts +0 -79
- package/src/server/implementation/mutations/signature.ts +0 -39
- package/src/server/implementation/mutations/signout.ts +0 -35
- package/src/server/implementation/mutations/store.ts +0 -7
- package/src/server/implementation/mutations/verifier.ts +0 -24
- package/src/server/implementation/mutations/verify.ts +0 -194
- package/src/server/implementation/passkey.ts +0 -620
- package/src/server/implementation/provider.ts +0 -36
- package/src/server/implementation/ratelimit.ts +0 -79
- package/src/server/implementation/refresh.ts +0 -172
- package/src/server/implementation/signin.ts +0 -296
- package/src/server/implementation/totp.ts +0 -342
- package/src/server/implementation/types.ts +0 -444
- package/src/server/implementation/utils.ts +0 -91
- package/src/server/version.ts +0 -2
|
@@ -1,1583 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
Auth,
|
|
3
|
-
GenericActionCtx,
|
|
4
|
-
GenericDataModel,
|
|
5
|
-
HttpRouter,
|
|
6
|
-
actionGeneric,
|
|
7
|
-
httpActionGeneric,
|
|
8
|
-
internalMutationGeneric,
|
|
9
|
-
} from "convex/server";
|
|
10
|
-
import { ConvexError, GenericId, v } from "convex/values";
|
|
11
|
-
import { throwAuthError, isAuthError } from "../errors";
|
|
12
|
-
import { parse as parseCookies, serialize as serializeCookie } from "cookie";
|
|
13
|
-
import { redirectToParamCookie, useRedirectToParam } from "../cookies";
|
|
14
|
-
import type { FunctionReferenceFromExport } from "../types";
|
|
15
|
-
import {
|
|
16
|
-
configDefaults,
|
|
17
|
-
listAvailableProviders,
|
|
18
|
-
materializeProvider,
|
|
19
|
-
} from "../providers";
|
|
20
|
-
import {
|
|
21
|
-
AuthProviderConfig,
|
|
22
|
-
ConvexAuthConfig,
|
|
23
|
-
CorsConfig,
|
|
24
|
-
HttpKeyContext,
|
|
25
|
-
UserOrderBy,
|
|
26
|
-
UserWhere,
|
|
27
|
-
} from "../types";
|
|
28
|
-
import { requireEnv } from "../utils";
|
|
29
|
-
import {
|
|
30
|
-
ActionCtx,
|
|
31
|
-
MutationCtx,
|
|
32
|
-
KeyDoc,
|
|
33
|
-
} from "./types";
|
|
34
|
-
import type { Tokens } from "./types";
|
|
35
|
-
export type { Doc, Tokens } from "./types";
|
|
36
|
-
import {
|
|
37
|
-
LOG_LEVELS,
|
|
38
|
-
TOKEN_SUB_CLAIM_DIVIDER,
|
|
39
|
-
logError,
|
|
40
|
-
logWithLevel,
|
|
41
|
-
} from "./utils";
|
|
42
|
-
import { GetProviderOrThrowFunc } from "./provider";
|
|
43
|
-
import {
|
|
44
|
-
callCreateAccountFromCredentials,
|
|
45
|
-
callInvalidateSessions,
|
|
46
|
-
callModifyAccount,
|
|
47
|
-
callRetreiveAccountWithCredentials,
|
|
48
|
-
callSignOut,
|
|
49
|
-
callUserOAuth,
|
|
50
|
-
callVerifierSignature,
|
|
51
|
-
storeArgs,
|
|
52
|
-
storeImpl,
|
|
53
|
-
} from "./mutations/index";
|
|
54
|
-
import { signInImpl } from "./signin";
|
|
55
|
-
import { redirectAbsoluteUrl, setURLSearchParam } from "./redirects";
|
|
56
|
-
import {
|
|
57
|
-
generateApiKey,
|
|
58
|
-
hashApiKey,
|
|
59
|
-
buildScopeChecker,
|
|
60
|
-
validateScopes,
|
|
61
|
-
checkKeyRateLimit,
|
|
62
|
-
} from "./keys";
|
|
63
|
-
import {
|
|
64
|
-
createOAuthAuthorizationURL,
|
|
65
|
-
handleOAuthCallback,
|
|
66
|
-
} from "../oauth";
|
|
67
|
-
import type { OAuthMaterializedConfig } from "../types";
|
|
68
|
-
|
|
69
|
-
/**
|
|
70
|
-
* The type of the signIn Convex Action returned from the auth() helper.
|
|
71
|
-
*
|
|
72
|
-
* This type is exported for implementors of other client integrations.
|
|
73
|
-
* However it is not stable, and may change until this library reaches 1.0.
|
|
74
|
-
*/
|
|
75
|
-
export type SignInAction = FunctionReferenceFromExport<
|
|
76
|
-
ReturnType<typeof Auth>["signIn"]
|
|
77
|
-
>;
|
|
78
|
-
/**
|
|
79
|
-
* The type of the signOut Convex Action returned from the auth() helper.
|
|
80
|
-
*
|
|
81
|
-
* This type is exported for implementors of other client integrations.
|
|
82
|
-
* However it is not stable, and may change until this library reaches 1.0.
|
|
83
|
-
*/
|
|
84
|
-
export type SignOutAction = FunctionReferenceFromExport<
|
|
85
|
-
ReturnType<typeof Auth>["signOut"]
|
|
86
|
-
>;
|
|
87
|
-
/**
|
|
88
|
-
* Configure the Convex Auth library. Returns an object with
|
|
89
|
-
* functions and `auth` helper. You must export the functions
|
|
90
|
-
* from `convex/auth.ts` to make them callable:
|
|
91
|
-
*
|
|
92
|
-
* ```ts filename="convex/auth.ts"
|
|
93
|
-
* import { Auth } from "@robelest/convex-auth/component";
|
|
94
|
-
* import { components } from "./_generated/api";
|
|
95
|
-
*
|
|
96
|
-
* export const { auth, signIn, signOut, store } = Auth({
|
|
97
|
-
* component: components.auth,
|
|
98
|
-
* providers: [],
|
|
99
|
-
* });
|
|
100
|
-
* ```
|
|
101
|
-
*
|
|
102
|
-
* @returns An object with fields you should reexport from your
|
|
103
|
-
* `convex/auth.ts` file.
|
|
104
|
-
*/
|
|
105
|
-
export function Auth(config_: ConvexAuthConfig) {
|
|
106
|
-
const config = configDefaults(config_);
|
|
107
|
-
const hasOAuth = config.providers.some(
|
|
108
|
-
(provider) => provider.type === "oauth",
|
|
109
|
-
);
|
|
110
|
-
const getProvider = (id: string, allowExtraProviders: boolean = false) => {
|
|
111
|
-
return (
|
|
112
|
-
config.providers.find((provider) => provider.id === id) ??
|
|
113
|
-
(allowExtraProviders
|
|
114
|
-
? config.extraProviders.find((provider) => provider.id === id)
|
|
115
|
-
: undefined)
|
|
116
|
-
);
|
|
117
|
-
};
|
|
118
|
-
const getProviderOrThrow: GetProviderOrThrowFunc = (
|
|
119
|
-
id: string,
|
|
120
|
-
allowExtraProviders: boolean = false,
|
|
121
|
-
) => {
|
|
122
|
-
const provider = getProvider(id, allowExtraProviders);
|
|
123
|
-
if (provider === undefined) {
|
|
124
|
-
const detail =
|
|
125
|
-
`Provider \`${id}\` is not configured, ` +
|
|
126
|
-
`available providers are ${listAvailableProviders(config, allowExtraProviders)}.`;
|
|
127
|
-
logWithLevel(LOG_LEVELS.ERROR, detail);
|
|
128
|
-
throwAuthError("PROVIDER_NOT_CONFIGURED", detail, { provider: id });
|
|
129
|
-
}
|
|
130
|
-
return provider;
|
|
131
|
-
};
|
|
132
|
-
type ComponentCtx = Pick<
|
|
133
|
-
GenericActionCtx<GenericDataModel>,
|
|
134
|
-
"runQuery" | "runMutation"
|
|
135
|
-
>;
|
|
136
|
-
type ComponentReadCtx = Pick<GenericActionCtx<GenericDataModel>, "runQuery">;
|
|
137
|
-
type ComponentAuthReadCtx = ComponentReadCtx & { auth: Auth };
|
|
138
|
-
type AccountCredentials = { id: string; secret?: string };
|
|
139
|
-
type CreateAccountArgs = {
|
|
140
|
-
provider: string;
|
|
141
|
-
account: AccountCredentials;
|
|
142
|
-
profile: Record<string, unknown>;
|
|
143
|
-
shouldLinkViaEmail?: boolean;
|
|
144
|
-
shouldLinkViaPhone?: boolean;
|
|
145
|
-
};
|
|
146
|
-
type RetrieveAccountArgs = { provider: string; account: AccountCredentials };
|
|
147
|
-
type UpdateAccountCredentialsArgs = {
|
|
148
|
-
provider: string;
|
|
149
|
-
account: { id: string; secret: string };
|
|
150
|
-
};
|
|
151
|
-
|
|
152
|
-
const auth = {
|
|
153
|
-
user: {
|
|
154
|
-
/**
|
|
155
|
-
* Get the current user's ID from the auth context, or `null` if
|
|
156
|
-
* not signed in.
|
|
157
|
-
*
|
|
158
|
-
* @param ctx - Any Convex context with an `auth` field (query, mutation, or action).
|
|
159
|
-
* @returns The user's `Id<"user">`, or `null` when unauthenticated.
|
|
160
|
-
*/
|
|
161
|
-
current: async (ctx: { auth: Auth }) => {
|
|
162
|
-
const identity = await ctx.auth.getUserIdentity();
|
|
163
|
-
if (identity === null) {
|
|
164
|
-
return null;
|
|
165
|
-
}
|
|
166
|
-
const [userId] = identity.subject.split(TOKEN_SUB_CLAIM_DIVIDER);
|
|
167
|
-
return userId as GenericId<"user">;
|
|
168
|
-
},
|
|
169
|
-
/**
|
|
170
|
-
* Get the current user's ID, or throw if not signed in.
|
|
171
|
-
* Use this when authentication is required.
|
|
172
|
-
*
|
|
173
|
-
* @param ctx - Any Convex context with an `auth` field.
|
|
174
|
-
* @returns The user's `Id<"user">`.
|
|
175
|
-
* @throws `ConvexError` with code `NOT_SIGNED_IN` when unauthenticated.
|
|
176
|
-
*/
|
|
177
|
-
require: async (ctx: { auth: Auth }) => {
|
|
178
|
-
const identity = await ctx.auth.getUserIdentity();
|
|
179
|
-
if (identity === null) {
|
|
180
|
-
throwAuthError("NOT_SIGNED_IN");
|
|
181
|
-
}
|
|
182
|
-
const [userId] = identity.subject.split(TOKEN_SUB_CLAIM_DIVIDER);
|
|
183
|
-
return userId as GenericId<"user">;
|
|
184
|
-
},
|
|
185
|
-
/**
|
|
186
|
-
* Retrieve a user document by their ID.
|
|
187
|
-
*
|
|
188
|
-
* @param ctx - Convex context with `runQuery`.
|
|
189
|
-
* @param userId - The user document ID.
|
|
190
|
-
* @returns The user document, or `null` if not found.
|
|
191
|
-
*/
|
|
192
|
-
get: async (ctx: ComponentReadCtx, userId: string) => {
|
|
193
|
-
return await ctx.runQuery(config.component.public.userGetById, { userId });
|
|
194
|
-
},
|
|
195
|
-
/**
|
|
196
|
-
* List users with optional filters, sorting, and pagination.
|
|
197
|
-
*
|
|
198
|
-
* @param opts.where - Optional filters (email, phone, name, anonymous).
|
|
199
|
-
* @param opts.limit - Max users to return (default 50).
|
|
200
|
-
* @param opts.cursor - Pagination cursor from a previous page.
|
|
201
|
-
* @param opts.orderBy - Sort field.
|
|
202
|
-
* @param opts.order - Sort direction.
|
|
203
|
-
* @returns `{ items, nextCursor }`.
|
|
204
|
-
*/
|
|
205
|
-
list: async (
|
|
206
|
-
ctx: ComponentReadCtx,
|
|
207
|
-
opts: {
|
|
208
|
-
where?: UserWhere;
|
|
209
|
-
limit?: number;
|
|
210
|
-
cursor?: string | null;
|
|
211
|
-
orderBy?: UserOrderBy;
|
|
212
|
-
order?: "asc" | "desc";
|
|
213
|
-
} = {},
|
|
214
|
-
) => {
|
|
215
|
-
return await ctx.runQuery(config.component.public.userList, opts);
|
|
216
|
-
},
|
|
217
|
-
/**
|
|
218
|
-
* Get the currently signed-in user's document, or `null` if not
|
|
219
|
-
* signed in. Convenience combining `current()` + `get()`.
|
|
220
|
-
*
|
|
221
|
-
* @param ctx - Convex context with `auth` and `runQuery`.
|
|
222
|
-
* @returns The user document, or `null` when unauthenticated.
|
|
223
|
-
*/
|
|
224
|
-
viewer: async (ctx: ComponentAuthReadCtx) => {
|
|
225
|
-
const userId = await auth.user.current(ctx);
|
|
226
|
-
if (userId === null) {
|
|
227
|
-
return null;
|
|
228
|
-
}
|
|
229
|
-
return await ctx.runQuery(config.component.public.userGetById, { userId });
|
|
230
|
-
},
|
|
231
|
-
/**
|
|
232
|
-
* Update a user document with partial data.
|
|
233
|
-
*
|
|
234
|
-
* @param ctx - Convex context with `runMutation`.
|
|
235
|
-
* @param userId - The user document ID.
|
|
236
|
-
* @param data - Partial data to merge into the user document.
|
|
237
|
-
*/
|
|
238
|
-
patch: async (
|
|
239
|
-
ctx: ComponentCtx,
|
|
240
|
-
userId: string,
|
|
241
|
-
data: Record<string, unknown>,
|
|
242
|
-
) => {
|
|
243
|
-
await ctx.runMutation(config.component.public.userPatch, {
|
|
244
|
-
userId,
|
|
245
|
-
data,
|
|
246
|
-
});
|
|
247
|
-
},
|
|
248
|
-
/**
|
|
249
|
-
* Query a user's group memberships.
|
|
250
|
-
*/
|
|
251
|
-
group: {
|
|
252
|
-
/**
|
|
253
|
-
* List all groups a user belongs to. Returns member records which
|
|
254
|
-
* include the `groupId`, `role`, `status`, and `extend` for each.
|
|
255
|
-
*
|
|
256
|
-
* This is a convenience wrapper around `auth.group.member.list`
|
|
257
|
-
* with `where: { userId }`.
|
|
258
|
-
*/
|
|
259
|
-
list: async (
|
|
260
|
-
ctx: ComponentReadCtx,
|
|
261
|
-
opts: {
|
|
262
|
-
userId: string;
|
|
263
|
-
limit?: number;
|
|
264
|
-
cursor?: string | null;
|
|
265
|
-
order?: "asc" | "desc";
|
|
266
|
-
},
|
|
267
|
-
) => {
|
|
268
|
-
return await ctx.runQuery(config.component.public.memberList, {
|
|
269
|
-
where: { userId: opts.userId },
|
|
270
|
-
limit: opts.limit,
|
|
271
|
-
cursor: opts.cursor,
|
|
272
|
-
order: opts.order,
|
|
273
|
-
});
|
|
274
|
-
},
|
|
275
|
-
/**
|
|
276
|
-
* Look up a user's membership in a specific group. Returns the member
|
|
277
|
-
* record (with role, status, extend) or `null` if the user is not
|
|
278
|
-
* a member.
|
|
279
|
-
*/
|
|
280
|
-
get: async (
|
|
281
|
-
ctx: ComponentReadCtx,
|
|
282
|
-
opts: { userId: string; groupId: string },
|
|
283
|
-
) => {
|
|
284
|
-
return await ctx.runQuery(
|
|
285
|
-
config.component.public.memberGetByGroupAndUser,
|
|
286
|
-
opts,
|
|
287
|
-
);
|
|
288
|
-
},
|
|
289
|
-
},
|
|
290
|
-
},
|
|
291
|
-
session: {
|
|
292
|
-
/**
|
|
293
|
-
* Get the current session ID from the auth context, or `null` if
|
|
294
|
-
* not signed in.
|
|
295
|
-
*
|
|
296
|
-
* @param ctx - Any Convex context with an `auth` field.
|
|
297
|
-
* @returns The session's `Id<"session">`, or `null` when unauthenticated.
|
|
298
|
-
*/
|
|
299
|
-
current: async (ctx: { auth: Auth }) => {
|
|
300
|
-
const identity = await ctx.auth.getUserIdentity();
|
|
301
|
-
if (identity === null) {
|
|
302
|
-
return null;
|
|
303
|
-
}
|
|
304
|
-
const [, sessionId] = identity.subject.split(TOKEN_SUB_CLAIM_DIVIDER);
|
|
305
|
-
return sessionId as GenericId<"session">;
|
|
306
|
-
},
|
|
307
|
-
/**
|
|
308
|
-
* Invalidate sessions for a user, optionally preserving specific sessions.
|
|
309
|
-
*
|
|
310
|
-
* @param ctx - Convex action context.
|
|
311
|
-
* @param args.userId - The user whose sessions to invalidate.
|
|
312
|
-
* @param args.except - Session IDs to preserve (e.g. the current session).
|
|
313
|
-
*/
|
|
314
|
-
invalidate: async <DataModel extends GenericDataModel>(
|
|
315
|
-
ctx: GenericActionCtx<DataModel>,
|
|
316
|
-
args: {
|
|
317
|
-
userId: GenericId<"user">;
|
|
318
|
-
except?: GenericId<"session">[];
|
|
319
|
-
},
|
|
320
|
-
): Promise<void> => {
|
|
321
|
-
const actionCtx = ctx as unknown as ActionCtx;
|
|
322
|
-
return await callInvalidateSessions(actionCtx, args);
|
|
323
|
-
},
|
|
324
|
-
},
|
|
325
|
-
account: {
|
|
326
|
-
/**
|
|
327
|
-
* Create an account and user for a credentials provider.
|
|
328
|
-
*
|
|
329
|
-
* @param ctx - Convex action context.
|
|
330
|
-
* @param args - Provider ID, account credentials, profile data, and link flags.
|
|
331
|
-
* @returns `{ account, user }` — the created account and user documents.
|
|
332
|
-
*/
|
|
333
|
-
create: async <DataModel extends GenericDataModel>(
|
|
334
|
-
ctx: GenericActionCtx<DataModel>,
|
|
335
|
-
args: CreateAccountArgs,
|
|
336
|
-
) => {
|
|
337
|
-
const actionCtx = ctx as unknown as ActionCtx;
|
|
338
|
-
return await callCreateAccountFromCredentials(actionCtx, args);
|
|
339
|
-
},
|
|
340
|
-
/**
|
|
341
|
-
* Retrieve an account and user for a credentials provider.
|
|
342
|
-
*
|
|
343
|
-
* @param ctx - Convex action context.
|
|
344
|
-
* @param args - Provider ID and account credentials (id, optional secret).
|
|
345
|
-
* @returns `{ account, user }` — the matched account and user documents.
|
|
346
|
-
* @throws `ConvexError` with code `ACCOUNT_NOT_FOUND` when no match exists.
|
|
347
|
-
*/
|
|
348
|
-
get: async <DataModel extends GenericDataModel>(
|
|
349
|
-
ctx: GenericActionCtx<DataModel>,
|
|
350
|
-
args: RetrieveAccountArgs,
|
|
351
|
-
) => {
|
|
352
|
-
const actionCtx = ctx as unknown as ActionCtx;
|
|
353
|
-
const result = await callRetreiveAccountWithCredentials(actionCtx, args);
|
|
354
|
-
if (typeof result === "string") {
|
|
355
|
-
throwAuthError("ACCOUNT_NOT_FOUND", result);
|
|
356
|
-
}
|
|
357
|
-
return result;
|
|
358
|
-
},
|
|
359
|
-
/**
|
|
360
|
-
* Update account credentials (secret) for an existing account.
|
|
361
|
-
*
|
|
362
|
-
* @param ctx - Convex action context.
|
|
363
|
-
* @param args - Provider ID and new account credentials (id + secret).
|
|
364
|
-
*/
|
|
365
|
-
update: async <DataModel extends GenericDataModel>(
|
|
366
|
-
ctx: GenericActionCtx<DataModel>,
|
|
367
|
-
args: UpdateAccountCredentialsArgs,
|
|
368
|
-
): Promise<void> => {
|
|
369
|
-
const actionCtx = ctx as unknown as ActionCtx;
|
|
370
|
-
return await callModifyAccount(actionCtx, args);
|
|
371
|
-
},
|
|
372
|
-
},
|
|
373
|
-
provider: {
|
|
374
|
-
/**
|
|
375
|
-
* Sign in via another provider, typically from a credentials flow.
|
|
376
|
-
*
|
|
377
|
-
* @param ctx - Convex action context.
|
|
378
|
-
* @param provider - The provider config to sign in with.
|
|
379
|
-
* @param args - Optional account ID and params.
|
|
380
|
-
* @returns `{ userId, sessionId }` on success, or `null`.
|
|
381
|
-
*/
|
|
382
|
-
signIn: async <DataModel extends GenericDataModel>(
|
|
383
|
-
ctx: GenericActionCtx<DataModel>,
|
|
384
|
-
provider: AuthProviderConfig,
|
|
385
|
-
args: {
|
|
386
|
-
accountId?: GenericId<"account">;
|
|
387
|
-
params?: Record<string, unknown>;
|
|
388
|
-
},
|
|
389
|
-
) => {
|
|
390
|
-
const result = await signInImpl(
|
|
391
|
-
enrichCtx(ctx),
|
|
392
|
-
materializeProvider(provider),
|
|
393
|
-
// params type widened: Record<string, unknown> → Record<string, any>
|
|
394
|
-
args as { accountId?: GenericId<"account">; params?: Record<string, any> },
|
|
395
|
-
{
|
|
396
|
-
generateTokens: false,
|
|
397
|
-
allowExtraProviders: true,
|
|
398
|
-
},
|
|
399
|
-
);
|
|
400
|
-
return result.kind === "signedIn"
|
|
401
|
-
? result.signedIn !== null
|
|
402
|
-
? { userId: result.signedIn.userId, sessionId: result.signedIn.sessionId }
|
|
403
|
-
: null
|
|
404
|
-
: null;
|
|
405
|
-
},
|
|
406
|
-
},
|
|
407
|
-
/**
|
|
408
|
-
* Hierarchical group management. Groups can nest arbitrarily deep
|
|
409
|
-
* via `parentGroupId`. A root group has no parent.
|
|
410
|
-
*
|
|
411
|
-
* ```ts
|
|
412
|
-
* const groupId = await auth.group.create(ctx, { name: "Acme Corp" });
|
|
413
|
-
* const subGroupId = await auth.group.create(ctx, {
|
|
414
|
-
* name: "Engineering",
|
|
415
|
-
* parentGroupId: groupId,
|
|
416
|
-
* });
|
|
417
|
-
* ```
|
|
418
|
-
*/
|
|
419
|
-
group: {
|
|
420
|
-
/**
|
|
421
|
-
* Create a new group. Omit `parentGroupId` for a root-level group,
|
|
422
|
-
* or provide it to create a nested group.
|
|
423
|
-
*
|
|
424
|
-
* @returns The ID of the newly created group.
|
|
425
|
-
*/
|
|
426
|
-
create: async (
|
|
427
|
-
ctx: ComponentCtx,
|
|
428
|
-
data: {
|
|
429
|
-
name: string;
|
|
430
|
-
slug?: string;
|
|
431
|
-
type?: string;
|
|
432
|
-
parentGroupId?: string;
|
|
433
|
-
tags?: Array<{ key: string; value: string }>;
|
|
434
|
-
extend?: Record<string, unknown>;
|
|
435
|
-
},
|
|
436
|
-
): Promise<string> => {
|
|
437
|
-
return (await ctx.runMutation(
|
|
438
|
-
config.component.public.groupCreate,
|
|
439
|
-
data,
|
|
440
|
-
)) as string;
|
|
441
|
-
},
|
|
442
|
-
/**
|
|
443
|
-
* Retrieve a group by its ID. Returns `null` if not found.
|
|
444
|
-
*/
|
|
445
|
-
get: async (ctx: ComponentReadCtx, groupId: string) => {
|
|
446
|
-
return await ctx.runQuery(config.component.public.groupGet, { groupId });
|
|
447
|
-
},
|
|
448
|
-
/**
|
|
449
|
-
* List groups with optional filtering, sorting, and pagination.
|
|
450
|
-
*
|
|
451
|
-
* Empty `where` returns **all** groups.
|
|
452
|
-
*
|
|
453
|
-
* ```ts
|
|
454
|
-
* // All groups of type "team"
|
|
455
|
-
* await auth.group.list(ctx, { where: { type: "team" } });
|
|
456
|
-
*
|
|
457
|
-
* // Paginated
|
|
458
|
-
* const page1 = await auth.group.list(ctx, { limit: 10 });
|
|
459
|
-
* const page2 = await auth.group.list(ctx, { limit: 10, cursor: page1.nextCursor });
|
|
460
|
-
* ```
|
|
461
|
-
*/
|
|
462
|
-
list: async (
|
|
463
|
-
ctx: ComponentReadCtx,
|
|
464
|
-
opts?: {
|
|
465
|
-
where?: {
|
|
466
|
-
slug?: string;
|
|
467
|
-
type?: string;
|
|
468
|
-
parentGroupId?: string;
|
|
469
|
-
name?: string;
|
|
470
|
-
isRoot?: boolean;
|
|
471
|
-
tagsAll?: Array<{ key: string; value: string }>;
|
|
472
|
-
tagsAny?: Array<{ key: string; value: string }>;
|
|
473
|
-
};
|
|
474
|
-
limit?: number;
|
|
475
|
-
cursor?: string | null;
|
|
476
|
-
orderBy?: "_creationTime" | "name" | "slug" | "type";
|
|
477
|
-
order?: "asc" | "desc";
|
|
478
|
-
},
|
|
479
|
-
) => {
|
|
480
|
-
return await ctx.runQuery(config.component.public.groupList, {
|
|
481
|
-
where: opts?.where,
|
|
482
|
-
limit: opts?.limit,
|
|
483
|
-
cursor: opts?.cursor,
|
|
484
|
-
orderBy: opts?.orderBy,
|
|
485
|
-
order: opts?.order,
|
|
486
|
-
});
|
|
487
|
-
},
|
|
488
|
-
/**
|
|
489
|
-
* Update a group's fields (name, slug, tags, extend, parentGroupId).
|
|
490
|
-
*/
|
|
491
|
-
update: async (
|
|
492
|
-
ctx: ComponentCtx,
|
|
493
|
-
groupId: string,
|
|
494
|
-
data: Record<string, unknown>,
|
|
495
|
-
) => {
|
|
496
|
-
await ctx.runMutation(config.component.public.groupUpdate, { groupId, data });
|
|
497
|
-
},
|
|
498
|
-
/**
|
|
499
|
-
* Delete a group and cascade to all descendants. Deletes child groups
|
|
500
|
-
* (recursively), all members, and all invites for this group and its
|
|
501
|
-
* descendants.
|
|
502
|
-
*/
|
|
503
|
-
delete: async (ctx: ComponentCtx, groupId: string) => {
|
|
504
|
-
await ctx.runMutation(config.component.public.groupDelete, { groupId });
|
|
505
|
-
},
|
|
506
|
-
|
|
507
|
-
/**
|
|
508
|
-
* Manage group membership. A member links a user to a group with an
|
|
509
|
-
* application-defined role string (e.g. "owner", "admin", "member").
|
|
510
|
-
*
|
|
511
|
-
* The auth component stores roles but does not enforce access control.
|
|
512
|
-
* Your application defines what each role means.
|
|
513
|
-
*/
|
|
514
|
-
member: {
|
|
515
|
-
/**
|
|
516
|
-
* Add a user as a member of a group.
|
|
517
|
-
*
|
|
518
|
-
* @param data.groupId - The group to add the member to.
|
|
519
|
-
* @param data.userId - The user to add.
|
|
520
|
-
* @param data.role - Application-defined role (e.g. "owner", "admin", "member").
|
|
521
|
-
* @param data.status - Optional membership status (e.g. "active", "suspended").
|
|
522
|
-
* @param data.extend - Optional arbitrary JSON extension data.
|
|
523
|
-
* @throws ConvexError with code `DUPLICATE_MEMBERSHIP` if the user is
|
|
524
|
-
* already a member of the target group.
|
|
525
|
-
* @returns The ID of the new member record.
|
|
526
|
-
*/
|
|
527
|
-
add: async (
|
|
528
|
-
ctx: ComponentCtx,
|
|
529
|
-
data: {
|
|
530
|
-
groupId: string;
|
|
531
|
-
userId: string;
|
|
532
|
-
role?: string;
|
|
533
|
-
status?: string;
|
|
534
|
-
extend?: Record<string, unknown>;
|
|
535
|
-
},
|
|
536
|
-
): Promise<string> => {
|
|
537
|
-
return (await ctx.runMutation(
|
|
538
|
-
config.component.public.memberAdd,
|
|
539
|
-
data,
|
|
540
|
-
)) as string;
|
|
541
|
-
},
|
|
542
|
-
/**
|
|
543
|
-
* Retrieve a member record by its ID. Returns `null` if not found.
|
|
544
|
-
*/
|
|
545
|
-
get: async (ctx: ComponentReadCtx, memberId: string) => {
|
|
546
|
-
return await ctx.runQuery(config.component.public.memberGet, { memberId });
|
|
547
|
-
},
|
|
548
|
-
/**
|
|
549
|
-
* List members with optional filtering, sorting, and pagination.
|
|
550
|
-
*
|
|
551
|
-
* ```ts
|
|
552
|
-
* // All members of a group
|
|
553
|
-
* await auth.group.member.list(ctx, { where: { groupId } });
|
|
554
|
-
*
|
|
555
|
-
* // Admins only
|
|
556
|
-
* await auth.group.member.list(ctx, { where: { groupId, role: "admin" } });
|
|
557
|
-
* ```
|
|
558
|
-
*/
|
|
559
|
-
list: async (
|
|
560
|
-
ctx: ComponentReadCtx,
|
|
561
|
-
opts?: {
|
|
562
|
-
where?: {
|
|
563
|
-
groupId?: string;
|
|
564
|
-
userId?: string;
|
|
565
|
-
role?: string;
|
|
566
|
-
status?: string;
|
|
567
|
-
};
|
|
568
|
-
limit?: number;
|
|
569
|
-
cursor?: string | null;
|
|
570
|
-
orderBy?: "_creationTime" | "role" | "status";
|
|
571
|
-
order?: "asc" | "desc";
|
|
572
|
-
},
|
|
573
|
-
) => {
|
|
574
|
-
return await ctx.runQuery(config.component.public.memberList, {
|
|
575
|
-
where: opts?.where,
|
|
576
|
-
limit: opts?.limit,
|
|
577
|
-
cursor: opts?.cursor,
|
|
578
|
-
orderBy: opts?.orderBy,
|
|
579
|
-
order: opts?.order,
|
|
580
|
-
});
|
|
581
|
-
},
|
|
582
|
-
/**
|
|
583
|
-
* Remove a member from a group by deleting the member record.
|
|
584
|
-
*/
|
|
585
|
-
remove: async (ctx: ComponentCtx, memberId: string) => {
|
|
586
|
-
await ctx.runMutation(config.component.public.memberRemove, { memberId });
|
|
587
|
-
},
|
|
588
|
-
/**
|
|
589
|
-
* Update a member's fields (role, status, extend).
|
|
590
|
-
*
|
|
591
|
-
* ```ts
|
|
592
|
-
* await auth.group.member.update(ctx, memberId, { role: "admin" });
|
|
593
|
-
* ```
|
|
594
|
-
*/
|
|
595
|
-
update: async (
|
|
596
|
-
ctx: ComponentCtx,
|
|
597
|
-
memberId: string,
|
|
598
|
-
data: Record<string, unknown>,
|
|
599
|
-
) => {
|
|
600
|
-
await ctx.runMutation(config.component.public.memberUpdate, {
|
|
601
|
-
memberId,
|
|
602
|
-
data,
|
|
603
|
-
});
|
|
604
|
-
},
|
|
605
|
-
},
|
|
606
|
-
|
|
607
|
-
},
|
|
608
|
-
/**
|
|
609
|
-
* Manage platform-level invitations.
|
|
610
|
-
*
|
|
611
|
-
* Invites can optionally target a group by setting `groupId`, but they do
|
|
612
|
-
* not require groups and can be used in apps with user-only collaboration.
|
|
613
|
-
*/
|
|
614
|
-
invite: {
|
|
615
|
-
/**
|
|
616
|
-
* Create a new invitation.
|
|
617
|
-
*
|
|
618
|
-
* @param data.groupId - Optional group to invite the user into.
|
|
619
|
-
* @param data.invitedByUserId - Optional user sending the invitation
|
|
620
|
-
* (omit for CLI-generated invites).
|
|
621
|
-
* @param data.email - Optional email of the invitee (omit for
|
|
622
|
-
* CLI-generated invite links where the email is unknown upfront).
|
|
623
|
-
* @param data.tokenHash - Hashed token for secure acceptance.
|
|
624
|
-
* @param data.role - Optional role to assign on acceptance.
|
|
625
|
-
* @param data.status - Initial status (typically "pending").
|
|
626
|
-
* @param data.expiresTime - Optional expiration timestamp (omit for
|
|
627
|
-
* single-use, non-expiring invites).
|
|
628
|
-
* @param data.extend - Optional arbitrary JSON extension data.
|
|
629
|
-
* @throws ConvexError with code `DUPLICATE_INVITE` if a pending invite
|
|
630
|
-
* already exists for this email and scope.
|
|
631
|
-
* @returns The ID of the new invite record.
|
|
632
|
-
*/
|
|
633
|
-
create: async (
|
|
634
|
-
ctx: ComponentCtx,
|
|
635
|
-
data: {
|
|
636
|
-
groupId?: string;
|
|
637
|
-
invitedByUserId?: string;
|
|
638
|
-
email?: string;
|
|
639
|
-
tokenHash: string;
|
|
640
|
-
role?: string;
|
|
641
|
-
status: "pending" | "accepted" | "revoked" | "expired";
|
|
642
|
-
expiresTime?: number;
|
|
643
|
-
extend?: Record<string, unknown>;
|
|
644
|
-
},
|
|
645
|
-
): Promise<string> => {
|
|
646
|
-
return (await ctx.runMutation(config.component.public.inviteCreate, data)) as string;
|
|
647
|
-
},
|
|
648
|
-
/**
|
|
649
|
-
* Retrieve an invite by its ID. Returns `null` if not found.
|
|
650
|
-
*/
|
|
651
|
-
get: async (ctx: ComponentReadCtx, inviteId: string) => {
|
|
652
|
-
return await ctx.runQuery(config.component.public.inviteGet, { inviteId });
|
|
653
|
-
},
|
|
654
|
-
/**
|
|
655
|
-
* List invites with optional filtering, sorting, and pagination.
|
|
656
|
-
*
|
|
657
|
-
* ```ts
|
|
658
|
-
* // Pending invites for a group
|
|
659
|
-
* await auth.invite.list(ctx, { where: { groupId, status: "pending" } });
|
|
660
|
-
* ```
|
|
661
|
-
*/
|
|
662
|
-
list: async (
|
|
663
|
-
ctx: ComponentReadCtx,
|
|
664
|
-
opts?: {
|
|
665
|
-
where?: {
|
|
666
|
-
tokenHash?: string;
|
|
667
|
-
groupId?: string;
|
|
668
|
-
status?: "pending" | "accepted" | "revoked" | "expired";
|
|
669
|
-
email?: string;
|
|
670
|
-
invitedByUserId?: string;
|
|
671
|
-
role?: string;
|
|
672
|
-
acceptedByUserId?: string;
|
|
673
|
-
};
|
|
674
|
-
limit?: number;
|
|
675
|
-
cursor?: string | null;
|
|
676
|
-
orderBy?: "_creationTime" | "status" | "email" | "expiresTime" | "acceptedTime";
|
|
677
|
-
order?: "asc" | "desc";
|
|
678
|
-
},
|
|
679
|
-
) => {
|
|
680
|
-
return await ctx.runQuery(config.component.public.inviteList, {
|
|
681
|
-
where: opts?.where,
|
|
682
|
-
limit: opts?.limit,
|
|
683
|
-
cursor: opts?.cursor,
|
|
684
|
-
orderBy: opts?.orderBy,
|
|
685
|
-
order: opts?.order,
|
|
686
|
-
});
|
|
687
|
-
},
|
|
688
|
-
/**
|
|
689
|
-
* Accept an invitation. Marks the invite as "accepted" and records
|
|
690
|
-
* the timestamp. If the invite has a group, the caller is responsible
|
|
691
|
-
* for creating the member record via `auth.group.member.add` in the
|
|
692
|
-
* same Convex mutation for transactional safety.
|
|
693
|
-
*
|
|
694
|
-
* @param ctx - Convex context with `runMutation`.
|
|
695
|
-
* @param inviteId - The invite document ID.
|
|
696
|
-
* @param acceptedByUserId - User accepting the invite (recorded for audit).
|
|
697
|
-
* @throws `ConvexError` with code `INVITE_NOT_FOUND` when the invite does not exist.
|
|
698
|
-
* @throws `ConvexError` with code `INVITE_NOT_PENDING` when the invite is not in `pending` status.
|
|
699
|
-
*
|
|
700
|
-
* @example
|
|
701
|
-
* ```ts
|
|
702
|
-
* export const acceptInvite = mutation({
|
|
703
|
-
* args: { inviteId: v.string() },
|
|
704
|
-
* handler: async (ctx, { inviteId }) => {
|
|
705
|
-
* const userId = await auth.user.require(ctx);
|
|
706
|
-
* const invite = await auth.invite.get(ctx, inviteId);
|
|
707
|
-
* if (!invite) throw new Error("Invite not found");
|
|
708
|
-
*
|
|
709
|
-
* await auth.invite.accept(ctx, inviteId);
|
|
710
|
-
* if (invite.groupId) {
|
|
711
|
-
* await auth.group.member.add(ctx, {
|
|
712
|
-
* groupId: invite.groupId,
|
|
713
|
-
* userId,
|
|
714
|
-
* role: invite.role,
|
|
715
|
-
* });
|
|
716
|
-
* }
|
|
717
|
-
* },
|
|
718
|
-
* });
|
|
719
|
-
* ```
|
|
720
|
-
*/
|
|
721
|
-
accept: async (ctx: ComponentCtx, inviteId: string, acceptedByUserId?: string) => {
|
|
722
|
-
await ctx.runMutation(config.component.public.inviteAccept, {
|
|
723
|
-
inviteId,
|
|
724
|
-
...(acceptedByUserId ? { acceptedByUserId } : {}),
|
|
725
|
-
});
|
|
726
|
-
},
|
|
727
|
-
/**
|
|
728
|
-
* Revoke a pending invitation.
|
|
729
|
-
*
|
|
730
|
-
* @param ctx - Convex context with `runMutation`.
|
|
731
|
-
* @param inviteId - The invite document ID.
|
|
732
|
-
* @throws `ConvexError` with code `INVITE_NOT_FOUND` when the invite does not exist.
|
|
733
|
-
* @throws `ConvexError` with code `INVITE_NOT_PENDING` when the invite is not in `pending` status.
|
|
734
|
-
*/
|
|
735
|
-
revoke: async (ctx: ComponentCtx, inviteId: string) => {
|
|
736
|
-
await ctx.runMutation(config.component.public.inviteRevoke, { inviteId });
|
|
737
|
-
},
|
|
738
|
-
},
|
|
739
|
-
/**
|
|
740
|
-
* Manage passkey credentials for users.
|
|
741
|
-
*
|
|
742
|
-
* ```ts
|
|
743
|
-
* const passkeys = await auth.passkey.list(ctx, { userId });
|
|
744
|
-
* await auth.passkey.rename(ctx, passkeyId, "MacBook Touch ID");
|
|
745
|
-
* await auth.passkey.remove(ctx, passkeyId);
|
|
746
|
-
* ```
|
|
747
|
-
*/
|
|
748
|
-
passkey: {
|
|
749
|
-
/**
|
|
750
|
-
* List all passkeys for a user.
|
|
751
|
-
*
|
|
752
|
-
* @param opts.userId - The user whose passkeys to list.
|
|
753
|
-
* @returns Array of passkey records with credentialId, name, deviceType,
|
|
754
|
-
* backedUp, createdAt, and lastUsedAt.
|
|
755
|
-
*/
|
|
756
|
-
list: async (ctx: ComponentReadCtx, opts: { userId: string }) => {
|
|
757
|
-
return await ctx.runQuery(
|
|
758
|
-
config.component.public.passkeyListByUserId,
|
|
759
|
-
opts,
|
|
760
|
-
);
|
|
761
|
-
},
|
|
762
|
-
/**
|
|
763
|
-
* Rename a passkey (set a user-friendly display name).
|
|
764
|
-
*
|
|
765
|
-
* @param passkeyId - The passkey document ID.
|
|
766
|
-
* @param name - New display name (e.g. "MacBook Touch ID").
|
|
767
|
-
*/
|
|
768
|
-
rename: async (ctx: ComponentCtx, passkeyId: string, name: string) => {
|
|
769
|
-
await ctx.runMutation(
|
|
770
|
-
config.component.public.passkeyUpdateMeta,
|
|
771
|
-
{ passkeyId, data: { name } },
|
|
772
|
-
);
|
|
773
|
-
},
|
|
774
|
-
/**
|
|
775
|
-
* Delete a passkey credential.
|
|
776
|
-
*
|
|
777
|
-
* @param passkeyId - The passkey document ID to remove.
|
|
778
|
-
*/
|
|
779
|
-
remove: async (ctx: ComponentCtx, passkeyId: string) => {
|
|
780
|
-
await ctx.runMutation(
|
|
781
|
-
config.component.public.passkeyDelete,
|
|
782
|
-
{ passkeyId },
|
|
783
|
-
);
|
|
784
|
-
},
|
|
785
|
-
},
|
|
786
|
-
/**
|
|
787
|
-
* Manage TOTP two-factor authentication enrollments for users.
|
|
788
|
-
*
|
|
789
|
-
* ```ts
|
|
790
|
-
* const enrollments = await auth.totp.list(ctx, { userId });
|
|
791
|
-
* await auth.totp.remove(ctx, totpId);
|
|
792
|
-
* ```
|
|
793
|
-
*/
|
|
794
|
-
totp: {
|
|
795
|
-
/**
|
|
796
|
-
* List all TOTP enrollments for a user.
|
|
797
|
-
*
|
|
798
|
-
* @param opts.userId - The user whose enrollments to list.
|
|
799
|
-
* @returns Array of TOTP enrollment records.
|
|
800
|
-
*/
|
|
801
|
-
list: async (ctx: ComponentReadCtx, opts: { userId: string }) => {
|
|
802
|
-
return await ctx.runQuery(
|
|
803
|
-
config.component.public.totpListByUserId,
|
|
804
|
-
opts,
|
|
805
|
-
);
|
|
806
|
-
},
|
|
807
|
-
/**
|
|
808
|
-
* Delete a TOTP enrollment.
|
|
809
|
-
*
|
|
810
|
-
* @param totpId - The TOTP document ID to remove.
|
|
811
|
-
*/
|
|
812
|
-
remove: async (ctx: ComponentCtx, totpId: string) => {
|
|
813
|
-
await ctx.runMutation(
|
|
814
|
-
config.component.public.totpDelete,
|
|
815
|
-
{ totpId },
|
|
816
|
-
);
|
|
817
|
-
},
|
|
818
|
-
},
|
|
819
|
-
/**
|
|
820
|
-
* Manage API keys for programmatic access.
|
|
821
|
-
*
|
|
822
|
-
* Keys use SHA-256 hashing (via `@oslojs/crypto`) and support
|
|
823
|
-
* scoped resource:action permissions with optional per-key rate limiting.
|
|
824
|
-
*
|
|
825
|
-
* ```ts
|
|
826
|
-
* const { keyId, raw } = await auth.key.create(ctx, {
|
|
827
|
-
* userId,
|
|
828
|
-
* name: "CI Pipeline",
|
|
829
|
-
* scopes: [{ resource: "users", actions: ["read", "list"] }],
|
|
830
|
-
* });
|
|
831
|
-
* // raw = "sk_live_abc123..." — show once, never stored
|
|
832
|
-
*
|
|
833
|
-
* const result = await auth.key.verify(ctx, rawKey);
|
|
834
|
-
* result.scopes.can("users", "read"); // true
|
|
835
|
-
* ```
|
|
836
|
-
*/
|
|
837
|
-
key: {
|
|
838
|
-
/**
|
|
839
|
-
* Create a new API key. Returns the raw key **once** — it cannot
|
|
840
|
-
* be retrieved again after creation.
|
|
841
|
-
*
|
|
842
|
-
* @param opts.userId - The user this key belongs to.
|
|
843
|
-
* @param opts.name - Human-readable name (e.g. "CI Pipeline").
|
|
844
|
-
* @param opts.scopes - Resource:action permissions for this key.
|
|
845
|
-
* @param opts.rateLimit - Optional per-key rate limit override.
|
|
846
|
-
* @param opts.expiresAt - Optional expiration timestamp.
|
|
847
|
-
* @returns `{ keyId, raw }` where `raw` is the full key string.
|
|
848
|
-
*/
|
|
849
|
-
create: async (
|
|
850
|
-
ctx: ComponentCtx,
|
|
851
|
-
opts: {
|
|
852
|
-
userId: string;
|
|
853
|
-
name: string;
|
|
854
|
-
scopes: import("../types.js").KeyScope[];
|
|
855
|
-
rateLimit?: { maxRequests: number; windowMs: number };
|
|
856
|
-
expiresAt?: number;
|
|
857
|
-
},
|
|
858
|
-
): Promise<{ keyId: string; raw: string }> => {
|
|
859
|
-
const prefix = config.apiKeys?.prefix ?? "sk_live_";
|
|
860
|
-
|
|
861
|
-
// Validate scopes against config if defined
|
|
862
|
-
validateScopes(opts.scopes, config.apiKeys?.scopes);
|
|
863
|
-
|
|
864
|
-
const { raw, hashedKey, displayPrefix } = await generateApiKey(prefix);
|
|
865
|
-
|
|
866
|
-
const keyId = (await ctx.runMutation(
|
|
867
|
-
config.component.public.keyInsert,
|
|
868
|
-
{
|
|
869
|
-
userId: opts.userId,
|
|
870
|
-
prefix: displayPrefix,
|
|
871
|
-
hashedKey,
|
|
872
|
-
name: opts.name,
|
|
873
|
-
scopes: opts.scopes,
|
|
874
|
-
rateLimit: opts.rateLimit ?? config.apiKeys?.defaultRateLimit,
|
|
875
|
-
expiresAt: opts.expiresAt,
|
|
876
|
-
},
|
|
877
|
-
)) as string;
|
|
878
|
-
|
|
879
|
-
return { keyId, raw };
|
|
880
|
-
},
|
|
881
|
-
|
|
882
|
-
/**
|
|
883
|
-
* Verify a raw API key string. Returns the userId and a scope checker
|
|
884
|
-
* if the key is valid, not revoked, not expired, and not rate-limited.
|
|
885
|
-
*
|
|
886
|
-
* Also updates `lastUsedAt` and rate limit state as a side effect.
|
|
887
|
-
*
|
|
888
|
-
* @throws Error if the key is invalid, revoked, expired, or rate-limited.
|
|
889
|
-
*/
|
|
890
|
-
verify: async (
|
|
891
|
-
ctx: ComponentCtx,
|
|
892
|
-
rawKey: string,
|
|
893
|
-
): Promise<{
|
|
894
|
-
userId: string;
|
|
895
|
-
keyId: string;
|
|
896
|
-
scopes: import("../types.js").ScopeChecker;
|
|
897
|
-
}> => {
|
|
898
|
-
const hashedKey = await hashApiKey(rawKey);
|
|
899
|
-
|
|
900
|
-
const key = (await ctx.runQuery(
|
|
901
|
-
config.component.public.keyGetByHashedKey,
|
|
902
|
-
{ hashedKey },
|
|
903
|
-
)) as KeyDoc | null;
|
|
904
|
-
if (!key) {
|
|
905
|
-
throwAuthError("INVALID_API_KEY");
|
|
906
|
-
}
|
|
907
|
-
if (key.revoked) {
|
|
908
|
-
throwAuthError("API_KEY_REVOKED");
|
|
909
|
-
}
|
|
910
|
-
if (key.expiresAt && key.expiresAt < Date.now()) {
|
|
911
|
-
throwAuthError("API_KEY_EXPIRED");
|
|
912
|
-
}
|
|
913
|
-
|
|
914
|
-
// Check per-key rate limit
|
|
915
|
-
const patchData: Record<string, unknown> = { lastUsedAt: Date.now() };
|
|
916
|
-
|
|
917
|
-
if (key.rateLimit) {
|
|
918
|
-
const { limited, newState } = checkKeyRateLimit(
|
|
919
|
-
key.rateLimit,
|
|
920
|
-
key.rateLimitState ?? undefined,
|
|
921
|
-
);
|
|
922
|
-
if (limited) {
|
|
923
|
-
throwAuthError("API_KEY_RATE_LIMITED");
|
|
924
|
-
}
|
|
925
|
-
patchData.rateLimitState = newState;
|
|
926
|
-
}
|
|
927
|
-
|
|
928
|
-
// Update lastUsedAt (and rate limit state if applicable)
|
|
929
|
-
await ctx.runMutation(config.component.public.keyPatch, {
|
|
930
|
-
keyId: key._id,
|
|
931
|
-
data: patchData,
|
|
932
|
-
});
|
|
933
|
-
|
|
934
|
-
return {
|
|
935
|
-
userId: key.userId,
|
|
936
|
-
keyId: key._id,
|
|
937
|
-
scopes: buildScopeChecker(key.scopes),
|
|
938
|
-
};
|
|
939
|
-
},
|
|
940
|
-
|
|
941
|
-
/**
|
|
942
|
-
* List API keys with optional filtering, sorting, and pagination.
|
|
943
|
-
* Never includes the raw key — only the display prefix.
|
|
944
|
-
*
|
|
945
|
-
* ```ts
|
|
946
|
-
* // All keys for a user
|
|
947
|
-
* await auth.key.list(ctx, { where: { userId } });
|
|
948
|
-
*
|
|
949
|
-
* // Only active (non-revoked)
|
|
950
|
-
* await auth.key.list(ctx, { where: { userId, revoked: false } });
|
|
951
|
-
* ```
|
|
952
|
-
*/
|
|
953
|
-
list: async (
|
|
954
|
-
ctx: ComponentReadCtx,
|
|
955
|
-
opts?: {
|
|
956
|
-
where?: {
|
|
957
|
-
userId?: string;
|
|
958
|
-
revoked?: boolean;
|
|
959
|
-
name?: string;
|
|
960
|
-
prefix?: string;
|
|
961
|
-
};
|
|
962
|
-
limit?: number;
|
|
963
|
-
cursor?: string | null;
|
|
964
|
-
orderBy?: "_creationTime" | "name" | "lastUsedAt" | "expiresAt" | "revoked";
|
|
965
|
-
order?: "asc" | "desc";
|
|
966
|
-
},
|
|
967
|
-
) => {
|
|
968
|
-
return await ctx.runQuery(config.component.public.keyList, {
|
|
969
|
-
where: opts?.where,
|
|
970
|
-
limit: opts?.limit,
|
|
971
|
-
cursor: opts?.cursor,
|
|
972
|
-
orderBy: opts?.orderBy,
|
|
973
|
-
order: opts?.order,
|
|
974
|
-
});
|
|
975
|
-
},
|
|
976
|
-
|
|
977
|
-
/**
|
|
978
|
-
* Get a single API key by its document ID.
|
|
979
|
-
* Returns `null` if not found.
|
|
980
|
-
*/
|
|
981
|
-
get: async (ctx: ComponentReadCtx, keyId: string): Promise<KeyDoc | null> => {
|
|
982
|
-
return (await ctx.runQuery(
|
|
983
|
-
config.component.public.keyGetById,
|
|
984
|
-
{ keyId },
|
|
985
|
-
)) as KeyDoc | null;
|
|
986
|
-
},
|
|
987
|
-
|
|
988
|
-
/**
|
|
989
|
-
* Update an API key's metadata (name, scopes, rate limit).
|
|
990
|
-
*/
|
|
991
|
-
update: async (
|
|
992
|
-
ctx: ComponentCtx,
|
|
993
|
-
keyId: string,
|
|
994
|
-
data: {
|
|
995
|
-
name?: string;
|
|
996
|
-
scopes?: import("../types.js").KeyScope[];
|
|
997
|
-
rateLimit?: { maxRequests: number; windowMs: number };
|
|
998
|
-
},
|
|
999
|
-
) => {
|
|
1000
|
-
if (data.scopes) {
|
|
1001
|
-
validateScopes(data.scopes, config.apiKeys?.scopes);
|
|
1002
|
-
}
|
|
1003
|
-
await ctx.runMutation(config.component.public.keyPatch, {
|
|
1004
|
-
keyId,
|
|
1005
|
-
data,
|
|
1006
|
-
});
|
|
1007
|
-
},
|
|
1008
|
-
|
|
1009
|
-
/**
|
|
1010
|
-
* Revoke an API key (soft delete). The key record is preserved
|
|
1011
|
-
* for audit purposes but can no longer be used for authentication.
|
|
1012
|
-
*/
|
|
1013
|
-
revoke: async (ctx: ComponentCtx, keyId: string) => {
|
|
1014
|
-
await ctx.runMutation(config.component.public.keyPatch, {
|
|
1015
|
-
keyId,
|
|
1016
|
-
data: { revoked: true },
|
|
1017
|
-
});
|
|
1018
|
-
},
|
|
1019
|
-
|
|
1020
|
-
/**
|
|
1021
|
-
* Hard delete an API key record.
|
|
1022
|
-
*/
|
|
1023
|
-
remove: async (ctx: ComponentCtx, keyId: string) => {
|
|
1024
|
-
await ctx.runMutation(config.component.public.keyDelete, {
|
|
1025
|
-
keyId,
|
|
1026
|
-
});
|
|
1027
|
-
},
|
|
1028
|
-
},
|
|
1029
|
-
/**
|
|
1030
|
-
* HTTP namespace — route registration and Bearer-authenticated endpoints.
|
|
1031
|
-
*/
|
|
1032
|
-
http: {
|
|
1033
|
-
/**
|
|
1034
|
-
* Register core HTTP routes for JWT verification and OAuth sign-in.
|
|
1035
|
-
*
|
|
1036
|
-
* ```ts
|
|
1037
|
-
* import { httpRouter } from "convex/server";
|
|
1038
|
-
* import { auth } from "./auth";
|
|
1039
|
-
*
|
|
1040
|
-
* const http = httpRouter();
|
|
1041
|
-
*
|
|
1042
|
-
* auth.http.add(http);
|
|
1043
|
-
*
|
|
1044
|
-
* export default http;
|
|
1045
|
-
* ```
|
|
1046
|
-
*
|
|
1047
|
-
* The following routes are handled always:
|
|
1048
|
-
*
|
|
1049
|
-
* - `/.well-known/openid-configuration`
|
|
1050
|
-
* - `/.well-known/jwks.json`
|
|
1051
|
-
*
|
|
1052
|
-
* The following routes are handled if OAuth is configured:
|
|
1053
|
-
*
|
|
1054
|
-
* - `/api/auth/signin/*`
|
|
1055
|
-
* - `/api/auth/callback/*`
|
|
1056
|
-
*
|
|
1057
|
-
* @param http your HTTP router
|
|
1058
|
-
*/
|
|
1059
|
-
add: (http: HttpRouter) => {
|
|
1060
|
-
http.route({
|
|
1061
|
-
path: "/.well-known/openid-configuration",
|
|
1062
|
-
method: "GET",
|
|
1063
|
-
handler: httpActionGeneric(async () => {
|
|
1064
|
-
return new Response(
|
|
1065
|
-
JSON.stringify({
|
|
1066
|
-
issuer: requireEnv("CONVEX_SITE_URL"),
|
|
1067
|
-
jwks_uri:
|
|
1068
|
-
requireEnv("CONVEX_SITE_URL") + "/.well-known/jwks.json",
|
|
1069
|
-
authorization_endpoint:
|
|
1070
|
-
requireEnv("CONVEX_SITE_URL") + "/oauth/authorize",
|
|
1071
|
-
}),
|
|
1072
|
-
{
|
|
1073
|
-
status: 200,
|
|
1074
|
-
headers: {
|
|
1075
|
-
"Content-Type": "application/json",
|
|
1076
|
-
"Cache-Control":
|
|
1077
|
-
"public, max-age=15, stale-while-revalidate=15, stale-if-error=86400",
|
|
1078
|
-
},
|
|
1079
|
-
},
|
|
1080
|
-
);
|
|
1081
|
-
}),
|
|
1082
|
-
});
|
|
1083
|
-
|
|
1084
|
-
http.route({
|
|
1085
|
-
path: "/.well-known/jwks.json",
|
|
1086
|
-
method: "GET",
|
|
1087
|
-
handler: httpActionGeneric(async () => {
|
|
1088
|
-
return new Response(requireEnv("JWKS"), {
|
|
1089
|
-
status: 200,
|
|
1090
|
-
headers: {
|
|
1091
|
-
"Content-Type": "application/json",
|
|
1092
|
-
"Cache-Control":
|
|
1093
|
-
"public, max-age=15, stale-while-revalidate=15, stale-if-error=86400",
|
|
1094
|
-
},
|
|
1095
|
-
});
|
|
1096
|
-
}),
|
|
1097
|
-
});
|
|
1098
|
-
|
|
1099
|
-
if (hasOAuth) {
|
|
1100
|
-
http.route({
|
|
1101
|
-
pathPrefix: "/api/auth/signin/",
|
|
1102
|
-
method: "GET",
|
|
1103
|
-
handler: httpActionGeneric(
|
|
1104
|
-
convertErrorsToResponse(400, async (ctx, request) => {
|
|
1105
|
-
const url = new URL(request.url);
|
|
1106
|
-
const pathParts = url.pathname.split("/");
|
|
1107
|
-
const providerId = pathParts.at(-1)!;
|
|
1108
|
-
if (providerId === null) {
|
|
1109
|
-
throwAuthError("OAUTH_MISSING_PROVIDER");
|
|
1110
|
-
}
|
|
1111
|
-
const verifier = url.searchParams.get("code");
|
|
1112
|
-
if (verifier === null) {
|
|
1113
|
-
throwAuthError("OAUTH_MISSING_VERIFIER");
|
|
1114
|
-
}
|
|
1115
|
-
const provider = getProviderOrThrow(providerId);
|
|
1116
|
-
|
|
1117
|
-
const oauthConfig = provider as OAuthMaterializedConfig;
|
|
1118
|
-
const { redirect, cookies, signature } =
|
|
1119
|
-
await createOAuthAuthorizationURL(
|
|
1120
|
-
providerId,
|
|
1121
|
-
oauthConfig.provider,
|
|
1122
|
-
oauthConfig,
|
|
1123
|
-
);
|
|
1124
|
-
|
|
1125
|
-
await callVerifierSignature(ctx, {
|
|
1126
|
-
verifier,
|
|
1127
|
-
signature,
|
|
1128
|
-
});
|
|
1129
|
-
|
|
1130
|
-
const redirectTo = url.searchParams.get("redirectTo");
|
|
1131
|
-
if (redirectTo !== null) {
|
|
1132
|
-
cookies.push(redirectToParamCookie(providerId, redirectTo));
|
|
1133
|
-
}
|
|
1134
|
-
|
|
1135
|
-
const headers = new Headers({ Location: redirect });
|
|
1136
|
-
for (const { name, value, options } of cookies) {
|
|
1137
|
-
headers.append(
|
|
1138
|
-
"Set-Cookie",
|
|
1139
|
-
serializeCookie(name, value, options as any),
|
|
1140
|
-
);
|
|
1141
|
-
}
|
|
1142
|
-
|
|
1143
|
-
return new Response(null, { status: 302, headers });
|
|
1144
|
-
}),
|
|
1145
|
-
),
|
|
1146
|
-
});
|
|
1147
|
-
|
|
1148
|
-
const callbackAction = httpActionGeneric(
|
|
1149
|
-
async (genericCtx, request) => {
|
|
1150
|
-
const ctx = genericCtx as unknown as ActionCtx;
|
|
1151
|
-
const url = new URL(request.url);
|
|
1152
|
-
const pathParts = url.pathname.split("/");
|
|
1153
|
-
const providerId = pathParts.at(-1)!;
|
|
1154
|
-
logWithLevel(
|
|
1155
|
-
LOG_LEVELS.DEBUG,
|
|
1156
|
-
"Handling OAuth callback for provider:",
|
|
1157
|
-
providerId,
|
|
1158
|
-
);
|
|
1159
|
-
const provider = getProviderOrThrow(providerId);
|
|
1160
|
-
|
|
1161
|
-
const cookies = getCookies(request);
|
|
1162
|
-
|
|
1163
|
-
const maybeRedirectTo = useRedirectToParam(provider.id, cookies);
|
|
1164
|
-
|
|
1165
|
-
const destinationUrl = await redirectAbsoluteUrl(config, {
|
|
1166
|
-
redirectTo: maybeRedirectTo?.redirectTo,
|
|
1167
|
-
});
|
|
1168
|
-
|
|
1169
|
-
const params = url.searchParams;
|
|
1170
|
-
|
|
1171
|
-
// Handle OAuth providers that use formData (such as Apple)
|
|
1172
|
-
if (
|
|
1173
|
-
request.headers.get("Content-Type") ===
|
|
1174
|
-
"application/x-www-form-urlencoded"
|
|
1175
|
-
) {
|
|
1176
|
-
const formData = await request.formData();
|
|
1177
|
-
for (const [key, value] of formData.entries()) {
|
|
1178
|
-
if (typeof value === "string") {
|
|
1179
|
-
params.append(key, value);
|
|
1180
|
-
}
|
|
1181
|
-
}
|
|
1182
|
-
}
|
|
1183
|
-
|
|
1184
|
-
try {
|
|
1185
|
-
const oauthConfig = provider as OAuthMaterializedConfig;
|
|
1186
|
-
const result = await handleOAuthCallback(
|
|
1187
|
-
providerId,
|
|
1188
|
-
oauthConfig.provider,
|
|
1189
|
-
oauthConfig,
|
|
1190
|
-
Object.fromEntries(params.entries()),
|
|
1191
|
-
cookies,
|
|
1192
|
-
);
|
|
1193
|
-
const { id: profileId, ...profileData } = result.profile;
|
|
1194
|
-
const { signature } = result;
|
|
1195
|
-
|
|
1196
|
-
const verificationCode = await callUserOAuth(ctx, {
|
|
1197
|
-
provider: providerId,
|
|
1198
|
-
providerAccountId: profileId,
|
|
1199
|
-
profile: profileData,
|
|
1200
|
-
signature,
|
|
1201
|
-
});
|
|
1202
|
-
|
|
1203
|
-
return new Response(null, {
|
|
1204
|
-
status: 302,
|
|
1205
|
-
headers: {
|
|
1206
|
-
Location: setURLSearchParam(
|
|
1207
|
-
destinationUrl,
|
|
1208
|
-
"code",
|
|
1209
|
-
verificationCode,
|
|
1210
|
-
),
|
|
1211
|
-
"Cache-Control": "must-revalidate",
|
|
1212
|
-
},
|
|
1213
|
-
});
|
|
1214
|
-
} catch (error) {
|
|
1215
|
-
logError(error);
|
|
1216
|
-
return Response.redirect(destinationUrl);
|
|
1217
|
-
}
|
|
1218
|
-
},
|
|
1219
|
-
);
|
|
1220
|
-
|
|
1221
|
-
http.route({
|
|
1222
|
-
pathPrefix: "/api/auth/callback/",
|
|
1223
|
-
method: "GET",
|
|
1224
|
-
handler: callbackAction,
|
|
1225
|
-
});
|
|
1226
|
-
|
|
1227
|
-
http.route({
|
|
1228
|
-
pathPrefix: "/api/auth/callback/",
|
|
1229
|
-
method: "POST",
|
|
1230
|
-
handler: callbackAction,
|
|
1231
|
-
});
|
|
1232
|
-
}
|
|
1233
|
-
},
|
|
1234
|
-
|
|
1235
|
-
/**
|
|
1236
|
-
* Wrap an HTTP action handler with Bearer token authentication.
|
|
1237
|
-
*
|
|
1238
|
-
* Extracts the `Authorization: Bearer <key>` header, verifies the
|
|
1239
|
-
* API key via `auth.key.verify()`, and injects `ctx.key` with the
|
|
1240
|
-
* verified key info. Returns structured JSON error responses for
|
|
1241
|
-
* missing/invalid/revoked/expired/rate-limited keys.
|
|
1242
|
-
*
|
|
1243
|
-
* If the handler returns a plain object, it is auto-wrapped in a
|
|
1244
|
-
* `200 JSON` response. If it returns a `Response`, CORS headers
|
|
1245
|
-
* are merged and the response is passed through.
|
|
1246
|
-
*
|
|
1247
|
-
* ```ts
|
|
1248
|
-
* const handler = auth.http.action(async (ctx, request) => {
|
|
1249
|
-
* const data = await ctx.runQuery(api.data.get, { userId: ctx.key.userId });
|
|
1250
|
-
* return { data };
|
|
1251
|
-
* });
|
|
1252
|
-
* http.route({ path: "/api/data", method: "GET", handler });
|
|
1253
|
-
* ```
|
|
1254
|
-
*
|
|
1255
|
-
* @param handler - Receives enriched `ctx` (with `ctx.key`) and the raw `Request`.
|
|
1256
|
-
* @param options.scope - Optional scope check; returns 403 if the key lacks permission.
|
|
1257
|
-
* @param options.cors - CORS config; defaults to permissive (`*`).
|
|
1258
|
-
*/
|
|
1259
|
-
action: (
|
|
1260
|
-
handler: (
|
|
1261
|
-
ctx: GenericActionCtx<GenericDataModel> & HttpKeyContext,
|
|
1262
|
-
request: Request,
|
|
1263
|
-
) => Promise<Response | Record<string, unknown>>,
|
|
1264
|
-
options?: {
|
|
1265
|
-
scope?: { resource: string; action: string };
|
|
1266
|
-
cors?: CorsConfig;
|
|
1267
|
-
},
|
|
1268
|
-
) => {
|
|
1269
|
-
const corsConfig = options?.cors ?? {};
|
|
1270
|
-
const corsHeaders: Record<string, string> = {
|
|
1271
|
-
"Access-Control-Allow-Origin": corsConfig.origin ?? "*",
|
|
1272
|
-
"Access-Control-Allow-Methods":
|
|
1273
|
-
corsConfig.methods ?? "GET,POST,PUT,PATCH,DELETE,OPTIONS",
|
|
1274
|
-
"Access-Control-Allow-Headers":
|
|
1275
|
-
corsConfig.headers ?? "Content-Type,Authorization",
|
|
1276
|
-
};
|
|
1277
|
-
|
|
1278
|
-
const jsonError = (
|
|
1279
|
-
status: number,
|
|
1280
|
-
code: string,
|
|
1281
|
-
message: string,
|
|
1282
|
-
) =>
|
|
1283
|
-
new Response(JSON.stringify({ error: message, code }), {
|
|
1284
|
-
status,
|
|
1285
|
-
headers: { ...corsHeaders, "Content-Type": "application/json" },
|
|
1286
|
-
});
|
|
1287
|
-
|
|
1288
|
-
return httpActionGeneric(async (genericCtx, request) => {
|
|
1289
|
-
const ctx = genericCtx as unknown as GenericActionCtx<GenericDataModel>;
|
|
1290
|
-
|
|
1291
|
-
try {
|
|
1292
|
-
// 1. Extract Bearer token
|
|
1293
|
-
const authHeader = request.headers.get("Authorization");
|
|
1294
|
-
if (!authHeader?.startsWith("Bearer ")) {
|
|
1295
|
-
return jsonError(
|
|
1296
|
-
401,
|
|
1297
|
-
"MISSING_BEARER_TOKEN",
|
|
1298
|
-
"Missing or malformed Authorization: Bearer header.",
|
|
1299
|
-
);
|
|
1300
|
-
}
|
|
1301
|
-
const rawKey = authHeader.slice(7);
|
|
1302
|
-
|
|
1303
|
-
// 2. Verify API key
|
|
1304
|
-
let keyResult: { userId: string; keyId: string; scopes: import("../types.js").ScopeChecker };
|
|
1305
|
-
try {
|
|
1306
|
-
keyResult = await auth.key.verify(ctx, rawKey);
|
|
1307
|
-
} catch (error: unknown) {
|
|
1308
|
-
if (isAuthError(error)) {
|
|
1309
|
-
const { code, message } = error.data as { code: string; message: string };
|
|
1310
|
-
return jsonError(403, code, message);
|
|
1311
|
-
}
|
|
1312
|
-
throw error;
|
|
1313
|
-
}
|
|
1314
|
-
|
|
1315
|
-
// 3. Optional scope check
|
|
1316
|
-
if (options?.scope) {
|
|
1317
|
-
if (!keyResult.scopes.can(options.scope.resource, options.scope.action)) {
|
|
1318
|
-
return jsonError(
|
|
1319
|
-
403,
|
|
1320
|
-
"SCOPE_CHECK_FAILED",
|
|
1321
|
-
"This API key does not have the required permissions.",
|
|
1322
|
-
);
|
|
1323
|
-
}
|
|
1324
|
-
}
|
|
1325
|
-
|
|
1326
|
-
// 4. Enrich context with key info
|
|
1327
|
-
const enrichedCtx = Object.assign(ctx, {
|
|
1328
|
-
key: {
|
|
1329
|
-
userId: keyResult.userId,
|
|
1330
|
-
keyId: keyResult.keyId,
|
|
1331
|
-
scopes: keyResult.scopes,
|
|
1332
|
-
},
|
|
1333
|
-
});
|
|
1334
|
-
|
|
1335
|
-
// 5. Call handler
|
|
1336
|
-
const result = await handler(enrichedCtx, request);
|
|
1337
|
-
|
|
1338
|
-
// 6. Auto-wrap plain objects as JSON responses
|
|
1339
|
-
if (result instanceof Response) {
|
|
1340
|
-
// Merge CORS headers into existing response
|
|
1341
|
-
const headers = new Headers(result.headers);
|
|
1342
|
-
for (const [k, val] of Object.entries(corsHeaders)) {
|
|
1343
|
-
if (!headers.has(k)) headers.set(k, val);
|
|
1344
|
-
}
|
|
1345
|
-
return new Response(result.body, {
|
|
1346
|
-
status: result.status,
|
|
1347
|
-
statusText: result.statusText,
|
|
1348
|
-
headers,
|
|
1349
|
-
});
|
|
1350
|
-
}
|
|
1351
|
-
|
|
1352
|
-
return new Response(JSON.stringify(result), {
|
|
1353
|
-
status: 200,
|
|
1354
|
-
headers: { ...corsHeaders, "Content-Type": "application/json" },
|
|
1355
|
-
});
|
|
1356
|
-
} catch (error: unknown) {
|
|
1357
|
-
logError(error);
|
|
1358
|
-
return jsonError(500, "INTERNAL_ERROR", "An unexpected error occurred.");
|
|
1359
|
-
}
|
|
1360
|
-
});
|
|
1361
|
-
},
|
|
1362
|
-
|
|
1363
|
-
/**
|
|
1364
|
-
* Register a Bearer-authenticated route **and** its OPTIONS preflight
|
|
1365
|
-
* in a single call.
|
|
1366
|
-
*
|
|
1367
|
-
* ```ts
|
|
1368
|
-
* auth.http.route(http, {
|
|
1369
|
-
* path: "/api/messages",
|
|
1370
|
-
* method: "POST",
|
|
1371
|
-
* handler: async (ctx, request) => {
|
|
1372
|
-
* const { body } = await request.json();
|
|
1373
|
-
* await ctx.runMutation(internal.messages.sendAsUser, {
|
|
1374
|
-
* userId: ctx.key.userId,
|
|
1375
|
-
* body,
|
|
1376
|
-
* });
|
|
1377
|
-
* return { success: true };
|
|
1378
|
-
* },
|
|
1379
|
-
* });
|
|
1380
|
-
* ```
|
|
1381
|
-
*
|
|
1382
|
-
* @param http - The Convex HTTP router.
|
|
1383
|
-
* @param routeConfig.path - The URL path to match.
|
|
1384
|
-
* @param routeConfig.method - HTTP method (GET, POST, PUT, PATCH, DELETE).
|
|
1385
|
-
* @param routeConfig.handler - Receives enriched `ctx` (with `ctx.key`) and the raw `Request`.
|
|
1386
|
-
* @param routeConfig.scope - Optional scope check; returns 403 if the key lacks permission.
|
|
1387
|
-
* @param routeConfig.cors - CORS config; defaults to permissive (`*`).
|
|
1388
|
-
*/
|
|
1389
|
-
route: (
|
|
1390
|
-
http: HttpRouter,
|
|
1391
|
-
routeConfig: {
|
|
1392
|
-
path: string;
|
|
1393
|
-
method: "GET" | "POST" | "PUT" | "PATCH" | "DELETE";
|
|
1394
|
-
handler: (
|
|
1395
|
-
ctx: GenericActionCtx<GenericDataModel> & HttpKeyContext,
|
|
1396
|
-
request: Request,
|
|
1397
|
-
) => Promise<Response | Record<string, unknown>>;
|
|
1398
|
-
scope?: { resource: string; action: string };
|
|
1399
|
-
cors?: CorsConfig;
|
|
1400
|
-
},
|
|
1401
|
-
) => {
|
|
1402
|
-
const corsConfig = routeConfig.cors ?? {};
|
|
1403
|
-
const corsHeaders: Record<string, string> = {
|
|
1404
|
-
"Access-Control-Allow-Origin": corsConfig.origin ?? "*",
|
|
1405
|
-
"Access-Control-Allow-Methods":
|
|
1406
|
-
corsConfig.methods ?? "GET,POST,PUT,PATCH,DELETE,OPTIONS",
|
|
1407
|
-
"Access-Control-Allow-Headers":
|
|
1408
|
-
corsConfig.headers ?? "Content-Type,Authorization",
|
|
1409
|
-
};
|
|
1410
|
-
|
|
1411
|
-
// Register OPTIONS preflight
|
|
1412
|
-
http.route({
|
|
1413
|
-
path: routeConfig.path,
|
|
1414
|
-
method: "OPTIONS",
|
|
1415
|
-
handler: httpActionGeneric(async () => {
|
|
1416
|
-
return new Response(null, { status: 204, headers: corsHeaders });
|
|
1417
|
-
}),
|
|
1418
|
-
});
|
|
1419
|
-
|
|
1420
|
-
// Register the main route with Bearer auth wrapping
|
|
1421
|
-
http.route({
|
|
1422
|
-
path: routeConfig.path,
|
|
1423
|
-
method: routeConfig.method,
|
|
1424
|
-
handler: auth.http.action(routeConfig.handler, {
|
|
1425
|
-
scope: routeConfig.scope,
|
|
1426
|
-
cors: routeConfig.cors,
|
|
1427
|
-
}),
|
|
1428
|
-
});
|
|
1429
|
-
},
|
|
1430
|
-
},
|
|
1431
|
-
};
|
|
1432
|
-
const enrichCtx = <DataModel extends GenericDataModel>(
|
|
1433
|
-
ctx: GenericActionCtx<DataModel>,
|
|
1434
|
-
) => ({
|
|
1435
|
-
...ctx,
|
|
1436
|
-
auth: {
|
|
1437
|
-
...ctx.auth,
|
|
1438
|
-
config,
|
|
1439
|
-
account: auth.account,
|
|
1440
|
-
session: auth.session,
|
|
1441
|
-
provider: auth.provider,
|
|
1442
|
-
},
|
|
1443
|
-
});
|
|
1444
|
-
|
|
1445
|
-
return {
|
|
1446
|
-
/**
|
|
1447
|
-
* Helper for configuring HTTP actions.
|
|
1448
|
-
*/
|
|
1449
|
-
auth,
|
|
1450
|
-
/**
|
|
1451
|
-
* Action called by the client to sign the user in.
|
|
1452
|
-
*
|
|
1453
|
-
* Also used for refreshing the session.
|
|
1454
|
-
*/
|
|
1455
|
-
signIn: actionGeneric({
|
|
1456
|
-
args: {
|
|
1457
|
-
provider: v.optional(v.string()),
|
|
1458
|
-
params: v.optional(v.any()),
|
|
1459
|
-
verifier: v.optional(v.string()),
|
|
1460
|
-
refreshToken: v.optional(v.string()),
|
|
1461
|
-
calledBy: v.optional(v.string()),
|
|
1462
|
-
},
|
|
1463
|
-
handler: async (
|
|
1464
|
-
ctx,
|
|
1465
|
-
args,
|
|
1466
|
-
): Promise<{
|
|
1467
|
-
redirect?: string;
|
|
1468
|
-
verifier?: string;
|
|
1469
|
-
tokens?: Tokens | null;
|
|
1470
|
-
started?: boolean;
|
|
1471
|
-
options?: Record<string, any>;
|
|
1472
|
-
totpRequired?: boolean;
|
|
1473
|
-
totpSetup?: { uri: string; secret: string; totpId: string };
|
|
1474
|
-
deviceCode?: {
|
|
1475
|
-
deviceCode: string;
|
|
1476
|
-
userCode: string;
|
|
1477
|
-
verificationUri: string;
|
|
1478
|
-
verificationUriComplete: string;
|
|
1479
|
-
expiresIn: number;
|
|
1480
|
-
interval: number;
|
|
1481
|
-
};
|
|
1482
|
-
}> => {
|
|
1483
|
-
if (args.calledBy !== undefined) {
|
|
1484
|
-
logWithLevel("INFO", `\`auth:signIn\` called by ${args.calledBy}`);
|
|
1485
|
-
}
|
|
1486
|
-
const provider =
|
|
1487
|
-
args.provider !== undefined
|
|
1488
|
-
? getProviderOrThrow(args.provider)
|
|
1489
|
-
: null;
|
|
1490
|
-
const result = await signInImpl(enrichCtx(ctx), provider, args, {
|
|
1491
|
-
generateTokens: true,
|
|
1492
|
-
allowExtraProviders: false,
|
|
1493
|
-
});
|
|
1494
|
-
switch (result.kind) {
|
|
1495
|
-
case "redirect":
|
|
1496
|
-
return { redirect: result.redirect, verifier: result.verifier };
|
|
1497
|
-
case "signedIn":
|
|
1498
|
-
case "refreshTokens":
|
|
1499
|
-
return { tokens: result.signedIn?.tokens ?? null };
|
|
1500
|
-
case "started":
|
|
1501
|
-
return { started: true };
|
|
1502
|
-
case "passkeyOptions":
|
|
1503
|
-
return { options: result.options, verifier: result.verifier };
|
|
1504
|
-
case "totpRequired":
|
|
1505
|
-
return { totpRequired: true, verifier: result.verifier };
|
|
1506
|
-
case "totpSetup":
|
|
1507
|
-
return { totpSetup: { uri: result.uri, secret: result.secret, totpId: result.totpId }, verifier: result.verifier };
|
|
1508
|
-
case "deviceCode":
|
|
1509
|
-
return {
|
|
1510
|
-
deviceCode: {
|
|
1511
|
-
deviceCode: result.deviceCode,
|
|
1512
|
-
userCode: result.userCode,
|
|
1513
|
-
verificationUri: result.verificationUri,
|
|
1514
|
-
verificationUriComplete: result.verificationUriComplete,
|
|
1515
|
-
expiresIn: result.expiresIn,
|
|
1516
|
-
interval: result.interval,
|
|
1517
|
-
},
|
|
1518
|
-
};
|
|
1519
|
-
default: {
|
|
1520
|
-
const _typecheck: never = result;
|
|
1521
|
-
throwAuthError("INTERNAL_ERROR", `Unexpected result from signIn, ${String(result)}`);
|
|
1522
|
-
}
|
|
1523
|
-
}
|
|
1524
|
-
},
|
|
1525
|
-
}),
|
|
1526
|
-
/**
|
|
1527
|
-
* Action called by the client to invalidate the current session.
|
|
1528
|
-
*/
|
|
1529
|
-
signOut: actionGeneric({
|
|
1530
|
-
args: {},
|
|
1531
|
-
handler: async (ctx) => {
|
|
1532
|
-
await callSignOut(ctx);
|
|
1533
|
-
},
|
|
1534
|
-
}),
|
|
1535
|
-
|
|
1536
|
-
/**
|
|
1537
|
-
* Internal mutation used by the library to read and write
|
|
1538
|
-
* to the database during signin and signout.
|
|
1539
|
-
*/
|
|
1540
|
-
store: internalMutationGeneric({
|
|
1541
|
-
args: storeArgs,
|
|
1542
|
-
handler: async (ctx: MutationCtx, args) => {
|
|
1543
|
-
return storeImpl(ctx, args, getProviderOrThrow, config);
|
|
1544
|
-
},
|
|
1545
|
-
}),
|
|
1546
|
-
|
|
1547
|
-
};
|
|
1548
|
-
}
|
|
1549
|
-
|
|
1550
|
-
function convertErrorsToResponse(
|
|
1551
|
-
errorStatusCode: number,
|
|
1552
|
-
action: (ctx: GenericActionCtx<any>, request: Request) => Promise<Response>,
|
|
1553
|
-
) {
|
|
1554
|
-
return async (ctx: GenericActionCtx<any>, request: Request) => {
|
|
1555
|
-
try {
|
|
1556
|
-
return await action(ctx, request);
|
|
1557
|
-
} catch (error) {
|
|
1558
|
-
if (isAuthError(error)) {
|
|
1559
|
-
return new Response(
|
|
1560
|
-
JSON.stringify({ code: error.data.code, message: error.data.message }),
|
|
1561
|
-
{
|
|
1562
|
-
status: errorStatusCode,
|
|
1563
|
-
headers: { "Content-Type": "application/json" },
|
|
1564
|
-
},
|
|
1565
|
-
);
|
|
1566
|
-
} else if (error instanceof ConvexError) {
|
|
1567
|
-
return new Response(null, {
|
|
1568
|
-
status: errorStatusCode,
|
|
1569
|
-
statusText: typeof error.data === "string" ? error.data : "Error",
|
|
1570
|
-
});
|
|
1571
|
-
} else {
|
|
1572
|
-
logError(error);
|
|
1573
|
-
return new Response(null, {
|
|
1574
|
-
status: 500,
|
|
1575
|
-
statusText: "Internal Server Error",
|
|
1576
|
-
});
|
|
1577
|
-
}
|
|
1578
|
-
}
|
|
1579
|
-
};
|
|
1580
|
-
}
|
|
1581
|
-
function getCookies(request: Request): Record<string, string | undefined> {
|
|
1582
|
-
return parseCookies(request.headers.get("Cookie") ?? "");
|
|
1583
|
-
}
|