# @feature/auth Playbook ## 1. Overview Handles Authentication (OTP, Magic Link, Federated), Session Management, and Biometrics with risk-adaptive security. **Key Features (per FRD):** - F.ID.001: Login, Registration, and Forgot Password flows - F.ID.002: Configurable verification (OTP, Email, Magic Links) - F.ID.003: Secure session token storage and rotation - F.ID.004: Device biometrics integration (FaceID/TouchID/Android Biometrics) - F.ID.005: Configurable "Remember Me" duration - F.ID.006: Enhanced Magic Link security with nonce and expiry - F.ID.007: Federated Login connectors (Google, Apple) ## 2. Setup & Dependencies **Required Core SDKs:** - `@core/security` - DPoP key generation and signing - `@core/trust` - Runtime Risk Score; triggers Step-Up MFA if score is high - `@core/policy` - Risk-adaptive policy checks - `@core/storage` - Encrypted session storage **Installation:** ```bash # Install auth feature layers pnpm add @feature/auth/domain @feature/auth/data @feature/auth/ui-rn # Peer dependencies (automatically resolved in monorepo) # @core/security @core/trust @core/policy @core/storage ``` ## 3. Core Workflow: DPoP Login and Risk Assessment ```mermaid sequenceDiagram participant App participant Auth as @feature/auth participant Trust as @core/trust participant Security as @core/security participant Policy as @core/policy participant BFF App->>Auth: login(credentials) Auth->>Trust: calculateRiskScore() Trust-->>Auth: { score: 45, signals: {...} } Auth->>Security: initializeDPoP() Security-->>Auth: publicKey Auth->>BFF: exchangeCredentials(creds, pubKey) BFF-->>Auth: session + tokens alt Risk Score > Threshold Auth->>Policy: check('step-up-mfa', context) Policy-->>Auth: requires_verification: true Auth-->>App: { success: true, requiresStepUp: true } else Low Risk Auth-->>App: { success: true, session } end ``` ## 4. Integration Points ### @core/security Integration ```typescript // DPoP key generation and signing const publicKey = await this.authRepository.initializeDPoP(); const signedProof = await this.securityCore.signDPoPProof('POST', '/auth/login', accessToken); ``` ### @core/trust Integration ```typescript // Risk assessment for adaptive authentication const { score, signals } = await this.trustRepository.calculateRiskScore(); const requiresStepUp = this.shouldRequireStepUp(score, signals); ``` ### @core/policy Integration ```typescript // Risk-adaptive policy checks const allowed = await this.policyClient.check('login', 'User', { riskScore: 60, deviceSignals: signals }); ``` ## 5. Policy Enforcement Examples **Risk-Adaptive Login:** ```typescript // Low risk (score < 50): Standard login await policyClient.check('login', 'User', { riskScore: 35 }); // → true // Medium risk (50-75): Email verification await policyClient.check('login', 'User', { riskScore: 65 }); // → requires email MFA // High risk (75+): OTP + Device attestation await policyClient.check('login', 'User', { riskScore: 85 }); // → requires OTP + attestation ``` **Organization Access:** ```typescript // Check organization membership with role-based permissions await policyClient.check('access-org', 'Organization', { orgId: 'org-123', userRole: 'member', riskScore: 40 }); ``` ## 6. API Usage Examples ### Basic Login Flow ```typescript import { LoginUseCase } from '@feature/auth/domain'; import { AuthRepository } from '@feature/auth/data'; const authRepo = new AuthRepository(securityCore, bffClient); const trustRepo = new TrustRepository(trustCore); const loginUseCase = new LoginUseCase(authRepo, trustRepo, config); const result = await loginUseCase.execute({ identifier: 'user@example.com', password: 'secure_password', deviceId: 'device-uuid' }); if (result.success) { if (result.requiresStepUp) { // Handle step-up MFA flow console.log('Additional verification required:', result.verificationMethod); } else { // Login successful console.log('User session:', result.session); } } ``` ### Biometric Authentication ```typescript import { BiometricUseCase } from '@feature/auth/domain'; const biometricUseCase = new BiometricUseCase(authRepo, biometricConfig); const result = await biometricUseCase.authenticate({ promptMessage: 'Authenticate to access LynkedUp', fallbackToPassword: true }); ``` ### Magic Link Flow ```typescript // Generate magic link const magicLink = await authRepo.generateMagicLink('user@example.com'); // Verify magic link (typically called from deep link handler) const result = await loginUseCase.executeWithMagicLink(token, nonce); ``` ## 7. Configuration ```typescript const authConfig: AuthConfig = { requireEmailVerification: true, requirePhoneVerification: false, biometrics: { enabled: true, fallbackToPassword: true, promptMessage: 'Authenticate with LynkedUp' }, rememberMeDays: 30, maxLoginAttempts: 5, lockoutDurationMinutes: 15 }; ``` ## 8. Error Handling ```typescript // Standard error codes returned by AuthResult switch (result.errorCode) { case 'INVALID_CREDENTIALS': // Handle invalid login break; case 'ACCOUNT_LOCKED': // Handle account lockout break; case 'VERIFICATION_REQUIRED': // Handle unverified account break; case 'DEVICE_NOT_TRUSTED': // Handle untrusted device break; case 'POLICY_VIOLATION': // Handle policy-based denial break; } ``` ## 9. Testing Strategy ### Unit Tests ```typescript // Domain layer testing (LoginUseCase) describe('LoginUseCase', () => { it('should require step-up for high risk score', async () => { mockTrustRepo.calculateRiskScore.mockResolvedValue({ score: 85, signals: {} }); const result = await loginUseCase.execute(validCredentials); expect(result.requiresStepUp).toBe(true); }); }); ``` ### Contract Tests ```typescript // Data layer testing against mocked BFF import { setupServer } from 'msw/node'; import { graphql } from 'msw'; const server = setupServer( graphql.mutation('Login', (req, res, ctx) => { return res(ctx.data({ login: { accessToken: 'mock-token', user: mockUser } })); }) ); ``` ## 10. Security Notes **Critical Security Requirements:** - Private keys MUST remain in the Secure Enclave/TEE - Magic links MUST enforce nonce and expiry (see F.ID.006) - DPoP proofs MUST be bound to specific HTTP requests - Session tokens MUST be stored in hardware-backed keychain - Step-up MFA triggers MUST be policy-driven, not hardcoded **Risk Signals Handling:** - Root/Jailbreak detection → Immediate step-up required - Device attestation failure → Block access + notify admin - Geolocation deviation → Email verification required - New device → SMS OTP required ## 11. Troubleshooting **Common Issues:** 1. **"SecurityCore must be initialized"** - Ensure `securityCore.initialize()` is called before auth operations 2. **"DPoP key generation failed"** - Verify hardware-backed storage is available - Check device security settings (passcode/biometrics enabled) 3. **"Policy evaluation failed"** - Verify policy bundles are cached locally - Check network connectivity for policy updates 4. **Biometric authentication unavailable** - Verify device biometric enrollment - Check app permissions for biometric access ## 12. Performance Considerations - **Key Operations**: DPoP key generation (one-time, ~100ms) - **Risk Assessment**: Device evaluation (~50-200ms depending on signals) - **Policy Evaluation**: Local cache lookup (~1-5ms) - **Session Storage**: Keychain operations (~10-50ms) **Optimization Tips:** - Cache risk assessment results for 5-10 minutes - Pre-warm DPoP keys during app initialization - Batch policy evaluations when possible