@techelusive/nest-auth 0.0.0-stage → 0.2.0
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/CHANGELOG.md +64 -0
- package/LICENSE +21 -0
- package/README.md +204 -2
- package/api/openapi.json +4399 -0
- package/api/techelusive-authentication.postman_collection.json +3178 -0
- package/dist/auth-options.d.ts +156 -0
- package/dist/auth-options.js +3 -0
- package/dist/auth-options.js.map +1 -0
- package/dist/auth-options.validation.d.ts +9 -0
- package/dist/auth-options.validation.js +74 -0
- package/dist/auth-options.validation.js.map +1 -0
- package/dist/auth.module.d.ts +38 -0
- package/dist/auth.module.js +173 -0
- package/dist/auth.module.js.map +1 -0
- package/dist/common/auth-error.d.ts +16 -0
- package/dist/common/auth-error.js +23 -0
- package/dist/common/auth-error.js.map +1 -0
- package/dist/common/auth-exception.filter.d.ts +24 -0
- package/dist/common/auth-exception.filter.js +66 -0
- package/dist/common/auth-exception.filter.js.map +1 -0
- package/dist/common/crypto/jwt.d.ts +89 -0
- package/dist/common/crypto/jwt.js +144 -0
- package/dist/common/crypto/jwt.js.map +1 -0
- package/dist/common/crypto/random-secrets.d.ts +78 -0
- package/dist/common/crypto/random-secrets.js +113 -0
- package/dist/common/crypto/random-secrets.js.map +1 -0
- package/dist/common/crypto/remote-public-keys.d.ts +49 -0
- package/dist/common/crypto/remote-public-keys.js +105 -0
- package/dist/common/crypto/remote-public-keys.js.map +1 -0
- package/dist/common/crypto/totp.d.ts +68 -0
- package/dist/common/crypto/totp.js +148 -0
- package/dist/common/crypto/totp.js.map +1 -0
- package/dist/common/encryption.service.d.ts +36 -0
- package/dist/common/encryption.service.js +111 -0
- package/dist/common/encryption.service.js.map +1 -0
- package/dist/common/identifiers.d.ts +48 -0
- package/dist/common/identifiers.js +89 -0
- package/dist/common/identifiers.js.map +1 -0
- package/dist/common/network-safety.d.ts +19 -0
- package/dist/common/network-safety.js +72 -0
- package/dist/common/network-safety.js.map +1 -0
- package/dist/common/rate-limiter.service.d.ts +63 -0
- package/dist/common/rate-limiter.service.js +158 -0
- package/dist/common/rate-limiter.service.js.map +1 -0
- package/dist/common/refresh-token-cookie.d.ts +78 -0
- package/dist/common/refresh-token-cookie.js +185 -0
- package/dist/common/refresh-token-cookie.js.map +1 -0
- package/dist/common/request-context.d.ts +14 -0
- package/dist/common/request-context.js +22 -0
- package/dist/common/request-context.js.map +1 -0
- package/dist/common/strict-validation.pipe.d.ts +8 -0
- package/dist/common/strict-validation.pipe.js +16 -0
- package/dist/common/strict-validation.pipe.js.map +1 -0
- package/dist/common/time.d.ts +15 -0
- package/dist/common/time.js +34 -0
- package/dist/common/time.js.map +1 -0
- package/dist/constants.d.ts +1326 -0
- package/dist/constants.js +1142 -0
- package/dist/constants.js.map +1 -0
- package/dist/database/create-auth-tables.migration.d.ts +26 -0
- package/dist/database/create-auth-tables.migration.js +291 -0
- package/dist/database/create-auth-tables.migration.js.map +1 -0
- package/dist/database/email-change-and-retention.migration.d.ts +25 -0
- package/dist/database/email-change-and-retention.migration.js +54 -0
- package/dist/database/email-change-and-retention.migration.js.map +1 -0
- package/dist/database/entities/api-key.entity.d.ts +17 -0
- package/dist/database/entities/api-key.entity.js +80 -0
- package/dist/database/entities/api-key.entity.js.map +1 -0
- package/dist/database/entities/audit-log.entity.d.ts +13 -0
- package/dist/database/entities/audit-log.entity.js +64 -0
- package/dist/database/entities/audit-log.entity.js.map +1 -0
- package/dist/database/entities/backup-code.entity.d.ts +9 -0
- package/dist/database/entities/backup-code.entity.js +52 -0
- package/dist/database/entities/backup-code.entity.js.map +1 -0
- package/dist/database/entities/index.d.ts +43 -0
- package/dist/database/entities/index.js +82 -0
- package/dist/database/entities/index.js.map +1 -0
- package/dist/database/entities/json-object.d.ts +12 -0
- package/dist/database/entities/json-object.js +3 -0
- package/dist/database/entities/json-object.js.map +1 -0
- package/dist/database/entities/link-token.entity.d.ts +15 -0
- package/dist/database/entities/link-token.entity.js +64 -0
- package/dist/database/entities/link-token.entity.js.map +1 -0
- package/dist/database/entities/one-time-code.entity.d.ts +16 -0
- package/dist/database/entities/one-time-code.entity.js +69 -0
- package/dist/database/entities/one-time-code.entity.js.map +1 -0
- package/dist/database/entities/organization-invitation.entity.d.ts +14 -0
- package/dist/database/entities/organization-invitation.entity.js +73 -0
- package/dist/database/entities/organization-invitation.entity.js.map +1 -0
- package/dist/database/entities/organization-member.entity.d.ts +9 -0
- package/dist/database/entities/organization-member.entity.js +48 -0
- package/dist/database/entities/organization-member.entity.js.map +1 -0
- package/dist/database/entities/organization.entity.d.ts +12 -0
- package/dist/database/entities/organization.entity.js +58 -0
- package/dist/database/entities/organization.entity.js.map +1 -0
- package/dist/database/entities/passkey.entity.d.ts +19 -0
- package/dist/database/entities/passkey.entity.js +78 -0
- package/dist/database/entities/passkey.entity.js.map +1 -0
- package/dist/database/entities/password.entity.d.ts +6 -0
- package/dist/database/entities/password.entity.js +36 -0
- package/dist/database/entities/password.entity.js.map +1 -0
- package/dist/database/entities/refresh-token.entity.d.ts +9 -0
- package/dist/database/entities/refresh-token.entity.js +53 -0
- package/dist/database/entities/refresh-token.entity.js.map +1 -0
- package/dist/database/entities/session.entity.d.ts +20 -0
- package/dist/database/entities/session.entity.js +87 -0
- package/dist/database/entities/session.entity.js.map +1 -0
- package/dist/database/entities/settings.entity.d.ts +7 -0
- package/dist/database/entities/settings.entity.js +41 -0
- package/dist/database/entities/settings.entity.js.map +1 -0
- package/dist/database/entities/sign-in-challenge.entity.d.ts +23 -0
- package/dist/database/entities/sign-in-challenge.entity.js +80 -0
- package/dist/database/entities/sign-in-challenge.entity.js.map +1 -0
- package/dist/database/entities/signing-key.entity.d.ts +11 -0
- package/dist/database/entities/signing-key.entity.js +54 -0
- package/dist/database/entities/signing-key.entity.js.map +1 -0
- package/dist/database/entities/social-account.entity.d.ts +13 -0
- package/dist/database/entities/social-account.entity.js +54 -0
- package/dist/database/entities/social-account.entity.js.map +1 -0
- package/dist/database/entities/two-factor-secret.entity.d.ts +10 -0
- package/dist/database/entities/two-factor-secret.entity.js +48 -0
- package/dist/database/entities/two-factor-secret.entity.js.map +1 -0
- package/dist/database/entities/user.entity.d.ts +34 -0
- package/dist/database/entities/user.entity.js +129 -0
- package/dist/database/entities/user.entity.js.map +1 -0
- package/dist/database/entities/webhook-delivery.entity.d.ts +17 -0
- package/dist/database/entities/webhook-delivery.entity.js +79 -0
- package/dist/database/entities/webhook-delivery.entity.js.map +1 -0
- package/dist/database/entities/webhook.entity.d.ts +12 -0
- package/dist/database/entities/webhook.entity.js +58 -0
- package/dist/database/entities/webhook.entity.js.map +1 -0
- package/dist/database/typeorm-row.d.ts +21 -0
- package/dist/database/typeorm-row.js +29 -0
- package/dist/database/typeorm-row.js.map +1 -0
- package/dist/features/account/account.controller.d.ts +259 -0
- package/dist/features/account/account.controller.js +372 -0
- package/dist/features/account/account.controller.js.map +1 -0
- package/dist/features/account/account.dto.d.ts +16 -0
- package/dist/features/account/account.dto.js +61 -0
- package/dist/features/account/account.dto.js.map +1 -0
- package/dist/features/account/data-export.service.d.ts +85 -0
- package/dist/features/account/data-export.service.js +125 -0
- package/dist/features/account/data-export.service.js.map +1 -0
- package/dist/features/account/health.service.d.ts +30 -0
- package/dist/features/account/health.service.js +59 -0
- package/dist/features/account/health.service.js.map +1 -0
- package/dist/features/admin/admin.controller.d.ts +382 -0
- package/dist/features/admin/admin.controller.js +623 -0
- package/dist/features/admin/admin.controller.js.map +1 -0
- package/dist/features/admin/admin.dto.d.ts +61 -0
- package/dist/features/admin/admin.dto.js +253 -0
- package/dist/features/admin/admin.dto.js.map +1 -0
- package/dist/features/admin/admin.service.d.ts +142 -0
- package/dist/features/admin/admin.service.js +227 -0
- package/dist/features/admin/admin.service.js.map +1 -0
- package/dist/features/api-keys/api-keys.service.d.ts +67 -0
- package/dist/features/api-keys/api-keys.service.js +144 -0
- package/dist/features/api-keys/api-keys.service.js.map +1 -0
- package/dist/features/email-change/email-change.controller.d.ts +38 -0
- package/dist/features/email-change/email-change.controller.js +85 -0
- package/dist/features/email-change/email-change.controller.js.map +1 -0
- package/dist/features/email-change/email-change.dto.d.ts +10 -0
- package/dist/features/email-change/email-change.dto.js +43 -0
- package/dist/features/email-change/email-change.dto.js.map +1 -0
- package/dist/features/email-change/email-change.service.d.ts +74 -0
- package/dist/features/email-change/email-change.service.js +179 -0
- package/dist/features/email-change/email-change.service.js.map +1 -0
- package/dist/features/email-links/email-verification.service.d.ts +46 -0
- package/dist/features/email-links/email-verification.service.js +94 -0
- package/dist/features/email-links/email-verification.service.js.map +1 -0
- package/dist/features/email-links/link-tokens.service.d.ts +44 -0
- package/dist/features/email-links/link-tokens.service.js +122 -0
- package/dist/features/email-links/link-tokens.service.js.map +1 -0
- package/dist/features/events/auth-events.service.d.ts +52 -0
- package/dist/features/events/auth-events.service.js +117 -0
- package/dist/features/events/auth-events.service.js.map +1 -0
- package/dist/features/maintenance/data-retention.service.d.ts +60 -0
- package/dist/features/maintenance/data-retention.service.js +182 -0
- package/dist/features/maintenance/data-retention.service.js.map +1 -0
- package/dist/features/notifications/notifications.service.d.ts +40 -0
- package/dist/features/notifications/notifications.service.js +94 -0
- package/dist/features/notifications/notifications.service.js.map +1 -0
- package/dist/features/one-time-codes/one-time-codes.service.d.ts +40 -0
- package/dist/features/one-time-codes/one-time-codes.service.js +102 -0
- package/dist/features/one-time-codes/one-time-codes.service.js.map +1 -0
- package/dist/features/organizations/organizations.controller.d.ts +220 -0
- package/dist/features/organizations/organizations.controller.js +337 -0
- package/dist/features/organizations/organizations.controller.js.map +1 -0
- package/dist/features/organizations/organizations.dto.d.ts +31 -0
- package/dist/features/organizations/organizations.dto.js +100 -0
- package/dist/features/organizations/organizations.dto.js.map +1 -0
- package/dist/features/organizations/organizations.service.d.ts +274 -0
- package/dist/features/organizations/organizations.service.js +481 -0
- package/dist/features/organizations/organizations.service.js.map +1 -0
- package/dist/features/passkeys/passkeys.controller.d.ts +92 -0
- package/dist/features/passkeys/passkeys.controller.js +183 -0
- package/dist/features/passkeys/passkeys.controller.js.map +1 -0
- package/dist/features/passkeys/passkeys.dto.d.ts +13 -0
- package/dist/features/passkeys/passkeys.dto.js +50 -0
- package/dist/features/passkeys/passkeys.dto.js.map +1 -0
- package/dist/features/passkeys/passkeys.service.d.ts +159 -0
- package/dist/features/passkeys/passkeys.service.js +350 -0
- package/dist/features/passkeys/passkeys.service.js.map +1 -0
- package/dist/features/passwordless/passwordless-auth.service.d.ts +152 -0
- package/dist/features/passwordless/passwordless-auth.service.js +304 -0
- package/dist/features/passwordless/passwordless-auth.service.js.map +1 -0
- package/dist/features/passwordless/passwordless.controller.d.ts +75 -0
- package/dist/features/passwordless/passwordless.controller.js +163 -0
- package/dist/features/passwordless/passwordless.controller.js.map +1 -0
- package/dist/features/passwordless/passwordless.dto.d.ts +29 -0
- package/dist/features/passwordless/passwordless.dto.js +101 -0
- package/dist/features/passwordless/passwordless.dto.js.map +1 -0
- package/dist/features/passwords/password-auth.service.d.ts +154 -0
- package/dist/features/passwords/password-auth.service.js +317 -0
- package/dist/features/passwords/password-auth.service.js.map +1 -0
- package/dist/features/passwords/password-policy.service.d.ts +63 -0
- package/dist/features/passwords/password-policy.service.js +175 -0
- package/dist/features/passwords/password-policy.service.js.map +1 -0
- package/dist/features/passwords/password.controller.d.ts +95 -0
- package/dist/features/passwords/password.controller.js +193 -0
- package/dist/features/passwords/password.controller.js.map +1 -0
- package/dist/features/passwords/password.dto.d.ts +36 -0
- package/dist/features/passwords/password.dto.js +140 -0
- package/dist/features/passwords/password.dto.js.map +1 -0
- package/dist/features/sessions/session.service.d.ts +132 -0
- package/dist/features/sessions/session.service.js +308 -0
- package/dist/features/sessions/session.service.js.map +1 -0
- package/dist/features/sessions/session.types.d.ts +34 -0
- package/dist/features/sessions/session.types.js +3 -0
- package/dist/features/sessions/session.types.js.map +1 -0
- package/dist/features/settings/settings.defaults.d.ts +2 -0
- package/dist/features/settings/settings.defaults.js +7 -0
- package/dist/features/settings/settings.defaults.js.map +1 -0
- package/dist/features/settings/settings.service.d.ts +44 -0
- package/dist/features/settings/settings.service.js +112 -0
- package/dist/features/settings/settings.service.js.map +1 -0
- package/dist/features/settings/settings.types.d.ts +133 -0
- package/dist/features/settings/settings.types.js +3 -0
- package/dist/features/settings/settings.types.js.map +1 -0
- package/dist/features/settings/settings.validation.d.ts +33 -0
- package/dist/features/settings/settings.validation.js +614 -0
- package/dist/features/settings/settings.validation.js.map +1 -0
- package/dist/features/sign-in/sign-in-challenges.service.d.ts +54 -0
- package/dist/features/sign-in/sign-in-challenges.service.js +104 -0
- package/dist/features/sign-in/sign-in-challenges.service.js.map +1 -0
- package/dist/features/sign-in/sign-in.service.d.ts +127 -0
- package/dist/features/sign-in/sign-in.service.js +248 -0
- package/dist/features/sign-in/sign-in.service.js.map +1 -0
- package/dist/features/sign-in/sign-in.types.d.ts +22 -0
- package/dist/features/sign-in/sign-in.types.js +3 -0
- package/dist/features/sign-in/sign-in.types.js.map +1 -0
- package/dist/features/signing-keys/jwks.controller.d.ts +17 -0
- package/dist/features/signing-keys/jwks.controller.js +51 -0
- package/dist/features/signing-keys/jwks.controller.js.map +1 -0
- package/dist/features/signing-keys/signing-keys.service.d.ts +67 -0
- package/dist/features/signing-keys/signing-keys.service.js +142 -0
- package/dist/features/signing-keys/signing-keys.service.js.map +1 -0
- package/dist/features/social/social-auth.service.d.ts +100 -0
- package/dist/features/social/social-auth.service.js +232 -0
- package/dist/features/social/social-auth.service.js.map +1 -0
- package/dist/features/social/social-providers.service.d.ts +97 -0
- package/dist/features/social/social-providers.service.js +214 -0
- package/dist/features/social/social-providers.service.js.map +1 -0
- package/dist/features/social/social.controller.d.ts +54 -0
- package/dist/features/social/social.controller.js +124 -0
- package/dist/features/social/social.controller.js.map +1 -0
- package/dist/features/social/social.dto.d.ts +11 -0
- package/dist/features/social/social.dto.js +38 -0
- package/dist/features/social/social.dto.js.map +1 -0
- package/dist/features/two-factor/two-factor.controller.d.ts +84 -0
- package/dist/features/two-factor/two-factor.controller.js +174 -0
- package/dist/features/two-factor/two-factor.controller.js.map +1 -0
- package/dist/features/two-factor/two-factor.dto.d.ts +10 -0
- package/dist/features/two-factor/two-factor.dto.js +37 -0
- package/dist/features/two-factor/two-factor.dto.js.map +1 -0
- package/dist/features/two-factor/two-factor.service.d.ts +171 -0
- package/dist/features/two-factor/two-factor.service.js +348 -0
- package/dist/features/two-factor/two-factor.service.js.map +1 -0
- package/dist/features/users/sign-in-methods.service.d.ts +40 -0
- package/dist/features/users/sign-in-methods.service.js +81 -0
- package/dist/features/users/sign-in-methods.service.js.map +1 -0
- package/dist/features/users/sign-up-rules.d.ts +12 -0
- package/dist/features/users/sign-up-rules.js +29 -0
- package/dist/features/users/sign-up-rules.js.map +1 -0
- package/dist/features/users/users.service.d.ts +246 -0
- package/dist/features/users/users.service.js +509 -0
- package/dist/features/users/users.service.js.map +1 -0
- package/dist/features/users/users.types.d.ts +24 -0
- package/dist/features/users/users.types.js +3 -0
- package/dist/features/users/users.types.js.map +1 -0
- package/dist/features/webhooks/webhook-delivery.worker.d.ts +55 -0
- package/dist/features/webhooks/webhook-delivery.worker.js +175 -0
- package/dist/features/webhooks/webhook-delivery.worker.js.map +1 -0
- package/dist/features/webhooks/webhook-signature.d.ts +28 -0
- package/dist/features/webhooks/webhook-signature.js +85 -0
- package/dist/features/webhooks/webhook-signature.js.map +1 -0
- package/dist/features/webhooks/webhooks.service.d.ts +144 -0
- package/dist/features/webhooks/webhooks.service.js +238 -0
- package/dist/features/webhooks/webhooks.service.js.map +1 -0
- package/dist/guards/auth.decorators.d.ts +65 -0
- package/dist/guards/auth.decorators.js +68 -0
- package/dist/guards/auth.decorators.js.map +1 -0
- package/dist/guards/auth.guard.d.ts +47 -0
- package/dist/guards/auth.guard.js +132 -0
- package/dist/guards/auth.guard.js.map +1 -0
- package/dist/index.d.ts +38 -0
- package/dist/index.js +95 -0
- package/dist/index.js.map +1 -0
- package/dist/integrations/console-email-sender.d.ts +15 -0
- package/dist/integrations/console-email-sender.js +26 -0
- package/dist/integrations/console-email-sender.js.map +1 -0
- package/dist/integrations/msg91-sms-sender.d.ts +28 -0
- package/dist/integrations/msg91-sms-sender.js +46 -0
- package/dist/integrations/msg91-sms-sender.js.map +1 -0
- package/docs/README.md +39 -0
- package/docs/admin-api-keys-webhooks.md +147 -0
- package/docs/api-reference.md +175 -0
- package/docs/architecture.md +119 -0
- package/docs/client-integration.md +192 -0
- package/docs/code-walkthrough.md +273 -0
- package/docs/configuration.md +229 -0
- package/docs/endpoints/README.md +151 -0
- package/docs/endpoints/account.md +363 -0
- package/docs/endpoints/admin.md +422 -0
- package/docs/endpoints/email-password.md +261 -0
- package/docs/endpoints/organizations.md +192 -0
- package/docs/endpoints/passkeys.md +195 -0
- package/docs/endpoints/passwordless.md +214 -0
- package/docs/endpoints/social.md +116 -0
- package/docs/endpoints/two-factor.md +146 -0
- package/docs/error-codes.md +100 -0
- package/docs/events.md +83 -0
- package/docs/getting-started.md +139 -0
- package/docs/manual-testing.md +215 -0
- package/docs/organizations.md +86 -0
- package/docs/production-checklist.md +60 -0
- package/docs/protecting-routes.md +147 -0
- package/docs/security.md +61 -0
- package/docs/sign-in-flows.md +294 -0
- package/package.json +92 -4
|
@@ -0,0 +1,192 @@
|
|
|
1
|
+
# Organizations
|
|
2
|
+
|
|
3
|
+
Needs `organizations.enabled`; otherwise `403 FEATURE_DISABLED`. Every route needs a signed-in user, and roles (`owner`, `admin`, `member`) are checked per organization. If you're not a member, the organization's routes return `404 NOT_FOUND`. Concepts are explained in [Organizations](../organizations.md).
|
|
4
|
+
|
|
5
|
+
## Organization object
|
|
6
|
+
|
|
7
|
+
```json
|
|
8
|
+
{
|
|
9
|
+
"id": "a1b2c3d4-0000-4000-8000-000000000001",
|
|
10
|
+
"name": "Acme Travels",
|
|
11
|
+
"slug": "acme-travels",
|
|
12
|
+
"metadata": {},
|
|
13
|
+
"createdByUserId": "5f0c8a2e-1d3b-4c5a-9e7f-0a1b2c3d4e5f",
|
|
14
|
+
"createdAt": "2026-10-20T06:30:00.000Z",
|
|
15
|
+
"updatedAt": "2026-10-20T06:30:00.000Z"
|
|
16
|
+
}
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
---
|
|
20
|
+
|
|
21
|
+
## GET /auth/organizations
|
|
22
|
+
|
|
23
|
+
The organizations the user belongs to.
|
|
24
|
+
|
|
25
|
+
**Response `200`**
|
|
26
|
+
|
|
27
|
+
```json
|
|
28
|
+
{
|
|
29
|
+
"success": true,
|
|
30
|
+
"organizations": [
|
|
31
|
+
{ "id": "a1b2...", "name": "Acme Travels", "slug": "acme-travels", "metadata": {}, "role": "owner", "joinedAt": "2026-10-20T06:30:00.000Z" }
|
|
32
|
+
]
|
|
33
|
+
}
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
## POST /auth/organizations
|
|
37
|
+
|
|
38
|
+
Creates an organization; the caller becomes its owner. Session checked live. When `organizations.allowUsersToCreate` is off, only app admins can create.
|
|
39
|
+
|
|
40
|
+
**Request**
|
|
41
|
+
|
|
42
|
+
```json
|
|
43
|
+
{ "name": "Acme Travels", "slug": "acme-travels" }
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
| Field | Type | Required | Rules |
|
|
47
|
+
|---|---|---|---|
|
|
48
|
+
| `name` | string | yes | up to 100 characters |
|
|
49
|
+
| `slug` | string | yes | 3–50 lowercase letters, digits and dashes; can't start or end with a dash |
|
|
50
|
+
|
|
51
|
+
**Response `201`:** `{ "success": true, "organization": { ...organization object } }`
|
|
52
|
+
|
|
53
|
+
**Errors:** `409 ORGANIZATION_SLUG_TAKEN`, `403 FORBIDDEN` (users may not create), `400 VALIDATION_ERROR` (`problems: ["too many organizations"]`, 100 per user).
|
|
54
|
+
|
|
55
|
+
## POST /auth/organizations/switch
|
|
56
|
+
|
|
57
|
+
Picks the organization this device works in. **Replace the stored access token** with the returned one; refreshes keep the organization. Session checked live.
|
|
58
|
+
|
|
59
|
+
**Request**
|
|
60
|
+
|
|
61
|
+
```json
|
|
62
|
+
{ "organizationId": "a1b2c3d4-0000-4000-8000-000000000001" }
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
Send `{ "organizationId": null }` to leave organization mode.
|
|
66
|
+
|
|
67
|
+
**Response `200`**
|
|
68
|
+
|
|
69
|
+
```json
|
|
70
|
+
{ "success": true, "accessToken": "eyJhbGciOiJFUzI1NiIs...", "expiresIn": 900, "organizationId": "a1b2c3d4-0000-4000-8000-000000000001" }
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
The new token carries `"org_id"` and `"org_role"`.
|
|
74
|
+
|
|
75
|
+
## POST /auth/organizations/invitations/accept
|
|
76
|
+
|
|
77
|
+
Accepts an emailed invitation. The signed-in user's **verified** email must match the invited email. Session checked live.
|
|
78
|
+
|
|
79
|
+
**Request**
|
|
80
|
+
|
|
81
|
+
```json
|
|
82
|
+
{ "token": "oi_aW52aXRhdGlvbmV4YW1wbGV0b2tlbjEyMzQ1Njc4OTAxMjM" }
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
**Response `200`**
|
|
86
|
+
|
|
87
|
+
```json
|
|
88
|
+
{ "success": true, "organizationId": "a1b2c3d4-0000-4000-8000-000000000001", "role": "member" }
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
**Errors:** `400 INVALID_TOKEN` (unknown, used, expired (`organizations.invitationExpiresInDays`, 7 by default), cancelled, or a different / unverified email), `409 ALREADY_MEMBER`.
|
|
92
|
+
|
|
93
|
+
---
|
|
94
|
+
|
|
95
|
+
## GET /auth/organizations/:organizationId
|
|
96
|
+
|
|
97
|
+
Any member. **Response `200`:** `{ "success": true, "organization": { ...organization object, "myRole": "admin" } }`
|
|
98
|
+
|
|
99
|
+
## PATCH /auth/organizations/:organizationId
|
|
100
|
+
|
|
101
|
+
Admin or owner. Session checked live.
|
|
102
|
+
|
|
103
|
+
**Request** (all optional):
|
|
104
|
+
|
|
105
|
+
```json
|
|
106
|
+
{ "name": "Acme Travels India", "slug": "acme-india", "metadata": { "gstNumber": "29ABCDE1234F1Z5" } }
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
**Response `200`:** `{ "success": true, "organization": { ... } }`. Errors: `409 ORGANIZATION_SLUG_TAKEN`, `403 FORBIDDEN`.
|
|
110
|
+
|
|
111
|
+
## DELETE /auth/organizations/:organizationId
|
|
112
|
+
|
|
113
|
+
Owner only. Removes members, invitations and the organization's API keys. Session checked live. **Response `200`:** `{ "success": true }`
|
|
114
|
+
|
|
115
|
+
---
|
|
116
|
+
|
|
117
|
+
## GET /auth/organizations/:organizationId/members
|
|
118
|
+
|
|
119
|
+
Any member.
|
|
120
|
+
|
|
121
|
+
**Response `200`**
|
|
122
|
+
|
|
123
|
+
```json
|
|
124
|
+
{
|
|
125
|
+
"success": true,
|
|
126
|
+
"members": [
|
|
127
|
+
{ "userId": "5f0c...", "email": "asha@example.com", "firstName": "Asha", "lastName": "Rao", "role": "owner", "joinedAt": "2026-10-20T06:30:00.000Z" },
|
|
128
|
+
{ "userId": "9d2e...", "email": "ravi@example.com", "firstName": "Ravi", "lastName": "Kumar", "role": "member", "joinedAt": "2026-10-21T09:00:00.000Z" }
|
|
129
|
+
]
|
|
130
|
+
}
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
## PATCH /auth/organizations/:organizationId/members/:memberUserId
|
|
134
|
+
|
|
135
|
+
Changes a member's role. Admins manage members and admins; **only owners** can make or unmake owners. Session checked live.
|
|
136
|
+
|
|
137
|
+
**Request**
|
|
138
|
+
|
|
139
|
+
```json
|
|
140
|
+
{ "role": "admin" }
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
`role` is one of `"owner"`, `"admin"`, `"member"`.
|
|
144
|
+
|
|
145
|
+
**Response `200`:** `{ "success": true }`. Errors: `403 FORBIDDEN`, `404 NOT_FOUND`, `409 LAST_OWNER`.
|
|
146
|
+
|
|
147
|
+
## DELETE /auth/organizations/:organizationId/members/:memberUserId
|
|
148
|
+
|
|
149
|
+
Removes a member. Use your own user id to **leave**. Session checked live. **Response `200`:** `{ "success": true }`. Errors: `403 FORBIDDEN`, `404 NOT_FOUND`, `409 LAST_OWNER`.
|
|
150
|
+
|
|
151
|
+
---
|
|
152
|
+
|
|
153
|
+
## GET /auth/organizations/:organizationId/invitations
|
|
154
|
+
|
|
155
|
+
Admin or owner. Open (not accepted, not cancelled) invitations.
|
|
156
|
+
|
|
157
|
+
**Response `200`**
|
|
158
|
+
|
|
159
|
+
```json
|
|
160
|
+
{
|
|
161
|
+
"success": true,
|
|
162
|
+
"invitations": [
|
|
163
|
+
{
|
|
164
|
+
"id": "c3d4...",
|
|
165
|
+
"organizationId": "a1b2...",
|
|
166
|
+
"email": "ravi@example.com",
|
|
167
|
+
"role": "member",
|
|
168
|
+
"invitedByUserId": "5f0c...",
|
|
169
|
+
"expiresAt": "2026-10-27T06:30:00.000Z",
|
|
170
|
+
"acceptedAt": null,
|
|
171
|
+
"revokedAt": null,
|
|
172
|
+
"createdAt": "2026-10-20T06:30:00.000Z"
|
|
173
|
+
}
|
|
174
|
+
]
|
|
175
|
+
}
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
## POST /auth/organizations/:organizationId/invitations
|
|
179
|
+
|
|
180
|
+
Admin or owner (inviting an `owner` needs an owner). Sends an `organization_invitation` email; a new invitation to the same email replaces the old one. Session checked live.
|
|
181
|
+
|
|
182
|
+
**Request**
|
|
183
|
+
|
|
184
|
+
```json
|
|
185
|
+
{ "email": "ravi@example.com", "role": "member" }
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
**Response `201`:** `{ "success": true }`. Errors: `400 INVALID_EMAIL`, `403 FORBIDDEN`.
|
|
189
|
+
|
|
190
|
+
## DELETE /auth/organizations/:organizationId/invitations/:invitationId
|
|
191
|
+
|
|
192
|
+
Admin or owner. Cancels an open invitation. Session checked live. **Response `200`:** `{ "success": true }`. Errors: `404 NOT_FOUND`.
|
|
@@ -0,0 +1,195 @@
|
|
|
1
|
+
# Passkeys
|
|
2
|
+
|
|
3
|
+
Needs `passkeys.enabled` and the `passkeys` option on the server; otherwise `403 SIGN_IN_METHOD_DISABLED` / `501 NOT_CONFIGURED`. Each ceremony is two calls: **options** (the server creates a challenge) and **verify** (the device signed it). Browser code is in [Sign-in flows](../sign-in-flows.md#passkeys). Shared formats, the sign-in result and the user object are described in [Endpoints](README.md).
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## POST /auth/passkeys/register/options
|
|
8
|
+
|
|
9
|
+
Starts adding a passkey for the signed-in user.
|
|
10
|
+
|
|
11
|
+
| | |
|
|
12
|
+
|---|---|
|
|
13
|
+
| Auth | User, session checked live |
|
|
14
|
+
|
|
15
|
+
**Request:** no body.
|
|
16
|
+
|
|
17
|
+
**Response `200`**
|
|
18
|
+
|
|
19
|
+
```json
|
|
20
|
+
{
|
|
21
|
+
"success": true,
|
|
22
|
+
"challengeToken": "ch_Zm9vYmFyZXhhbXBsZWNoYWxsZW5nZXRva2VuMTIzNDU2Nzg",
|
|
23
|
+
"options": {
|
|
24
|
+
"challenge": "lB3yW9kQ2x...",
|
|
25
|
+
"rp": { "name": "MyApp", "id": "myapp.com" },
|
|
26
|
+
"user": { "id": "NWYwYzhhMmUt...", "name": "asha@example.com", "displayName": "Asha Rao" },
|
|
27
|
+
"pubKeyCredParams": [{ "alg": -8, "type": "public-key" }, { "alg": -7, "type": "public-key" }, { "alg": -257, "type": "public-key" }],
|
|
28
|
+
"timeout": 60000,
|
|
29
|
+
"attestation": "none",
|
|
30
|
+
"excludeCredentials": [],
|
|
31
|
+
"authenticatorSelection": { "residentKey": "required", "userVerification": "required", "requireResidentKey": true }
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
Pass `options` unchanged to `startRegistration({ optionsJSON: options })` (browser) or your platform's passkey API. The challenge expires after 5 minutes.
|
|
37
|
+
|
|
38
|
+
**Errors**
|
|
39
|
+
|
|
40
|
+
| Status | `code` | When |
|
|
41
|
+
|---|---|---|
|
|
42
|
+
| 400 | `VALIDATION_ERROR` | `problems: ["too many passkeys"]` (20 per user) |
|
|
43
|
+
|
|
44
|
+
---
|
|
45
|
+
|
|
46
|
+
## POST /auth/passkeys/register/verify
|
|
47
|
+
|
|
48
|
+
Saves the new passkey.
|
|
49
|
+
|
|
50
|
+
| | |
|
|
51
|
+
|---|---|
|
|
52
|
+
| Auth | User, session checked live |
|
|
53
|
+
|
|
54
|
+
**Request**
|
|
55
|
+
|
|
56
|
+
```json
|
|
57
|
+
{
|
|
58
|
+
"challengeToken": "ch_Zm9vYmFyZXhhbXBsZWNoYWxsZW5nZXRva2VuMTIzNDU2Nzg",
|
|
59
|
+
"name": "My laptop",
|
|
60
|
+
"response": {
|
|
61
|
+
"id": "Q2xpZW50Q3JlZGVudGlhbElk",
|
|
62
|
+
"rawId": "Q2xpZW50Q3JlZGVudGlhbElk",
|
|
63
|
+
"type": "public-key",
|
|
64
|
+
"response": {
|
|
65
|
+
"clientDataJSON": "eyJ0eXBlIjoid2ViYXV0aG4uY3JlYXRlIi...",
|
|
66
|
+
"attestationObject": "o2NmbXRkbm9uZWdhdHRTdG10oGhhdXRoRGF0YV...",
|
|
67
|
+
"transports": ["internal", "hybrid"]
|
|
68
|
+
},
|
|
69
|
+
"clientExtensionResults": {},
|
|
70
|
+
"authenticatorAttachment": "platform"
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
| Field | Type | Required | Notes |
|
|
76
|
+
|---|---|---|---|
|
|
77
|
+
| `challengeToken` | string | yes | from `register/options` |
|
|
78
|
+
| `response` | object | yes | exactly what the browser / platform API returned, as JSON |
|
|
79
|
+
| `name` | string | no | up to 60 characters; default `"Passkey"` |
|
|
80
|
+
|
|
81
|
+
**Response `200`**
|
|
82
|
+
|
|
83
|
+
```json
|
|
84
|
+
{
|
|
85
|
+
"success": true,
|
|
86
|
+
"passkey": { "id": "a7c1...", "name": "My laptop", "isBackedUp": true, "createdAt": "2026-10-20T06:30:00.000Z", "lastUsedAt": null }
|
|
87
|
+
}
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
**Errors**
|
|
91
|
+
|
|
92
|
+
| Status | `code` | When |
|
|
93
|
+
|---|---|---|
|
|
94
|
+
| 400 | `INVALID_TOKEN` | Challenge unknown, used or expired |
|
|
95
|
+
| 401 | `INVALID_PASSKEY` | Verification failed (wrong origin, no fingerprint/PIN, tampered response) |
|
|
96
|
+
|
|
97
|
+
---
|
|
98
|
+
|
|
99
|
+
## POST /auth/passkeys/sign-in/options
|
|
100
|
+
|
|
101
|
+
Starts a passkey sign-in. No email is needed: the device offers the user's passkeys for your site.
|
|
102
|
+
|
|
103
|
+
| | |
|
|
104
|
+
|---|---|
|
|
105
|
+
| Auth | Public |
|
|
106
|
+
| Rate limit | 30 per IP per 15 minutes |
|
|
107
|
+
|
|
108
|
+
**Request:** no body.
|
|
109
|
+
|
|
110
|
+
**Response `200`**
|
|
111
|
+
|
|
112
|
+
```json
|
|
113
|
+
{
|
|
114
|
+
"success": true,
|
|
115
|
+
"challengeToken": "ch_YW5vdGhlcmV4YW1wbGVjaGFsbGVuZ2V0b2tlbjEyMzQ1Njc",
|
|
116
|
+
"options": { "challenge": "pX9...", "timeout": 60000, "rpId": "myapp.com", "userVerification": "required" }
|
|
117
|
+
}
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
---
|
|
121
|
+
|
|
122
|
+
## POST /auth/passkeys/sign-in/verify
|
|
123
|
+
|
|
124
|
+
Finishes the sign-in. No 2FA step follows: a passkey counts as two factors.
|
|
125
|
+
|
|
126
|
+
| | |
|
|
127
|
+
|---|---|
|
|
128
|
+
| Auth | Public |
|
|
129
|
+
|
|
130
|
+
**Request**
|
|
131
|
+
|
|
132
|
+
```json
|
|
133
|
+
{
|
|
134
|
+
"challengeToken": "ch_YW5vdGhlcmV4YW1wbGVjaGFsbGVuZ2V0b2tlbjEyMzQ1Njc",
|
|
135
|
+
"response": {
|
|
136
|
+
"id": "Q2xpZW50Q3JlZGVudGlhbElk",
|
|
137
|
+
"rawId": "Q2xpZW50Q3JlZGVudGlhbElk",
|
|
138
|
+
"type": "public-key",
|
|
139
|
+
"response": {
|
|
140
|
+
"clientDataJSON": "eyJ0eXBlIjoid2ViYXV0aG4uZ2V0Ii...",
|
|
141
|
+
"authenticatorData": "SZYN5YgOjGh0NBcPZHZgW4_krrmihjLHmVzzuoMdl2MFAAAAAQ",
|
|
142
|
+
"signature": "MEUCIQDf...",
|
|
143
|
+
"userHandle": "NWYwYzhhMmUt..."
|
|
144
|
+
},
|
|
145
|
+
"clientExtensionResults": {}
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
**Response `200`:** the [sign-in result](README.md#sign-in-result) (always `signed_in` when successful).
|
|
151
|
+
|
|
152
|
+
**Errors**
|
|
153
|
+
|
|
154
|
+
| Status | `code` | When |
|
|
155
|
+
|---|---|---|
|
|
156
|
+
| 400 | `INVALID_TOKEN` | Challenge unknown, used or expired |
|
|
157
|
+
| 401 | `INVALID_PASSKEY` | Unknown passkey or bad signature |
|
|
158
|
+
| 403 | `ACCOUNT_*` | See [sign-in result](README.md#sign-in-result) |
|
|
159
|
+
|
|
160
|
+
---
|
|
161
|
+
|
|
162
|
+
## GET /auth/passkeys
|
|
163
|
+
|
|
164
|
+
| | |
|
|
165
|
+
|---|---|
|
|
166
|
+
| Auth | User |
|
|
167
|
+
|
|
168
|
+
**Response `200`**
|
|
169
|
+
|
|
170
|
+
```json
|
|
171
|
+
{
|
|
172
|
+
"success": true,
|
|
173
|
+
"passkeys": [
|
|
174
|
+
{ "id": "a7c1...", "name": "My laptop", "isBackedUp": true, "createdAt": "2026-10-20T06:30:00.000Z", "lastUsedAt": "2026-10-21T08:00:00.000Z" }
|
|
175
|
+
]
|
|
176
|
+
}
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
## PATCH /auth/passkeys/:passkeyId
|
|
180
|
+
|
|
181
|
+
Renames a passkey. Auth: User.
|
|
182
|
+
|
|
183
|
+
**Request**
|
|
184
|
+
|
|
185
|
+
```json
|
|
186
|
+
{ "name": "Work phone" }
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
**Response `200`:** `{ "success": true }`. Errors: `404 NOT_FOUND`.
|
|
190
|
+
|
|
191
|
+
## DELETE /auth/passkeys/:passkeyId
|
|
192
|
+
|
|
193
|
+
Removes a passkey. Auth: User, session checked live. No body.
|
|
194
|
+
|
|
195
|
+
**Response `200`:** `{ "success": true }`. Errors: `404 NOT_FOUND`, `409 LAST_SIGN_IN_METHOD`.
|
|
@@ -0,0 +1,214 @@
|
|
|
1
|
+
# Passwordless: email code, magic link, phone code
|
|
2
|
+
|
|
3
|
+
The same endpoints **sign in**, **sign up** (when `allowSignUp` is on) and **verify** the email or phone, because receiving the code proves ownership. Shared formats, the sign-in result and the user object are described in [Endpoints](README.md).
|
|
4
|
+
|
|
5
|
+
## Sign-up details
|
|
6
|
+
|
|
7
|
+
The verify endpoints accept these optional fields. They are used **only when the request creates a new account**:
|
|
8
|
+
|
|
9
|
+
| Field | Type | Rules |
|
|
10
|
+
|---|---|---|
|
|
11
|
+
| `firstName` | string | up to 100 characters |
|
|
12
|
+
| `lastName` | string | up to 100 characters |
|
|
13
|
+
| `acceptTerms` | boolean | |
|
|
14
|
+
| `acceptPrivacyPolicy` | boolean | |
|
|
15
|
+
|
|
16
|
+
If your settings require them and they are missing, the response is:
|
|
17
|
+
|
|
18
|
+
```json
|
|
19
|
+
{
|
|
20
|
+
"success": false,
|
|
21
|
+
"code": "VALIDATION_ERROR",
|
|
22
|
+
"message": "Some fields are missing or invalid.",
|
|
23
|
+
"missingSignUpDetails": ["firstName", "lastName", "acceptTerms"]
|
|
24
|
+
}
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
For codes, the code is **not used up** by this error: show a form for the missing details and send the same code again with them.
|
|
28
|
+
|
|
29
|
+
---
|
|
30
|
+
|
|
31
|
+
## POST /auth/email/send-otp
|
|
32
|
+
|
|
33
|
+
Emails a sign-in code. Needs `emailOtp.enabled`.
|
|
34
|
+
|
|
35
|
+
| | |
|
|
36
|
+
|---|---|
|
|
37
|
+
| Auth | Public |
|
|
38
|
+
| Rate limit | 10 per IP and 5 per email per hour; one code per minute per email |
|
|
39
|
+
|
|
40
|
+
**Request**
|
|
41
|
+
|
|
42
|
+
```json
|
|
43
|
+
{ "email": "asha@example.com" }
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
**Response `200`** (always the same, whether or not the email has an account):
|
|
47
|
+
|
|
48
|
+
```json
|
|
49
|
+
{ "success": true, "message": "If this destination can receive codes, a code is on its way." }
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
**Errors**
|
|
53
|
+
|
|
54
|
+
| Status | `code` | When |
|
|
55
|
+
|---|---|---|
|
|
56
|
+
| 400 | `INVALID_EMAIL` | |
|
|
57
|
+
| 403 | `SIGN_IN_METHOD_DISABLED` | `emailOtp.enabled` is off |
|
|
58
|
+
| 429 | `TOO_MANY_REQUESTS` | A code was sent less than `emailOtp.resendAfterSeconds` ago (60 by default, returned as `retryAfterSeconds`), or a rate limit was hit |
|
|
59
|
+
|
|
60
|
+
---
|
|
61
|
+
|
|
62
|
+
## POST /auth/email/verify-otp
|
|
63
|
+
|
|
64
|
+
Signs in with the emailed code. Marks the email verified. Creates the account if the email is new and sign-up is allowed.
|
|
65
|
+
|
|
66
|
+
| | |
|
|
67
|
+
|---|---|
|
|
68
|
+
| Auth | Public |
|
|
69
|
+
| Rate limit | 30 per IP per 15 minutes |
|
|
70
|
+
|
|
71
|
+
**Request**
|
|
72
|
+
|
|
73
|
+
```json
|
|
74
|
+
{
|
|
75
|
+
"email": "asha@example.com",
|
|
76
|
+
"code": "482913",
|
|
77
|
+
"firstName": "Asha",
|
|
78
|
+
"lastName": "Rao",
|
|
79
|
+
"acceptTerms": true,
|
|
80
|
+
"acceptPrivacyPolicy": true
|
|
81
|
+
}
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
| Field | Type | Required |
|
|
85
|
+
|---|---|---|
|
|
86
|
+
| `email` | string | yes |
|
|
87
|
+
| `code` | string | yes |
|
|
88
|
+
| sign-up details | | only for new accounts, see above |
|
|
89
|
+
|
|
90
|
+
**Response `200`:** the [sign-in result](README.md#sign-in-result).
|
|
91
|
+
|
|
92
|
+
**Errors**
|
|
93
|
+
|
|
94
|
+
| Status | `code` | When | Extra |
|
|
95
|
+
|---|---|---|---|
|
|
96
|
+
| 400 | `INVALID_OTP` | Wrong code | `attemptsLeft` |
|
|
97
|
+
| 400 | `OTP_EXPIRED` | Expired (10 min), used, 5 wrong tries, or never sent | |
|
|
98
|
+
| 400 | `VALIDATION_ERROR` | New account and details missing | `missingSignUpDetails` |
|
|
99
|
+
| 400 | `EMAIL_DOMAIN_NOT_ALLOWED` | New account outside `allowedEmailDomains` | |
|
|
100
|
+
| 403 | `SIGN_UP_CLOSED` | New email and sign-up is off | |
|
|
101
|
+
|
|
102
|
+
```json
|
|
103
|
+
{ "success": false, "code": "INVALID_OTP", "message": "This code is incorrect.", "attemptsLeft": 3 }
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
---
|
|
107
|
+
|
|
108
|
+
## POST /auth/magic-link/send
|
|
109
|
+
|
|
110
|
+
Emails a one-click sign-in link (valid `magicLink.expiresInMinutes`, 15 by default). Needs `magicLink.enabled`.
|
|
111
|
+
|
|
112
|
+
| | |
|
|
113
|
+
|---|---|
|
|
114
|
+
| Auth | Public |
|
|
115
|
+
| Rate limit | 10 per IP and 3 per email per hour |
|
|
116
|
+
|
|
117
|
+
**Request**
|
|
118
|
+
|
|
119
|
+
```json
|
|
120
|
+
{ "email": "asha@example.com" }
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
**Response `200`** (always the same):
|
|
124
|
+
|
|
125
|
+
```json
|
|
126
|
+
{ "success": true, "message": "If this email can sign in, a sign-in link is on its way." }
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
---
|
|
130
|
+
|
|
131
|
+
## POST /auth/magic-link/verify
|
|
132
|
+
|
|
133
|
+
Signs in with the token from the link. The link works **once**, so for new users collect the sign-up details on the page before calling this.
|
|
134
|
+
|
|
135
|
+
| | |
|
|
136
|
+
|---|---|
|
|
137
|
+
| Auth | Public |
|
|
138
|
+
| Rate limit | 30 per IP per 15 minutes |
|
|
139
|
+
|
|
140
|
+
**Request**
|
|
141
|
+
|
|
142
|
+
```json
|
|
143
|
+
{
|
|
144
|
+
"token": "ml_Q2x4bWZkY2V0ZXN0dG9rZW5leGFtcGxlMTIzNDU2Nzg5MDE",
|
|
145
|
+
"firstName": "Asha",
|
|
146
|
+
"lastName": "Rao",
|
|
147
|
+
"acceptTerms": true,
|
|
148
|
+
"acceptPrivacyPolicy": true
|
|
149
|
+
}
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
**Response `200`:** the [sign-in result](README.md#sign-in-result).
|
|
153
|
+
|
|
154
|
+
**Errors**
|
|
155
|
+
|
|
156
|
+
| Status | `code` | When |
|
|
157
|
+
|---|---|---|
|
|
158
|
+
| 400 | `INVALID_TOKEN` | Unknown, used or expired link |
|
|
159
|
+
| 400 | `VALIDATION_ERROR` | New account and `missingSignUpDetails` |
|
|
160
|
+
| 403 | `SIGN_UP_CLOSED` / `SIGN_IN_METHOD_DISABLED` | |
|
|
161
|
+
|
|
162
|
+
---
|
|
163
|
+
|
|
164
|
+
## POST /auth/phone/send-otp
|
|
165
|
+
|
|
166
|
+
Sends a sign-in code by SMS. Needs `phoneOtp.enabled` and an `smsSender`.
|
|
167
|
+
|
|
168
|
+
| | |
|
|
169
|
+
|---|---|
|
|
170
|
+
| Auth | Public |
|
|
171
|
+
| Rate limit | 10 per IP and 5 per number per hour; one code per minute per number |
|
|
172
|
+
|
|
173
|
+
**Request**
|
|
174
|
+
|
|
175
|
+
```json
|
|
176
|
+
{ "phoneNumber": "+91 98765 43210" }
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
**Response `200`** (always the same):
|
|
180
|
+
|
|
181
|
+
```json
|
|
182
|
+
{ "success": true, "message": "If this destination can receive codes, a code is on its way." }
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
**Errors**
|
|
186
|
+
|
|
187
|
+
| Status | `code` | When |
|
|
188
|
+
|---|---|---|
|
|
189
|
+
| 400 | `INVALID_PHONE` | No country code, or not a phone number |
|
|
190
|
+
| 400 | `PHONE_COUNTRY_NOT_ALLOWED` | Country not in `phoneOtp.allowedCountryCodes` |
|
|
191
|
+
| 403 | `SIGN_IN_METHOD_DISABLED` | Phone sign-in is off |
|
|
192
|
+
| 501 | `NOT_CONFIGURED` | No `smsSender` set up on the server |
|
|
193
|
+
| 429 | `TOO_MANY_REQUESTS` | Within `phoneOtp.resendAfterSeconds` (60 by default) of the last code, or a rate limit |
|
|
194
|
+
|
|
195
|
+
---
|
|
196
|
+
|
|
197
|
+
## POST /auth/phone/verify-otp
|
|
198
|
+
|
|
199
|
+
Signs in with the SMS code. Marks the phone verified, which is also how an account with `pendingVerifications: ["phone"]` finishes activation.
|
|
200
|
+
|
|
201
|
+
| | |
|
|
202
|
+
|---|---|
|
|
203
|
+
| Auth | Public |
|
|
204
|
+
| Rate limit | 30 per IP per 15 minutes |
|
|
205
|
+
|
|
206
|
+
**Request**
|
|
207
|
+
|
|
208
|
+
```json
|
|
209
|
+
{ "phoneNumber": "+919876543210", "code": "482913", "firstName": "Asha", "lastName": "Rao", "acceptTerms": true, "acceptPrivacyPolicy": true }
|
|
210
|
+
```
|
|
211
|
+
|
|
212
|
+
**Response `200`:** the [sign-in result](README.md#sign-in-result).
|
|
213
|
+
|
|
214
|
+
**Errors:** same as [email verify-otp](#post-authemailverify-otp), plus `INVALID_PHONE`.
|