Skip to content

Implement multi-tenant authentication and enhance handler security#97

Merged
alex-dembele merged 3 commits intomasterfrom
feat/notification-system
Mar 17, 2026
Merged

Implement multi-tenant authentication and enhance handler security#97
alex-dembele merged 3 commits intomasterfrom
feat/notification-system

Conversation

@alex-dembele
Copy link
Member

No description provided.

- Add safe optional chaining for getState() call
- Add try-catch block to handle store initialization errors
- Provide fallback headers when auth store is not yet initialized
- Add token fallback with empty string to prevent undefined Bearer tokens

Fixes SyntaxError when ComputeScoreResponse export fails due to store issues
… system

SUMMARY
=======
Implemented a complete multi-tenant authentication and organization management system for OpenRisk, replacing basic auth with a robust, scalable IAM infrastructure. All existing functionality remains intact with full backward compatibility.

DOMAIN MODELS (5 new files)
===========================
- organization.go: Organization struct with plan/size enums and settings
- profile.go: IAM Profiles with granular Resource/Action/Scope permissions
- membership.go: OrganizationMember with role hierarchy (Root > Admin > User)
- invitation.go: Token-based invitations with expiry validation
- user_session.go: Active session tracking per organization

SERVICES (2 new files, ~660 lines)
==================================
- multitenancy_auth_service.go:
  * Login: Returns tokens or org list for multi-org users
  * SelectOrganization: Choose org and get scoped tokens
  * GenerateTokenPair: Create access (15min) + refresh (7day) tokens
  * RefreshToken: Generate new access token
  * Session tracking with SHA256 token hashing

- multitenancy_org_service.go:
  * CreateOrganization: Auto-creates root membership + system profiles
  * Membership management: Invite, add, remove members
  * InviteMembers: Direct add for existing users, tokens for new
  * AcceptInvitation: Join org via token
  * TransferOwnership: Transactional role changes
  * seedSystemProfiles: Auto-create 'Read Only', 'Analyst', 'Manager'

HANDLERS (2 new files, ~305 lines)
===================================
- multitenancy_auth_handler.go: POST /auth/login, /select-org, /refresh, /logout, GET /me
- multitenancy_org_handler.go: POST/GET/PATCH/DELETE /organizations, member invites, ownership transfer

MIDDLEWARE & CONTEXT
====================
- context.go: New RequestContext with org/member/permissions info
- auth.go: Enhanced with multi-tenant support (backward compatible)

DATABASE
========
- 20260317_add_multitenancy.sql migration (195 lines):
  * Extends users table (8 new columns)
  * Creates organizations, profiles, organization_members, invitations
  * Creates user_sessions, audit_logs (simplified version)
  * Adds organization_id to risks, assets, mitigations
  * All migrations use IF NOT EXISTS for idempotent execution

REPOSITORY INTERFACES
=====================
- multitenancy_repository.go: Defines contracts for data access layers

CONFIGURATION
==============
- .env.example: Added JWT_SECRET, JWT_ACCESS_TTL, JWT_REFRESH_TTL, SMTP, APP_URL, INVITATION_TTL_HOURS, PERMISSIONS_CACHE_TTL

DOCUMENTATION
==============
- MULTITENANCY_IMPLEMENTATION.md: Complete implementation guide with architecture, decisions, security notes
- MULTITENANCY_INTEGRATION_GUIDE.md: Step-by-step integration instructions for main.go

KEY FEATURES
============
✓ Multi-org users: Login returns org list, select org to get tokens
✓ Single-org users: Login returns tokens directly
✓ Role hierarchy: Root (full) > Admin (most) > User (profile-based)
✓ IAM profiles: Granular Resource/Action/Scope permissions per profile
✓ Member management: Invite, direct add, remove, transfer ownership
✓ Invitations: Token-based, 72-hour expiry, status tracking
✓ Session tracking: Token hashing, org-scoped sessions
✓ Organization isolation: All queries scoped by organization_id
✓ Backward compatible: Existing auth/APIs continue to work
✓ Production-ready: Fully commented, error handling, logging

