279 lines
7.7 KiB
Markdown
279 lines
7.7 KiB
Markdown
# @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 |