@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 +1 @@
|
|
|
1
|
-
{"version":3,"file":"errors.js","names":[],"sources":["../../../src/server/errors.ts"],"sourcesContent":["/**\n * Structured error handling for Convex Auth.\n *\n * Every error thrown by the auth system uses `ConvexError` with a\n * `{ code, message }` payload so clients can distinguish error types\n * and display user-friendly messages.\n *\n * @module\n */\n\nimport { ConvexError } from \"convex/values\";\n\n// ============================================================================\n// Error code → default message map (single source of truth)\n// ============================================================================\n\n/**\n * Map of every auth error code to its default human-readable message.\n *\n * Use the keys as the `code` argument to {@link throwAuthError}.\n * Clients can match on these codes for conditional error handling.\n *\n * @example\n * ```ts\n * throwAuthError(\"NOT_SIGNED_IN\");\n * // ConvexError { data: { code: \"NOT_SIGNED_IN\", message: \"You must be signed in...\" } }\n * ```\n */\nexport const AUTH_ERRORS = {\n // ---- Configuration ----\n PROVIDER_NOT_CONFIGURED:\n \"This sign-in method is not available.\",\n EMAIL_CONFIG_REQUIRED:\n \"Email transport is not configured. Configure email in your Auth constructor.\",\n MISSING_ENV_VAR:\n \"A required server environment variable is missing.\",\n MISSING_ACTION_CONTEXT:\n \"Action context is required for this operation.\",\n\n // ---- Authentication ----\n NOT_SIGNED_IN:\n \"You must be signed in to perform this action.\",\n INVALID_VERIFICATION_CODE:\n \"Invalid or expired verification code.\",\n INVALID_REFRESH_TOKEN:\n \"Your session has expired. Please sign in again.\",\n SIGN_IN_MISSING_PARAMS:\n \"Cannot sign in: missing provider, code, or refresh token.\",\n UNSUPPORTED_PROVIDER_TYPE:\n \"This provider type is not supported.\",\n INVALID_REDIRECT:\n \"Invalid redirect URL.\",\n\n // ---- Email / Phone ----\n EMAIL_SEND_FAILED:\n \"Failed to send verification email. Please try again.\",\n\n // ---- API Keys ----\n INVALID_API_KEY:\n \"Invalid API key.\",\n API_KEY_REVOKED:\n \"This API key has been revoked.\",\n API_KEY_EXPIRED:\n \"This API key has expired.\",\n API_KEY_RATE_LIMITED:\n \"API key rate limit exceeded. Please try again later.\",\n API_KEY_INVALID_SCOPE:\n \"Invalid scope requested for API key.\",\n\n // ---- HTTP Bearer Auth ----\n MISSING_BEARER_TOKEN:\n \"Missing or malformed Authorization: Bearer header.\",\n SCOPE_CHECK_FAILED:\n \"This API key does not have the required permissions.\",\n\n // ---- OAuth ----\n OAUTH_MISSING_PROVIDER:\n \"Missing OAuth provider ID.\",\n OAUTH_MISSING_VERIFIER:\n \"Missing sign-in verifier.\",\n OAUTH_INVALID_STATE:\n \"Invalid OAuth state. Please try signing in again.\",\n OAUTH_PROVIDER_ERROR:\n \"The sign-in provider returned an error.\",\n OAUTH_MISSING_ID_TOKEN:\n \"ID token claims are missing from the provider response.\",\n OAUTH_INVALID_PROFILE:\n \"The sign-in provider returned an invalid profile.\",\n OAUTH_UNSUPPORTED_AUTH_METHOD:\n \"Unsupported OAuth client authentication method.\",\n OAUTH_NO_USERINFO:\n \"No userinfo endpoint configured for this provider.\",\n\n // ---- Credentials ----\n ACCOUNT_ALREADY_EXISTS:\n \"An account with these credentials already exists.\",\n ACCOUNT_NOT_FOUND:\n \"Account not found.\",\n INVALID_CREDENTIALS_PROVIDER:\n \"This provider does not support credential operations.\",\n MISSING_CRYPTO_FUNCTION:\n \"This provider is missing a required cryptographic function.\",\n USER_UPDATE_FAILED:\n \"Could not update the user record.\",\n\n // ---- Verifier ----\n INVALID_VERIFIER:\n \"Invalid or expired verifier.\",\n\n // ---- Passkey ----\n PASSKEY_MISSING_CONFIG:\n \"Passkey provider requires SITE_URL or explicit rpId configuration.\",\n PASSKEY_AUTH_REQUIRED:\n \"Sign in first, then add a passkey to your account.\",\n PASSKEY_MISSING_VERIFIER:\n \"Missing verifier for passkey operation.\",\n PASSKEY_INVALID_CLIENT_DATA:\n \"Invalid passkey client data.\",\n PASSKEY_INVALID_ORIGIN:\n \"Passkey origin does not match the expected value.\",\n PASSKEY_INVALID_CHALLENGE:\n \"Invalid or expired passkey challenge.\",\n PASSKEY_RP_MISMATCH:\n \"Relying party ID mismatch.\",\n PASSKEY_USER_PRESENCE:\n \"User presence flag not set.\",\n PASSKEY_USER_VERIFICATION:\n \"User verification required but not performed.\",\n PASSKEY_NO_CREDENTIAL:\n \"No credential in attestation.\",\n PASSKEY_UNSUPPORTED_ALGORITHM:\n \"Unsupported passkey algorithm.\",\n PASSKEY_INVALID_SIGNATURE:\n \"Invalid passkey signature.\",\n PASSKEY_UNKNOWN_CREDENTIAL:\n \"Unknown passkey credential.\",\n PASSKEY_COUNTER_ERROR:\n \"Authenticator counter did not increase — possible credential cloning detected.\",\n PASSKEY_MISSING_FLOW:\n \"Missing passkey flow parameter.\",\n PASSKEY_UNKNOWN_FLOW:\n \"Unknown passkey flow.\",\n\n // ---- TOTP ----\n TOTP_AUTH_REQUIRED:\n \"Sign in first, then set up two-factor authentication.\",\n TOTP_MISSING_VERIFIER:\n \"Missing verifier for TOTP operation.\",\n TOTP_MISSING_CODE:\n \"Missing TOTP code.\",\n TOTP_MISSING_ID:\n \"Missing TOTP enrollment ID.\",\n TOTP_NOT_FOUND:\n \"TOTP enrollment not found.\",\n TOTP_ALREADY_VERIFIED:\n \"TOTP enrollment is already verified.\",\n TOTP_INVALID_CODE:\n \"Invalid TOTP code.\",\n TOTP_INVALID_VERIFIER:\n \"Invalid or expired TOTP verifier.\",\n TOTP_NO_ENROLLMENT:\n \"No verified TOTP enrollment found.\",\n TOTP_MISSING_FLOW:\n \"Missing TOTP flow parameter.\",\n TOTP_UNKNOWN_FLOW:\n \"Unknown TOTP flow.\",\n\n // ---- Device Authorization (RFC 8628) ----\n DEVICE_CODE_EXPIRED:\n \"The device code has expired. Please start a new authorization request.\",\n DEVICE_CODE_DENIED:\n \"The authorization request was denied.\",\n DEVICE_AUTHORIZATION_PENDING:\n \"The user has not yet authorized this device.\",\n DEVICE_SLOW_DOWN:\n \"Polling too frequently. Increase the interval between requests.\",\n DEVICE_INVALID_USER_CODE:\n \"Invalid or expired user code.\",\n DEVICE_ALREADY_AUTHORIZED:\n \"This device code has already been authorized.\",\n DEVICE_MISSING_FLOW:\n \"Missing device flow parameter.\",\n DEVICE_UNKNOWN_FLOW:\n \"Unknown device flow.\",\n\n // ---- Internal (should never reach user) ----\n INTERNAL_ERROR:\n \"An unexpected error occurred.\",\n} as const satisfies Record<string, string>;\n\n/** Union of all recognized auth error code strings (keys of {@link AUTH_ERRORS}). */\nexport type AuthErrorCode = keyof typeof AUTH_ERRORS;\n\n// ============================================================================\n// Error helpers\n// ============================================================================\n\n/**\n * Throw a structured `ConvexError` with `{ code, message }`.\n *\n * @param code Machine-readable error code from `AUTH_ERRORS`.\n * @param message Optional override for the default human-readable message.\n * @param context Optional extra fields merged into the error payload.\n */\nexport function throwAuthError(\n code: AuthErrorCode,\n message?: string,\n context?: Record<string, unknown>,\n): never {\n throw new ConvexError({\n code,\n message: message ?? AUTH_ERRORS[code],\n ...context,\n });\n}\n\n/**\n * Type guard: check whether a caught value is a structured auth `ConvexError`.\n *\n * @param error - The caught value (typically from a `catch` block).\n * @returns `true` when `error` is a `ConvexError` with `{ code, message }` data.\n *\n * @example\n * ```ts\n * try { await auth.signIn('email', { email }); }\n * catch (e) {\n * if (isAuthError(e)) console.log(e.data.code); // \"EMAIL_SEND_FAILED\"\n * }\n * ```\n */\nexport function isAuthError(\n error: unknown,\n): error is ConvexError<{ code: AuthErrorCode; message: string }> {\n return (\n error instanceof ConvexError &&\n typeof error.data === \"object\" &&\n error.data !== null &&\n \"code\" in error.data &&\n \"message\" in error.data\n );\n}\n\n/**\n * Extract `{ code, message }` from a caught error.\n *\n * Works for `ConvexError` (from Convex actions), plain `Error`\n * instances, and structured auth errors. Returns `null` when the\n * value is not an error object.\n *\n * @param error - The caught value to parse.\n * @returns `{ code, message }` when extractable, or `null`.\n * When `code` is `null`, the error is not a structured auth error\n * but `message` still contains the error text.\n *\n * @example\n * ```ts\n * try {\n * await auth.signIn(\"email\", { email });\n * } catch (e) {\n * const err = parseAuthError(e);\n * if (err?.code === \"EMAIL_SEND_FAILED\") { ... }\n * }\n * ```\n */\nexport function parseAuthError(\n error: unknown,\n): { code: AuthErrorCode; message: string } | { code: null; message: string } | null {\n if (isAuthError(error)) {\n const { code, message } = error.data as { code: AuthErrorCode; message: string };\n return { code, message };\n }\n if (error instanceof ConvexError && typeof error.data === \"string\") {\n return { code: null, message: error.data };\n }\n if (error instanceof Error) {\n return { code: null, message: error.message };\n }\n return null;\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;AA4BA,MAAa,cAAc;CAEzB,yBACE;CACF,uBACE;CACF,iBACE;CACF,wBACE;CAGF,eACE;CACF,2BACE;CACF,uBACE;CACF,wBACE;CACF,2BACE;CACF,kBACE;CAGF,mBACE;CAGF,iBACE;CACF,iBACE;CACF,iBACE;CACF,sBACE;CACF,uBACE;CAGF,sBACE;CACF,oBACE;CAGF,wBACE;CACF,wBACE;CACF,qBACE;CACF,sBACE;CACF,wBACE;CACF,uBACE;CACF,+BACE;CACF,mBACE;CAGF,wBACE;CACF,mBACE;CACF,8BACE;CACF,yBACE;CACF,oBACE;CAGF,kBACE;CAGF,wBACE;CACF,uBACE;CACF,0BACE;CACF,6BACE;CACF,wBACE;CACF,2BACE;CACF,qBACE;CACF,uBACE;CACF,2BACE;CACF,uBACE;CACF,+BACE;CACF,2BACE;CACF,4BACE;CACF,uBACE;CACF,sBACE;CACF,sBACE;CAGF,oBACE;CACF,uBACE;CACF,mBACE;CACF,iBACE;CACF,gBACE;CACF,uBACE;CACF,mBACE;CACF,uBACE;CACF,oBACE;CACF,mBACE;CACF,mBACE;CAGF,qBACE;CACF,oBACE;CACF,8BACE;CACF,kBACE;CACF,0BACE;CACF,2BACE;CACF,qBACE;CACF,qBACE;CAGF,gBACE;CACH;;;;;;;;AAgBD,SAAgB,eACd,MACA,SACA,SACO;AACP,OAAM,IAAI,YAAY;EACpB;EACA,SAAS,WAAW,YAAY;EAChC,GAAG;EACJ,CAAC;;;;;;;;;;;;;;;;AAiBJ,SAAgB,YACd,OACgE;AAChE,QACE,iBAAiB,eACjB,OAAO,MAAM,SAAS,YACtB,MAAM,SAAS,QACf,UAAU,MAAM,QAChB,aAAa,MAAM"}
|
|
1
|
+
{"version":3,"file":"errors.js","names":[],"sources":["../../../src/server/errors.ts"],"sourcesContent":["/**\n * Structured error handling for Convex Auth.\n *\n * Every error thrown by the auth system uses `ConvexError` with a\n * `{ code, message }` payload so clients can distinguish error types\n * and display user-friendly messages.\n *\n * **Consumer API:** Use {@link throwAuthError} to throw structured errors\n * from your own Convex functions (e.g. custom authorization checks).\n *\n * **Internal pattern:** The library itself uses `new AuthError(code)` with\n * the `@robelest/fx` effect system (`Fx.fail(new AuthError(code))`).\n * You do not need to use `AuthError` directly — it is an implementation detail.\n *\n * @module\n */\n\nimport { ConvexError } from \"convex/values\";\n\n// ============================================================================\n// Error code → default message map (single source of truth)\n// ============================================================================\n\n/**\n * Map of every auth error code to its default human-readable message.\n *\n * Use the keys as the `code` argument to {@link throwAuthError}.\n * Clients can match on these codes for conditional error handling.\n *\n * @example\n * ```ts\n * throwAuthError(\"NOT_SIGNED_IN\");\n * // ConvexError { data: { code: \"NOT_SIGNED_IN\", message: \"You must be signed in...\" } }\n * ```\n */\nexport const AUTH_ERRORS = {\n // ---- Configuration ----\n PROVIDER_NOT_CONFIGURED: \"This sign-in method is not available.\",\n EMAIL_CONFIG_REQUIRED:\n \"Email transport is not configured. Configure email in createAuth(...).\",\n MISSING_ENV_VAR: \"A required server environment variable is missing.\",\n MISSING_ACTION_CONTEXT: \"Action context is required for this operation.\",\n INVALID_PARAMETERS: \"The provided parameters are invalid.\",\n\n // ---- Authentication ----\n NOT_SIGNED_IN: \"You must be signed in to perform this action.\",\n INVALID_VERIFICATION_CODE: \"Invalid or expired verification code.\",\n INVALID_REFRESH_TOKEN: \"Your session has expired. Please sign in again.\",\n AUTH_HANDSHAKE_TIMEOUT:\n \"Sign-in succeeded but authentication confirmation timed out.\",\n AUTH_HANDSHAKE_REJECTED:\n \"Authentication was rejected while confirming the session.\",\n SIGN_IN_MISSING_PARAMS:\n \"Cannot sign in: missing provider, code, or refresh token.\",\n UNSUPPORTED_PROVIDER_TYPE: \"This provider type is not supported.\",\n INVALID_REDIRECT: \"Invalid redirect URL.\",\n\n // ---- Email / Phone ----\n EMAIL_SEND_FAILED: \"Failed to send verification email. Please try again.\",\n\n // ---- API Keys ----\n INVALID_API_KEY: \"Invalid API key.\",\n API_KEY_REVOKED: \"This API key has been revoked.\",\n API_KEY_EXPIRED: \"This API key has expired.\",\n API_KEY_RATE_LIMITED: \"API key rate limit exceeded. Please try again later.\",\n API_KEY_INVALID_SCOPE: \"Invalid scope requested for API key.\",\n KEY_NOT_FOUND: \"API key not found.\",\n\n // ---- HTTP Bearer Auth ----\n MISSING_BEARER_TOKEN: \"Missing or malformed Authorization: Bearer header.\",\n SCOPE_CHECK_FAILED: \"This API key does not have the required permissions.\",\n\n // ---- OAuth ----\n OAUTH_MISSING_PROVIDER: \"Missing OAuth provider ID.\",\n OAUTH_MISSING_VERIFIER: \"Missing sign-in verifier.\",\n OAUTH_INVALID_STATE: \"Invalid OAuth state. Please try signing in again.\",\n OAUTH_PROVIDER_ERROR: \"The sign-in provider returned an error.\",\n OAUTH_MISSING_ID_TOKEN:\n \"ID token claims are missing from the provider response.\",\n OAUTH_INVALID_PROFILE: \"The sign-in provider returned an invalid profile.\",\n OAUTH_UNSUPPORTED_AUTH_METHOD:\n \"Unsupported OAuth client authentication method.\",\n OAUTH_NO_USERINFO: \"No userinfo endpoint configured for this provider.\",\n\n // ---- Credentials ----\n ACCOUNT_ALREADY_EXISTS: \"An account with these credentials already exists.\",\n ACCOUNT_NOT_FOUND: \"Account not found.\",\n INVALID_CREDENTIALS_PROVIDER:\n \"This provider does not support credential operations.\",\n MISSING_CRYPTO_FUNCTION:\n \"This provider is missing a required cryptographic function.\",\n USER_UPDATE_FAILED: \"Could not update the user record.\",\n\n // ---- Verifier ----\n INVALID_VERIFIER: \"Invalid or expired verifier.\",\n\n // ---- Passkey ----\n PASSKEY_MISSING_CONFIG:\n \"Passkey provider requires SITE_URL or explicit rpId configuration.\",\n PASSKEY_AUTH_REQUIRED: \"Sign in first, then add a passkey to your account.\",\n PASSKEY_MISSING_VERIFIER: \"Missing verifier for passkey operation.\",\n PASSKEY_INVALID_CLIENT_DATA: \"Invalid passkey client data.\",\n PASSKEY_INVALID_ORIGIN: \"Passkey origin does not match the expected value.\",\n PASSKEY_INVALID_CHALLENGE: \"Invalid or expired passkey challenge.\",\n PASSKEY_RP_MISMATCH: \"Relying party ID mismatch.\",\n PASSKEY_USER_PRESENCE: \"User presence flag not set.\",\n PASSKEY_USER_VERIFICATION: \"User verification required but not performed.\",\n PASSKEY_NO_CREDENTIAL: \"No credential in attestation.\",\n PASSKEY_UNSUPPORTED_ALGORITHM: \"Unsupported passkey algorithm.\",\n PASSKEY_INVALID_SIGNATURE: \"Invalid passkey signature.\",\n PASSKEY_UNKNOWN_CREDENTIAL: \"Unknown passkey credential.\",\n PASSKEY_COUNTER_ERROR:\n \"Authenticator counter did not increase — possible credential cloning detected.\",\n PASSKEY_MISSING_FLOW: \"Missing passkey flow parameter.\",\n PASSKEY_UNKNOWN_FLOW: \"Unknown passkey flow.\",\n\n // ---- TOTP ----\n TOTP_AUTH_REQUIRED: \"Sign in first, then set up two-factor authentication.\",\n TOTP_MISSING_VERIFIER: \"Missing verifier for TOTP operation.\",\n TOTP_MISSING_CODE: \"Missing TOTP code.\",\n TOTP_MISSING_ID: \"Missing TOTP enrollment ID.\",\n TOTP_NOT_FOUND: \"TOTP enrollment not found.\",\n TOTP_ALREADY_VERIFIED: \"TOTP enrollment is already verified.\",\n TOTP_INVALID_CODE: \"Invalid TOTP code.\",\n TOTP_INVALID_VERIFIER: \"Invalid or expired TOTP verifier.\",\n TOTP_NO_ENROLLMENT: \"No verified TOTP enrollment found.\",\n TOTP_MISSING_FLOW: \"Missing TOTP flow parameter.\",\n TOTP_UNKNOWN_FLOW: \"Unknown TOTP flow.\",\n\n // ---- Device Authorization (RFC 8628) ----\n DEVICE_CODE_EXPIRED:\n \"The device code has expired. Please start a new authorization request.\",\n DEVICE_CODE_DENIED: \"The authorization request was denied.\",\n DEVICE_AUTHORIZATION_PENDING: \"The user has not yet authorized this device.\",\n DEVICE_SLOW_DOWN:\n \"Polling too frequently. Increase the interval between requests.\",\n DEVICE_INVALID_USER_CODE: \"Invalid or expired user code.\",\n DEVICE_ALREADY_AUTHORIZED: \"This device code has already been authorized.\",\n DEVICE_MISSING_FLOW: \"Missing device flow parameter.\",\n DEVICE_UNKNOWN_FLOW: \"Unknown device flow.\",\n\n // ---- Invites ----\n INVITE_EXPIRED: \"This invitation has expired.\",\n INVITE_EMAIL_MISMATCH: \"This invitation is for a different email.\",\n INVITE_ALREADY_ACCEPTED: \"This invitation has already been accepted.\",\n DUPLICATE_INVITE:\n \"A pending invite already exists for this email in this group.\",\n INVITE_NOT_FOUND: \"Invite not found.\",\n INVITE_NOT_PENDING: \"Cannot accept or revoke invite that is not pending.\",\n\n // ---- Groups / Members ----\n FORBIDDEN: \"Access denied.\",\n NO_ACTIVE_GROUP: \"User has no active group set.\",\n DUPLICATE_MEMBERSHIP: \"User is already a member of this group.\",\n\n // ---- Enterprise ----\n ENTERPRISE_ALREADY_EXISTS:\n \"An enterprise record already exists for this group.\",\n ENTERPRISE_DOMAIN_TAKEN:\n \"That domain is already attached to another enterprise.\",\n\n // ---- Internal (should never reach user) ----\n INTERNAL_ERROR: \"An unexpected error occurred.\",\n} as const satisfies Record<string, string>;\n\n/** Union of all recognized auth error code strings (keys of {@link AUTH_ERRORS}). */\nexport type AuthErrorCode = keyof typeof AUTH_ERRORS;\n\n// ============================================================================\n// Error helpers\n// ============================================================================\n\n/**\n * Throw a structured `ConvexError` with `{ code, message }`.\n *\n * Use this in your own Convex functions (queries, mutations, actions)\n * to throw auth-domain errors that clients can match on by `code`.\n * The library itself uses `AuthError` internally, but consumers\n * should prefer this helper for simplicity.\n *\n * @param code Machine-readable error code from `AUTH_ERRORS`.\n * @param message Optional override for the default human-readable message.\n * @param context Optional extra fields merged into the error payload.\n *\n * @example\n * ```ts\n * import { throwAuthError } from \"@robelest/convex-auth/server\";\n *\n * // In a custom mutation:\n * if (!isAdmin) {\n * throwAuthError(\"FORBIDDEN\");\n * }\n * ```\n *\n * @throws {ConvexError} Always — throws a `ConvexError` with `{ code, message }` payload.\n */\nexport function throwAuthError(\n code: AuthErrorCode,\n message?: string,\n context?: Record<string, unknown>,\n): never {\n throw new ConvexError({\n code,\n message: message ?? AUTH_ERRORS[code],\n ...context,\n });\n}\n\n/**\n * Type guard: check whether a caught value is a structured auth `ConvexError`.\n *\n * @param error - The caught value (typically from a `catch` block).\n * @returns `true` when `error` is a `ConvexError` with `{ code, message }` data.\n *\n * @example\n * ```ts\n * try { await auth.signIn('email', { email }); }\n * catch (e) {\n * if (isAuthError(e)) console.log(e.data.code); // \"EMAIL_SEND_FAILED\"\n * }\n * ```\n */\nexport function isAuthError(\n error: unknown,\n): error is ConvexError<{ code: AuthErrorCode; message: string }> {\n return (\n error instanceof ConvexError &&\n typeof error.data === \"object\" &&\n error.data !== null &&\n \"code\" in error.data &&\n \"message\" in error.data\n );\n}\n\n/**\n * Extract `{ code, message }` from a caught error.\n *\n * Works for `ConvexError` (from Convex actions), plain `Error`\n * instances, and structured auth errors. Returns `null` when the\n * value is not an error object.\n *\n * @param error - The caught value to parse.\n * @returns `{ code, message }` when extractable, or `null`.\n * When `code` is `null`, the error is not a structured auth error\n * but `message` still contains the error text.\n *\n * @example\n * ```ts\n * try {\n * await auth.signIn(\"email\", { email });\n * } catch (e) {\n * const err = parseAuthError(e);\n * if (err?.code === \"EMAIL_SEND_FAILED\") { ... }\n * }\n * ```\n */\nexport function parseAuthError(\n error: unknown,\n):\n | { code: AuthErrorCode; message: string }\n | { code: null; message: string }\n | null {\n if (isAuthError(error)) {\n const { code, message } = error.data as {\n code: AuthErrorCode;\n message: string;\n };\n return { code, message };\n }\n // Recognize the Fx-native AuthError class (has _tag + code)\n if (\n error instanceof Error &&\n \"_tag\" in error &&\n (error as any)._tag === \"AuthError\" &&\n \"code\" in error &&\n typeof (error as any).code === \"string\"\n ) {\n return {\n code: (error as any).code as AuthErrorCode,\n message: error.message,\n };\n }\n if (error instanceof ConvexError && typeof error.data === \"string\") {\n return { code: null, message: error.data };\n }\n if (error instanceof Error) {\n return { code: null, message: error.message };\n }\n return null;\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAmCA,MAAa,cAAc;CAEzB,yBAAyB;CACzB,uBACE;CACF,iBAAiB;CACjB,wBAAwB;CACxB,oBAAoB;CAGpB,eAAe;CACf,2BAA2B;CAC3B,uBAAuB;CACvB,wBACE;CACF,yBACE;CACF,wBACE;CACF,2BAA2B;CAC3B,kBAAkB;CAGlB,mBAAmB;CAGnB,iBAAiB;CACjB,iBAAiB;CACjB,iBAAiB;CACjB,sBAAsB;CACtB,uBAAuB;CACvB,eAAe;CAGf,sBAAsB;CACtB,oBAAoB;CAGpB,wBAAwB;CACxB,wBAAwB;CACxB,qBAAqB;CACrB,sBAAsB;CACtB,wBACE;CACF,uBAAuB;CACvB,+BACE;CACF,mBAAmB;CAGnB,wBAAwB;CACxB,mBAAmB;CACnB,8BACE;CACF,yBACE;CACF,oBAAoB;CAGpB,kBAAkB;CAGlB,wBACE;CACF,uBAAuB;CACvB,0BAA0B;CAC1B,6BAA6B;CAC7B,wBAAwB;CACxB,2BAA2B;CAC3B,qBAAqB;CACrB,uBAAuB;CACvB,2BAA2B;CAC3B,uBAAuB;CACvB,+BAA+B;CAC/B,2BAA2B;CAC3B,4BAA4B;CAC5B,uBACE;CACF,sBAAsB;CACtB,sBAAsB;CAGtB,oBAAoB;CACpB,uBAAuB;CACvB,mBAAmB;CACnB,iBAAiB;CACjB,gBAAgB;CAChB,uBAAuB;CACvB,mBAAmB;CACnB,uBAAuB;CACvB,oBAAoB;CACpB,mBAAmB;CACnB,mBAAmB;CAGnB,qBACE;CACF,oBAAoB;CACpB,8BAA8B;CAC9B,kBACE;CACF,0BAA0B;CAC1B,2BAA2B;CAC3B,qBAAqB;CACrB,qBAAqB;CAGrB,gBAAgB;CAChB,uBAAuB;CACvB,yBAAyB;CACzB,kBACE;CACF,kBAAkB;CAClB,oBAAoB;CAGpB,WAAW;CACX,iBAAiB;CACjB,sBAAsB;CAGtB,2BACE;CACF,yBACE;CAGF,gBAAgB;CACjB;;;;;;;;;;;;;;;AA2DD,SAAgB,YACd,OACgE;AAChE,QACE,iBAAiB,eACjB,OAAO,MAAM,SAAS,YACtB,MAAM,SAAS,QACf,UAAU,MAAM,QAChB,aAAa,MAAM"}
|
|
@@ -0,0 +1,288 @@
|
|
|
1
|
+
import { isAuthError } from "./errors.js";
|
|
2
|
+
import { AuthError } from "./authError.js";
|
|
3
|
+
import { logError } from "./utils.js";
|
|
4
|
+
import { httpActionGeneric } from "convex/server";
|
|
5
|
+
import { ConvexError } from "convex/values";
|
|
6
|
+
import { parse } from "cookie";
|
|
7
|
+
import { Fx } from "@robelest/fx";
|
|
8
|
+
|
|
9
|
+
//#region src/server/http.ts
|
|
10
|
+
function createHttpAction(auth) {
|
|
11
|
+
return (handler, options) => {
|
|
12
|
+
const corsConfig = options?.cors ?? {};
|
|
13
|
+
const corsHeaders = {
|
|
14
|
+
"Access-Control-Allow-Origin": corsConfig.origin ?? "*",
|
|
15
|
+
"Access-Control-Allow-Methods": corsConfig.methods ?? "GET,POST,PUT,PATCH,DELETE,OPTIONS",
|
|
16
|
+
"Access-Control-Allow-Headers": corsConfig.headers ?? "Content-Type,Authorization"
|
|
17
|
+
};
|
|
18
|
+
return httpActionGeneric(async (genericCtx, request) => {
|
|
19
|
+
return Fx.run(Fx.from({
|
|
20
|
+
ok: async () => {
|
|
21
|
+
const authHeader = request.headers.get("Authorization");
|
|
22
|
+
if (!authHeader?.startsWith("Bearer ")) return new Response(JSON.stringify({
|
|
23
|
+
error: "Missing or malformed Authorization: Bearer header.",
|
|
24
|
+
code: "MISSING_BEARER_TOKEN"
|
|
25
|
+
}), {
|
|
26
|
+
status: 401,
|
|
27
|
+
headers: {
|
|
28
|
+
...corsHeaders,
|
|
29
|
+
"Content-Type": "application/json"
|
|
30
|
+
}
|
|
31
|
+
});
|
|
32
|
+
const rawKey = authHeader.slice(7);
|
|
33
|
+
const keyResult = await Fx.run(Fx.from({
|
|
34
|
+
ok: () => auth.key.verify(genericCtx, rawKey),
|
|
35
|
+
err: (error) => error
|
|
36
|
+
}).pipe(Fx.fold({
|
|
37
|
+
ok: (result$1) => ({
|
|
38
|
+
ok: true,
|
|
39
|
+
value: result$1
|
|
40
|
+
}),
|
|
41
|
+
err: (error) => ({
|
|
42
|
+
ok: false,
|
|
43
|
+
error
|
|
44
|
+
})
|
|
45
|
+
})));
|
|
46
|
+
if (!keyResult.ok) {
|
|
47
|
+
if (isAuthError(keyResult.error)) {
|
|
48
|
+
const { code, message } = keyResult.error.data;
|
|
49
|
+
return new Response(JSON.stringify({
|
|
50
|
+
error: message,
|
|
51
|
+
code
|
|
52
|
+
}), {
|
|
53
|
+
status: 403,
|
|
54
|
+
headers: {
|
|
55
|
+
...corsHeaders,
|
|
56
|
+
"Content-Type": "application/json"
|
|
57
|
+
}
|
|
58
|
+
});
|
|
59
|
+
}
|
|
60
|
+
throw keyResult.error;
|
|
61
|
+
}
|
|
62
|
+
if (options?.scope && !keyResult.value.scopes.can(options.scope.resource, options.scope.action)) return new Response(JSON.stringify({
|
|
63
|
+
error: "This API key does not have the required permissions.",
|
|
64
|
+
code: "SCOPE_CHECK_FAILED"
|
|
65
|
+
}), {
|
|
66
|
+
status: 403,
|
|
67
|
+
headers: {
|
|
68
|
+
...corsHeaders,
|
|
69
|
+
"Content-Type": "application/json"
|
|
70
|
+
}
|
|
71
|
+
});
|
|
72
|
+
const result = await handler(Object.assign(genericCtx, { key: {
|
|
73
|
+
userId: keyResult.value.userId,
|
|
74
|
+
keyId: keyResult.value.keyId,
|
|
75
|
+
scopes: keyResult.value.scopes
|
|
76
|
+
} }), request);
|
|
77
|
+
if (result instanceof Response) {
|
|
78
|
+
const headers = new Headers(result.headers);
|
|
79
|
+
for (const [k, val] of Object.entries(corsHeaders)) if (!headers.has(k)) headers.set(k, val);
|
|
80
|
+
return new Response(result.body, {
|
|
81
|
+
status: result.status,
|
|
82
|
+
statusText: result.statusText,
|
|
83
|
+
headers
|
|
84
|
+
});
|
|
85
|
+
}
|
|
86
|
+
return new Response(JSON.stringify(result), {
|
|
87
|
+
status: 200,
|
|
88
|
+
headers: {
|
|
89
|
+
...corsHeaders,
|
|
90
|
+
"Content-Type": "application/json"
|
|
91
|
+
}
|
|
92
|
+
});
|
|
93
|
+
},
|
|
94
|
+
err: (error) => error
|
|
95
|
+
}).pipe(Fx.recover((error) => {
|
|
96
|
+
logError(error);
|
|
97
|
+
return Fx.succeed(new Response(JSON.stringify({
|
|
98
|
+
error: "An unexpected error occurred.",
|
|
99
|
+
code: "INTERNAL_ERROR"
|
|
100
|
+
}), {
|
|
101
|
+
status: 500,
|
|
102
|
+
headers: {
|
|
103
|
+
...corsHeaders,
|
|
104
|
+
"Content-Type": "application/json"
|
|
105
|
+
}
|
|
106
|
+
}));
|
|
107
|
+
})));
|
|
108
|
+
});
|
|
109
|
+
};
|
|
110
|
+
}
|
|
111
|
+
function createHttpRoute(wrapAction) {
|
|
112
|
+
return (http, routeConfig) => {
|
|
113
|
+
const corsConfig = routeConfig.cors ?? {};
|
|
114
|
+
const corsHeaders = {
|
|
115
|
+
"Access-Control-Allow-Origin": corsConfig.origin ?? "*",
|
|
116
|
+
"Access-Control-Allow-Methods": corsConfig.methods ?? "GET,POST,PUT,PATCH,DELETE,OPTIONS",
|
|
117
|
+
"Access-Control-Allow-Headers": corsConfig.headers ?? "Content-Type,Authorization"
|
|
118
|
+
};
|
|
119
|
+
http.route({
|
|
120
|
+
path: routeConfig.path,
|
|
121
|
+
method: "OPTIONS",
|
|
122
|
+
handler: httpActionGeneric(async () => {
|
|
123
|
+
return new Response(null, {
|
|
124
|
+
status: 204,
|
|
125
|
+
headers: corsHeaders
|
|
126
|
+
});
|
|
127
|
+
})
|
|
128
|
+
});
|
|
129
|
+
http.route({
|
|
130
|
+
path: routeConfig.path,
|
|
131
|
+
method: routeConfig.method,
|
|
132
|
+
handler: wrapAction(routeConfig.handler, {
|
|
133
|
+
scope: routeConfig.scope,
|
|
134
|
+
cors: routeConfig.cors
|
|
135
|
+
})
|
|
136
|
+
});
|
|
137
|
+
};
|
|
138
|
+
}
|
|
139
|
+
function convertErrorsToResponse(errorStatusCode, action) {
|
|
140
|
+
return async (ctx, request) => {
|
|
141
|
+
return Fx.run(Fx.from({
|
|
142
|
+
ok: () => action(ctx, request),
|
|
143
|
+
err: (error) => error
|
|
144
|
+
}).pipe(Fx.recover((error) => {
|
|
145
|
+
if (isAuthError(error)) return Fx.succeed(new Response(JSON.stringify({
|
|
146
|
+
code: error.data.code,
|
|
147
|
+
message: error.data.message
|
|
148
|
+
}), {
|
|
149
|
+
status: errorStatusCode,
|
|
150
|
+
headers: { "Content-Type": "application/json" }
|
|
151
|
+
}));
|
|
152
|
+
else if (error instanceof ConvexError) return Fx.succeed(new Response(null, {
|
|
153
|
+
status: errorStatusCode,
|
|
154
|
+
statusText: typeof error.data === "string" ? error.data : "Error"
|
|
155
|
+
}));
|
|
156
|
+
else {
|
|
157
|
+
logError(error);
|
|
158
|
+
return Fx.succeed(new Response(null, {
|
|
159
|
+
status: 500,
|
|
160
|
+
statusText: "Internal Server Error"
|
|
161
|
+
}));
|
|
162
|
+
}
|
|
163
|
+
})));
|
|
164
|
+
};
|
|
165
|
+
}
|
|
166
|
+
function getCookies(request) {
|
|
167
|
+
return parse(request.headers.get("Cookie") ?? "");
|
|
168
|
+
}
|
|
169
|
+
function parseEnterpriseRuntimeRoute(pathname, routeBase) {
|
|
170
|
+
const runtimePrefix = `${routeBase}/`;
|
|
171
|
+
const [runtimeEnterpriseId, protocol, ...rest] = pathname.startsWith(runtimePrefix) ? pathname.slice(runtimePrefix.length).split("/").filter(Boolean) : [];
|
|
172
|
+
if (runtimeEnterpriseId === void 0 || protocol !== "oidc" && protocol !== "saml" && protocol !== "scim" || rest.length === 0) return null;
|
|
173
|
+
return {
|
|
174
|
+
pathname,
|
|
175
|
+
enterpriseId: runtimeEnterpriseId,
|
|
176
|
+
protocol,
|
|
177
|
+
rest
|
|
178
|
+
};
|
|
179
|
+
}
|
|
180
|
+
function addOpenIdRoutes(http, deps) {
|
|
181
|
+
const cacheControl = "public, max-age=15, stale-while-revalidate=15, stale-if-error=86400";
|
|
182
|
+
http.route({
|
|
183
|
+
path: "/.well-known/openid-configuration",
|
|
184
|
+
method: "GET",
|
|
185
|
+
handler: httpActionGeneric(async () => {
|
|
186
|
+
const issuer = deps.getIssuer();
|
|
187
|
+
return new Response(JSON.stringify({
|
|
188
|
+
issuer,
|
|
189
|
+
jwks_uri: `${issuer}/.well-known/jwks.json`
|
|
190
|
+
}), {
|
|
191
|
+
status: 200,
|
|
192
|
+
headers: {
|
|
193
|
+
"Content-Type": "application/json",
|
|
194
|
+
"Cache-Control": cacheControl
|
|
195
|
+
}
|
|
196
|
+
});
|
|
197
|
+
})
|
|
198
|
+
});
|
|
199
|
+
http.route({
|
|
200
|
+
path: "/.well-known/jwks.json",
|
|
201
|
+
method: "GET",
|
|
202
|
+
handler: httpActionGeneric(async () => {
|
|
203
|
+
return new Response(deps.getJwks(), {
|
|
204
|
+
status: 200,
|
|
205
|
+
headers: {
|
|
206
|
+
"Content-Type": "application/json",
|
|
207
|
+
"Cache-Control": cacheControl
|
|
208
|
+
}
|
|
209
|
+
});
|
|
210
|
+
})
|
|
211
|
+
});
|
|
212
|
+
}
|
|
213
|
+
function addAuthRoutes(http, deps) {
|
|
214
|
+
http.route({
|
|
215
|
+
pathPrefix: "/api/auth/signin/",
|
|
216
|
+
method: "GET",
|
|
217
|
+
handler: httpActionGeneric(deps.handleSignIn)
|
|
218
|
+
});
|
|
219
|
+
const callbackHandler = httpActionGeneric(deps.handleCallback);
|
|
220
|
+
http.route({
|
|
221
|
+
pathPrefix: "/api/auth/callback/",
|
|
222
|
+
method: "GET",
|
|
223
|
+
handler: callbackHandler
|
|
224
|
+
});
|
|
225
|
+
http.route({
|
|
226
|
+
pathPrefix: "/api/auth/callback/",
|
|
227
|
+
method: "POST",
|
|
228
|
+
handler: callbackHandler
|
|
229
|
+
});
|
|
230
|
+
}
|
|
231
|
+
function addSSORoutes(http, deps) {
|
|
232
|
+
const routePrefix = `${deps.routeBase}/`;
|
|
233
|
+
http.route({
|
|
234
|
+
pathPrefix: routePrefix,
|
|
235
|
+
method: "GET",
|
|
236
|
+
handler: httpActionGeneric(deps.convertErrorsToResponse(400, async (ctx, request) => {
|
|
237
|
+
const route = parseEnterpriseRuntimeRoute(new URL(request.url).pathname, deps.routeBase);
|
|
238
|
+
if (!route) throw new AuthError("INVALID_PARAMETERS", "Invalid enterprise runtime path.").toConvexError();
|
|
239
|
+
if (route.protocol === "saml" && route.rest.length === 1) {
|
|
240
|
+
if (route.rest[0] === "metadata") return await deps.handleSamlMetadata(ctx, request, route);
|
|
241
|
+
if (route.rest[0] === "signin") return await deps.handleSamlSignIn(ctx, request, route);
|
|
242
|
+
if (route.rest[0] === "acs") return await deps.handleSamlAcs(ctx, request, route);
|
|
243
|
+
if (route.rest[0] === "slo") return await deps.handleSamlSlo(ctx, request, route);
|
|
244
|
+
}
|
|
245
|
+
if (route.protocol === "oidc" && route.rest.length === 1) {
|
|
246
|
+
if (route.rest[0] === "signin") return await deps.handleOidcSignIn(ctx, request, route);
|
|
247
|
+
if (route.rest[0] === "callback") return await deps.handleOidcCallback(ctx, request, route);
|
|
248
|
+
}
|
|
249
|
+
if (route.protocol === "scim" && route.rest[0] === "v2") return await deps.handleScimRequest(ctx, request);
|
|
250
|
+
throw new AuthError("INVALID_PARAMETERS", "Invalid enterprise runtime path.").toConvexError();
|
|
251
|
+
}))
|
|
252
|
+
});
|
|
253
|
+
http.route({
|
|
254
|
+
pathPrefix: routePrefix,
|
|
255
|
+
method: "POST",
|
|
256
|
+
handler: httpActionGeneric(deps.convertErrorsToResponse(400, async (ctx, request) => {
|
|
257
|
+
const route = parseEnterpriseRuntimeRoute(new URL(request.url).pathname, deps.routeBase);
|
|
258
|
+
if (route?.protocol === "saml" && route.rest.length === 1) {
|
|
259
|
+
if (route.rest[0] === "acs") return await deps.handleSamlAcs(ctx, request, route);
|
|
260
|
+
if (route.rest[0] === "slo") return await deps.handleSamlSlo(ctx, request, route);
|
|
261
|
+
}
|
|
262
|
+
if (route?.protocol === "scim" && route.rest[0] === "v2") return await deps.handleScimRequest(ctx, request);
|
|
263
|
+
throw new AuthError("INVALID_PARAMETERS", "Invalid enterprise runtime path.").toConvexError();
|
|
264
|
+
}))
|
|
265
|
+
});
|
|
266
|
+
http.route({
|
|
267
|
+
pathPrefix: routePrefix,
|
|
268
|
+
method: "PUT",
|
|
269
|
+
handler: httpActionGeneric(deps.convertErrorsToResponse(400, async (ctx, request) => {
|
|
270
|
+
const route = parseEnterpriseRuntimeRoute(new URL(request.url).pathname, deps.routeBase);
|
|
271
|
+
if (route?.protocol === "scim" && route.rest[0] === "v2") return await deps.handleScimRequest(ctx, request);
|
|
272
|
+
throw new AuthError("INVALID_PARAMETERS", "Invalid enterprise runtime path.").toConvexError();
|
|
273
|
+
}))
|
|
274
|
+
});
|
|
275
|
+
for (const method of ["PATCH", "DELETE"]) http.route({
|
|
276
|
+
pathPrefix: routePrefix,
|
|
277
|
+
method,
|
|
278
|
+
handler: httpActionGeneric(async (ctx, request) => {
|
|
279
|
+
const route = parseEnterpriseRuntimeRoute(new URL(request.url).pathname, deps.routeBase);
|
|
280
|
+
if (!route || route.protocol !== "scim" || route.rest[0] !== "v2") return deps.scimError(404, "notFound", "SCIM resource not found.");
|
|
281
|
+
return await deps.handleScimRequest(ctx, request);
|
|
282
|
+
})
|
|
283
|
+
});
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
//#endregion
|
|
287
|
+
export { addAuthRoutes, addOpenIdRoutes, addSSORoutes, convertErrorsToResponse, createHttpAction, createHttpRoute, getCookies };
|
|
288
|
+
//# sourceMappingURL=http.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"http.js","names":["result","parseCookies"],"sources":["../../../src/server/http.ts"],"sourcesContent":["import {\n GenericActionCtx,\n GenericDataModel,\n HttpRouter,\n httpActionGeneric,\n} from \"convex/server\";\nimport { ConvexError } from \"convex/values\";\nimport { parse as parseCookies } from \"cookie\";\n\nimport { isAuthError } from \"./errors\";\nimport { Fx } from \"@robelest/fx\";\n\nimport { AuthError } from \"./authError\";\nimport type { CorsConfig, HttpKeyContext } from \"./types\";\nimport { logError } from \"./utils\";\n\nexport function createHttpAction(auth: {\n key: { verify: (ctx: GenericActionCtx<any>, rawKey: string) => Promise<any> };\n}) {\n return (\n handler: (\n ctx: GenericActionCtx<GenericDataModel> & HttpKeyContext,\n request: Request,\n ) => Promise<Response | Record<string, unknown>>,\n options?: {\n scope?: { resource: string; action: string };\n cors?: CorsConfig;\n },\n ) => {\n const corsConfig = options?.cors ?? {};\n const corsHeaders: Record<string, string> = {\n \"Access-Control-Allow-Origin\": corsConfig.origin ?? \"*\",\n \"Access-Control-Allow-Methods\":\n corsConfig.methods ?? \"GET,POST,PUT,PATCH,DELETE,OPTIONS\",\n \"Access-Control-Allow-Headers\":\n corsConfig.headers ?? \"Content-Type,Authorization\",\n };\n\n return httpActionGeneric(async (genericCtx, request) => {\n return Fx.run(\n Fx.from({\n ok: async () => {\n const authHeader = request.headers.get(\"Authorization\");\n if (!authHeader?.startsWith(\"Bearer \")) {\n return new Response(\n JSON.stringify({\n error: \"Missing or malformed Authorization: Bearer header.\",\n code: \"MISSING_BEARER_TOKEN\",\n }),\n {\n status: 401,\n headers: {\n ...corsHeaders,\n \"Content-Type\": \"application/json\",\n },\n },\n );\n }\n const rawKey = authHeader.slice(7);\n\n const keyResult = await Fx.run(\n Fx.from({\n ok: () => auth.key.verify(genericCtx, rawKey),\n err: (error) => error,\n }).pipe(\n Fx.fold({\n ok: (result) => ({ ok: true, value: result }) as const,\n err: (error) => ({ ok: false, error }) as const,\n }),\n ),\n );\n\n if (!keyResult.ok) {\n if (isAuthError(keyResult.error)) {\n const { code, message } = keyResult.error.data as {\n code: string;\n message: string;\n };\n return new Response(JSON.stringify({ error: message, code }), {\n status: 403,\n headers: {\n ...corsHeaders,\n \"Content-Type\": \"application/json\",\n },\n });\n }\n throw keyResult.error;\n }\n\n if (\n options?.scope &&\n !keyResult.value.scopes.can(\n options.scope.resource,\n options.scope.action,\n )\n ) {\n return new Response(\n JSON.stringify({\n error: \"This API key does not have the required permissions.\",\n code: \"SCOPE_CHECK_FAILED\",\n }),\n {\n status: 403,\n headers: {\n ...corsHeaders,\n \"Content-Type\": \"application/json\",\n },\n },\n );\n }\n\n const enrichedCtx = Object.assign(genericCtx, {\n key: {\n userId: keyResult.value.userId,\n keyId: keyResult.value.keyId,\n scopes: keyResult.value.scopes,\n },\n });\n const result = await handler(enrichedCtx, request);\n\n if (result instanceof Response) {\n const headers = new Headers(result.headers);\n for (const [k, val] of Object.entries(corsHeaders)) {\n if (!headers.has(k)) headers.set(k, val);\n }\n return new Response(result.body, {\n status: result.status,\n statusText: result.statusText,\n headers,\n });\n }\n\n return new Response(JSON.stringify(result), {\n status: 200,\n headers: {\n ...corsHeaders,\n \"Content-Type\": \"application/json\",\n },\n });\n },\n err: (error) => error,\n }).pipe(\n Fx.recover((error) => {\n logError(error);\n return Fx.succeed(\n new Response(\n JSON.stringify({\n error: \"An unexpected error occurred.\",\n code: \"INTERNAL_ERROR\",\n }),\n {\n status: 500,\n headers: {\n ...corsHeaders,\n \"Content-Type\": \"application/json\",\n },\n },\n ),\n );\n }),\n ),\n );\n });\n };\n}\n\nexport function createHttpRoute(\n wrapAction: ReturnType<typeof createHttpAction>,\n) {\n return (\n http: { route: (config: any) => void },\n routeConfig: {\n path: string;\n method: \"GET\" | \"POST\" | \"PUT\" | \"PATCH\" | \"DELETE\";\n handler: (\n ctx: GenericActionCtx<GenericDataModel> & HttpKeyContext,\n request: Request,\n ) => Promise<Response | Record<string, unknown>>;\n scope?: { resource: string; action: string };\n cors?: CorsConfig;\n },\n ) => {\n const corsConfig = routeConfig.cors ?? {};\n const corsHeaders: Record<string, string> = {\n \"Access-Control-Allow-Origin\": corsConfig.origin ?? \"*\",\n \"Access-Control-Allow-Methods\":\n corsConfig.methods ?? \"GET,POST,PUT,PATCH,DELETE,OPTIONS\",\n \"Access-Control-Allow-Headers\":\n corsConfig.headers ?? \"Content-Type,Authorization\",\n };\n\n http.route({\n path: routeConfig.path,\n method: \"OPTIONS\",\n handler: httpActionGeneric(async () => {\n return new Response(null, { status: 204, headers: corsHeaders });\n }),\n });\n\n http.route({\n path: routeConfig.path,\n method: routeConfig.method,\n handler: wrapAction(routeConfig.handler, {\n scope: routeConfig.scope,\n cors: routeConfig.cors,\n }),\n });\n };\n}\n\nexport function convertErrorsToResponse(\n errorStatusCode: number,\n action: (ctx: GenericActionCtx<any>, request: Request) => Promise<Response>,\n) {\n return async (ctx: GenericActionCtx<any>, request: Request) => {\n return Fx.run(\n Fx.from({\n ok: () => action(ctx, request),\n err: (error) => error,\n }).pipe(\n Fx.recover((error) => {\n if (isAuthError(error)) {\n return Fx.succeed(\n new Response(\n JSON.stringify({\n code: error.data.code,\n message: error.data.message,\n }),\n {\n status: errorStatusCode,\n headers: { \"Content-Type\": \"application/json\" },\n },\n ),\n );\n } else if (error instanceof ConvexError) {\n return Fx.succeed(\n new Response(null, {\n status: errorStatusCode,\n statusText:\n typeof error.data === \"string\" ? error.data : \"Error\",\n }),\n );\n } else {\n logError(error);\n return Fx.succeed(\n new Response(null, {\n status: 500,\n statusText: \"Internal Server Error\",\n }),\n );\n }\n }),\n ),\n );\n };\n}\n\nexport function getCookies(\n request: Request,\n): Record<string, string | undefined> {\n return parseCookies(request.headers.get(\"Cookie\") ?? \"\");\n}\n\nexport type SSORuntimeRoute = {\n pathname?: string;\n enterpriseId: string;\n protocol: \"oidc\" | \"saml\" | \"scim\";\n rest: string[];\n};\n\nfunction parseEnterpriseRuntimeRoute(\n pathname: string,\n routeBase: string,\n): SSORuntimeRoute | null {\n const runtimePrefix = `${routeBase}/`;\n const runtimeParts = pathname.startsWith(runtimePrefix)\n ? pathname.slice(runtimePrefix.length).split(\"/\").filter(Boolean)\n : [];\n const [runtimeEnterpriseId, protocol, ...rest] = runtimeParts;\n if (\n runtimeEnterpriseId === undefined ||\n (protocol !== \"oidc\" && protocol !== \"saml\" && protocol !== \"scim\") ||\n rest.length === 0\n ) {\n return null;\n }\n return {\n pathname,\n enterpriseId: runtimeEnterpriseId,\n protocol,\n rest,\n };\n}\n\nexport function addOpenIdRoutes(\n http: HttpRouter,\n deps: {\n getIssuer: () => string;\n getJwks: () => string;\n },\n) {\n const cacheControl =\n \"public, max-age=15, stale-while-revalidate=15, stale-if-error=86400\";\n\n http.route({\n path: \"/.well-known/openid-configuration\",\n method: \"GET\",\n handler: httpActionGeneric(async () => {\n const issuer = deps.getIssuer();\n return new Response(\n JSON.stringify({\n issuer,\n jwks_uri: `${issuer}/.well-known/jwks.json`,\n }),\n {\n status: 200,\n headers: {\n \"Content-Type\": \"application/json\",\n \"Cache-Control\": cacheControl,\n },\n },\n );\n }),\n });\n\n http.route({\n path: \"/.well-known/jwks.json\",\n method: \"GET\",\n handler: httpActionGeneric(async () => {\n return new Response(deps.getJwks(), {\n status: 200,\n headers: {\n \"Content-Type\": \"application/json\",\n \"Cache-Control\": cacheControl,\n },\n });\n }),\n });\n}\n\nexport function addAuthRoutes(\n http: HttpRouter,\n deps: {\n handleSignIn: (\n ctx: GenericActionCtx<any>,\n request: Request,\n ) => Promise<Response>;\n handleCallback: (\n ctx: GenericActionCtx<any>,\n request: Request,\n ) => Promise<Response>;\n },\n) {\n http.route({\n pathPrefix: \"/api/auth/signin/\",\n method: \"GET\",\n handler: httpActionGeneric(deps.handleSignIn),\n });\n\n const callbackHandler = httpActionGeneric(deps.handleCallback);\n\n http.route({\n pathPrefix: \"/api/auth/callback/\",\n method: \"GET\",\n handler: callbackHandler,\n });\n\n http.route({\n pathPrefix: \"/api/auth/callback/\",\n method: \"POST\",\n handler: callbackHandler,\n });\n}\n\nexport function addSSORoutes(\n http: HttpRouter,\n deps: {\n routeBase: string;\n convertErrorsToResponse: typeof convertErrorsToResponse;\n handleSamlMetadata: (\n ctx: GenericActionCtx<any>,\n request: Request,\n route: SSORuntimeRoute,\n ) => Promise<Response>;\n handleSamlSignIn: (\n ctx: GenericActionCtx<any>,\n request: Request,\n route: SSORuntimeRoute,\n ) => Promise<Response>;\n handleOidcSignIn: (\n ctx: GenericActionCtx<any>,\n request: Request,\n route: SSORuntimeRoute,\n ) => Promise<Response>;\n handleOidcCallback: (\n ctx: GenericActionCtx<any>,\n request: Request,\n route: SSORuntimeRoute,\n ) => Promise<Response>;\n handleSamlAcs: (\n ctx: GenericActionCtx<any>,\n request: Request,\n route: SSORuntimeRoute,\n ) => Promise<Response>;\n handleSamlSlo: (\n ctx: GenericActionCtx<any>,\n request: Request,\n route: SSORuntimeRoute,\n ) => Promise<Response>;\n handleScimRequest: (\n ctx: GenericActionCtx<any>,\n request: Request,\n ) => Promise<Response>;\n scimError: (status: number, scimType: string, detail: string) => Response;\n },\n) {\n const routePrefix = `${deps.routeBase}/`;\n\n http.route({\n pathPrefix: routePrefix,\n method: \"GET\",\n handler: httpActionGeneric(\n deps.convertErrorsToResponse(400, async (ctx, request) => {\n const route = parseEnterpriseRuntimeRoute(\n new URL(request.url).pathname,\n deps.routeBase,\n );\n if (!route) {\n throw new AuthError(\n \"INVALID_PARAMETERS\",\n \"Invalid enterprise runtime path.\",\n ).toConvexError();\n }\n if (route.protocol === \"saml\" && route.rest.length === 1) {\n if (route.rest[0] === \"metadata\") {\n return await deps.handleSamlMetadata(ctx, request, route);\n }\n if (route.rest[0] === \"signin\") {\n return await deps.handleSamlSignIn(ctx, request, route);\n }\n if (route.rest[0] === \"acs\") {\n return await deps.handleSamlAcs(ctx, request, route);\n }\n if (route.rest[0] === \"slo\") {\n return await deps.handleSamlSlo(ctx, request, route);\n }\n }\n if (route.protocol === \"oidc\" && route.rest.length === 1) {\n if (route.rest[0] === \"signin\") {\n return await deps.handleOidcSignIn(ctx, request, route);\n }\n if (route.rest[0] === \"callback\") {\n return await deps.handleOidcCallback(ctx, request, route);\n }\n }\n if (route.protocol === \"scim\" && route.rest[0] === \"v2\") {\n return await deps.handleScimRequest(ctx, request);\n }\n throw new AuthError(\n \"INVALID_PARAMETERS\",\n \"Invalid enterprise runtime path.\",\n ).toConvexError();\n }),\n ),\n });\n\n http.route({\n pathPrefix: routePrefix,\n method: \"POST\",\n handler: httpActionGeneric(\n deps.convertErrorsToResponse(400, async (ctx, request) => {\n const route = parseEnterpriseRuntimeRoute(\n new URL(request.url).pathname,\n deps.routeBase,\n );\n if (route?.protocol === \"saml\" && route.rest.length === 1) {\n if (route.rest[0] === \"acs\") {\n return await deps.handleSamlAcs(ctx, request, route);\n }\n if (route.rest[0] === \"slo\") {\n return await deps.handleSamlSlo(ctx, request, route);\n }\n }\n if (route?.protocol === \"scim\" && route.rest[0] === \"v2\") {\n return await deps.handleScimRequest(ctx, request);\n }\n throw new AuthError(\n \"INVALID_PARAMETERS\",\n \"Invalid enterprise runtime path.\",\n ).toConvexError();\n }),\n ),\n });\n\n http.route({\n pathPrefix: routePrefix,\n method: \"PUT\",\n handler: httpActionGeneric(\n deps.convertErrorsToResponse(400, async (ctx, request) => {\n const route = parseEnterpriseRuntimeRoute(\n new URL(request.url).pathname,\n deps.routeBase,\n );\n if (route?.protocol === \"scim\" && route.rest[0] === \"v2\") {\n return await deps.handleScimRequest(ctx, request);\n }\n throw new AuthError(\n \"INVALID_PARAMETERS\",\n \"Invalid enterprise runtime path.\",\n ).toConvexError();\n }),\n ),\n });\n\n for (const method of [\"PATCH\", \"DELETE\"] as const) {\n http.route({\n pathPrefix: routePrefix,\n method,\n handler: httpActionGeneric(async (ctx, request) => {\n const route = parseEnterpriseRuntimeRoute(\n new URL(request.url).pathname,\n deps.routeBase,\n );\n if (!route || route.protocol !== \"scim\" || route.rest[0] !== \"v2\") {\n return deps.scimError(404, \"notFound\", \"SCIM resource not found.\");\n }\n return await deps.handleScimRequest(ctx, request);\n }),\n });\n }\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { AuthError } from "./authError.js";
|
|
2
|
+
|
|
3
|
+
//#region src/server/identity.ts
|
|
4
|
+
/** @internal */
|
|
5
|
+
function userIdFromIdentitySubject(subject) {
|
|
6
|
+
const [userId, ...rest] = subject.split("|");
|
|
7
|
+
if (typeof userId !== "string" || userId.length === 0 || rest.length === 0 || rest.some((segment) => segment.length === 0)) throw new AuthError("INTERNAL_ERROR", "Authenticated identity subject is malformed.");
|
|
8
|
+
return userId;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
//#endregion
|
|
12
|
+
export { userIdFromIdentitySubject };
|
|
13
|
+
//# sourceMappingURL=identity.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"identity.js","names":[],"sources":["../../../src/server/identity.ts"],"sourcesContent":["import { AuthError } from \"./authError\";\n\n/** @internal */\nexport function userIdFromIdentitySubject(subject: string): string {\n const [userId, ...rest] = subject.split(\"|\");\n if (\n typeof userId !== \"string\" ||\n userId.length === 0 ||\n rest.length === 0 ||\n rest.some((segment) => segment.length === 0)\n ) {\n throw new AuthError(\n \"INTERNAL_ERROR\",\n \"Authenticated identity subject is malformed.\",\n );\n }\n return userId;\n}\n"],"mappings":";;;;AAGA,SAAgB,0BAA0B,SAAyB;CACjE,MAAM,CAAC,QAAQ,GAAG,QAAQ,QAAQ,MAAM,IAAI;AAC5C,KACE,OAAO,WAAW,YAClB,OAAO,WAAW,KAClB,KAAK,WAAW,KAChB,KAAK,MAAM,YAAY,QAAQ,WAAW,EAAE,CAE5C,OAAM,IAAI,UACR,kBACA,+CACD;AAEH,QAAO"}
|
|
@@ -1,22 +1,12 @@
|
|
|
1
|
-
import { throwAuthError } from "../errors.js";
|
|
2
1
|
import { generateRandomString, sha256 } from "./utils.js";
|
|
3
2
|
|
|
4
|
-
//#region src/server/
|
|
5
|
-
|
|
6
|
-
* API Key crypto utilities.
|
|
7
|
-
*
|
|
8
|
-
* Uses `@oslojs/crypto` primitives for key generation and hashing:
|
|
9
|
-
* - SHA-256 for hashing keys (API keys have high entropy, no need for bcrypt)
|
|
10
|
-
* - Cryptographically secure random generation for key material
|
|
11
|
-
*
|
|
12
|
-
* @module
|
|
13
|
-
*/
|
|
14
|
-
const DEFAULT_KEY_PREFIX = "sk_live_";
|
|
3
|
+
//#region src/server/keys.ts
|
|
4
|
+
const DEFAULT_KEY_PREFIX = "sk_";
|
|
15
5
|
const KEY_RANDOM_LENGTH = 32;
|
|
16
6
|
const KEY_RANDOM_ALPHABET = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
|
|
17
7
|
/**
|
|
18
8
|
* How many characters of the full key to store as the visible prefix.
|
|
19
|
-
* Includes the prefix string (e.g. "
|
|
9
|
+
* Includes the prefix string (e.g. "sk_") plus a few random chars.
|
|
20
10
|
*/
|
|
21
11
|
const VISIBLE_PREFIX_EXTRA_CHARS = 4;
|
|
22
12
|
/**
|
|
@@ -25,9 +15,10 @@ const VISIBLE_PREFIX_EXTRA_CHARS = 4;
|
|
|
25
15
|
* Returns the raw key (to be shown once to the user) and metadata for storage.
|
|
26
16
|
* The raw key is `{prefix}{32 random alphanumeric chars}`.
|
|
27
17
|
*
|
|
28
|
-
* @param prefix - Key prefix, defaults to "
|
|
18
|
+
* @param prefix - Key prefix, defaults to "sk_"
|
|
29
19
|
* @returns `{ raw, hashedKey, displayPrefix }`
|
|
30
20
|
*/
|
|
21
|
+
/** @internal */
|
|
31
22
|
async function generateApiKey(prefix = DEFAULT_KEY_PREFIX) {
|
|
32
23
|
const raw = `${prefix}${generateRandomString(KEY_RANDOM_LENGTH, KEY_RANDOM_ALPHABET)}`;
|
|
33
24
|
return {
|
|
@@ -41,6 +32,7 @@ async function generateApiKey(prefix = DEFAULT_KEY_PREFIX) {
|
|
|
41
32
|
*
|
|
42
33
|
* Used during Bearer token verification to find the stored key record.
|
|
43
34
|
*/
|
|
35
|
+
/** @internal */
|
|
44
36
|
async function hashApiKey(rawKey) {
|
|
45
37
|
return sha256(rawKey);
|
|
46
38
|
}
|
|
@@ -53,6 +45,7 @@ async function hashApiKey(rawKey) {
|
|
|
53
45
|
* A wildcard action `"*"` grants all actions on that resource.
|
|
54
46
|
* A wildcard resource `"*"` grants the action on all resources.
|
|
55
47
|
*/
|
|
48
|
+
/** @internal */
|
|
56
49
|
function buildScopeChecker(scopes) {
|
|
57
50
|
return {
|
|
58
51
|
scopes,
|
|
@@ -62,22 +55,6 @@ function buildScopeChecker(scopes) {
|
|
|
62
55
|
};
|
|
63
56
|
}
|
|
64
57
|
/**
|
|
65
|
-
* Validate that requested scopes are a subset of the allowed scopes
|
|
66
|
-
* defined in the API key config.
|
|
67
|
-
*
|
|
68
|
-
* @param requested - Scopes the user wants on the new key.
|
|
69
|
-
* @param allowed - The scope definition from `apiKeys.scopes` config.
|
|
70
|
-
* @throws Error if any requested scope is not in the allowed set.
|
|
71
|
-
*/
|
|
72
|
-
function validateScopes(requested, allowed) {
|
|
73
|
-
if (!allowed) return;
|
|
74
|
-
for (const scope of requested) {
|
|
75
|
-
const allowedActions = allowed[scope.resource];
|
|
76
|
-
if (!allowedActions) throwAuthError("API_KEY_INVALID_SCOPE", `Unknown resource "${scope.resource}" in API key scopes. Allowed resources: ${Object.keys(allowed).join(", ")}`);
|
|
77
|
-
for (const action of scope.actions) if (action !== "*" && !allowedActions.includes(action)) throwAuthError("API_KEY_INVALID_SCOPE", `Unknown action "${action}" for resource "${scope.resource}". Allowed actions: ${allowedActions.join(", ")}`);
|
|
78
|
-
}
|
|
79
|
-
}
|
|
80
|
-
/**
|
|
81
58
|
* Check whether a key is rate-limited based on its stored state.
|
|
82
59
|
*
|
|
83
60
|
* Uses the same token-bucket algorithm as sign-in rate limiting:
|
|
@@ -85,6 +62,7 @@ function validateScopes(requested, allowed) {
|
|
|
85
62
|
*
|
|
86
63
|
* @returns `{ limited: boolean; newState: { attemptsLeft, lastAttemptTime } }`
|
|
87
64
|
*/
|
|
65
|
+
/** @internal */
|
|
88
66
|
function checkKeyRateLimit(rateLimit, state) {
|
|
89
67
|
const now = Date.now();
|
|
90
68
|
if (!state) return {
|
|
@@ -114,5 +92,5 @@ function checkKeyRateLimit(rateLimit, state) {
|
|
|
114
92
|
}
|
|
115
93
|
|
|
116
94
|
//#endregion
|
|
117
|
-
export { buildScopeChecker, checkKeyRateLimit, generateApiKey, hashApiKey
|
|
95
|
+
export { buildScopeChecker, checkKeyRateLimit, generateApiKey, hashApiKey };
|
|
118
96
|
//# sourceMappingURL=keys.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"keys.js","names":[],"sources":["../../../src/server/keys.ts"],"sourcesContent":["/**\n * API Key crypto utilities.\n *\n * Uses `@oslojs/crypto` primitives for key generation and hashing:\n * - SHA-256 for hashing keys (API keys have high entropy, no need for bcrypt)\n * - Cryptographically secure random generation for key material\n *\n * @module\n */\n\nimport type { KeyScope, ScopeChecker } from \"./types\";\nimport { sha256, generateRandomString } from \"./utils\";\n\n// ============================================================================\n// Constants\n// ============================================================================\n\nconst DEFAULT_KEY_PREFIX = \"sk_\";\nconst KEY_RANDOM_LENGTH = 32;\nconst KEY_RANDOM_ALPHABET =\n \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789\";\n\n/**\n * How many characters of the full key to store as the visible prefix.\n * Includes the prefix string (e.g. \"sk_\") plus a few random chars.\n */\nconst VISIBLE_PREFIX_EXTRA_CHARS = 4;\n\n// ============================================================================\n// Key generation\n// ============================================================================\n\n/**\n * Generate a new API key.\n *\n * Returns the raw key (to be shown once to the user) and metadata for storage.\n * The raw key is `{prefix}{32 random alphanumeric chars}`.\n *\n * @param prefix - Key prefix, defaults to \"sk_\"\n * @returns `{ raw, hashedKey, displayPrefix }`\n */\n/** @internal */\nexport async function generateApiKey(\n prefix: string = DEFAULT_KEY_PREFIX,\n): Promise<{\n /** The full raw key — show to user once, never store. */\n raw: string;\n /** SHA-256 hex hash of the raw key — store this. */\n hashedKey: string;\n /** Truncated prefix for display (e.g. \"sk_aBc1...\"). */\n displayPrefix: string;\n}> {\n const randomPart = generateRandomString(\n KEY_RANDOM_LENGTH,\n KEY_RANDOM_ALPHABET,\n );\n const raw = `${prefix}${randomPart}`;\n const hashedKey = await sha256(raw);\n const displayPrefix = `${raw.substring(0, prefix.length + VISIBLE_PREFIX_EXTRA_CHARS)}...`;\n\n return { raw, hashedKey, displayPrefix };\n}\n\n/**\n * Hash a raw API key for lookup.\n *\n * Used during Bearer token verification to find the stored key record.\n */\n/** @internal */\nexport async function hashApiKey(rawKey: string): Promise<string> {\n return sha256(rawKey);\n}\n\n// ============================================================================\n// Scope checker\n// ============================================================================\n\n/**\n * Build a `ScopeChecker` from an array of `KeyScope` entries.\n *\n * The checker provides a `.can(resource, action)` method that returns `true`\n * if any scope entry grants the requested permission.\n *\n * A wildcard action `\"*\"` grants all actions on that resource.\n * A wildcard resource `\"*\"` grants the action on all resources.\n */\n/** @internal */\nexport function buildScopeChecker(scopes: KeyScope[]): ScopeChecker {\n return {\n scopes,\n can(resource: string, action: string): boolean {\n return scopes.some(\n (scope) =>\n (scope.resource === resource || scope.resource === \"*\") &&\n (scope.actions.includes(action) || scope.actions.includes(\"*\")),\n );\n },\n };\n}\n\n// ============================================================================\n// Per-key rate limiting (token-bucket)\n// ============================================================================\n\n/**\n * Check whether a key is rate-limited based on its stored state.\n *\n * Uses the same token-bucket algorithm as sign-in rate limiting:\n * tokens refill linearly over the configured window.\n *\n * @returns `{ limited: boolean; newState: { attemptsLeft, lastAttemptTime } }`\n */\n/** @internal */\nexport function checkKeyRateLimit(\n rateLimit: { maxRequests: number; windowMs: number },\n state: { attemptsLeft: number; lastAttemptTime: number } | undefined,\n): {\n limited: boolean;\n newState: { attemptsLeft: number; lastAttemptTime: number };\n} {\n const now = Date.now();\n\n if (!state) {\n // First request — create initial state with one token consumed.\n return {\n limited: false,\n newState: {\n attemptsLeft: rateLimit.maxRequests - 1,\n lastAttemptTime: now,\n },\n };\n }\n\n const elapsed = now - state.lastAttemptTime;\n const refillRate = rateLimit.maxRequests / rateLimit.windowMs;\n const refilled = Math.min(\n rateLimit.maxRequests,\n state.attemptsLeft + elapsed * refillRate,\n );\n\n if (refilled < 1) {\n return {\n limited: true,\n newState: {\n attemptsLeft: refilled,\n lastAttemptTime: now,\n },\n };\n }\n\n return {\n limited: false,\n newState: {\n attemptsLeft: refilled - 1,\n lastAttemptTime: now,\n },\n };\n}\n"],"mappings":";;;AAiBA,MAAM,qBAAqB;AAC3B,MAAM,oBAAoB;AAC1B,MAAM,sBACJ;;;;;AAMF,MAAM,6BAA6B;;;;;;;;;;;AAgBnC,eAAsB,eACpB,SAAiB,oBAQhB;CAKD,MAAM,MAAM,GAAG,SAJI,qBACjB,mBACA,oBACD;AAKD,QAAO;EAAE;EAAK,WAHI,MAAM,OAAO,IAAI;EAGV,eAFH,GAAG,IAAI,UAAU,GAAG,OAAO,SAAS,2BAA2B,CAAC;EAE9C;;;;;;;;AAS1C,eAAsB,WAAW,QAAiC;AAChE,QAAO,OAAO,OAAO;;;;;;;;;;;;AAiBvB,SAAgB,kBAAkB,QAAkC;AAClE,QAAO;EACL;EACA,IAAI,UAAkB,QAAyB;AAC7C,UAAO,OAAO,MACX,WACE,MAAM,aAAa,YAAY,MAAM,aAAa,SAClD,MAAM,QAAQ,SAAS,OAAO,IAAI,MAAM,QAAQ,SAAS,IAAI,EACjE;;EAEJ;;;;;;;;;;;AAgBH,SAAgB,kBACd,WACA,OAIA;CACA,MAAM,MAAM,KAAK,KAAK;AAEtB,KAAI,CAAC,MAEH,QAAO;EACL,SAAS;EACT,UAAU;GACR,cAAc,UAAU,cAAc;GACtC,iBAAiB;GAClB;EACF;CAGH,MAAM,UAAU,MAAM,MAAM;CAC5B,MAAM,aAAa,UAAU,cAAc,UAAU;CACrD,MAAM,WAAW,KAAK,IACpB,UAAU,aACV,MAAM,eAAe,UAAU,WAChC;AAED,KAAI,WAAW,EACb,QAAO;EACL,SAAS;EACT,UAAU;GACR,cAAc;GACd,iBAAiB;GAClB;EACF;AAGH,QAAO;EACL,SAAS;EACT,UAAU;GACR,cAAc,WAAW;GACzB,iBAAiB;GAClB;EACF"}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { AuthError } from "./authError.js";
|
|
2
|
+
import { errorMessage } from "./utils.js";
|
|
3
|
+
import { authDb } from "./db.js";
|
|
4
|
+
import { Fx } from "@robelest/fx";
|
|
5
|
+
|
|
6
|
+
//#region src/server/limits.ts
|
|
7
|
+
const DEFAULT_MAX_SIGN_IN_ATTEMPTS_PER_HOUR = 10;
|
|
8
|
+
/**
|
|
9
|
+
* Check whether the given identifier is currently rate-limited.
|
|
10
|
+
*/
|
|
11
|
+
/** @internal */
|
|
12
|
+
const isSignInRateLimited = (ctx, identifier, config) => getRateLimitState(ctx, identifier, config).pipe(Fx.map((state) => state !== null && state.attemptsLeft < 1));
|
|
13
|
+
/**
|
|
14
|
+
* Record a failed sign-in attempt for the given identifier.
|
|
15
|
+
*
|
|
16
|
+
* If a record exists, decrement; otherwise create.
|
|
17
|
+
*/
|
|
18
|
+
/** @internal */
|
|
19
|
+
const recordFailedSignIn = (ctx, identifier, config) => getRateLimitState(ctx, identifier, config).pipe(Fx.chain((state) => state !== null ? Fx.from({
|
|
20
|
+
ok: () => authDb(ctx, config).rateLimits.patch(state.limit._id, {
|
|
21
|
+
attemptsLeft: state.attemptsLeft - 1,
|
|
22
|
+
lastAttemptTime: Date.now()
|
|
23
|
+
}),
|
|
24
|
+
err: (e) => new AuthError("INTERNAL_ERROR", `Failed to patch rate limit: ${errorMessage(e)}`)
|
|
25
|
+
}) : Fx.from({
|
|
26
|
+
ok: () => authDb(ctx, config).rateLimits.create({
|
|
27
|
+
identifier,
|
|
28
|
+
attemptsLeft: (config.signIn?.maxFailedAttemptsPerHour ?? DEFAULT_MAX_SIGN_IN_ATTEMPTS_PER_HOUR) - 1,
|
|
29
|
+
lastAttemptTime: Date.now()
|
|
30
|
+
}),
|
|
31
|
+
err: (e) => new AuthError("INTERNAL_ERROR", `Failed to create rate limit: ${errorMessage(e)}`)
|
|
32
|
+
})), Fx.map(() => void 0));
|
|
33
|
+
/**
|
|
34
|
+
* Reset the rate limit for the given identifier (e.g. after successful sign-in).
|
|
35
|
+
*/
|
|
36
|
+
/** @internal */
|
|
37
|
+
const resetSignInRateLimit = (ctx, identifier, config) => getRateLimitState(ctx, identifier, config).pipe(Fx.chain((state) => state !== null ? Fx.from({
|
|
38
|
+
ok: () => authDb(ctx, config).rateLimits.delete(state.limit._id),
|
|
39
|
+
err: (e) => new AuthError("INTERNAL_ERROR", `Failed to delete rate limit: ${errorMessage(e)}`)
|
|
40
|
+
}) : Fx.unit));
|
|
41
|
+
const getRateLimitState = (ctx, identifier, config) => {
|
|
42
|
+
const now = Date.now();
|
|
43
|
+
const maxAttemptsPerHour = config.signIn?.maxFailedAttemptsPerHour ?? DEFAULT_MAX_SIGN_IN_ATTEMPTS_PER_HOUR;
|
|
44
|
+
return Fx.from({
|
|
45
|
+
ok: () => authDb(ctx, config).rateLimits.get(identifier),
|
|
46
|
+
err: (e) => new AuthError("INTERNAL_ERROR", `Failed to get rate limit: ${errorMessage(e)}`)
|
|
47
|
+
}).pipe(Fx.map((raw) => {
|
|
48
|
+
const limit = raw;
|
|
49
|
+
if (limit === null) return null;
|
|
50
|
+
const elapsed = now - limit.lastAttemptTime;
|
|
51
|
+
const maxAttemptsPerMs = maxAttemptsPerHour / (3600 * 1e3);
|
|
52
|
+
return {
|
|
53
|
+
limit,
|
|
54
|
+
attemptsLeft: Math.min(maxAttemptsPerHour, limit.attemptsLeft + elapsed * maxAttemptsPerMs)
|
|
55
|
+
};
|
|
56
|
+
}));
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
//#endregion
|
|
60
|
+
export { isSignInRateLimited, recordFailedSignIn, resetSignInRateLimit };
|
|
61
|
+
//# sourceMappingURL=limits.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"limits.js","names":[],"sources":["../../../src/server/limits.ts"],"sourcesContent":["import { Fx } from \"@robelest/fx\";\n\nimport { authDb } from \"./db\";\nimport { AuthError } from \"./authError\";\nimport { Doc, MutationCtx } from \"./types\";\nimport { ConvexAuthConfig } from \"./types\";\nimport { errorMessage } from \"./utils\";\n\nconst DEFAULT_MAX_SIGN_IN_ATTEMPTS_PER_HOUR = 10;\n\n/**\n * Check whether the given identifier is currently rate-limited.\n */\n/** @internal */\nexport const isSignInRateLimited = (\n ctx: MutationCtx,\n identifier: string,\n config: ConvexAuthConfig,\n): Fx<boolean, AuthError> =>\n getRateLimitState(ctx, identifier, config).pipe(\n Fx.map((state) => state !== null && state.attemptsLeft < 1),\n );\n\n/**\n * Record a failed sign-in attempt for the given identifier.\n *\n * If a record exists, decrement; otherwise create.\n */\n/** @internal */\nexport const recordFailedSignIn = (\n ctx: MutationCtx,\n identifier: string,\n config: ConvexAuthConfig,\n): Fx<void, AuthError> =>\n getRateLimitState(ctx, identifier, config).pipe(\n Fx.chain((state) =>\n state !== null\n ? Fx.from({\n ok: () =>\n authDb(ctx, config).rateLimits.patch(state.limit._id, {\n attemptsLeft: state.attemptsLeft - 1,\n lastAttemptTime: Date.now(),\n }),\n err: (e) =>\n new AuthError(\n \"INTERNAL_ERROR\",\n `Failed to patch rate limit: ${errorMessage(e)}`,\n ),\n })\n : Fx.from({\n ok: () =>\n authDb(ctx, config).rateLimits.create({\n identifier,\n attemptsLeft:\n (config.signIn?.maxFailedAttemptsPerHour ??\n DEFAULT_MAX_SIGN_IN_ATTEMPTS_PER_HOUR) - 1,\n lastAttemptTime: Date.now(),\n }),\n err: (e) =>\n new AuthError(\n \"INTERNAL_ERROR\",\n `Failed to create rate limit: ${errorMessage(e)}`,\n ),\n }),\n ),\n Fx.map(() => undefined),\n );\n\n/**\n * Reset the rate limit for the given identifier (e.g. after successful sign-in).\n */\n/** @internal */\nexport const resetSignInRateLimit = (\n ctx: MutationCtx,\n identifier: string,\n config: ConvexAuthConfig,\n): Fx<void, AuthError> =>\n getRateLimitState(ctx, identifier, config).pipe(\n Fx.chain((state) =>\n state !== null\n ? Fx.from({\n ok: () => authDb(ctx, config).rateLimits.delete(state.limit._id),\n err: (e) =>\n new AuthError(\n \"INTERNAL_ERROR\",\n `Failed to delete rate limit: ${errorMessage(e)}`,\n ),\n })\n : Fx.unit,\n ),\n );\n\n// ---------------------------------------------------------------------------\n// Internal\n// ---------------------------------------------------------------------------\n\ntype RateLimitState = {\n limit: Doc<\"RateLimit\"> & { attemptsLeft: number; lastAttemptTime: number };\n attemptsLeft: number;\n} | null;\n\nconst getRateLimitState = (\n ctx: MutationCtx,\n identifier: string,\n config: ConvexAuthConfig,\n): Fx<RateLimitState, AuthError> => {\n const now = Date.now();\n const maxAttemptsPerHour =\n config.signIn?.maxFailedAttemptsPerHour ??\n DEFAULT_MAX_SIGN_IN_ATTEMPTS_PER_HOUR;\n\n return Fx.from({\n ok: () => authDb(ctx, config).rateLimits.get(identifier),\n err: (e) =>\n new AuthError(\n \"INTERNAL_ERROR\",\n `Failed to get rate limit: ${errorMessage(e)}`,\n ),\n }).pipe(\n Fx.map((raw) => {\n const limit = raw as\n | (Doc<\"RateLimit\"> & { attemptsLeft: number; lastAttemptTime: number })\n | null;\n if (limit === null) return null;\n const elapsed = now - limit.lastAttemptTime;\n const maxAttemptsPerMs = maxAttemptsPerHour / (60 * 60 * 1000);\n const attemptsLeft = Math.min(\n maxAttemptsPerHour,\n limit.attemptsLeft + elapsed * maxAttemptsPerMs,\n );\n return { limit, attemptsLeft };\n }),\n );\n};\n"],"mappings":";;;;;;AAQA,MAAM,wCAAwC;;;;;AAM9C,MAAa,uBACX,KACA,YACA,WAEA,kBAAkB,KAAK,YAAY,OAAO,CAAC,KACzC,GAAG,KAAK,UAAU,UAAU,QAAQ,MAAM,eAAe,EAAE,CAC5D;;;;;;;AAQH,MAAa,sBACX,KACA,YACA,WAEA,kBAAkB,KAAK,YAAY,OAAO,CAAC,KACzC,GAAG,OAAO,UACR,UAAU,OACN,GAAG,KAAK;CACN,UACE,OAAO,KAAK,OAAO,CAAC,WAAW,MAAM,MAAM,MAAM,KAAK;EACpD,cAAc,MAAM,eAAe;EACnC,iBAAiB,KAAK,KAAK;EAC5B,CAAC;CACJ,MAAM,MACJ,IAAI,UACF,kBACA,+BAA+B,aAAa,EAAE,GAC/C;CACJ,CAAC,GACF,GAAG,KAAK;CACN,UACE,OAAO,KAAK,OAAO,CAAC,WAAW,OAAO;EACpC;EACA,eACG,OAAO,QAAQ,4BACd,yCAAyC;EAC7C,iBAAiB,KAAK,KAAK;EAC5B,CAAC;CACJ,MAAM,MACJ,IAAI,UACF,kBACA,gCAAgC,aAAa,EAAE,GAChD;CACJ,CAAC,CACP,EACD,GAAG,UAAU,OAAU,CACxB;;;;;AAMH,MAAa,wBACX,KACA,YACA,WAEA,kBAAkB,KAAK,YAAY,OAAO,CAAC,KACzC,GAAG,OAAO,UACR,UAAU,OACN,GAAG,KAAK;CACN,UAAU,OAAO,KAAK,OAAO,CAAC,WAAW,OAAO,MAAM,MAAM,IAAI;CAChE,MAAM,MACJ,IAAI,UACF,kBACA,gCAAgC,aAAa,EAAE,GAChD;CACJ,CAAC,GACF,GAAG,KACR,CACF;AAWH,MAAM,qBACJ,KACA,YACA,WACkC;CAClC,MAAM,MAAM,KAAK,KAAK;CACtB,MAAM,qBACJ,OAAO,QAAQ,4BACf;AAEF,QAAO,GAAG,KAAK;EACb,UAAU,OAAO,KAAK,OAAO,CAAC,WAAW,IAAI,WAAW;EACxD,MAAM,MACJ,IAAI,UACF,kBACA,6BAA6B,aAAa,EAAE,GAC7C;EACJ,CAAC,CAAC,KACD,GAAG,KAAK,QAAQ;EACd,MAAM,QAAQ;AAGd,MAAI,UAAU,KAAM,QAAO;EAC3B,MAAM,UAAU,MAAM,MAAM;EAC5B,MAAM,mBAAmB,sBAAsB,OAAU;AAKzD,SAAO;GAAE;GAAO,cAJK,KAAK,IACxB,oBACA,MAAM,eAAe,UAAU,iBAChC;GAC6B;GAC9B,CACH"}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { AuthError } from "../authError.js";
|
|
2
|
+
import { LOG_LEVELS, logWithLevel, maybeRedact } from "../utils.js";
|
|
3
|
+
import { authDb } from "../db.js";
|
|
4
|
+
import { hash } from "../crypto.js";
|
|
5
|
+
import { AUTH_STORE_REF } from "./store/refs.js";
|
|
6
|
+
import { v } from "convex/values";
|
|
7
|
+
import { Fx } from "@robelest/fx";
|
|
8
|
+
|
|
9
|
+
//#region src/server/mutations/account.ts
|
|
10
|
+
const modifyAccountArgs = v.object({
|
|
11
|
+
provider: v.string(),
|
|
12
|
+
account: v.object({
|
|
13
|
+
id: v.string(),
|
|
14
|
+
secret: v.string()
|
|
15
|
+
})
|
|
16
|
+
});
|
|
17
|
+
function modifyAccountImpl(ctx, args, getProviderOrThrow, config) {
|
|
18
|
+
const { provider, account } = args;
|
|
19
|
+
const db = authDb(ctx, config);
|
|
20
|
+
logWithLevel(LOG_LEVELS.DEBUG, "modifyAccountImpl args:", {
|
|
21
|
+
provider,
|
|
22
|
+
account: {
|
|
23
|
+
id: account.id,
|
|
24
|
+
secret: maybeRedact(account.secret ?? "")
|
|
25
|
+
}
|
|
26
|
+
});
|
|
27
|
+
return Fx.from({
|
|
28
|
+
ok: () => db.accounts.get(provider, account.id),
|
|
29
|
+
err: () => new AuthError("ACCOUNT_NOT_FOUND", `Cannot modify account with ID ${account.id} because it does not exist`)
|
|
30
|
+
}).pipe(Fx.chain((doc) => doc === null ? Fx.fail(new AuthError("ACCOUNT_NOT_FOUND", `Cannot modify account with ID ${account.id} because it does not exist`)) : Fx.succeed(doc)), Fx.chain((existingAccount) => hash(getProviderOrThrow(provider), account.secret).pipe(Fx.chain((hashedSecret) => Fx.from({
|
|
31
|
+
ok: () => db.accounts.patch(existingAccount._id, { secret: hashedSecret }),
|
|
32
|
+
err: () => new AuthError("INTERNAL_ERROR", "Failed to patch account")
|
|
33
|
+
})))), Fx.map(() => void 0));
|
|
34
|
+
}
|
|
35
|
+
const callModifyAccount = async (ctx, args) => {
|
|
36
|
+
return ctx.runMutation(AUTH_STORE_REF, { args: {
|
|
37
|
+
type: "modifyAccount",
|
|
38
|
+
...args
|
|
39
|
+
} });
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
//#endregion
|
|
43
|
+
export { callModifyAccount, modifyAccountArgs, modifyAccountImpl };
|
|
44
|
+
//# sourceMappingURL=account.js.map
|