Skip to content

ADR-026: Customer authentication — Cognito, mobile-first, passwordless

Status Accepted
Date 2026-04-10
Deciders CTO, Chief Risk Officer, Chief Compliance Officer
Affects repos bank-kyc, bank-app

Context

The bank requires a customer authentication architecture that satisfies three constraints simultaneously: regulatory compliance (RBNZ, APRA, and conduct obligations), strong security, and a customer experience that matches or exceeds neobank peers. Traditional username/password authentication is the weakest pattern in use — it is the primary attack surface for account takeover and creates friction that drives abandonment.

The customer interface at launch is mobile-only (iOS and Android). Web-based customer access is not in scope at launch. This constraint enables a cleaner, device-bound authentication model.

Decision

AWS Cognito User Pool (customer pool). Mobile-only. Passwordless from day one. Passkey/biometric-bound authentication after onboarding.

Auth flow

Step What happens
Onboarding Customer enters mobile number → SMS OTP verifies device ownership → KYC/eIDV completes (MOD-009) → email address captured → passkey registered on device (Face ID / Touch ID)
Login Biometric prompt → device passkey challenge → Cognito JWT issued
Step-up Second biometric prompt required for: payments above threshold, changes to account details, adding payees. SMS OTP added for high-value transactions
No password No password is ever created, stored, or transmitted. No password reset flow exists

Implementation

  • Cognito custom authentication Lambda triggers implement the OTP verification and passkey challenge flow
  • WebAuthn/passkey registration occurs during onboarding and is bound to the device
  • Cognito issues short-lived JWTs; refresh tokens are stored in the device's secure enclave
  • JWT claims carry customer ID, device ID, and authenticated level — API Gateway validates on every request

Account recovery

Email is captured and verified during onboarding (KYC step). The specific recovery flow — whether email magic link, contact centre with liveness check, or a combination — is defined as part of the KYC detailed design. The recovery process will be documented, auditable, and consistent with CCCFA (NZ) and NCCP Act (AU) obligations for customer identification. No recovery path bypasses identity verification.

Mobile-only rationale

The customer application at launch is iOS and Android only. This is recorded as the scope of this ADR. If web customer access is added in a future phase, a supplementary ADR will address browser-based passkey UX and session management for that surface.

Consequences

Positive: - No password eliminates the primary account takeover attack surface (credential stuffing, phishing, reuse) - Device-bound passkeys cannot be phished — the credential never leaves the device - Biometric authentication matches the neobank peer standard (Monzo, Up Bank, Revolut) - Cognito is AWS-native — customer identity data stays within the ap-southeast-2 boundary; no additional vendor - Cognito free tier covers 50,000 MAUs — significant headroom before authentication cost becomes material - Step-up authentication on high-value actions satisfies RBNZ and APRA strong authentication expectations

Negative: - Device loss requires account recovery — the recovery process adds support overhead and must be clearly designed (see KYC detailed design) - Passkey support requires iOS 16+ and Android 9+ — devices older than this cannot use the app - Cognito custom auth flows are complex to implement and test; Lambda trigger errors must not lock customers out

Alternatives considered

Traditional username/password with MFA: Rejected. Passwords are the weakest link; this ADR specifically eliminates them. MFA on top of passwords is inferior to passwordless from a security and UX standpoint.

Auth0 / Okta: Rejected. Additional vendor outside AWS; customer identity data would leave the ap-southeast-2 boundary. Comparable features available via Cognito at lower cost and within the existing cloud boundary.

Supabase Auth: Rejected. Overlaps with Neon Postgres decision (ADR-024) and adds another product dependency. Cognito is the better choice when already on AWS.

Custom auth (Postgres + JWT library): Rejected. Maximum build effort for a solved problem. Security-critical code should not be custom-built when a mature managed service exists.



Signoff record

Date Name Role Status
2026-04-10 Ross Millen CTO Approved
2026-04-10 Ross Millen Head of Architecture Approved
2026-04-10 Ross Millen Head of Data Approved

Capabilities

Capability Description Relationship
CAP-024 Biometric login (Face ID / fingerprint) enabled — passkey/biometric is the primary login mechanism from onboarding
CAP-036 Passkey / FIDO2 authentication enabled — WebAuthn passkey registration and challenge are the core auth flow
CAP-037 Step-up authentication for high-value transactions enabled — second biometric and SMS OTP step-up for payments above threshold
CAP-108 Device registration & trust enabled — device passkey bound to secure enclave; device ID in JWT claims
CAP-109 Session lifecycle management enabled — Cognito short-lived JWTs with refresh tokens in device secure enclave

ADR Title Relationship
ADR-007 Frontend framework — React/Next.js with Capacitor Capacitor plugins provide native biometric API access
ADR-018 KYC and digital onboarding architecture passkey registered at end of onboarding
ADR-023 Cloud provider and region strategy Cognito in ap-southeast-2 keeps customer identity within region
ADR-027 Internal staff authentication — Cognito and corporate SSO separate staff Cognito pool with different security policy

All ADRs Compiled 2026-05-22 from source/entities/adrs/ADR-026.yaml