@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,105 +0,0 @@
|
|
|
1
|
-
import { LOG_LEVELS, logWithLevel, sha256 } from "../utils.js";
|
|
2
|
-
import { authDb } from "../db.js";
|
|
3
|
-
import { createNewAndDeleteExistingSession, getAuthSessionId, maybeGenerateTokensForSession } from "../sessions.js";
|
|
4
|
-
import { AUTH_STORE_REF } from "./store.js";
|
|
5
|
-
import { isSignInRateLimited, recordFailedSignIn, resetSignInRateLimit } from "../ratelimit.js";
|
|
6
|
-
import { upsertUserAndAccount } from "../users.js";
|
|
7
|
-
import { v } from "convex/values";
|
|
8
|
-
|
|
9
|
-
//#region src/server/implementation/mutations/verify.ts
|
|
10
|
-
const verifyCodeAndSignInArgs = v.object({
|
|
11
|
-
params: v.any(),
|
|
12
|
-
provider: v.optional(v.string()),
|
|
13
|
-
verifier: v.optional(v.string()),
|
|
14
|
-
generateTokens: v.boolean(),
|
|
15
|
-
allowExtraProviders: v.boolean()
|
|
16
|
-
});
|
|
17
|
-
async function verifyCodeAndSignInImpl(ctx, args, getProviderOrThrow, config) {
|
|
18
|
-
logWithLevel(LOG_LEVELS.DEBUG, "verifyCodeAndSignInImpl args:", {
|
|
19
|
-
params: {
|
|
20
|
-
email: args.params.email,
|
|
21
|
-
phone: args.params.phone
|
|
22
|
-
},
|
|
23
|
-
provider: args.provider,
|
|
24
|
-
verifier: args.verifier,
|
|
25
|
-
generateTokens: args.generateTokens,
|
|
26
|
-
allowExtraProviders: args.allowExtraProviders
|
|
27
|
-
});
|
|
28
|
-
const { generateTokens, provider, allowExtraProviders } = args;
|
|
29
|
-
const identifier = args.params.email ?? args.params.phone;
|
|
30
|
-
if (identifier !== void 0) {
|
|
31
|
-
if (await isSignInRateLimited(ctx, identifier, config)) {
|
|
32
|
-
logWithLevel(LOG_LEVELS.ERROR, "Too many failed attempts to verify code for this email");
|
|
33
|
-
return null;
|
|
34
|
-
}
|
|
35
|
-
}
|
|
36
|
-
const verifyResult = await verifyCodeOnly(ctx, args, provider ?? null, getProviderOrThrow, allowExtraProviders, config, await getAuthSessionId(ctx));
|
|
37
|
-
if (verifyResult === null) {
|
|
38
|
-
if (identifier !== void 0) await recordFailedSignIn(ctx, identifier, config);
|
|
39
|
-
return null;
|
|
40
|
-
}
|
|
41
|
-
if (identifier !== void 0) await resetSignInRateLimit(ctx, identifier, config);
|
|
42
|
-
const { userId } = verifyResult;
|
|
43
|
-
return await maybeGenerateTokensForSession(ctx, config, userId, await createNewAndDeleteExistingSession(ctx, config, userId), generateTokens);
|
|
44
|
-
}
|
|
45
|
-
const callVerifyCodeAndSignIn = async (ctx, args) => {
|
|
46
|
-
return ctx.runMutation(AUTH_STORE_REF, { args: {
|
|
47
|
-
type: "verifyCodeAndSignIn",
|
|
48
|
-
...args
|
|
49
|
-
} });
|
|
50
|
-
};
|
|
51
|
-
async function verifyCodeOnly(ctx, args, methodProviderId, getProviderOrThrow, allowExtraProviders, config, sessionId) {
|
|
52
|
-
const db = authDb(ctx, config);
|
|
53
|
-
const { params, verifier } = args;
|
|
54
|
-
const codeHash = await sha256(params.code);
|
|
55
|
-
const verificationCode = await db.verificationCodes.getByCode(codeHash);
|
|
56
|
-
if (verificationCode === null) {
|
|
57
|
-
logWithLevel(LOG_LEVELS.ERROR, "Invalid verification code");
|
|
58
|
-
return null;
|
|
59
|
-
}
|
|
60
|
-
await db.verificationCodes.delete(verificationCode._id);
|
|
61
|
-
if (verificationCode.verifier !== verifier) {
|
|
62
|
-
logWithLevel(LOG_LEVELS.ERROR, "Invalid verifier");
|
|
63
|
-
return null;
|
|
64
|
-
}
|
|
65
|
-
if (verificationCode.expirationTime < Date.now()) {
|
|
66
|
-
logWithLevel(LOG_LEVELS.ERROR, "Expired verification code");
|
|
67
|
-
return null;
|
|
68
|
-
}
|
|
69
|
-
const { accountId, emailVerified, phoneVerified } = verificationCode;
|
|
70
|
-
const account = await db.accounts.getById(accountId);
|
|
71
|
-
if (account === null) {
|
|
72
|
-
logWithLevel(LOG_LEVELS.ERROR, "Account associated with this email has been deleted");
|
|
73
|
-
return null;
|
|
74
|
-
}
|
|
75
|
-
if (methodProviderId !== null && verificationCode.provider !== methodProviderId) {
|
|
76
|
-
logWithLevel(LOG_LEVELS.ERROR, `Invalid provider "${methodProviderId}" for given \`code\`, which was generated by provider "${verificationCode.provider}"`);
|
|
77
|
-
return null;
|
|
78
|
-
}
|
|
79
|
-
const methodProvider = getProviderOrThrow(verificationCode.provider, allowExtraProviders);
|
|
80
|
-
if (methodProvider !== null && (methodProvider.type === "email" || methodProvider.type === "phone") && methodProvider.authorize !== void 0) await methodProvider.authorize(args.params, account);
|
|
81
|
-
let userId = account.userId;
|
|
82
|
-
const provider = getProviderOrThrow(account.provider);
|
|
83
|
-
if (provider.type !== "oauth") ({userId} = await upsertUserAndAccount(ctx, sessionId, { existingAccount: account }, {
|
|
84
|
-
type: "verification",
|
|
85
|
-
provider,
|
|
86
|
-
profile: {
|
|
87
|
-
...emailVerified !== void 0 ? {
|
|
88
|
-
email: emailVerified,
|
|
89
|
-
emailVerified: true
|
|
90
|
-
} : {},
|
|
91
|
-
...phoneVerified !== void 0 ? {
|
|
92
|
-
phone: phoneVerified,
|
|
93
|
-
phoneVerified: true
|
|
94
|
-
} : {}
|
|
95
|
-
}
|
|
96
|
-
}, config));
|
|
97
|
-
return {
|
|
98
|
-
providerAccountId: account.providerAccountId,
|
|
99
|
-
userId
|
|
100
|
-
};
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
//#endregion
|
|
104
|
-
export { callVerifyCodeAndSignIn, verifyCodeAndSignInArgs, verifyCodeAndSignInImpl };
|
|
105
|
-
//# sourceMappingURL=verify.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"verify.js","names":[],"sources":["../../../../src/server/implementation/mutations/verify.ts"],"sourcesContent":["import { GenericId, Infer, v } from \"convex/values\";\nimport { ActionCtx, MutationCtx, SessionInfo } from \"../types\";\nimport {\n isSignInRateLimited,\n recordFailedSignIn,\n resetSignInRateLimit,\n} from \"../ratelimit\";\nimport * as Provider from \"../provider\";\nimport {\n createNewAndDeleteExistingSession,\n getAuthSessionId,\n maybeGenerateTokensForSession,\n} from \"../sessions\";\nimport { ConvexAuthConfig } from \"../../types\";\nimport { LOG_LEVELS, logWithLevel, sha256 } from \"../utils\";\nimport { upsertUserAndAccount } from \"../users\";\nimport { authDb } from \"../db\";\nimport { AUTH_STORE_REF } from \"./store\";\n\nexport const verifyCodeAndSignInArgs = v.object({\n params: v.any(),\n provider: v.optional(v.string()),\n verifier: v.optional(v.string()),\n generateTokens: v.boolean(),\n allowExtraProviders: v.boolean(),\n});\n\ntype ReturnType = null | SessionInfo;\n\nexport async function verifyCodeAndSignInImpl(\n ctx: MutationCtx,\n args: Infer<typeof verifyCodeAndSignInArgs>,\n getProviderOrThrow: Provider.GetProviderOrThrowFunc,\n config: Provider.Config,\n): Promise<ReturnType> {\n logWithLevel(LOG_LEVELS.DEBUG, \"verifyCodeAndSignInImpl args:\", {\n params: { email: args.params.email, phone: args.params.phone },\n provider: args.provider,\n verifier: args.verifier,\n generateTokens: args.generateTokens,\n allowExtraProviders: args.allowExtraProviders,\n });\n const { generateTokens, provider, allowExtraProviders } = args;\n const identifier = args.params.email ?? args.params.phone;\n if (identifier !== undefined) {\n if (await isSignInRateLimited(ctx, identifier, config)) {\n logWithLevel(\n LOG_LEVELS.ERROR,\n \"Too many failed attempts to verify code for this email\",\n );\n return null;\n }\n }\n const verifyResult = await verifyCodeOnly(\n ctx,\n args,\n provider ?? null,\n getProviderOrThrow,\n allowExtraProviders,\n config,\n await getAuthSessionId(ctx),\n );\n if (verifyResult === null) {\n if (identifier !== undefined) {\n await recordFailedSignIn(ctx, identifier, config);\n }\n return null;\n }\n if (identifier !== undefined) {\n await resetSignInRateLimit(ctx, identifier, config);\n }\n const { userId } = verifyResult;\n const sessionId = await createNewAndDeleteExistingSession(\n ctx,\n config,\n userId,\n );\n return await maybeGenerateTokensForSession(\n ctx,\n config,\n userId,\n sessionId,\n generateTokens,\n );\n}\n\nexport const callVerifyCodeAndSignIn = async (\n ctx: ActionCtx,\n args: Infer<typeof verifyCodeAndSignInArgs>,\n): Promise<ReturnType> => {\n return ctx.runMutation(AUTH_STORE_REF, {\n args: {\n type: \"verifyCodeAndSignIn\",\n ...args,\n },\n });\n};\n\nasync function verifyCodeOnly(\n ctx: MutationCtx,\n args: {\n params: any;\n verifier?: string;\n identifier?: string;\n },\n /**\n * There are two providers at play:\n * 1. the provider that generated the code\n * 2. the provider the account is tied to.\n * This is because we allow signing into an account\n * via another provider, see {@link signInViaProvider}.\n * This is the first provider.\n */\n methodProviderId: string | null,\n getProviderOrThrow: Provider.GetProviderOrThrowFunc,\n allowExtraProviders: boolean,\n config: ConvexAuthConfig,\n sessionId: GenericId<\"session\"> | null,\n) {\n const db = authDb(ctx, config);\n const { params, verifier } = args;\n const codeHash = await sha256(params.code);\n const verificationCode = await db.verificationCodes.getByCode(codeHash);\n if (verificationCode === null) {\n logWithLevel(LOG_LEVELS.ERROR, \"Invalid verification code\");\n return null;\n }\n await db.verificationCodes.delete(verificationCode._id);\n if (verificationCode.verifier !== verifier) {\n logWithLevel(LOG_LEVELS.ERROR, \"Invalid verifier\");\n return null;\n }\n if (verificationCode.expirationTime < Date.now()) {\n logWithLevel(LOG_LEVELS.ERROR, \"Expired verification code\");\n return null;\n }\n const { accountId, emailVerified, phoneVerified } = verificationCode;\n const account = await db.accounts.getById(accountId);\n if (account === null) {\n logWithLevel(\n LOG_LEVELS.ERROR,\n \"Account associated with this email has been deleted\",\n );\n return null;\n }\n if (\n methodProviderId !== null &&\n verificationCode.provider !== methodProviderId\n ) {\n logWithLevel(\n LOG_LEVELS.ERROR,\n `Invalid provider \"${methodProviderId}\" for given \\`code\\`, ` +\n `which was generated by provider \"${verificationCode.provider}\"`,\n );\n return null;\n }\n // OTP providers perform an additional check against the provided\n // params.\n const methodProvider = getProviderOrThrow(\n verificationCode.provider,\n allowExtraProviders,\n );\n if (\n methodProvider !== null &&\n (methodProvider.type === \"email\" || methodProvider.type === \"phone\") &&\n methodProvider.authorize !== undefined\n ) {\n await methodProvider.authorize(args.params, account);\n }\n let userId = account.userId;\n const provider = getProviderOrThrow(account.provider);\n if (provider.type !== \"oauth\") {\n ({ userId } = await upsertUserAndAccount(\n ctx,\n sessionId,\n { existingAccount: account },\n {\n type: \"verification\",\n provider,\n profile: {\n ...(emailVerified !== undefined\n ? { email: emailVerified, emailVerified: true }\n : {}),\n ...(phoneVerified !== undefined\n ? { phone: phoneVerified, phoneVerified: true }\n : {}),\n },\n },\n config,\n ));\n }\n\n return { providerAccountId: account.providerAccountId, userId };\n}\n"],"mappings":"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"}
|
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
import { AuthDataModel, SessionInfo } from "./types.js";
|
|
2
|
-
import { GenericActionCtxWithAuthConfig, PasskeyProviderConfig } from "../types.js";
|
|
3
|
-
|
|
4
|
-
//#region src/server/implementation/passkey.d.ts
|
|
5
|
-
type EnrichedActionCtx = GenericActionCtxWithAuthConfig<AuthDataModel>;
|
|
6
|
-
/**
|
|
7
|
-
* Main passkey handler dispatched from signIn.ts.
|
|
8
|
-
*
|
|
9
|
-
* Routes to the appropriate phase based on `params.flow`.
|
|
10
|
-
*/
|
|
11
|
-
declare function handlePasskey(ctx: EnrichedActionCtx, provider: PasskeyProviderConfig, args: {
|
|
12
|
-
params?: Record<string, any>;
|
|
13
|
-
verifier?: string;
|
|
14
|
-
}): Promise<{
|
|
15
|
-
kind: "signedIn";
|
|
16
|
-
signedIn: SessionInfo | null;
|
|
17
|
-
} | {
|
|
18
|
-
kind: "passkeyOptions";
|
|
19
|
-
options: Record<string, any>;
|
|
20
|
-
verifier: string;
|
|
21
|
-
}>;
|
|
22
|
-
//#endregion
|
|
23
|
-
export { handlePasskey };
|
|
24
|
-
//# sourceMappingURL=passkey.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"passkey.d.ts","names":[],"sources":["../../../src/server/implementation/passkey.ts"],"mappings":";;;;KA8DK,iBAAA,GAAoB,8BAAA,CAA+B,aAAA;;;;;;iBA0flC,aAAA,CACpB,GAAA,EAAK,iBAAA,EACL,QAAA,EAAU,qBAAA,EACV,IAAA;EACE,MAAA,GAAS,MAAA;EACT,QAAA;AAAA,IAED,OAAA;EACG,IAAA;EAAkB,QAAA,EAAU,WAAA;AAAA;EAC5B,IAAA;EAAwB,OAAA,EAAS,MAAA;EAAqB,QAAA;AAAA"}
|
|
@@ -1,307 +0,0 @@
|
|
|
1
|
-
import { throwAuthError } from "../errors.js";
|
|
2
|
-
import { authDb } from "./db.js";
|
|
3
|
-
import { callSignIn } from "./mutations/signin.js";
|
|
4
|
-
import { callVerifierSignature } from "./mutations/signature.js";
|
|
5
|
-
import { callVerifier } from "./mutations/verifier.js";
|
|
6
|
-
import { mutatePasskeyInsert, mutatePasskeyUpdateCounter, mutateVerifierDelete, queryPasskeyByCredentialId, queryPasskeysByUserId, queryUserById, queryUserByVerifiedEmail, queryVerifierById } from "./types.js";
|
|
7
|
-
import { sha256 } from "@oslojs/crypto/sha2";
|
|
8
|
-
import { decodeBase64urlIgnorePadding, encodeBase64urlNoPadding } from "@oslojs/encoding";
|
|
9
|
-
import { COSEKeyType, ClientDataType, coseAlgorithmES256, coseAlgorithmRS256, createAssertionSignatureMessage, parseAttestationObject, parseAuthenticatorData, parseClientDataJSON } from "@oslojs/webauthn";
|
|
10
|
-
import { decodePKIXECDSASignature, decodeSEC1PublicKey, p256, verifyECDSASignature } from "@oslojs/crypto/ecdsa";
|
|
11
|
-
import { RSAPublicKey, decodePKCS1RSAPublicKey, sha256ObjectIdentifier, verifyRSASSAPKCS1v15Signature } from "@oslojs/crypto/rsa";
|
|
12
|
-
|
|
13
|
-
//#region src/server/implementation/passkey.ts
|
|
14
|
-
/**
|
|
15
|
-
* Server-side WebAuthn ceremony logic for passkey authentication.
|
|
16
|
-
*
|
|
17
|
-
* Handles the four phases of the WebAuthn flow:
|
|
18
|
-
* 1. register-options — generate PublicKeyCredentialCreationOptions
|
|
19
|
-
* 2. register-verify — verify attestation and store credential
|
|
20
|
-
* 3. auth-options — generate PublicKeyCredentialRequestOptions
|
|
21
|
-
* 4. auth-verify — verify assertion signature and sign in
|
|
22
|
-
*
|
|
23
|
-
* Uses `@oslojs/webauthn` for attestation/assertion parsing and
|
|
24
|
-
* `@oslojs/crypto` for signature verification.
|
|
25
|
-
*/
|
|
26
|
-
/**
|
|
27
|
-
* Resolve passkey relying party options from provider config and environment.
|
|
28
|
-
*/
|
|
29
|
-
function resolveRpOptions(provider) {
|
|
30
|
-
const siteUrl = process.env.SITE_URL;
|
|
31
|
-
if (!siteUrl && !provider.options.rpId) throwAuthError("PASSKEY_MISSING_CONFIG", "Passkey provider requires SITE_URL env var (your frontend URL) or explicit rpId / origin in the provider config. CONVEX_SITE_URL cannot be used because WebAuthn RP ID must match the frontend domain.");
|
|
32
|
-
const siteHostname = siteUrl ? new URL(siteUrl).hostname : void 0;
|
|
33
|
-
return {
|
|
34
|
-
rpName: provider.options.rpName ?? siteHostname ?? "localhost",
|
|
35
|
-
rpId: provider.options.rpId ?? siteHostname ?? "localhost",
|
|
36
|
-
origin: provider.options.origin ?? siteUrl ?? "http://localhost",
|
|
37
|
-
attestation: provider.options.attestation ?? "none",
|
|
38
|
-
userVerification: provider.options.userVerification ?? "required",
|
|
39
|
-
residentKey: provider.options.residentKey ?? "preferred",
|
|
40
|
-
authenticatorAttachment: provider.options.authenticatorAttachment,
|
|
41
|
-
algorithms: provider.options.algorithms ?? [coseAlgorithmES256, coseAlgorithmRS256],
|
|
42
|
-
challengeExpirationMs: provider.options.challengeExpirationMs ?? 3e5
|
|
43
|
-
};
|
|
44
|
-
}
|
|
45
|
-
/**
|
|
46
|
-
* Generate a cryptographically random challenge.
|
|
47
|
-
*/
|
|
48
|
-
function generateChallenge() {
|
|
49
|
-
const challenge = new Uint8Array(32);
|
|
50
|
-
crypto.getRandomValues(challenge);
|
|
51
|
-
return challenge;
|
|
52
|
-
}
|
|
53
|
-
/**
|
|
54
|
-
* Hash a challenge for storage in the verifier table's `signature` field.
|
|
55
|
-
*/
|
|
56
|
-
function hashChallenge(challenge) {
|
|
57
|
-
return encodeBase64urlNoPadding(new Uint8Array(sha256(challenge)));
|
|
58
|
-
}
|
|
59
|
-
/**
|
|
60
|
-
* Phase 1: Generate registration options.
|
|
61
|
-
*
|
|
62
|
-
* Requires an authenticated user — passkey registration always adds a
|
|
63
|
-
* credential to an existing account. The userId is taken from the
|
|
64
|
-
* current session identity.
|
|
65
|
-
*/
|
|
66
|
-
async function handleRegisterOptions(ctx, provider, params) {
|
|
67
|
-
const identity = await ctx.auth.getUserIdentity();
|
|
68
|
-
if (identity === null) throwAuthError("PASSKEY_AUTH_REQUIRED");
|
|
69
|
-
const [userId] = identity.subject.split("|");
|
|
70
|
-
const rp = resolveRpOptions(provider);
|
|
71
|
-
const challenge = generateChallenge();
|
|
72
|
-
const challengeHash = hashChallenge(challenge);
|
|
73
|
-
const verifier = await callVerifier(ctx);
|
|
74
|
-
await callVerifierSignature(ctx, {
|
|
75
|
-
verifier,
|
|
76
|
-
signature: challengeHash
|
|
77
|
-
});
|
|
78
|
-
const user = await queryUserById(ctx, userId);
|
|
79
|
-
const userName = params.userName ?? user?.email ?? "user";
|
|
80
|
-
const userDisplayName = params.userDisplayName ?? user?.name ?? userName;
|
|
81
|
-
const excludeCredentials = (await queryPasskeysByUserId(ctx, userId)).map((pk) => ({
|
|
82
|
-
id: pk.credentialId,
|
|
83
|
-
transports: pk.transports
|
|
84
|
-
}));
|
|
85
|
-
const userHandle = encodeBase64urlNoPadding(new TextEncoder().encode(userId));
|
|
86
|
-
return {
|
|
87
|
-
kind: "passkeyOptions",
|
|
88
|
-
options: {
|
|
89
|
-
rp: {
|
|
90
|
-
name: rp.rpName,
|
|
91
|
-
id: rp.rpId
|
|
92
|
-
},
|
|
93
|
-
user: {
|
|
94
|
-
id: userHandle,
|
|
95
|
-
name: userName,
|
|
96
|
-
displayName: userDisplayName
|
|
97
|
-
},
|
|
98
|
-
challenge: encodeBase64urlNoPadding(challenge),
|
|
99
|
-
pubKeyCredParams: rp.algorithms.map((alg) => ({
|
|
100
|
-
type: "public-key",
|
|
101
|
-
alg
|
|
102
|
-
})),
|
|
103
|
-
timeout: rp.challengeExpirationMs,
|
|
104
|
-
attestation: rp.attestation,
|
|
105
|
-
authenticatorSelection: {
|
|
106
|
-
residentKey: rp.residentKey,
|
|
107
|
-
requireResidentKey: rp.residentKey === "required",
|
|
108
|
-
userVerification: rp.userVerification,
|
|
109
|
-
...rp.authenticatorAttachment ? { authenticatorAttachment: rp.authenticatorAttachment } : {}
|
|
110
|
-
},
|
|
111
|
-
excludeCredentials
|
|
112
|
-
},
|
|
113
|
-
verifier
|
|
114
|
-
};
|
|
115
|
-
}
|
|
116
|
-
/**
|
|
117
|
-
* Phase 2: Verify registration attestation and store the credential.
|
|
118
|
-
*
|
|
119
|
-
* Requires an authenticated user. Parses the attestation, verifies the
|
|
120
|
-
* challenge, extracts the public key, creates an account + passkey record
|
|
121
|
-
* linked to the current user, and returns auth tokens.
|
|
122
|
-
*/
|
|
123
|
-
async function handleRegisterVerify(ctx, provider, params, verifierValue) {
|
|
124
|
-
const identity = await ctx.auth.getUserIdentity();
|
|
125
|
-
if (identity === null) throwAuthError("PASSKEY_AUTH_REQUIRED");
|
|
126
|
-
const [userId] = identity.subject.split("|");
|
|
127
|
-
const rp = resolveRpOptions(provider);
|
|
128
|
-
if (!verifierValue) throwAuthError("PASSKEY_MISSING_VERIFIER");
|
|
129
|
-
const clientData = parseClientDataJSON(decodeBase64urlIgnorePadding(params.clientDataJSON));
|
|
130
|
-
if (clientData.type !== ClientDataType.Create) throwAuthError("PASSKEY_INVALID_CLIENT_DATA", "Invalid client data type: expected webauthn.create");
|
|
131
|
-
const allowedOrigins = Array.isArray(rp.origin) ? rp.origin : [rp.origin];
|
|
132
|
-
if (!allowedOrigins.includes(clientData.origin)) throwAuthError("PASSKEY_INVALID_ORIGIN", `Invalid origin: ${clientData.origin}, expected one of: ${allowedOrigins.join(", ")}`);
|
|
133
|
-
const challengeHash = encodeBase64urlNoPadding(new Uint8Array(sha256(clientData.challenge)));
|
|
134
|
-
const verifierDoc = await queryVerifierById(ctx, verifierValue);
|
|
135
|
-
if (!verifierDoc || verifierDoc.signature !== challengeHash) throwAuthError("PASSKEY_INVALID_CHALLENGE");
|
|
136
|
-
await mutateVerifierDelete(ctx, verifierValue);
|
|
137
|
-
const authenticatorData = parseAttestationObject(decodeBase64urlIgnorePadding(params.attestationObject)).authenticatorData;
|
|
138
|
-
if (!authenticatorData.verifyRelyingPartyIdHash(rp.rpId)) throwAuthError("PASSKEY_RP_MISMATCH");
|
|
139
|
-
if (!authenticatorData.userPresent) throwAuthError("PASSKEY_USER_PRESENCE");
|
|
140
|
-
if (rp.userVerification === "required" && !authenticatorData.userVerified) throwAuthError("PASSKEY_USER_VERIFICATION");
|
|
141
|
-
const credential = authenticatorData.credential;
|
|
142
|
-
if (!credential) throwAuthError("PASSKEY_NO_CREDENTIAL");
|
|
143
|
-
const credentialId = encodeBase64urlNoPadding(credential.id);
|
|
144
|
-
const publicKey = credential.publicKey;
|
|
145
|
-
let algorithm;
|
|
146
|
-
let publicKeyBytes;
|
|
147
|
-
if (publicKey.isAlgorithmDefined()) algorithm = publicKey.algorithm();
|
|
148
|
-
else {
|
|
149
|
-
const keyType = publicKey.type();
|
|
150
|
-
algorithm = keyType === COSEKeyType.EC2 ? coseAlgorithmES256 : keyType === COSEKeyType.RSA ? coseAlgorithmRS256 : coseAlgorithmES256;
|
|
151
|
-
}
|
|
152
|
-
if (algorithm === coseAlgorithmES256) {
|
|
153
|
-
const ec2 = publicKey.ec2();
|
|
154
|
-
const xBytes = bigintToBytes(ec2.x, 32);
|
|
155
|
-
const yBytes = bigintToBytes(ec2.y, 32);
|
|
156
|
-
publicKeyBytes = new Uint8Array(65);
|
|
157
|
-
publicKeyBytes[0] = 4;
|
|
158
|
-
publicKeyBytes.set(xBytes, 1);
|
|
159
|
-
publicKeyBytes.set(yBytes, 33);
|
|
160
|
-
} else if (algorithm === coseAlgorithmRS256) {
|
|
161
|
-
const rsa = publicKey.rsa();
|
|
162
|
-
publicKeyBytes = new RSAPublicKey(rsa.n, rsa.e).encodePKCS1();
|
|
163
|
-
} else throwAuthError("PASSKEY_UNSUPPORTED_ALGORITHM", `Unsupported algorithm: ${algorithm}`);
|
|
164
|
-
const deviceType = params.deviceType ?? "single-device";
|
|
165
|
-
const backedUp = params.backedUp ?? false;
|
|
166
|
-
await authDb(ctx, ctx.auth.config).accounts.create({
|
|
167
|
-
userId,
|
|
168
|
-
provider: provider.id,
|
|
169
|
-
providerAccountId: credentialId
|
|
170
|
-
});
|
|
171
|
-
await mutatePasskeyInsert(ctx, {
|
|
172
|
-
userId,
|
|
173
|
-
credentialId,
|
|
174
|
-
publicKey: publicKeyBytes.buffer.slice(publicKeyBytes.byteOffset, publicKeyBytes.byteOffset + publicKeyBytes.byteLength),
|
|
175
|
-
algorithm,
|
|
176
|
-
counter: authenticatorData.signatureCounter,
|
|
177
|
-
transports: params.transports,
|
|
178
|
-
deviceType,
|
|
179
|
-
backedUp,
|
|
180
|
-
name: params.passkeyName,
|
|
181
|
-
createdAt: Date.now()
|
|
182
|
-
});
|
|
183
|
-
return {
|
|
184
|
-
kind: "signedIn",
|
|
185
|
-
signedIn: await callSignIn(ctx, {
|
|
186
|
-
userId,
|
|
187
|
-
generateTokens: true
|
|
188
|
-
})
|
|
189
|
-
};
|
|
190
|
-
}
|
|
191
|
-
/**
|
|
192
|
-
* Phase 3: Generate authentication options.
|
|
193
|
-
*
|
|
194
|
-
* Creates a challenge and returns PublicKeyCredentialRequestOptions.
|
|
195
|
-
* If an email is provided, scopes allowCredentials to that user's passkeys.
|
|
196
|
-
*/
|
|
197
|
-
async function handleAuthOptions(ctx, provider, params) {
|
|
198
|
-
const rp = resolveRpOptions(provider);
|
|
199
|
-
const challenge = generateChallenge();
|
|
200
|
-
const challengeHash = hashChallenge(challenge);
|
|
201
|
-
const verifier = await callVerifier(ctx);
|
|
202
|
-
await callVerifierSignature(ctx, {
|
|
203
|
-
verifier,
|
|
204
|
-
signature: challengeHash
|
|
205
|
-
});
|
|
206
|
-
let allowCredentials;
|
|
207
|
-
if (params.email) {
|
|
208
|
-
const user = await queryUserByVerifiedEmail(ctx, params.email);
|
|
209
|
-
if (user) {
|
|
210
|
-
const passkeys = await queryPasskeysByUserId(ctx, user._id);
|
|
211
|
-
if (passkeys.length > 0) allowCredentials = passkeys.map((pk) => ({
|
|
212
|
-
type: "public-key",
|
|
213
|
-
id: pk.credentialId,
|
|
214
|
-
transports: pk.transports
|
|
215
|
-
}));
|
|
216
|
-
}
|
|
217
|
-
}
|
|
218
|
-
const options = {
|
|
219
|
-
challenge: encodeBase64urlNoPadding(challenge),
|
|
220
|
-
timeout: rp.challengeExpirationMs,
|
|
221
|
-
rpId: rp.rpId,
|
|
222
|
-
userVerification: rp.userVerification
|
|
223
|
-
};
|
|
224
|
-
if (allowCredentials) options.allowCredentials = allowCredentials;
|
|
225
|
-
return {
|
|
226
|
-
kind: "passkeyOptions",
|
|
227
|
-
options,
|
|
228
|
-
verifier
|
|
229
|
-
};
|
|
230
|
-
}
|
|
231
|
-
/**
|
|
232
|
-
* Phase 4: Verify authentication assertion and sign in.
|
|
233
|
-
*
|
|
234
|
-
* Verifies the signature against the stored public key, checks the counter,
|
|
235
|
-
* and creates a session.
|
|
236
|
-
*/
|
|
237
|
-
async function handleAuthVerify(ctx, provider, params, verifierValue) {
|
|
238
|
-
const rp = resolveRpOptions(provider);
|
|
239
|
-
if (!verifierValue) throwAuthError("PASSKEY_MISSING_VERIFIER");
|
|
240
|
-
const clientDataJSON = decodeBase64urlIgnorePadding(params.clientDataJSON);
|
|
241
|
-
const clientData = parseClientDataJSON(clientDataJSON);
|
|
242
|
-
if (clientData.type !== ClientDataType.Get) throwAuthError("PASSKEY_INVALID_CLIENT_DATA", "Invalid client data type: expected webauthn.get");
|
|
243
|
-
const allowedOrigins = Array.isArray(rp.origin) ? rp.origin : [rp.origin];
|
|
244
|
-
if (!allowedOrigins.includes(clientData.origin)) throwAuthError("PASSKEY_INVALID_ORIGIN", `Invalid origin: ${clientData.origin}, expected one of: ${allowedOrigins.join(", ")}`);
|
|
245
|
-
const challengeHash = encodeBase64urlNoPadding(new Uint8Array(sha256(clientData.challenge)));
|
|
246
|
-
const verifierDoc = await queryVerifierById(ctx, verifierValue);
|
|
247
|
-
if (!verifierDoc || verifierDoc.signature !== challengeHash) throwAuthError("PASSKEY_INVALID_CHALLENGE");
|
|
248
|
-
await mutateVerifierDelete(ctx, verifierValue);
|
|
249
|
-
const credentialId = params.credentialId;
|
|
250
|
-
if (!credentialId) throwAuthError("PASSKEY_UNKNOWN_CREDENTIAL", "Missing credential ID");
|
|
251
|
-
const passkey = await queryPasskeyByCredentialId(ctx, credentialId);
|
|
252
|
-
if (!passkey) throwAuthError("PASSKEY_UNKNOWN_CREDENTIAL", "Unknown credential");
|
|
253
|
-
const authenticatorDataBytes = decodeBase64urlIgnorePadding(params.authenticatorData);
|
|
254
|
-
const authenticatorData = parseAuthenticatorData(authenticatorDataBytes);
|
|
255
|
-
if (!authenticatorData.verifyRelyingPartyIdHash(rp.rpId)) throwAuthError("PASSKEY_RP_MISMATCH");
|
|
256
|
-
if (!authenticatorData.userPresent) throwAuthError("PASSKEY_USER_PRESENCE");
|
|
257
|
-
if (rp.userVerification === "required" && !authenticatorData.userVerified) throwAuthError("PASSKEY_USER_VERIFICATION");
|
|
258
|
-
const signature = decodeBase64urlIgnorePadding(params.signature);
|
|
259
|
-
const messageHash = sha256(createAssertionSignatureMessage(authenticatorDataBytes, clientDataJSON));
|
|
260
|
-
const storedPublicKeyBytes = new Uint8Array(passkey.publicKey);
|
|
261
|
-
if (passkey.algorithm === coseAlgorithmES256) {
|
|
262
|
-
if (!verifyECDSASignature(decodeSEC1PublicKey(p256, storedPublicKeyBytes), messageHash, decodePKIXECDSASignature(signature))) throwAuthError("PASSKEY_INVALID_SIGNATURE");
|
|
263
|
-
} else if (passkey.algorithm === coseAlgorithmRS256) {
|
|
264
|
-
if (!verifyRSASSAPKCS1v15Signature(decodePKCS1RSAPublicKey(storedPublicKeyBytes), sha256ObjectIdentifier, messageHash, signature)) throwAuthError("PASSKEY_INVALID_SIGNATURE");
|
|
265
|
-
} else throwAuthError("PASSKEY_UNSUPPORTED_ALGORITHM", `Unsupported algorithm: ${passkey.algorithm}`);
|
|
266
|
-
if (passkey.counter !== 0 && authenticatorData.signatureCounter !== 0 && authenticatorData.signatureCounter <= passkey.counter) throwAuthError("PASSKEY_COUNTER_ERROR");
|
|
267
|
-
await mutatePasskeyUpdateCounter(ctx, passkey._id, authenticatorData.signatureCounter, Date.now());
|
|
268
|
-
return {
|
|
269
|
-
kind: "signedIn",
|
|
270
|
-
signedIn: await callSignIn(ctx, {
|
|
271
|
-
userId: passkey.userId,
|
|
272
|
-
generateTokens: true
|
|
273
|
-
})
|
|
274
|
-
};
|
|
275
|
-
}
|
|
276
|
-
/**
|
|
277
|
-
* Main passkey handler dispatched from signIn.ts.
|
|
278
|
-
*
|
|
279
|
-
* Routes to the appropriate phase based on `params.flow`.
|
|
280
|
-
*/
|
|
281
|
-
async function handlePasskey(ctx, provider, args) {
|
|
282
|
-
const flow = args.params?.flow;
|
|
283
|
-
if (!flow) throwAuthError("PASSKEY_MISSING_FLOW", "Missing `flow` parameter. Expected one of: register-options, register-verify, auth-options, auth-verify");
|
|
284
|
-
switch (flow) {
|
|
285
|
-
case "register-options": return handleRegisterOptions(ctx, provider, args.params ?? {});
|
|
286
|
-
case "register-verify": return handleRegisterVerify(ctx, provider, args.params ?? {}, args.verifier);
|
|
287
|
-
case "auth-options": return handleAuthOptions(ctx, provider, args.params ?? {});
|
|
288
|
-
case "auth-verify": return handleAuthVerify(ctx, provider, args.params ?? {}, args.verifier);
|
|
289
|
-
default: throwAuthError("PASSKEY_UNKNOWN_FLOW", `Unknown passkey flow: ${flow}. Expected one of: register-options, register-verify, auth-options, auth-verify`);
|
|
290
|
-
}
|
|
291
|
-
}
|
|
292
|
-
/**
|
|
293
|
-
* Convert a bigint to a fixed-size big-endian byte array.
|
|
294
|
-
*/
|
|
295
|
-
function bigintToBytes(value, length) {
|
|
296
|
-
const bytes = new Uint8Array(length);
|
|
297
|
-
let v = value;
|
|
298
|
-
for (let i = length - 1; i >= 0; i--) {
|
|
299
|
-
bytes[i] = Number(v & 255n);
|
|
300
|
-
v >>= 8n;
|
|
301
|
-
}
|
|
302
|
-
return bytes;
|
|
303
|
-
}
|
|
304
|
-
|
|
305
|
-
//#endregion
|
|
306
|
-
export { handlePasskey };
|
|
307
|
-
//# sourceMappingURL=passkey.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"passkey.js","names":[],"sources":["../../../src/server/implementation/passkey.ts"],"sourcesContent":["/**\n * Server-side WebAuthn ceremony logic for passkey authentication.\n *\n * Handles the four phases of the WebAuthn flow:\n * 1. register-options — generate PublicKeyCredentialCreationOptions\n * 2. register-verify — verify attestation and store credential\n * 3. auth-options — generate PublicKeyCredentialRequestOptions\n * 4. auth-verify — verify assertion signature and sign in\n *\n * Uses `@oslojs/webauthn` for attestation/assertion parsing and\n * `@oslojs/crypto` for signature verification.\n */\n\nimport {\n parseAttestationObject,\n parseClientDataJSON,\n parseAuthenticatorData,\n createAssertionSignatureMessage,\n ClientDataType,\n coseAlgorithmES256,\n coseAlgorithmRS256,\n COSEKeyType,\n} from \"@oslojs/webauthn\";\nimport {\n p256,\n verifyECDSASignature,\n decodeSEC1PublicKey,\n decodePKIXECDSASignature,\n} from \"@oslojs/crypto/ecdsa\";\nimport {\n RSAPublicKey,\n decodePKCS1RSAPublicKey,\n sha256ObjectIdentifier,\n verifyRSASSAPKCS1v15Signature,\n} from \"@oslojs/crypto/rsa\";\nimport { sha256 } from \"@oslojs/crypto/sha2\";\nimport {\n encodeBase64urlNoPadding,\n decodeBase64urlIgnorePadding,\n} from \"@oslojs/encoding\";\nimport {\n PasskeyProviderConfig,\n GenericActionCtxWithAuthConfig,\n} from \"../types\";\nimport {\n AuthDataModel,\n SessionInfo,\n queryUserById,\n queryUserByVerifiedEmail,\n queryPasskeysByUserId,\n queryPasskeyByCredentialId,\n queryVerifierById,\n mutatePasskeyInsert,\n mutatePasskeyUpdateCounter,\n mutateVerifierDelete,\n} from \"./types\";\nimport { callSignIn, callVerifier } from \"./mutations/index\";\nimport { callVerifierSignature } from \"./mutations/signature\";\nimport { authDb } from \"./db\";\nimport { throwAuthError } from \"../errors\";\n\n\ntype EnrichedActionCtx = GenericActionCtxWithAuthConfig<AuthDataModel>;\n\n/**\n * Resolve passkey relying party options from provider config and environment.\n */\nfunction resolveRpOptions(provider: PasskeyProviderConfig) {\n // WebAuthn RP ID and origin must match the *frontend* domain, not the\n // Convex backend. SITE_URL is the canonical frontend URL\n // (e.g. \"http://localhost:3000\" in dev, \"https://myapp.com\" in prod).\n // CONVEX_SITE_URL points to the Convex cloud HTTP actions endpoint and\n // must NOT be used here — the browser would reject the credential\n // because the RP ID wouldn't match the page origin.\n const siteUrl = process.env.SITE_URL;\n if (!siteUrl && !provider.options.rpId) {\n throwAuthError(\n \"PASSKEY_MISSING_CONFIG\",\n \"Passkey provider requires SITE_URL env var (your frontend URL) \" +\n \"or explicit rpId / origin in the provider config. \" +\n \"CONVEX_SITE_URL cannot be used because WebAuthn RP ID must match the frontend domain.\",\n );\n }\n const siteHostname = siteUrl ? new URL(siteUrl).hostname : undefined;\n\n return {\n rpName: provider.options.rpName ?? siteHostname ?? \"localhost\",\n rpId: provider.options.rpId ?? siteHostname ?? \"localhost\",\n origin: provider.options.origin ?? siteUrl ?? \"http://localhost\",\n attestation: provider.options.attestation ?? \"none\",\n userVerification: provider.options.userVerification ?? \"required\",\n residentKey: provider.options.residentKey ?? \"preferred\",\n authenticatorAttachment: provider.options.authenticatorAttachment,\n algorithms: provider.options.algorithms ?? [coseAlgorithmES256, coseAlgorithmRS256],\n challengeExpirationMs: provider.options.challengeExpirationMs ?? 300_000,\n };\n}\n\n/**\n * Generate a cryptographically random challenge.\n */\nfunction generateChallenge(): Uint8Array {\n const challenge = new Uint8Array(32);\n crypto.getRandomValues(challenge);\n return challenge;\n}\n\n/**\n * Hash a challenge for storage in the verifier table's `signature` field.\n */\nfunction hashChallenge(challenge: Uint8Array): string {\n return encodeBase64urlNoPadding(new Uint8Array(sha256(challenge)));\n}\n\n// ============================================================================\n// Registration flow\n// ============================================================================\n\n/**\n * Phase 1: Generate registration options.\n *\n * Requires an authenticated user — passkey registration always adds a\n * credential to an existing account. The userId is taken from the\n * current session identity.\n */\nasync function handleRegisterOptions(\n ctx: EnrichedActionCtx,\n provider: PasskeyProviderConfig,\n params: Record<string, any>,\n): Promise<{\n kind: \"passkeyOptions\";\n options: Record<string, any>;\n verifier: string;\n}> {\n // Passkey registration requires an authenticated user\n const identity = await ctx.auth.getUserIdentity();\n if (identity === null) {\n throwAuthError(\"PASSKEY_AUTH_REQUIRED\");\n }\n const [userId] = identity.subject.split(\"|\");\n\n const rp = resolveRpOptions(provider);\n const challenge = generateChallenge();\n const challengeHash = hashChallenge(challenge);\n\n // Store the challenge hash in the verifier table\n const verifier = await callVerifier(ctx);\n await callVerifierSignature(ctx, {\n verifier,\n signature: challengeHash,\n });\n\n // Get the user's profile for credential metadata\n const user = await queryUserById(ctx, userId!);\n const userName = params.userName ?? user?.email ?? \"user\";\n const userDisplayName = params.userDisplayName ?? user?.name ?? userName;\n\n // Collect existing credentials to prevent re-registration\n const existing = await queryPasskeysByUserId(ctx, userId!);\n const excludeCredentials = existing.map((pk) => ({\n id: pk.credentialId,\n transports: pk.transports,\n }));\n\n // User handle is derived from the Convex userId\n const userHandle = encodeBase64urlNoPadding(\n new TextEncoder().encode(userId!),\n );\n\n const options = {\n rp: {\n name: rp.rpName,\n id: rp.rpId,\n },\n user: {\n id: userHandle,\n name: userName,\n displayName: userDisplayName,\n },\n challenge: encodeBase64urlNoPadding(challenge),\n pubKeyCredParams: rp.algorithms.map((alg) => ({\n type: \"public-key\" as const,\n alg,\n })),\n timeout: rp.challengeExpirationMs,\n attestation: rp.attestation,\n authenticatorSelection: {\n residentKey: rp.residentKey,\n requireResidentKey: rp.residentKey === \"required\",\n userVerification: rp.userVerification,\n ...(rp.authenticatorAttachment\n ? { authenticatorAttachment: rp.authenticatorAttachment }\n : {}),\n },\n excludeCredentials,\n };\n\n return { kind: \"passkeyOptions\", options, verifier };\n}\n\n/**\n * Phase 2: Verify registration attestation and store the credential.\n *\n * Requires an authenticated user. Parses the attestation, verifies the\n * challenge, extracts the public key, creates an account + passkey record\n * linked to the current user, and returns auth tokens.\n */\nasync function handleRegisterVerify(\n ctx: EnrichedActionCtx,\n provider: PasskeyProviderConfig,\n params: Record<string, any>,\n verifierValue: string | undefined,\n): Promise<{ kind: \"signedIn\"; signedIn: SessionInfo | null }> {\n // Passkey registration requires an authenticated user\n const identity = await ctx.auth.getUserIdentity();\n if (identity === null) {\n throwAuthError(\"PASSKEY_AUTH_REQUIRED\");\n }\n const [userId] = identity.subject.split(\"|\");\n\n const rp = resolveRpOptions(provider);\n\n if (!verifierValue) {\n throwAuthError(\"PASSKEY_MISSING_VERIFIER\");\n }\n\n // Decode client data\n const clientDataJSON = decodeBase64urlIgnorePadding(params.clientDataJSON);\n const clientData = parseClientDataJSON(clientDataJSON);\n\n // Verify client data type is \"webauthn.create\"\n if (clientData.type !== ClientDataType.Create) {\n throwAuthError(\"PASSKEY_INVALID_CLIENT_DATA\", \"Invalid client data type: expected webauthn.create\");\n }\n\n // Verify origin\n const allowedOrigins = Array.isArray(rp.origin) ? rp.origin : [rp.origin];\n if (!allowedOrigins.includes(clientData.origin)) {\n throwAuthError(\n \"PASSKEY_INVALID_ORIGIN\",\n `Invalid origin: ${clientData.origin}, expected one of: ${allowedOrigins.join(\", \")}`,\n );\n }\n\n // Verify challenge matches the stored verifier\n const challengeHash = encodeBase64urlNoPadding(\n new Uint8Array(sha256(clientData.challenge)),\n );\n const verifierDoc = await queryVerifierById(ctx, verifierValue);\n if (!verifierDoc || verifierDoc.signature !== challengeHash) {\n throwAuthError(\"PASSKEY_INVALID_CHALLENGE\");\n }\n\n // Clean up the verifier\n await mutateVerifierDelete(ctx, verifierValue);\n\n // Parse attestation object\n const attestationObjectBytes = decodeBase64urlIgnorePadding(params.attestationObject);\n const attestation = parseAttestationObject(attestationObjectBytes);\n const authenticatorData = attestation.authenticatorData;\n\n // Verify RP ID hash\n if (!authenticatorData.verifyRelyingPartyIdHash(rp.rpId)) {\n throwAuthError(\"PASSKEY_RP_MISMATCH\");\n }\n\n // Verify user presence and verification flags\n if (!authenticatorData.userPresent) {\n throwAuthError(\"PASSKEY_USER_PRESENCE\");\n }\n if (rp.userVerification === \"required\" && !authenticatorData.userVerified) {\n throwAuthError(\"PASSKEY_USER_VERIFICATION\");\n }\n\n // Extract credential\n const credential = authenticatorData.credential;\n if (!credential) {\n throwAuthError(\"PASSKEY_NO_CREDENTIAL\");\n }\n\n const credentialId = encodeBase64urlNoPadding(credential.id);\n const publicKey = credential.publicKey;\n\n // Determine algorithm and encode the public key for storage\n let algorithm: number;\n let publicKeyBytes: Uint8Array;\n\n if (publicKey.isAlgorithmDefined()) {\n algorithm = publicKey.algorithm();\n } else {\n const keyType = publicKey.type();\n algorithm =\n keyType === COSEKeyType.EC2\n ? coseAlgorithmES256\n : keyType === COSEKeyType.RSA\n ? coseAlgorithmRS256\n : coseAlgorithmES256;\n }\n\n if (algorithm === coseAlgorithmES256) {\n const ec2 = publicKey.ec2();\n // Encode as SEC1 uncompressed point (0x04 || x || y)\n const xBytes = bigintToBytes(ec2.x, 32);\n const yBytes = bigintToBytes(ec2.y, 32);\n publicKeyBytes = new Uint8Array(65);\n publicKeyBytes[0] = 0x04;\n publicKeyBytes.set(xBytes, 1);\n publicKeyBytes.set(yBytes, 33);\n } else if (algorithm === coseAlgorithmRS256) {\n const rsa = publicKey.rsa();\n const rsaPubKey = new RSAPublicKey(rsa.n, rsa.e);\n publicKeyBytes = rsaPubKey.encodePKCS1();\n } else {\n throwAuthError(\"PASSKEY_UNSUPPORTED_ALGORITHM\", `Unsupported algorithm: ${algorithm}`);\n }\n\n const deviceType = params.deviceType ?? \"single-device\";\n const backedUp = params.backedUp ?? false;\n\n // Create an account record linking the passkey to the current user.\n // Unlike unauthenticated flows, we don't create a new user — we\n // attach the passkey credential to the existing authenticated user.\n const db = authDb(ctx, ctx.auth.config);\n await db.accounts.create({\n userId: userId!,\n provider: provider.id,\n providerAccountId: credentialId,\n });\n\n // Store the passkey credential\n await mutatePasskeyInsert(ctx, {\n userId: userId!,\n credentialId,\n publicKey: publicKeyBytes.buffer.slice(\n publicKeyBytes.byteOffset,\n publicKeyBytes.byteOffset + publicKeyBytes.byteLength,\n ),\n algorithm,\n counter: authenticatorData.signatureCounter,\n transports: params.transports,\n deviceType,\n backedUp,\n name: params.passkeyName,\n createdAt: Date.now(),\n });\n\n // Return tokens for the existing session\n const signInResult = await callSignIn(ctx, {\n userId: userId!,\n generateTokens: true,\n });\n\n return { kind: \"signedIn\", signedIn: signInResult };\n}\n\n// ============================================================================\n// Authentication flow\n// ============================================================================\n\n/**\n * Phase 3: Generate authentication options.\n *\n * Creates a challenge and returns PublicKeyCredentialRequestOptions.\n * If an email is provided, scopes allowCredentials to that user's passkeys.\n */\nasync function handleAuthOptions(\n ctx: EnrichedActionCtx,\n provider: PasskeyProviderConfig,\n params: Record<string, any>,\n): Promise<{\n kind: \"passkeyOptions\";\n options: Record<string, any>;\n verifier: string;\n}> {\n const rp = resolveRpOptions(provider);\n const challenge = generateChallenge();\n const challengeHash = hashChallenge(challenge);\n\n // Store the challenge hash in the verifier table\n const verifier = await callVerifier(ctx);\n await callVerifierSignature(ctx, {\n verifier,\n signature: challengeHash,\n });\n\n // Build allowCredentials if email is provided\n let allowCredentials: Array<{ type: string; id: string; transports?: string[] }> | undefined;\n if (params.email) {\n // Look up user by email, then find their passkeys\n const user = await queryUserByVerifiedEmail(ctx, params.email);\n if (user) {\n const passkeys = await queryPasskeysByUserId(ctx, user._id);\n if (passkeys.length > 0) {\n allowCredentials = passkeys.map((pk) => ({\n type: \"public-key\",\n id: pk.credentialId,\n transports: pk.transports,\n }));\n }\n }\n }\n\n const options: Record<string, any> = {\n challenge: encodeBase64urlNoPadding(challenge),\n timeout: rp.challengeExpirationMs,\n rpId: rp.rpId,\n userVerification: rp.userVerification,\n };\n\n if (allowCredentials) {\n options.allowCredentials = allowCredentials;\n }\n\n return { kind: \"passkeyOptions\", options, verifier };\n}\n\n/**\n * Phase 4: Verify authentication assertion and sign in.\n *\n * Verifies the signature against the stored public key, checks the counter,\n * and creates a session.\n */\nasync function handleAuthVerify(\n ctx: EnrichedActionCtx,\n provider: PasskeyProviderConfig,\n params: Record<string, any>,\n verifierValue: string | undefined,\n): Promise<{ kind: \"signedIn\"; signedIn: SessionInfo | null }> {\n const rp = resolveRpOptions(provider);\n\n if (!verifierValue) {\n throwAuthError(\"PASSKEY_MISSING_VERIFIER\");\n }\n\n // Decode client data\n const clientDataJSON = decodeBase64urlIgnorePadding(params.clientDataJSON);\n const clientData = parseClientDataJSON(clientDataJSON);\n\n // Verify client data type is \"webauthn.get\"\n if (clientData.type !== ClientDataType.Get) {\n throwAuthError(\"PASSKEY_INVALID_CLIENT_DATA\", \"Invalid client data type: expected webauthn.get\");\n }\n\n // Verify origin\n const allowedOrigins = Array.isArray(rp.origin) ? rp.origin : [rp.origin];\n if (!allowedOrigins.includes(clientData.origin)) {\n throwAuthError(\n \"PASSKEY_INVALID_ORIGIN\",\n `Invalid origin: ${clientData.origin}, expected one of: ${allowedOrigins.join(\", \")}`,\n );\n }\n\n // Verify challenge matches the stored verifier\n const challengeHash = encodeBase64urlNoPadding(\n new Uint8Array(sha256(clientData.challenge)),\n );\n const verifierDoc = await queryVerifierById(ctx, verifierValue);\n if (!verifierDoc || verifierDoc.signature !== challengeHash) {\n throwAuthError(\"PASSKEY_INVALID_CHALLENGE\");\n }\n\n // Clean up the verifier\n await mutateVerifierDelete(ctx, verifierValue);\n\n // Look up the credential\n const credentialId = params.credentialId;\n if (!credentialId) {\n throwAuthError(\"PASSKEY_UNKNOWN_CREDENTIAL\", \"Missing credential ID\");\n }\n\n const passkey = await queryPasskeyByCredentialId(ctx, credentialId);\n if (!passkey) {\n throwAuthError(\"PASSKEY_UNKNOWN_CREDENTIAL\", \"Unknown credential\");\n }\n\n // Parse authenticator data\n const authenticatorDataBytes = decodeBase64urlIgnorePadding(params.authenticatorData);\n const authenticatorData = parseAuthenticatorData(authenticatorDataBytes);\n\n // Verify RP ID hash\n if (!authenticatorData.verifyRelyingPartyIdHash(rp.rpId)) {\n throwAuthError(\"PASSKEY_RP_MISMATCH\");\n }\n\n // Verify user presence\n if (!authenticatorData.userPresent) {\n throwAuthError(\"PASSKEY_USER_PRESENCE\");\n }\n if (rp.userVerification === \"required\" && !authenticatorData.userVerified) {\n throwAuthError(\"PASSKEY_USER_VERIFICATION\");\n }\n\n // Verify signature\n const signature = decodeBase64urlIgnorePadding(params.signature);\n const signatureMessage = createAssertionSignatureMessage(\n authenticatorDataBytes,\n clientDataJSON,\n );\n const messageHash = sha256(signatureMessage);\n\n const storedPublicKeyBytes = new Uint8Array(passkey.publicKey);\n\n if (passkey.algorithm === coseAlgorithmES256) {\n // EC P-256 verification\n const ecPublicKey = decodeSEC1PublicKey(p256, storedPublicKeyBytes);\n // WebAuthn signatures for EC keys are DER/ASN.1 (PKIX) encoded\n const ecdsaSignature = decodePKIXECDSASignature(signature);\n const valid = verifyECDSASignature(\n ecPublicKey,\n messageHash,\n ecdsaSignature,\n );\n if (!valid) {\n throwAuthError(\"PASSKEY_INVALID_SIGNATURE\");\n }\n } else if (passkey.algorithm === coseAlgorithmRS256) {\n // RSA PKCS#1 v1.5 with SHA-256 verification\n // Decode the stored PKCS#1 public key\n const rsaPublicKey = decodePKCS1RSAPublicKey(storedPublicKeyBytes);\n const valid = verifyRSASSAPKCS1v15Signature(\n rsaPublicKey,\n sha256ObjectIdentifier,\n messageHash,\n signature,\n );\n if (!valid) {\n throwAuthError(\"PASSKEY_INVALID_SIGNATURE\");\n }\n } else {\n throwAuthError(\"PASSKEY_UNSUPPORTED_ALGORITHM\", `Unsupported algorithm: ${passkey.algorithm}`);\n }\n\n // Verify counter (clone detection)\n // Counter of 0 means the authenticator doesn't support counters\n if (\n passkey.counter !== 0 &&\n authenticatorData.signatureCounter !== 0 &&\n authenticatorData.signatureCounter <= passkey.counter\n ) {\n throwAuthError(\"PASSKEY_COUNTER_ERROR\");\n }\n\n // Update counter and last used timestamp\n await mutatePasskeyUpdateCounter(\n ctx,\n passkey._id,\n authenticatorData.signatureCounter,\n Date.now(),\n );\n\n // Sign in the user\n const signInResult = await callSignIn(ctx, {\n userId: passkey.userId,\n generateTokens: true,\n });\n\n return { kind: \"signedIn\", signedIn: signInResult };\n}\n\n// ============================================================================\n// Main dispatch\n// ============================================================================\n\n/**\n * Main passkey handler dispatched from signIn.ts.\n *\n * Routes to the appropriate phase based on `params.flow`.\n */\nexport async function handlePasskey(\n ctx: EnrichedActionCtx,\n provider: PasskeyProviderConfig,\n args: {\n params?: Record<string, any>;\n verifier?: string;\n },\n): Promise<\n | { kind: \"signedIn\"; signedIn: SessionInfo | null }\n | { kind: \"passkeyOptions\"; options: Record<string, any>; verifier: string }\n> {\n const flow = args.params?.flow;\n if (!flow) {\n throwAuthError(\n \"PASSKEY_MISSING_FLOW\",\n \"Missing `flow` parameter. Expected one of: register-options, register-verify, auth-options, auth-verify\",\n );\n }\n\n switch (flow) {\n case \"register-options\":\n return handleRegisterOptions(ctx, provider, args.params ?? {});\n case \"register-verify\":\n return handleRegisterVerify(ctx, provider, args.params ?? {}, args.verifier);\n case \"auth-options\":\n return handleAuthOptions(ctx, provider, args.params ?? {});\n case \"auth-verify\":\n return handleAuthVerify(ctx, provider, args.params ?? {}, args.verifier);\n default:\n throwAuthError(\n \"PASSKEY_UNKNOWN_FLOW\",\n `Unknown passkey flow: ${flow}. Expected one of: register-options, register-verify, auth-options, auth-verify`,\n );\n }\n}\n\n// ============================================================================\n// Helpers\n// ============================================================================\n\n/**\n * Convert a bigint to a fixed-size big-endian byte array.\n */\nfunction bigintToBytes(value: bigint, length: number): Uint8Array {\n const bytes = new Uint8Array(length);\n let v = value;\n for (let i = length - 1; i >= 0; i--) {\n bytes[i] = Number(v & 0xffn);\n v >>= 8n;\n }\n return bytes;\n}\n"],"mappings":"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"}
|
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
import { AuthProviderMaterializedConfig, ConvexAuthMaterializedConfig } from "../types.js";
|
|
2
|
-
|
|
3
|
-
//#region src/server/implementation/provider.d.ts
|
|
4
|
-
declare function hash(provider: any, secret: string): Promise<any>;
|
|
5
|
-
declare function verify(provider: AuthProviderMaterializedConfig, secret: string, hash: string): Promise<boolean>;
|
|
6
|
-
type GetProviderOrThrowFunc = (provider: string, allowExtraProviders?: boolean) => AuthProviderMaterializedConfig;
|
|
7
|
-
type Config = ConvexAuthMaterializedConfig;
|
|
8
|
-
//#endregion
|
|
9
|
-
export { Config, GetProviderOrThrowFunc, hash, verify };
|
|
10
|
-
//# sourceMappingURL=provider.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"provider.d.ts","names":[],"sources":["../../../src/server/implementation/provider.ts"],"mappings":";;;iBAIsB,IAAA,CAAK,QAAA,OAAe,MAAA,WAAc,OAAA;AAAA,iBAWlC,MAAA,CACpB,QAAA,EAAU,8BAAA,EACV,MAAA,UACA,IAAA,WAAY,OAAA;AAAA,KAYF,sBAAA,IACV,QAAA,UACA,mBAAA,eACG,8BAAA;AAAA,KAEO,MAAA,GAAS,4BAAA"}
|
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
import { throwAuthError } from "../errors.js";
|
|
2
|
-
|
|
3
|
-
//#region src/server/implementation/provider.ts
|
|
4
|
-
async function hash(provider, secret) {
|
|
5
|
-
if (provider.type !== "credentials") throwAuthError("INVALID_CREDENTIALS_PROVIDER", `Provider ${provider.id} is not a credentials provider`, { provider: provider.id });
|
|
6
|
-
const hashSecretFn = provider.crypto?.hashSecret;
|
|
7
|
-
if (hashSecretFn === void 0) throwAuthError("MISSING_CRYPTO_FUNCTION", `Provider ${provider.id} does not have a \`crypto.hashSecret\` function`, { provider: provider.id });
|
|
8
|
-
return await hashSecretFn(secret);
|
|
9
|
-
}
|
|
10
|
-
async function verify(provider, secret, hash) {
|
|
11
|
-
if (provider.type !== "credentials") throwAuthError("INVALID_CREDENTIALS_PROVIDER", `Provider ${provider.id} is not a credentials provider`, { provider: provider.id });
|
|
12
|
-
const verifySecretFn = provider.crypto?.verifySecret;
|
|
13
|
-
if (verifySecretFn === void 0) throwAuthError("MISSING_CRYPTO_FUNCTION", `Provider ${provider.id} does not have a \`crypto.verifySecret\` function`, { provider: provider.id });
|
|
14
|
-
return await verifySecretFn(secret, hash);
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
//#endregion
|
|
18
|
-
export { hash, verify };
|
|
19
|
-
//# sourceMappingURL=provider.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"provider.js","names":[],"sources":["../../../src/server/implementation/provider.ts"],"sourcesContent":["import { AuthProviderMaterializedConfig } from \"../types\";\nimport { ConvexAuthMaterializedConfig } from \"../types\";\nimport { throwAuthError } from \"../errors\";\n\nexport async function hash(provider: any, secret: string) {\n if (provider.type !== \"credentials\") {\n throwAuthError(\"INVALID_CREDENTIALS_PROVIDER\", `Provider ${provider.id} is not a credentials provider`, { provider: provider.id });\n }\n const hashSecretFn = provider.crypto?.hashSecret;\n if (hashSecretFn === undefined) {\n throwAuthError(\"MISSING_CRYPTO_FUNCTION\", `Provider ${provider.id} does not have a \\`crypto.hashSecret\\` function`, { provider: provider.id });\n }\n return await hashSecretFn(secret);\n}\n\nexport async function verify(\n provider: AuthProviderMaterializedConfig,\n secret: string,\n hash: string,\n) {\n if (provider.type !== \"credentials\") {\n throwAuthError(\"INVALID_CREDENTIALS_PROVIDER\", `Provider ${provider.id} is not a credentials provider`, { provider: provider.id });\n }\n const verifySecretFn = provider.crypto?.verifySecret;\n if (verifySecretFn === undefined) {\n throwAuthError(\"MISSING_CRYPTO_FUNCTION\", `Provider ${provider.id} does not have a \\`crypto.verifySecret\\` function`, { provider: provider.id });\n }\n return await verifySecretFn(secret, hash);\n}\n\nexport type GetProviderOrThrowFunc = (\n provider: string,\n allowExtraProviders?: boolean,\n) => AuthProviderMaterializedConfig;\n\nexport type Config = ConvexAuthMaterializedConfig;\n"],"mappings":";;;AAIA,eAAsB,KAAK,UAAe,QAAgB;AACxD,KAAI,SAAS,SAAS,cACpB,gBAAe,gCAAgC,YAAY,SAAS,GAAG,iCAAiC,EAAE,UAAU,SAAS,IAAI,CAAC;CAEpI,MAAM,eAAe,SAAS,QAAQ;AACtC,KAAI,iBAAiB,OACnB,gBAAe,2BAA2B,YAAY,SAAS,GAAG,kDAAkD,EAAE,UAAU,SAAS,IAAI,CAAC;AAEhJ,QAAO,MAAM,aAAa,OAAO;;AAGnC,eAAsB,OACpB,UACA,QACA,MACA;AACA,KAAI,SAAS,SAAS,cACpB,gBAAe,gCAAgC,YAAY,SAAS,GAAG,iCAAiC,EAAE,UAAU,SAAS,IAAI,CAAC;CAEpI,MAAM,iBAAiB,SAAS,QAAQ;AACxC,KAAI,mBAAmB,OACrB,gBAAe,2BAA2B,YAAY,SAAS,GAAG,oDAAoD,EAAE,UAAU,SAAS,IAAI,CAAC;AAElJ,QAAO,MAAM,eAAe,QAAQ,KAAK"}
|
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
import { MutationCtx } from "./types.js";
|
|
2
|
-
import { ConvexAuthConfig } from "../types.js";
|
|
3
|
-
|
|
4
|
-
//#region src/server/implementation/ratelimit.d.ts
|
|
5
|
-
declare function isSignInRateLimited(ctx: MutationCtx, identifier: string, config: ConvexAuthConfig): Promise<boolean>;
|
|
6
|
-
declare function recordFailedSignIn(ctx: MutationCtx, identifier: string, config: ConvexAuthConfig): Promise<void>;
|
|
7
|
-
declare function resetSignInRateLimit(ctx: MutationCtx, identifier: string, config: ConvexAuthConfig): Promise<void>;
|
|
8
|
-
//#endregion
|
|
9
|
-
export { isSignInRateLimited, recordFailedSignIn, resetSignInRateLimit };
|
|
10
|
-
//# sourceMappingURL=ratelimit.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"ratelimit.d.ts","names":[],"sources":["../../../src/server/implementation/ratelimit.ts"],"mappings":";;;;iBAMsB,mBAAA,CACpB,GAAA,EAAK,WAAA,EACL,UAAA,UACA,MAAA,EAAQ,gBAAA,GAAgB,OAAA;AAAA,iBASJ,kBAAA,CACpB,GAAA,EAAK,WAAA,EACL,UAAA,UACA,MAAA,EAAQ,gBAAA,GAAgB,OAAA;AAAA,iBAmBJ,oBAAA,CACpB,GAAA,EAAK,WAAA,EACL,UAAA,UACA,MAAA,EAAQ,gBAAA,GAAgB,OAAA"}
|
|
@@ -1,48 +0,0 @@
|
|
|
1
|
-
import { authDb } from "./db.js";
|
|
2
|
-
|
|
3
|
-
//#region src/server/implementation/ratelimit.ts
|
|
4
|
-
const DEFAULT_MAX_SIGN_IN_ATTEMPTS_PER_HOUR = 10;
|
|
5
|
-
async function isSignInRateLimited(ctx, identifier, config) {
|
|
6
|
-
const state = await getRateLimitState(ctx, identifier, config);
|
|
7
|
-
if (state === null) return false;
|
|
8
|
-
return state.attempsLeft < 1;
|
|
9
|
-
}
|
|
10
|
-
async function recordFailedSignIn(ctx, identifier, config) {
|
|
11
|
-
const db = authDb(ctx, config);
|
|
12
|
-
const state = await getRateLimitState(ctx, identifier, config);
|
|
13
|
-
if (state !== null) await db.rateLimits.patch(state.limit._id, {
|
|
14
|
-
attemptsLeft: state.attempsLeft - 1,
|
|
15
|
-
lastAttemptTime: Date.now()
|
|
16
|
-
});
|
|
17
|
-
else {
|
|
18
|
-
const maxAttempsPerHour = configuredMaxAttempsPerHour(config);
|
|
19
|
-
await db.rateLimits.create({
|
|
20
|
-
identifier,
|
|
21
|
-
attemptsLeft: maxAttempsPerHour - 1,
|
|
22
|
-
lastAttemptTime: Date.now()
|
|
23
|
-
});
|
|
24
|
-
}
|
|
25
|
-
}
|
|
26
|
-
async function resetSignInRateLimit(ctx, identifier, config) {
|
|
27
|
-
const existingState = await getRateLimitState(ctx, identifier, config);
|
|
28
|
-
if (existingState !== null) await authDb(ctx, config).rateLimits.delete(existingState.limit._id);
|
|
29
|
-
}
|
|
30
|
-
async function getRateLimitState(ctx, identifier, config) {
|
|
31
|
-
const now = Date.now();
|
|
32
|
-
const maxAttempsPerHour = configuredMaxAttempsPerHour(config);
|
|
33
|
-
const limit = await authDb(ctx, config).rateLimits.get(identifier);
|
|
34
|
-
if (limit === null) return null;
|
|
35
|
-
const elapsed = now - limit.lastAttemptTime;
|
|
36
|
-
const maxAttempsPerMs = maxAttempsPerHour / (3600 * 1e3);
|
|
37
|
-
return {
|
|
38
|
-
limit,
|
|
39
|
-
attempsLeft: Math.min(maxAttempsPerHour, limit.attemptsLeft + elapsed * maxAttempsPerMs)
|
|
40
|
-
};
|
|
41
|
-
}
|
|
42
|
-
function configuredMaxAttempsPerHour(config) {
|
|
43
|
-
return config.signIn?.maxFailedAttempsPerHour ?? DEFAULT_MAX_SIGN_IN_ATTEMPTS_PER_HOUR;
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
//#endregion
|
|
47
|
-
export { isSignInRateLimited, recordFailedSignIn, resetSignInRateLimit };
|
|
48
|
-
//# sourceMappingURL=ratelimit.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"ratelimit.js","names":[],"sources":["../../../src/server/implementation/ratelimit.ts"],"sourcesContent":["import { ConvexAuthConfig } from \"../types\";\nimport { Doc, MutationCtx } from \"./types\";\nimport { authDb } from \"./db\";\n\nconst DEFAULT_MAX_SIGN_IN_ATTEMPTS_PER_HOUR = 10;\n\nexport async function isSignInRateLimited(\n ctx: MutationCtx,\n identifier: string,\n config: ConvexAuthConfig,\n) {\n const state = await getRateLimitState(ctx, identifier, config);\n if (state === null) {\n return false;\n }\n return state.attempsLeft < 1;\n}\n\nexport async function recordFailedSignIn(\n ctx: MutationCtx,\n identifier: string,\n config: ConvexAuthConfig,\n) {\n const db = authDb(ctx, config);\n const state = await getRateLimitState(ctx, identifier, config);\n if (state !== null) {\n await db.rateLimits.patch(state.limit._id, {\n attemptsLeft: state.attempsLeft - 1,\n lastAttemptTime: Date.now(),\n });\n } else {\n const maxAttempsPerHour = configuredMaxAttempsPerHour(config);\n await db.rateLimits.create({\n identifier,\n attemptsLeft: maxAttempsPerHour - 1,\n lastAttemptTime: Date.now(),\n });\n }\n}\n\nexport async function resetSignInRateLimit(\n ctx: MutationCtx,\n identifier: string,\n config: ConvexAuthConfig,\n) {\n const existingState = await getRateLimitState(ctx, identifier, config);\n if (existingState !== null) {\n await authDb(ctx, config).rateLimits.delete(existingState.limit._id);\n }\n}\n\nasync function getRateLimitState(\n ctx: MutationCtx,\n identifier: string,\n config: ConvexAuthConfig,\n) {\n const now = Date.now();\n const maxAttempsPerHour = configuredMaxAttempsPerHour(config);\n const limit = (await authDb(ctx, config).rateLimits.get(identifier)) as\n | Doc<\"limit\">\n | null;\n if (limit === null) {\n return null;\n }\n const elapsed = now - limit.lastAttemptTime;\n const maxAttempsPerMs = maxAttempsPerHour / (60 * 60 * 1000);\n const attempsLeft = Math.min(\n maxAttempsPerHour,\n limit.attemptsLeft + elapsed * maxAttempsPerMs,\n );\n return { limit, attempsLeft };\n}\n\nfunction configuredMaxAttempsPerHour(config: ConvexAuthConfig) {\n return (\n config.signIn?.maxFailedAttempsPerHour ??\n DEFAULT_MAX_SIGN_IN_ATTEMPTS_PER_HOUR\n );\n}\n"],"mappings":";;;AAIA,MAAM,wCAAwC;AAE9C,eAAsB,oBACpB,KACA,YACA,QACA;CACA,MAAM,QAAQ,MAAM,kBAAkB,KAAK,YAAY,OAAO;AAC9D,KAAI,UAAU,KACZ,QAAO;AAET,QAAO,MAAM,cAAc;;AAG7B,eAAsB,mBACpB,KACA,YACA,QACA;CACA,MAAM,KAAK,OAAO,KAAK,OAAO;CAC9B,MAAM,QAAQ,MAAM,kBAAkB,KAAK,YAAY,OAAO;AAC9D,KAAI,UAAU,KACZ,OAAM,GAAG,WAAW,MAAM,MAAM,MAAM,KAAK;EACzC,cAAc,MAAM,cAAc;EAClC,iBAAiB,KAAK,KAAK;EAC5B,CAAC;MACG;EACL,MAAM,oBAAoB,4BAA4B,OAAO;AAC7D,QAAM,GAAG,WAAW,OAAO;GACzB;GACA,cAAc,oBAAoB;GAClC,iBAAiB,KAAK,KAAK;GAC5B,CAAC;;;AAIN,eAAsB,qBACpB,KACA,YACA,QACA;CACA,MAAM,gBAAgB,MAAM,kBAAkB,KAAK,YAAY,OAAO;AACtE,KAAI,kBAAkB,KACpB,OAAM,OAAO,KAAK,OAAO,CAAC,WAAW,OAAO,cAAc,MAAM,IAAI;;AAIxE,eAAe,kBACb,KACA,YACA,QACA;CACA,MAAM,MAAM,KAAK,KAAK;CACtB,MAAM,oBAAoB,4BAA4B,OAAO;CAC7D,MAAM,QAAS,MAAM,OAAO,KAAK,OAAO,CAAC,WAAW,IAAI,WAAW;AAGnE,KAAI,UAAU,KACZ,QAAO;CAET,MAAM,UAAU,MAAM,MAAM;CAC5B,MAAM,kBAAkB,qBAAqB,OAAU;AAKvD,QAAO;EAAE;EAAO,aAJI,KAAK,IACvB,mBACA,MAAM,eAAe,UAAU,gBAChC;EAC4B;;AAG/B,SAAS,4BAA4B,QAA0B;AAC7D,QACE,OAAO,QAAQ,2BACf"}
|