Files
2025-12-16 22:26:18 +05:30
..
2025-12-16 22:26:18 +05:30
2025-12-16 22:26:18 +05:30
2025-12-16 22:26:18 +05:30
2025-12-16 22:26:18 +05:30

@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:

# 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

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

// DPoP key generation and signing
const publicKey = await this.authRepository.initializeDPoP();
const signedProof = await this.securityCore.signDPoPProof('POST', '/auth/login', accessToken);

@core/trust Integration

// Risk assessment for adaptive authentication
const { score, signals } = await this.trustRepository.calculateRiskScore();
const requiresStepUp = this.shouldRequireStepUp(score, signals);

@core/policy Integration

// Risk-adaptive policy checks
const allowed = await this.policyClient.check('login', 'User', { 
  riskScore: 60, 
  deviceSignals: signals 
});

5. Policy Enforcement Examples

Risk-Adaptive Login:

// 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:

// 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

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

import { BiometricUseCase } from '@feature/auth/domain';

const biometricUseCase = new BiometricUseCase(authRepo, biometricConfig);

const result = await biometricUseCase.authenticate({
  promptMessage: 'Authenticate to access LynkedUp',
  fallbackToPassword: true
});
// 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

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

// 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

// 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

// 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