docs: keep demo identity replaceable
This commit is contained in:
@@ -7,7 +7,7 @@
|
||||
|
||||
## Objective
|
||||
|
||||
Allow hackathon judges and merchants to authenticate as distinct merchant users, while enforcing strict server-side tenant isolation. Seed one demo user per merchant through a secure one-time administrative workflow so different merchant dashboards can be demonstrated without adding self-service account management to the MVP.
|
||||
Allow hackathon judges and merchants to authenticate as distinct merchant users, while enforcing strict server-side tenant isolation. Seed one demo user per merchant through a secure one-time administrative workflow so different merchant dashboards can be demonstrated. This username/password capability is a deliberately small demo adapter: if the project is accepted, ZarinPal SSO replaces authentication while the reusable tenant-authorization boundary remains.
|
||||
|
||||
## Actors
|
||||
|
||||
@@ -39,11 +39,13 @@ Allow hackathon judges and merchants to authenticate as distinct merchant users,
|
||||
- User-created roles, permissions, or additional merchant users
|
||||
- Cross-merchant operator access in the browser
|
||||
- Storing credentials, session tokens, or generated credential exports in Git
|
||||
- Implementing or simulating ZarinPal SSO before the project is accepted
|
||||
- Production-grade identity lifecycle features that ZarinPal SSO will own
|
||||
|
||||
## Domain and data contract
|
||||
|
||||
- A `Merchant User` belongs to exactly one merchant in the MVP.
|
||||
- Usernames are unique after the approved normalization rule; the exact normalization remains open.
|
||||
- Demo usernames use stable lowercase ASCII identifiers such as `merchant-0001`. Comparison is case-insensitive, and rerunning the seed preserves an existing merchant's username.
|
||||
- Passwords are stored only as Argon2id encoded hashes with a unique salt and reviewed, versioned parameters. Plaintext passwords are accepted only at the login boundary or generated by the one-time credential workflow, then discarded.
|
||||
- An `Authenticated Session` belongs to one merchant user and records creation, last activity, idle expiry, absolute expiry, revocation, and minimal security provenance required by the approved retention policy.
|
||||
- The browser receives only a cryptographically random opaque session token. The server stores a non-reversible digest of that token, never the raw token.
|
||||
@@ -58,6 +60,9 @@ Allow hackathon judges and merchants to authenticate as distinct merchant users,
|
||||
5. Invalid username, invalid password, disabled account, and other expected login failures return the same user-facing message and externally equivalent response shape.
|
||||
6. Authentication and authorization failures never reveal password hashes, raw tokens, user existence, merchant existence, stack traces, or internal policy details.
|
||||
7. Protected HTTP and SSE requests use the same authenticated merchant boundary. SSE replay or reconnect never survives session expiry or revocation.
|
||||
8. State-changing authenticated requests require a valid CSRF token and same-origin evidence. `SameSite=Lax` is defense in depth, not the only CSRF control; unexpected `Origin`/Fetch Metadata requests fail closed.
|
||||
9. Each user may have at most two active sessions. Creating a third session atomically revokes the oldest active session.
|
||||
10. Failed logins are throttled by both normalized username and source IP without permanently locking the account. A limited request returns `429` with `Retry-After`; exact thresholds remain configurable and require approval.
|
||||
|
||||
## Demo credential workflow
|
||||
|
||||
@@ -72,8 +77,9 @@ Allow hackathon judges and merchants to authenticate as distinct merchant users,
|
||||
|
||||
| Boundary/asset | Main abuse case | Required control |
|
||||
|---|---|---|
|
||||
| Login endpoint / credentials | Enumeration or credential guessing | Generic failures; login throttling policy still requires approval |
|
||||
| Login endpoint / credentials | Enumeration or credential guessing | Generic failures; username and IP throttling; no permanent account lockout |
|
||||
| Browser / session token | Token theft through script or transport | `HttpOnly`, `Secure`, host-only cookie; HTTPS; no browser storage |
|
||||
| Authenticated mutation / session cookie | Cross-site request forgery | CSRF token, strict origin/fetch-metadata checks, `SameSite=Lax` |
|
||||
| Session store | Stolen database reveals usable tokens | Store only token digests; expire and revoke server-side |
|
||||
| Merchant API / tenant data | User changes a merchant id to read another tenant | Derive authorization scope from session on every operation |
|
||||
| Demo credential generation | Plaintext secrets leak into Git/logs/history | Random generation, one-time output, explicit secure destination, secret scanning |
|
||||
@@ -85,6 +91,7 @@ Allow hackathon judges and merchants to authenticate as distinct merchant users,
|
||||
- Authenticated users requesting a resource outside their merchant boundary receive a typed forbidden/not-found policy defined by the API spec without confirming another merchant's resource exists.
|
||||
- Session-store failure fails closed: protected requests do not proceed using unverifiable client state.
|
||||
- Credential-generation partial failure reports affected merchant identifiers without printing generated passwords again or leaving an apparently complete run.
|
||||
- A throttled login returns a typed `429` with `Retry-After` and does not perform password verification or create a session.
|
||||
|
||||
## Observability and audit
|
||||
|
||||
@@ -103,6 +110,10 @@ Allow hackathon judges and merchants to authenticate as distinct merchant users,
|
||||
- Invalid username, password, and disabled-account attempts are externally indistinguishable in user-facing content.
|
||||
- Modifying a merchant identifier cannot cross the merchant boundary enforced by the authenticated session.
|
||||
- The demo-user workflow creates missing users idempotently, displays new credentials once, and never commits or logs them.
|
||||
- Generated usernames are stable `merchant-NNNN`-style lowercase identifiers and compare case-insensitively.
|
||||
- Login throttling applies independently to normalized-username and source-IP buckets, returns `429` plus `Retry-After`, and never permanently locks an account.
|
||||
- State-changing requests fail without both an approved CSRF token and valid same-origin evidence.
|
||||
- No user has more than two active sessions; the third successful login revokes the oldest session.
|
||||
- Security tests cover enumeration resistance, session fixation/rotation, expiry, revocation, cross-tenant access, cookie flags, token-digest storage, and credential-output safety.
|
||||
|
||||
## Boundaries
|
||||
@@ -118,13 +129,15 @@ Allow hackathon judges and merchants to authenticate as distinct merchant users,
|
||||
- Hash passwords with Argon2id and return generic login failures.
|
||||
- Expire sessions after 12 hours idle and seven days absolute; revoke immediately on logout or account disablement.
|
||||
- Generate one demo user's credentials per merchant through a one-time administrative command, display them once, and keep them out of Git.
|
||||
- Use stable lowercase `merchant-NNNN`-style usernames with case-insensitive comparison.
|
||||
- Throttle failed logins by normalized username and source IP, return `429` with `Retry-After`, and do not use permanent account lockouts.
|
||||
- Require CSRF tokens plus strict same-origin evidence for state-changing authenticated requests.
|
||||
- Permit at most two active sessions per user; a third successful login revokes the oldest.
|
||||
- Treat local username/password authentication as a demo adapter that is replaced by ZarinPal SSO after acceptance; keep tenant authorization independent of the credential provider.
|
||||
|
||||
## Open decisions
|
||||
|
||||
- Exact username normalization and generated username format
|
||||
- Login rate-limit keys, thresholds, lockout behavior, and response contract
|
||||
- CSRF protection for state-changing authenticated requests
|
||||
- Number of simultaneous sessions permitted per user
|
||||
- Exact login rate-limit thresholds and time windows
|
||||
- Exact session store, token-digest algorithm, cookie name/path, and activity-write throttling
|
||||
- Credential replacement and secure delivery procedure
|
||||
- Security-event IP/user-agent collection and retention
|
||||
|
||||
Reference in New Issue
Block a user