Files

23 lines
4.7 KiB
Markdown

# Email authentication implementation audit
Verified on 2026-09-09 against commit `c452fc7` and the local production build `0.1.12-SNAPSHOT`. This supersedes the historical OIDC account-access description. The implementation node `auth-build` is complete; cross-browser/device acceptance and executable Gherkin coverage remain tracked separately.
| Requirement | Implementation and evidence |
| --- | --- |
| Invitation-only registration | `AdmissionService` creates hashed seven-day invitations. `EmailAccounts` checks eligibility before sending and again after email proof under the admission lock. `EmailAccountsTest` covers concurrent recipients, consumed/revoked/expired invitations and unknown addresses; `AdmissionServiceTest` verifies expiry and admin-only management. |
| Returning login without a provider | `LoginController` provides email request, code and fragment-link endpoints. `EmailLoginHttpTest` verifies actual security-chain admission, a different browser session entering the code, a protected Flow response and shared single-use alternatives. |
| Greylisting tolerance | `EmailProofLifetime` grants two hours from issuance. `EmailLoginChallengesTest` verifies 90-minute delay, expiry, replacement, five failed attempts and concurrent code/link redemption. |
| Controlled mail submission | `SendmailLoginMail` invokes local sendmail with the agreed sender. Five `LoginMailTest` cases cover message construction, process arguments, rejection and timeout. The operator confirmed the real test email and subsequently confirmed successful initial account setup. No further external mail was sent for this audit. |
| Request limits and generic responses | `EmailRequestLimitsTest` verifies persistent per-address, per-client and global limits, boundary expiry and concurrent enforcement. `LoginController` uses the server-resolved client address, returns the same public request result and does not log codes or recipients. |
| Bootstrap and recovery | Initial setup creates the administrator only after email proof. The consumed bootstrap cannot reactivate after deletion. The explicit offline recovery command stores a separate one-time digest and needs email proof. Ten `EmailAccountsTest` cases include recovery replacement, expiry and data-preserving promotion of an existing account. See `admin-recovery.md`. |
| Private identity and current permissions | `DeviceAuthenticationFilter` replaces the security context on every request; `AuthenticatedCurrentUser` requires an active UUID account. `OwnerTransactions` supplies the authenticated owner to tracking services. Existing catalog, work, habit and export tests exercise foreign-owner rejection. Admin status does not bypass owner-scoped tracking access. |
| Administration and blocking | `AdmissionService` exposes account/invitation metadata and version-checked account status changes. Blocking deletes device credentials. `AdmissionServiceTest` verifies permissions and that reactivation cannot revive revoked credentials. `DeviceLoginServiceTest` verifies current roles and inactive accounts. |
| Session lifetime and logout | Device credentials expire after 30 days without explicit activity. Passive requests do not renew them. Six `DeviceLoginServiceTest` and seven `AuthenticatedHttpTest` cases cover revocation, ambiguous cookies, CSRF, activity and logout-all owner isolation. Frontend checks cover draft cleanup and activity reporting. |
| Guest entry | The login page exposes shared guest access, using the existing guest UUID without administrator rights; covered by `EmailLoginHttpTest`. |
| Deletion | Dedicated email proof, device-bound short final grant and separate explicit confirmation precede transactional deletion. Seven proof, five transaction and three HTTP tests cover expiry, isolation, rollback and reuse. See `account-deletion.md`. |
| Removed provider integration | Active security configuration has no OAuth/OIDC registration or callbacks. Inspection of the built JAR found no OAuth2/Nimbus libraries. Historical database changesets remain intact; the old identity table is not used for login. |
All 57 tests in the twelve authentication-related test classes listed above passed without failures or skips. The full local run passed 131 JVM tests, 26 operations tests, 17 frontend tests and production smoke including the packaged offline recovery entry point. One separately invoked browser harness is intentionally outside that regular run.
This audit does not claim Cucumber execution, Firefox/Android acceptance, a real deletion email delivery or a production administrator recovery. The original browser evidence partly predates removal of OIDC and must not be treated as end-to-end proof of the new email flow. These acceptance boundaries remain visible in `auth-spike`, `browser-accept` and `identity-tests`.