5.8 KiB
SECURITY FIX: Cross-Tenant Access Validation
Executive Summary
Status: IMPLEMENTED ✓ Priority: CRITICAL Date: 2025-11-03 Modified Files: 1 Build Status: SUCCESS (0 warnings, 0 errors)
Security Vulnerability
Issue Identified
During Day 6 integration testing, a critical security gap was discovered in the Role Management API (TenantUsersController):
Vulnerability: Users from Tenant A could access and potentially manage Tenant B's users and roles by manipulating the tenantId route parameter.
Impact:
- Unauthorized access to other tenants' user lists
- Potential unauthorized role assignments across tenants
- Breach of multi-tenant data isolation principles
Severity: HIGH - Violates fundamental security principle of tenant isolation
Implementation
Modified File
src/ColaFlow.API/Controllers/TenantUsersController.cs
Endpoints Fixed
| Endpoint | Method | Authorization Policy | Validation Added |
|---|---|---|---|
/api/tenants/{tenantId}/users |
GET | RequireTenantAdmin | ✓ Yes |
/api/tenants/{tenantId}/users/{userId}/role |
POST | RequireTenantOwner | ✓ Yes |
/api/tenants/{tenantId}/users/{userId} |
DELETE | RequireTenantOwner | ✓ Yes |
/api/tenants/../roles |
GET | RequireTenantAdmin | N/A (Static data) |
Validation Logic
Each protected endpoint now includes:
// SECURITY: Validate user belongs to target tenant
var userTenantIdClaim = User.FindFirst("tenant_id")?.Value;
if (userTenantIdClaim == null)
return Unauthorized(new { error = "Tenant information not found in token" });
var userTenantId = Guid.Parse(userTenantIdClaim);
if (userTenantId != tenantId)
return StatusCode(403, new { error = "Access denied: You can only manage users in your own tenant" });
Security Flow
- Extract JWT Claim: Read
tenant_idfrom authenticated user's JWT token - Claim Validation: Return 401 Unauthorized if
tenant_idclaim is missing - Tenant Matching: Compare user's tenant ID with route parameter
tenantId - Access Control: Return 403 Forbidden if tenant IDs don't match
- Proceed: Continue to business logic only if validation passes
Expected Behavior After Fix
Scenario 1: Same Tenant Access (Authorized)
User: Tenant A Admin (tenant_id = "aaaa-1111")
Request: GET /api/tenants/aaaa-1111/users
Result: 200 OK + User list
Scenario 2: Cross-Tenant Access (Blocked)
User: Tenant A Admin (tenant_id = "aaaa-1111")
Request: GET /api/tenants/bbbb-2222/users
Result: 403 Forbidden + Error message
Scenario 3: Missing Tenant Claim (Invalid Token)
User: Token without tenant_id claim
Request: GET /api/tenants/aaaa-1111/users
Result: 401 Unauthorized + Error message
Verification
Build Status
Build succeeded.
0 Warning(s)
0 Error(s)
Time Elapsed 00:00:02.24
Code Quality
- ✓ Consistent validation pattern across all endpoints
- ✓ Clear security comments explaining purpose
- ✓ Proper HTTP status codes (401 vs 403)
- ✓ Descriptive error messages
- ✓ No code duplication (same pattern repeated)
Technical Details
JWT Claim Structure
The tenant_id claim is added by JwtService.GenerateToken():
new("tenant_id", tenant.Id.ToString())
Location: src/Modules/Identity/ColaFlow.Modules.Identity.Infrastructure/Services/JwtService.cs (Line 34)
Authorization Policies (Unchanged)
Existing policies remain in place:
RequireTenantOwner- Checks for TenantOwner roleRequireTenantAdmin- Checks for TenantAdmin or TenantOwner role
Important: These policies validate roles, while the new validation checks tenant membership.
Why GetAvailableRoles Doesn't Need Validation
The /api/tenants/../roles endpoint returns static role definitions (TenantOwner, TenantAdmin, etc.) and doesn't access tenant-specific data. The existing RequireTenantAdmin policy is sufficient.
Security Best Practices Followed
- Defense in Depth: Validation at API layer before business logic
- Fail Securely: Return 403 Forbidden on mismatch (don't reveal if tenant exists)
- Clear Error Messages: Help legitimate users understand authorization failures
- Consistent Implementation: Same pattern across all endpoints
- Minimal Changes: API-layer validation only, no changes to command handlers or repositories
Remaining Work
Testing Recommendations
- Unit Tests: Add tests for tenant validation logic
- Integration Tests: Update
RoleManagementTests.csto verify cross-tenant blocking - Security Testing: Penetration test with cross-tenant attack scenarios
Future Enhancements
- Centralized Validation: Consider extracting to an action filter or middleware
- Audit Logging: Log all 403 responses for security monitoring
- Rate Limiting: Add rate limiting on 403 responses to prevent tenant enumeration
References
- Original Report:
DAY6-TEST-REPORT.md- Section "Cross-Tenant Access Validation" - JWT Service:
src/Modules/Identity/ColaFlow.Modules.Identity.Infrastructure/Services/JwtService.cs - Modified Controller:
src/ColaFlow.API/Controllers/TenantUsersController.cs - Authorization Policies:
src/ColaFlow.API/Program.cs(Lines configuring authorization)
Sign-Off
Implemented By: Backend Agent (Claude Code) Reviewed By: Pending code review Status: Ready for integration testing Next Steps:
- User to commit the staged changes (1Password SSH signing required)
- Add integration tests to verify cross-tenant blocking
- Deploy to staging environment for security testing
Note: The implementation is complete and builds successfully. The file is staged for commit but cannot be committed automatically due to 1Password SSH signing configuration requiring user interaction.