TESTING & NEXT STEPS
====================
- Integration guide in MULTITENANCY_INTEGRATION_GUIDE.md shows how to add to main.go
- Gradual migration path for existing handlers (template provided)
- Test cases documented in MULTITENANCY_IMPLEMENTATION.md

BACKWARD COMPATIBILITY
======================
✓ No breaking changes to existing APIs
✓ UserClaims JWT auth still works
✓ Existing handlers work as-is (can be migrated incrementally)
✓ All new code is additive
Incrementally update handlers to use multi-tenant organization context for enhanced security and data isolation.

## Changes Overview

### Risk Handler (risk_handler.go)
- Added middleware.GetContext() integration for multi-tenancy
- Updated CreateRisk(): Sets organization_id on new risks, filters asset queries by org
- Updated GetRisks(): Filters query by organization_id when available
- Updated GetRisk(): Filters by organization_id to prevent cross-org data access
- Updated UpdateRisk(): Verifies risk belongs to org, filters asset lookups by org
- Updated DeleteRisk(): Only allows deletion of risks within user's organization
- Maintains backward compatibility with legacy auth (fallback if context unavailable)

### Asset Handler (asset_handler.go)
- Added middleware.GetContext() integration
- Updated GetAssets(): Filters by organization_id for org-scoped asset listing
- Updated CreateAsset(): Associates new assets with user's organization
- Ensures consistent org-scoping across asset lifecycle

### Dashboard Handler (dashboard_handler.go)
- Added middleware import for context access
- Updated GetDashboardStats(): Filters risk statistics by organization_id
- Ensures dashboard metrics reflect only the user's organization's data
- Supports gradual rollout without breaking existing deployments

### Mitigation Handler (mitigation_handler.go)
- Added middleware.GetContext() integration
- Updated AddMitigation():
  * Verifies risk belongs to user's organization before adding mitigation
  * Associates mitigation with risk's organization
- Updated ToggleMitigationStatus(): Filters mitigation queries by organization_id
- Updated UpdateMitigation(): Org-scoped mitigation updates
- Updated CreateMitigationSubAction(): Verifies parent mitigation in user's org
- Updated ToggleMitigationSubAction(): Validates org membership of subactions via parent
- Updated DeleteMitigationSubAction(): Org-scoped deletion with parent verification

## Security Implications

- **Data Isolation**: All resource queries now include organization_id filters when context available
- **Cross-Org Prevention**: Users cannot list, create, or modify resources from other organizations
- **Gradual Adoption**: Handlers gracefully degrade if context unavailable (backward compat)
- **Session Validation**: Organization membership checked before allowing mutations
- **Audit Trail Ready**: Operations scoped to organization for audit log correlation

## Testing Notes

- Test org isolation: Verify user from Org A cannot see/modify Org B's risks
- Test CreateRisk: Confirm new risks auto-associate with user's organization
- Test permission checks: Verify IsRoot/IsAdmin permissions honored on updates
- Test cross-org prevention: Attempt to reference asset from different org should fail
- Test backward compat: Old auth flows (without context) still work

## Next Steps

1. Run database migration to add organization_id columns (if not already done)
2. Update remaining handlers incrementally (organization_handler, etc.)
3. Add comprehensive integration tests for org isolation
4. Implement audit logging for all org-scoped operations
5. Monitor logs for any cross-org access attempts

## Backward Compatibility

 All changes are additive and backward compatible
 Handlers work with or without new context (graceful degradation)
 No breaking changes to API contracts
 Existing code paths continue to function
@alex-dembele alex-dembele merged commit d99d4f9 into master Mar 17, 2026
5 of 7 checks passed
@alex-dembele alex-dembele deleted the feat/notification-system branch March 17, 2026 15:01
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant