Implement Supabase Edge Function for BankID assertion validation
epic-bankid-vipps-login-api-clients-task-005 — Create the Supabase Edge Function that receives BankID assertion tokens from the mobile client, validates them against the BankID broker API (server-to-server), and returns a verified identity claim or a typed error. This is a security requirement: assertion validation must occur server-side. The function must handle test and production BankID environments, validate token signatures, check expiry, and return a normalized identity response (personnummer, display name) consumed by the BankID Provider Client.
Acceptance Criteria
Technical Requirements
Execution Context
Tier 1 - 540 tasks
Can start after Tier 0 completes
Implementation Notes
Structure the Edge Function as three route handlers in a single function entry point (or three separate Edge Functions if Supabase routing is cleaner). Use the jose Deno library for JWT signature verification against the BankID JWKS endpoint. Cache the JWKS document using a module-level Map to avoid re-fetching on every invocation. The sessionId is a server-generated UUID stored in a short-lived Supabase table (e.g., bankid_sessions with a 10-minute TTL enforced by created_at + pg_cron or Postgres TTL extension).
The validate endpoint deletes the session row after successful validation to prevent replay. Use Deno's built-in crypto for any HMAC operations. Never use console.log with the assertion token or personnummer — use structured logging with redaction.
Testing Requirements
Deno unit tests for: (1) valid assertion token returns correct identity payload; (2) expired token returns ASSERTION_EXPIRED error; (3) tampered/invalid signature returns ASSERTION_INVALID error; (4) malformed request body returns HTTP 400; (5) missing or invalid Supabase JWT returns HTTP 401; (6) BankID broker returning an error maps to typed EdgeFunctionServerFailure response. Use Deno test mocking for the BankID broker HTTP calls. Integration test in Supabase local development environment using supabase functions serve with test BankID credentials. Document test environment BankID credentials in CI secrets.
Norway has multiple BankID broker providers (e.g., Signicat, Criipto, Nets) with different integration contracts, pricing, and WebView behavior. If the broker is not selected and contractually agreed before implementation begins, the BankIDProviderClient may need to be rewritten after initial build.
Mitigation & Contingency
Mitigation: Define a minimal broker interface abstraction (session initiation, WebView URL generation, assertion validation) before writing any provider-specific code. Confirm broker selection with Norse Digital Products before starting this epic.
Contingency: If the broker changes after implementation, the abstraction layer allows replacing the provider-specific implementation behind the same interface with a targeted rewrite rather than a full redesign.
Android deep link handling with custom URI schemes can conflict with existing app links (HTTPS-based) or fail silently on certain Android versions if the intent filter is misconfigured, causing OAuth callbacks to never reach the app and leaving users stranded on the Vipps or BankID page.
Mitigation & Contingency
Mitigation: Use HTTPS app links (Android App Links) rather than custom URI schemes where possible, as they are more reliable on modern Android. Test deep link receipt on Android 12+ explicitly during development, as this version changed intent flag requirements.
Contingency: Implement a polling fallback for Vipps (check auth status on app foreground) as a secondary callback mechanism if deep link receipt fails on specific Android configurations.
Vipps Login has a separate test environment (mt2.vipps.no) that requires distinct test merchant credentials which must be applied for separately. If test credentials are delayed, integration testing of the VippsApiClient cannot proceed, blocking the entire authentication flow.
Mitigation & Contingency
Mitigation: Apply for Vipps test merchant credentials at the start of the project sprint, not when implementation begins. Use Vipps' publicly documented mock token responses for unit tests to decouple unit testing from live credentials.
Contingency: Implement the VippsApiClient with full mock injection support so all service-layer tests can run against a stub client while waiting for official test credentials.