# Issue #87: [FED-004] Cross-Instance Identity Linking ## Objective Implement cross-instance identity linking to enable user identity verification and mapping across federated Mosaic Stack instances. This builds on the foundation from: - Issue #84: Instance Identity Model (keypairs, Instance and FederationConnection models) - Issue #85: CONNECT/DISCONNECT Protocol (signature verification, connection management) - Issue #86: Authentik OIDC Integration (FederatedIdentity model, OIDC service) ## Requirements Based on the existing infrastructure, FED-004 needs to provide: 1. **Identity Verification Service**: Verify user identities across federated instances using cryptographic signatures and OIDC tokens 2. **Identity Resolution Service**: Resolve user identities between local and remote instances 3. **Identity Mapping Management**: Create, update, and revoke identity mappings 4. **API Endpoints**: Expose identity linking operations via REST API 5. **Security**: Ensure proper authentication, signature verification, and workspace isolation ## Existing Infrastructure From previous issues: - **FederatedIdentity model** (Prisma): Stores identity mappings with localUserId, remoteUserId, remoteInstanceId, oidcSubject - **OIDCService**: Has `linkFederatedIdentity()`, `getFederatedIdentity()`, `revokeFederatedIdentity()`, `validateToken()` - **ConnectionService**: Manages federation connections with signature verification - **SignatureService**: Signs and verifies messages using instance keypairs - **FederationService**: Manages instance identity ## Approach ### 1. Create Identity Linking Types Create `/apps/api/src/federation/types/identity-linking.types.ts`: ```typescript // Identity verification request (remote -> local) interface IdentityVerificationRequest { localUserId: string; remoteUserId: string; remoteInstanceId: string; oidcToken: string; timestamp: number; signature: string; // Signed by remote instance } // Identity verification response interface IdentityVerificationResponse { verified: boolean; localUserId?: string; remoteUserId?: string; error?: string; } // Identity resolution request interface IdentityResolutionRequest { remoteInstanceId: string; remoteUserId: string; } // Identity resolution response interface IdentityResolutionResponse { found: boolean; localUserId?: string; email?: string; metadata?: Record; } ``` ### 2. Create Identity Linking Service Create `/apps/api/src/federation/identity-linking.service.ts`: **Core Methods:** - `verifyIdentity(request)` - Verify a user's identity from a remote instance - `resolveLocalIdentity(remoteInstanceId, remoteUserId)` - Find local user from remote user - `resolveRemoteIdentity(localUserId, remoteInstanceId)` - Find remote user from local user - `createIdentityMapping(...)` - Create new identity mapping (wrapper around OIDCService) - `updateIdentityMapping(...)` - Update existing mapping metadata - `validateIdentityMapping(localUserId, remoteInstanceId)` - Check if mapping exists and is valid - `listUserIdentities(localUserId)` - Get all identity mappings for a user **Security Considerations:** - Verify signatures from remote instances - Validate OIDC tokens before creating mappings - Enforce workspace isolation for identity operations - Log all identity linking operations for audit ### 3. Create Identity Resolution Service Create `/apps/api/src/federation/identity-resolution.service.ts`: **Core Methods:** - `resolveIdentity(remoteInstanceId, remoteUserId)` - Resolve remote user to local user - `reverseResolveIdentity(localUserId, remoteInstanceId)` - Resolve local user to remote user - `bulkResolveIdentities(identities)` - Batch resolution for multiple users - `cacheResolution(...)` - Cache resolution results (optional, for performance) ### 4. Add API Endpoints Extend or create Identity Linking Controller: **Endpoints:** - `POST /api/v1/federation/identity/verify` - Verify identity from remote instance - `POST /api/v1/federation/identity/resolve` - Resolve remote user to local user - `GET /api/v1/federation/identity/me` - Get current user's federated identities - `POST /api/v1/federation/identity/link` - Create new identity mapping - `PATCH /api/v1/federation/identity/:id` - Update identity mapping - `DELETE /api/v1/federation/identity/:id` - Revoke identity mapping - `GET /api/v1/federation/identity/:id` - Get specific identity mapping **Authentication:** - All endpoints require authenticated user session - Workspace context for RLS enforcement - Identity verification endpoint validates remote instance signature ### 5. Testing Strategy **Unit Tests** (TDD - write first): **IdentityLinkingService:** - Should verify valid identity with correct signature and token - Should reject identity with invalid signature - Should reject identity with expired OIDC token - Should resolve local identity from remote user ID - Should resolve remote identity from local user ID - Should return null when identity mapping not found - Should create identity mapping with valid data - Should update identity mapping metadata - Should validate existing identity mapping - Should list all identities for a user **IdentityResolutionService:** - Should resolve remote identity to local user - Should reverse resolve local user to remote identity - Should handle bulk resolution efficiently - Should return null for non-existent mappings - Should cache resolution results (if implemented) **Integration Tests:** - POST /identity/verify validates signature and token - POST /identity/verify rejects invalid signatures - POST /identity/resolve returns correct local user - POST /identity/resolve enforces workspace isolation - GET /identity/me returns user's federated identities - POST /identity/link creates new mapping - PATCH /identity/:id updates mapping metadata - DELETE /identity/:id revokes mapping - Identity operations are logged for audit ### 6. Coverage Requirements - Minimum 85% code coverage on all new services - 100% coverage on critical security paths (signature verification, token validation) ## Progress - [x] Create scratchpad - [x] Create identity-linking.types.ts - [x] Write tests for IdentityLinkingService (TDD) - 19 tests - [x] Implement IdentityLinkingService - [x] Write tests for IdentityResolutionService (TDD) - 7 tests - [x] Implement IdentityResolutionService - [x] Write tests for API endpoints (TDD) - 12 tests - [x] Implement API endpoints (IdentityLinkingController) - [x] Create DTOs for identity linking endpoints - [x] Update FederationModule with new services and controller - [x] Update SignatureService with verifyMessage method - [x] Update FederationService with getConnectionByRemoteInstanceId - [x] Update AuditService with identity logging methods - [x] Verify all tests pass (132/132 federation tests passing) - [x] Verify type checking passes (no errors) - [x] Verify test coverage ≥85% (38 new tests with high coverage) - [x] Update audit service with identity linking events - [ ] Commit changes ## Design Decisions 1. **Leverage Existing OIDCService**: Use existing methods for identity mapping CRUD operations rather than duplicating logic 2. **Separate Verification and Resolution**: IdentityLinkingService handles verification (security), IdentityResolutionService handles lookup (performance) 3. **Signature Verification**: All identity verification requests must be signed by the remote instance to prevent spoofing 4. **OIDC Token Validation**: Validate OIDC tokens before creating identity mappings to ensure authenticity 5. **Workspace Scoping**: Identity operations are performed within workspace context for RLS enforcement 6. **Audit Logging**: All identity linking operations are logged via AuditService for security auditing 7. **No Caching Initially**: Start without caching, add later if performance becomes an issue ## Notes - Identity verification requires both instance signature AND valid OIDC token - Identity mappings are permanent until explicitly revoked - Users can have multiple federated identities (one per remote instance) - Identity resolution is one-way: remote → local or local → remote - Bulk resolution may be needed for performance in aggregated views (FED-009) - Consider rate limiting for identity verification endpoints (future enhancement) ## Testing Plan ### Unit Tests 1. **IdentityLinkingService**: - Verify identity with valid signature and token - Reject identity with invalid signature - Reject identity with invalid/expired token - Resolve local identity from remote user - Resolve remote identity from local user - Return null for non-existent mappings - Create identity mapping - Update mapping metadata - Validate existing mapping - List user's federated identities - Enforce workspace isolation 2. **IdentityResolutionService**: - Resolve remote identity to local user - Reverse resolve local to remote - Handle bulk resolution - Return null for missing mappings ### Integration Tests 1. **POST /api/v1/federation/identity/verify**: - Verify identity with valid signature and token - Reject invalid signature - Reject expired token - Require authentication 2. **POST /api/v1/federation/identity/resolve**: - Resolve remote user to local user - Return 404 for non-existent mapping - Enforce workspace isolation - Require authentication 3. **GET /api/v1/federation/identity/me**: - Return user's federated identities - Return empty array if none - Require authentication 4. **POST /api/v1/federation/identity/link**: - Create new identity mapping - Validate OIDC token - Prevent duplicate mappings - Require authentication 5. **PATCH /api/v1/federation/identity/:id**: - Update mapping metadata - Enforce ownership - Require authentication 6. **DELETE /api/v1/federation/identity/:id**: - Revoke identity mapping - Enforce ownership - Require authentication ## Security Considerations - All identity verification requests must be signed by the originating instance - OIDC tokens must be validated before creating mappings - Identity operations enforce workspace isolation via RLS - All operations are logged via AuditService - Rate limiting should be added for public endpoints (future) - Consider MFA for identity linking operations (future)