# Issue #86: [FED-003] Authentik OIDC Integration

## Objective

Integrate Authentik OIDC authentication with the federation system to enable:

- Federated authentication flows using Authentik as the identity provider
- User identity mapping across federated instances
- Token validation and verification for federated requests
- Secure API endpoints for federated authentication

This builds on issues #84 (Instance Identity Model) and #85 (CONNECT/DISCONNECT Protocol).

## Context

### Existing Infrastructure

From issue #84:

- Instance model with keypair for signing
- FederationConnection model for managing connections
- FederationService for instance identity management
- CryptoService for encryption/decryption

From issue #85:

- SignatureService for request signing/verification
- ConnectionService for connection lifecycle management
- Connection handshake protocol with status management

### Current Authentication Setup

The project uses BetterAuth with Authentik OIDC provider:

- `/apps/api/src/auth/auth.config.ts` - BetterAuth configuration with genericOAuth plugin
- `/apps/api/src/auth/auth.service.ts` - Auth service with session verification
- Environment variables: OIDC_ISSUER, OIDC_CLIENT_ID, OIDC_CLIENT_SECRET, OIDC_REDIRECT_URI

## Requirements

Based on federation architecture and existing code patterns:

1. **Federation-Specific OIDC Provider**: Create a dedicated OIDC provider configuration for federation that's separate from regular user authentication

2. **Cross-Instance Identity Linking**: Map users authenticated via OIDC to their identity on federated instances

3. **Token Validation for Federation**: Verify OIDC tokens in federated API requests

4. **Federated Authentication Endpoints**: API endpoints for initiating and completing federated authentication flows

5. **Security**: Ensure proper token validation, signature verification, and workspace isolation

## Approach

### 1. Create Federation OIDC Types

Create `/apps/api/src/federation/types/oidc.types.ts`:

```typescript
interface FederatedOIDCConfig {
  issuer: string;
  clientId: string;
  clientSecret: string;
  redirectUri: string;
  scopes: string[];
}

interface FederatedTokenValidation {
  valid: boolean;
  userId?: string;
  instanceId?: string;
  workspaceId?: string;
  error?: string;
}

interface FederatedIdentity {
  localUserId: string;
  remoteUserId: string;
  remoteInstanceId: string;
  oidcSubject: string;
  email: string;
  metadata: Record<string, unknown>;
}
```

### 2. Create OIDC Service for Federation

Create `/apps/api/src/federation/oidc.service.ts`:

- `configureFederatedProvider(instanceId, config)` - Configure OIDC for remote instance
- `validateFederatedToken(token)` - Validate OIDC token from federated request
- `linkFederatedIdentity(localUserId, remoteData)` - Link local user to remote identity
- `getFederatedIdentity(localUserId, remoteInstanceId)` - Retrieve identity mapping
- `revokeFederatedIdentity(localUserId, remoteInstanceId)` - Remove identity link

### 3. Extend Prisma Schema

Add model for federated identity mapping:

```prisma
model FederatedIdentity {
  id               String   @id @default(uuid()) @db.Uuid
  localUserId      String   @map("local_user_id") @db.Uuid
  remoteUserId     String   @map("remote_user_id")
  remoteInstanceId String   @map("remote_instance_id")
  oidcSubject      String   @map("oidc_subject")
  email            String
  metadata         Json     @default("{}")
  createdAt        DateTime @default(now()) @map("created_at") @db.Timestamptz
  updatedAt        DateTime @updatedAt @map("updated_at") @db.Timestamptz

  user User @relation(fields: [localUserId], references: [id], onDelete: Cascade)

  @@unique([localUserId, remoteInstanceId])
  @@index([localUserId])
  @@index([remoteInstanceId])
  @@index([oidcSubject])
  @@map("federated_identities")
}
```

### 4. Add Federation Auth Endpoints

Extend `FederationController` with:

- `POST /api/v1/federation/auth/initiate` - Start federated auth flow
- `GET /api/v1/federation/auth/callback` - Handle OIDC callback
- `POST /api/v1/federation/auth/validate` - Validate federated token
- `GET /api/v1/federation/auth/identities` - List user's federated identities
- `POST /api/v1/federation/auth/link` - Link identity to remote instance
- `DELETE /api/v1/federation/auth/identities/:id` - Revoke federated identity

### 5. Update Connection Service

Enhance `ConnectionService` to handle OIDC-based authentication:

- Store OIDC configuration in connection metadata
- Validate OIDC setup when accepting connections
- Provide OIDC discovery endpoints to remote instances

### 6. Security Considerations

- OIDC tokens must be validated using the issuer's public keys
- Federated requests must include both OIDC token AND instance signature
- Identity mapping must enforce workspace isolation
- Token expiration must be respected
- PKCE flow should be used for public clients
- Refresh tokens should be stored securely (encrypted)

### 7. Testing Strategy

**Unit Tests** (TDD approach):

- OIDCService.validateFederatedToken() validates tokens correctly
- OIDCService.validateFederatedToken() rejects invalid tokens
- OIDCService.linkFederatedIdentity() creates identity mapping
- OIDCService.getFederatedIdentity() retrieves correct mapping
- OIDCService.revokeFederatedIdentity() removes mapping
- Workspace isolation for identity mappings

**Integration Tests**:

- POST /auth/initiate starts OIDC flow with correct params
- GET /auth/callback handles OIDC response and creates identity
- POST /auth/validate validates tokens from federated instances
- GET /auth/identities returns user's federated identities
- Federated requests with valid tokens are authenticated
- Invalid or expired tokens are rejected

## Progress

- [x] Create scratchpad
- [x] Add FederatedIdentity model to Prisma schema
- [x] Generate migration
- [x] Create OIDC types
- [x] Write tests for OIDCService (14 tests)
- [x] Implement OIDCService
- [x] Write tests for federation auth endpoints (10 tests)
- [x] Implement auth endpoints in FederationAuthController
- [x] Update FederationModule
- [x] Update audit service with new logging methods
- [x] Verify all tests pass (24 OIDC tests, 94 total federation tests)
- [x] Verify type checking passes (no errors)
- [x] Verify test coverage (OIDCService: 79%, Controller: 100%)
- [x] Commit changes

## Design Decisions

1. **Separate OIDC Configuration**: Federation OIDC is separate from regular user auth to allow different IdPs per federated instance

2. **Identity Mapping Table**: Explicit FederatedIdentity table rather than storing in connection metadata for better querying and RLS

3. **Dual Authentication**: Federated requests require both OIDC token (user identity) AND instance signature (instance identity)

4. **Workspace Scoping**: Identity mappings are user-scoped but authenticated within workspace context

5. **Token Storage**: Store minimal token data; rely on OIDC provider for validation

## Notes

- Need to handle OIDC discovery for dynamic configuration
- Should support multiple OIDC providers per instance (one per federated connection)
- Consider token caching to reduce validation overhead
- May need webhook for token revocation notifications
- Future: Support for custom claims mapping
