Add complete SignalR infrastructure for real-time project collaboration and notifications with multi-tenant isolation and JWT authentication. Changes: - Created BaseHub with multi-tenant isolation and JWT authentication helpers - Created ProjectHub for real-time project collaboration (join/leave, typing indicators) - Created NotificationHub for user-level notifications - Implemented IRealtimeNotificationService for application layer integration - Configured SignalR in Program.cs with CORS and JWT query string support - Added SignalRTestController for connection testing - Documented hub endpoints, client events, and integration examples Features: - Multi-tenant isolation via automatic tenant group membership - JWT authentication (Bearer header + query string for WebSocket) - Hub endpoints: /hubs/project, /hubs/notification - Project-level events: IssueCreated, IssueUpdated, IssueStatusChanged, etc. - User-level notifications with tenant-wide broadcasting - Test endpoints for validation 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
10 KiB
SignalR Real-time Communication Implementation
Overview
This document describes the SignalR real-time communication infrastructure implemented for ColaFlow. The implementation provides real-time updates for project collaboration, issue tracking, and user notifications with multi-tenant isolation and JWT authentication.
Implementation Date
2025-11-04
Components Implemented
1. Hub Infrastructure
BaseHub (src/ColaFlow.API/Hubs/BaseHub.cs)
Base class for all SignalR hubs with:
- JWT Authentication: All hubs require authentication via
[Authorize]attribute - Multi-tenant Isolation: Automatically adds users to tenant-specific groups on connection
- User/Tenant Extraction: Helper methods to extract user ID and tenant ID from JWT claims
- Connection Lifecycle: Logging for connect/disconnect events
Key Features:
GetCurrentUserId(): Extracts user ID from JWT token (sub or user_id claim)GetCurrentTenantId(): Extracts tenant ID from JWT token (tenant_id claim)GetTenantGroupName(Guid tenantId): Returns standardized tenant group name- Automatic group membership on connection
- Error handling with connection abort on authentication failures
ProjectHub (src/ColaFlow.API/Hubs/ProjectHub.cs)
Hub for project-level real-time collaboration:
Methods:
JoinProject(Guid projectId): Join a project room to receive updatesLeaveProject(Guid projectId): Leave a project roomSendTypingIndicator(Guid projectId, Guid issueId, bool isTyping): Send typing indicators
Client Events:
UserJoinedProject: Notifies when a user joins a projectUserLeftProject: Notifies when a user leaves a projectTypingIndicator: Real-time typing indicators for issue editingProjectUpdated: General project updatesIssueCreated: New issue createdIssueUpdated: Issue updatedIssueDeleted: Issue deletedIssueStatusChanged: Issue status changed
NotificationHub (src/ColaFlow.API/Hubs/NotificationHub.cs)
Hub for user-level notifications:
Methods:
MarkAsRead(Guid notificationId): Mark a notification as read
Client Events:
Notification: General notificationsNotificationRead: Confirmation of read status
2. Realtime Notification Service
IRealtimeNotificationService (src/ColaFlow.API/Services/IRealtimeNotificationService.cs)
Service interface for sending real-time notifications from application layer.
Project-level Methods:
NotifyProjectUpdate(Guid tenantId, Guid projectId, object data)NotifyIssueCreated(Guid tenantId, Guid projectId, object issue)NotifyIssueUpdated(Guid tenantId, Guid projectId, object issue)NotifyIssueDeleted(Guid tenantId, Guid projectId, Guid issueId)NotifyIssueStatusChanged(Guid tenantId, Guid projectId, Guid issueId, string oldStatus, string newStatus)
User-level Methods:
NotifyUser(Guid userId, string message, string type = "info")NotifyUsersInTenant(Guid tenantId, string message, string type = "info")
RealtimeNotificationService (src/ColaFlow.API/Services/RealtimeNotificationService.cs)
Implementation of the notification service using IHubContext<T>.
3. Configuration
Program.cs Updates
SignalR Configuration:
builder.Services.AddSignalR(options =>
{
options.EnableDetailedErrors = builder.Environment.IsDevelopment();
options.ClientTimeoutInterval = TimeSpan.FromSeconds(60);
options.HandshakeTimeout = TimeSpan.FromSeconds(15);
options.KeepAliveInterval = TimeSpan.FromSeconds(15);
});
CORS Configuration (SignalR-compatible):
builder.Services.AddCors(options =>
{
options.AddPolicy("AllowFrontend", policy =>
{
policy.WithOrigins("http://localhost:3000", "https://localhost:3000")
.AllowAnyHeader()
.AllowAnyMethod()
.AllowCredentials(); // Required for SignalR
});
});
JWT Authentication for SignalR (Query String Support):
options.Events = new JwtBearerEvents
{
OnMessageReceived = context =>
{
var accessToken = context.Request.Query["access_token"];
var path = context.HttpContext.Request.Path;
if (!string.IsNullOrEmpty(accessToken) && path.StartsWithSegments("/hubs"))
{
context.Token = accessToken;
}
return Task.CompletedTask;
}
};
Hub Endpoints:
app.MapHub<ProjectHub>("/hubs/project");
app.MapHub<NotificationHub>("/hubs/notification");
Service Registration:
builder.Services.AddScoped<IRealtimeNotificationService, RealtimeNotificationService>();
4. Test Controller
SignalRTestController (src/ColaFlow.API/Controllers/SignalRTestController.cs)
Controller for testing SignalR functionality:
Endpoints:
POST /api/SignalRTest/test-user-notification: Send notification to current userPOST /api/SignalRTest/test-tenant-notification: Send notification to entire tenantPOST /api/SignalRTest/test-project-update: Send project update notificationPOST /api/SignalRTest/test-issue-status-change: Send issue status change notificationGET /api/SignalRTest/connection-info: Get connection information for debugging
SignalR Hub Endpoints
| Hub | Endpoint | Description |
|---|---|---|
| ProjectHub | /hubs/project |
Project-level real-time collaboration |
| NotificationHub | /hubs/notification |
User-level notifications |
Authentication
SignalR hubs use JWT authentication with two methods:
- Authorization Header: Standard
Bearer {token}in HTTP headers - Query String:
?access_token={token}for WebSocket upgrade requests
All hubs are protected with [Authorize] attribute and require valid JWT tokens.
Multi-Tenant Isolation
Users are automatically added to their tenant group (tenant-{tenantId}) on connection. This ensures:
- Notifications are only sent within tenant boundaries
- Cross-tenant data leakage is prevented
- Group-based broadcasting is efficient
Client Connection Example
JavaScript/TypeScript (SignalR Client)
import * as signalR from "@microsoft/signalr";
const connection = new signalR.HubConnectionBuilder()
.withUrl("https://localhost:5001/hubs/project", {
accessTokenFactory: () => getAccessToken() // Your JWT token
})
.withAutomaticReconnect()
.build();
// Listen for events
connection.on("IssueCreated", (issue) => {
console.log("New issue:", issue);
});
connection.on("IssueStatusChanged", (data) => {
console.log("Issue status changed:", data);
});
// Start connection
await connection.start();
// Join project
await connection.invoke("JoinProject", projectId);
// Send typing indicator
await connection.invoke("SendTypingIndicator", projectId, issueId, true);
Integration with Domain Events
To send SignalR notifications from application layer:
public class IssueCreatedEventHandler : INotificationHandler<IssueCreatedEvent>
{
private readonly IRealtimeNotificationService _realtimeNotification;
public async Task Handle(IssueCreatedEvent notification, CancellationToken cancellationToken)
{
await _realtimeNotification.NotifyIssueCreated(
notification.TenantId,
notification.ProjectId,
new
{
Id = notification.IssueId,
Title = notification.Title,
Status = notification.Status
}
);
}
}
Testing
Test Endpoints
-
Get Connection Info:
curl -X GET https://localhost:5001/api/SignalRTest/connection-info \ -H "Authorization: Bearer {your-jwt-token}" -
Test User Notification:
curl -X POST https://localhost:5001/api/SignalRTest/test-user-notification \ -H "Authorization: Bearer {your-jwt-token}" \ -H "Content-Type: application/json" \ -d "\"Test notification message\"" -
Test Tenant Notification:
curl -X POST https://localhost:5001/api/SignalRTest/test-tenant-notification \ -H "Authorization: Bearer {your-jwt-token}" \ -H "Content-Type: application/json" \ -d "\"Test tenant message\"" -
Test Project Update:
curl -X POST https://localhost:5001/api/SignalRTest/test-project-update \ -H "Authorization: Bearer {your-jwt-token}" \ -H "Content-Type: application/json" \ -d '{"projectId":"00000000-0000-0000-0000-000000000000","message":"Test update"}'
Build Status
✅ Build successful with no errors or warnings
cd colaflow-api
dotnet build src/ColaFlow.API/ColaFlow.API.csproj
Success Criteria Checklist
- SignalR infrastructure added (built-in .NET 9 SignalR)
- Created BaseHub, ProjectHub, NotificationHub
- Configured SignalR in Program.cs with CORS and JWT
- Implemented IRealtimeNotificationService
- Hub supports multi-tenant isolation (automatic tenant group membership)
- Hub supports JWT authentication (Bearer + query string)
- Created test controller (SignalRTestController)
- Compilation successful with no errors
Files Created/Modified
Created:
src/ColaFlow.API/Hubs/BaseHub.cssrc/ColaFlow.API/Hubs/ProjectHub.cssrc/ColaFlow.API/Hubs/NotificationHub.cssrc/ColaFlow.API/Services/IRealtimeNotificationService.cssrc/ColaFlow.API/Services/RealtimeNotificationService.cssrc/ColaFlow.API/Controllers/SignalRTestController.cs
Modified:
src/ColaFlow.API/Program.cs(SignalR configuration, CORS, JWT, hub endpoints)
Next Steps
- Frontend Integration: Implement SignalR client in Next.js frontend
- Domain Event Integration: Wire up notification service to domain events
- Permission Validation: Add authorization checks in ProjectHub.JoinProject()
- User Connection Mapping: Implement user-to-connection tracking for targeted notifications
- Scalability: Consider Redis backplane for multi-server deployments
- Monitoring: Add SignalR performance metrics and connection monitoring
Notes
- SignalR is built-in to .NET 9.0 ASP.NET Core, no separate NuGet package required
- CORS policy updated to include
AllowCredentials()for SignalR compatibility - JWT authentication supports both HTTP Authorization header and query string for WebSocket upgrade
- All hubs automatically enforce tenant isolation via BaseHub
- Notification service can be injected into any application service or event handler