high priority medium complexity testing pending testing specialist Tier 2

Acceptance Criteria

Happy path test: Vipps authorization code → token exchange → userinfo fetch succeeds and returns VippsIdentityResult with non-null sub, phoneNumber, and personnummer
Happy path test: BankID session initiation → assertion token forward → Edge Function validation returns BankIdIdentityResult with non-null personnummer and displayName
Happy path test: Deep link with valid state and code for Vipps routes to VippsApiClient.exchangeCodeForTokens and emits OAuthCallbackResult.vipps
Happy path test: Deep link with valid state and code for BankID routes to BankIdProviderClient.validateAssertion and emits OAuthCallbackResult.bankId
Error path: Vipps token exchange with expired code returns InvalidGrantFailure at service boundary (not a raw HTTP exception)
Error path: BankID assertion token rejected by Edge Function returns AssertionInvalidFailure at service boundary
Error path: Network failure during Vipps userinfo returns NetworkFailure (not an unhandled exception)
Error path: Deep link with mismatched state returns StateMismatchFailure without attempting token exchange
Error path: BankID session poll timeout (max retries exceeded) returns SessionExpiredFailure
Error path: Deep link with error=access_denied returns OAuthUserDeniedFailure
Verified that no raw HTTP response bodies, tokens, or personnummer values appear in test log output
All tests pass in CI with mock HTTP adapters — no real network calls to Vipps or BankID APIs

Technical Requirements

frameworks
Flutter
flutter_test
Riverpod (ProviderContainer for testing)
mockito or mocktail (Dart mocking)
apis
Vipps Login API (mocked)
Supabase Edge Functions BankID endpoints (mocked)
BankID broker (mocked via Edge Function mock)
performance requirements
All integration tests must complete within 60 seconds total
Each individual test case must complete within 10 seconds
security requirements
No real credentials or personnummer values in test fixtures — use clearly fake test data (e.g., 12345678901 as personnummer placeholder)
Test HTTP responses must not include real JWT signatures — use test-only HMAC keys
Mock flutter_secure_storage to avoid writing to device keychain during CI runs

Execution Context

Execution Tier
Tier 2

Tier 2 - 518 tasks

Can start after Tier 1 completes

Implementation Notes

The key goal of these tests is verifying the layer boundaries: typed errors from the client layer must reach the service layer boundary without being wrapped in untyped exceptions. Use a shared AuthTestFixtures class with factory methods for valid and invalid response payloads to keep tests DRY. For the deep link handler tests, inject a Stream controller that emits test URIs instead of real platform deep links. For BankID polling tests, use a fake clock (clock package) to advance time without real delays.

Document the test fixtures clearly — future developers need to understand what each mock response represents. Consider adding a golden file test for the full Vipps auth flow state machine if BLoC is used.

Testing Requirements

Integration tests using flutter_test with ProviderContainer for Riverpod dependency injection. Use mockito or mocktail to mock the HTTP client interface shared by both API clients. Create a MockHttpClient that returns pre-canned response fixtures for each endpoint. Tests should instantiate the full dependency chain (config → client → service boundary) to verify typed error propagation end-to-end.

Separate test groups for: (1) VippsApiClient integration, (2) BankIdProviderClient integration, (3) DeepLinkHandler routing. Use fake_async or a manual test scheduler for BankID session polling tests to avoid real time delays. Run via `flutter test test/integration/auth/` in CI.

Component
Deep Link / OAuth Redirect Handler
infrastructure medium
Dependencies (4)
Build the Vipps API Client infrastructure component responsible for all HTTP communication with the Vipps Login OAuth 2.0 endpoints. Implement token exchange (authorization code → access token), userinfo fetch (retrieve personnummer and profile), and refresh token handling. Use the environment-aware config from task-002 and surface typed errors from task-001. The client must support both test and production Vipps environments and be injectable as a dependency for the Vipps Authentication Service. epic-bankid-vipps-login-api-clients-task-003 Build the BankID Provider Client that communicates with the backend Supabase Edge Function responsible for BankID server-side assertion token validation. Implement session initiation (obtaining a BankID login URL), assertion token forwarding (posting the token from the app to the Edge Function for server-side verification), and session result polling or callback handling. The client must never trust BankID assertion tokens client-side only. Use typed errors from task-001 and environment config from task-002. epic-bankid-vipps-login-api-clients-task-004 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. epic-bankid-vipps-login-api-clients-task-005 Build the Deep Link and OAuth Redirect Handler that intercepts incoming OAuth callback deep links for both Vipps and BankID providers. Implement OAuth state parameter generation (before redirect) and validation (on callback) to prevent CSRF attacks. Parse the authorization code and error parameters from the redirect URI, determine which provider triggered the callback, and route the result to the appropriate authentication service. Register the app's custom URI scheme and/or Universal Link for both providers. epic-bankid-vipps-login-api-clients-task-006
Epic Risks (3)
high impact high prob dependency

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.

high impact medium prob technical

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.

medium impact medium prob dependency

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.