Separate second-factor verification and delivery from auth (#40)
This commit is contained in:
1 parent
12a38cd654
commit
ecb63b61c6
33 files changed
+1772
-123
No files matched your search
+12
-10
@@ -2,14 +2,14 @@
|
||||
|
||||
Task [#38](https://git.sendico.io/tech/sxchnge/issues/38), [PR #39](https://git.sendico.io/tech/sxchnge/pulls/39), branch `auth-38`.
|
||||
Primary module: auth; secondary modules: notification templates and Flutter auth.
|
||||
This change stacks on notifications PR #37, which stacks on BFF PR #35.
|
||||
Merge #35, then #37, then this contribution, retargeting each dependent PR to main.
|
||||
The initial integration is merged. Task #40 separates login verification into
|
||||
the [second-factor service](architecture/two-factor.md).
|
||||
|
||||
## Configuration
|
||||
|
||||
Load the `auth.activation` and `auth.login` revision 1 templates from
|
||||
Load the `auth.activation`, `auth.login` and `twofactor.code` revision 1 templates from
|
||||
`backend/notifications/templates.example.json` into the notification catalog.
|
||||
Both templates have English and Russian variants; product account locale selects
|
||||
These templates have English and Russian variants; product account locale selects
|
||||
Russian for `ru` variants and English otherwise. Publish subsequent template
|
||||
changes under a new revision rather than mutating deployed content.
|
||||
|
||||
@@ -66,9 +66,9 @@ envelope. Credentials, codes and activation tokens are sent in POST bodies.
|
||||
| POST `/signup` | `name`, `email`, `password`, `locale`, `idempotencyKey` | 202 with `userId`, after activation email queue acceptance |
|
||||
| POST `/verification/send` | `email`, `idempotencyKey` | 202; generic acceptance also applies to absent/already-active accounts |
|
||||
| POST `/verification/confirm` | `token` | 202 with `verified: true` after activation commits |
|
||||
| POST `/login` | `login: {login, password}`, `clientId`, `deviceId` | 202 with `userId`, `pendingToken: {token, expiration}`, masked `target`, `expiresAt`, `resendAt` |
|
||||
| POST `/login/resend` | `pendingToken`, `idempotencyKey` | 202 with the challenge timing and same pending credential |
|
||||
| POST `/login/verify` | `pendingToken`, six-digit `code` | 200 with account and existing access/refresh response |
|
||||
| POST `/login` | `login: {login, password}`, `clientId`, `deviceId` | 202 with `userId`, `pendingToken: {token, expiration}`, `challengeId`, `channel`, masked `target`, `expiresAt`, `resendAt` |
|
||||
| POST `/login/resend` | `pendingToken`, `challengeId`, `idempotencyKey` | 202 with the challenge timing and same pending credential |
|
||||
| POST `/login/verify` | `pendingToken`, `challengeId`, six-digit `code` | 200 with account and existing access/refresh response |
|
||||
|
||||
The pending JWT binds the customer, client and device. The verification record
|
||||
binds its code to a hash of that JWT. Password login does not create a session.
|
||||
@@ -79,7 +79,8 @@ and commits the account transition with token consumption in one transaction.
|
||||
|
||||
Login codes expire within 10 minutes and cannot outlive their pending JWT.
|
||||
Resending uses a one-minute cooldown, invalidates the previous code in that
|
||||
challenge, and allows five deliveries per destination per hour. Incorrect codes
|
||||
challenge, and allows five deliveries per customer and twenty per requesting IP per hour
|
||||
across second-factor purposes. Incorrect codes
|
||||
consume the existing five-attempt budget. Restart login after a pending credential
|
||||
expires or a challenge locks. Signup/resend request limits also apply per email
|
||||
(10/hour) and IP (30/hour), using shared atomic fixed-window counters.
|
||||
@@ -102,8 +103,9 @@ retries can create replacement messages; they are not distributed exactly-once
|
||||
operations. Tokens are stored before the RPC, so a process crash between those
|
||||
steps requires user recovery; there is no product-side delivery outbox.
|
||||
|
||||
Code consumption precedes session creation. If session creation or its HTTP
|
||||
response fails, restart password login; the code is not reusable. The adapter
|
||||
Code verification, one-use proof consumption and session creation now commit in
|
||||
one transaction. A session-write failure leaves the code retryable; a lost HTTP
|
||||
response after commit requires restarting password login. The adapter
|
||||
retains a confirmed session in memory and has no refresh/restore-on-reload flow
|
||||
in this contribution. Backend authorization remains authoritative for future
|
||||
protected APIs. Notification provider failures after queue acceptance are visible
|
||||
|
||||
Reference in new issue
Block a user