Real-time communication is a cornerstone of modern applications. ASP.NET Core provides two powerful frameworks for this purpose:
Because these technologies involve persistent connections and high-frequency data exchange, security is critical to prevent eavesdropping, impersonation, and denial of service.
This article explores practical security strategies for both gRPC and SignalR in ASP.NET Core.
1. Security Challenges in Real-Time Communication
Unauthorized Access: Clients connecting without proper authentication.
Data Leakage: Unencrypted messages intercepted over the network.
Message Tampering: Modified requests or injected payloads.
DoS Attacks: Malicious clients keep connections open or flood the server.
Multi-tenant Risks: Ensuring one client cannot access another client’s data.
2. Securing gRPC in ASP.NET Core
2.1. Enforce Transport Layer Security (TLS)
gRPC requires HTTP/2, which works best with TLS.
builder.WebHost.ConfigureKestrel(options =>
{
options.ListenAnyIP(5001, listenOptions =>
{
listenOptions.UseHttps("certificate.pfx", "certPassword");
});
});
All gRPC calls should be made over https:// to prevent eavesdropping.
2.2. Authentication with JWT / OAuth2
Use JWT bearer tokens for secure client authentication.
builder.Services.AddAuthentication("Bearer")
.AddJwtBearer("Bearer", options =>
{
options.Authority = "https://identity.example.com";
options.TokenValidationParameters = new()
{
ValidateAudience = false
};
});
builder.Services.AddAuthorization();
Apply to gRPC services:
[Authorize]
public class OrderService : Order.OrderBase
{
public override Task<OrderReply> GetOrder(OrderRequest request, ServerCallContext context)
{
// Authenticated user logic
}
}
2.3. Client-Side Token Injection
Clients must send tokens in metadata:
var headers = new Metadata
{
{ "Authorization", $"Bearer {token}" }
};
var response = await client.GetOrderAsync(new OrderRequest { Id = 1 }, headers);
2.4. Input Validation and Limits
builder.Services.AddGrpc(options =>
{
options.MaxReceiveMessageSize = 2 * 1024 * 1024; // 2 MB
options.MaxSendMessageSize = 2 * 1024 * 1024;
});
2.5. Mutual TLS (mTLS) [Optional]
For extra security in microservices, enforce client certificates:
listenOptions.UseHttps("server.pfx", "password", httpsOptions =>
{
httpsOptions.ClientCertificateMode = ClientCertificateMode.RequireCertificate;
});
3. Securing SignalR in ASP.NET Core
3.1. Use HTTPS for Transport
Always host SignalR hubs over TLS.
app.UseHttpsRedirection();
3.2. Authentication with JWT or Cookies
SignalR integrates seamlessly with ASP.NET Core Authentication.
Server configuration:
builder.Services.AddAuthentication("Bearer")
.AddJwtBearer("Bearer", options =>
{
options.Authority = "https://identity.example.com";
options.TokenValidationParameters = new()
{
ValidateAudience = false;
};
// Enable for WebSockets
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("/chathub"))
{
context.Token = accessToken;
}
return Task.CompletedTask;
}
};
});
Client connection:
const connection = new signalR.HubConnectionBuilder()
.withUrl("/chathub", { accessTokenFactory: () => token })
.build();
3.3. Authorization on Hub Methods
[Authorize(Roles = "Admin")]
public class ChatHub : Hub
{
public async Task SendMessage(string message)
{
await Clients.All.SendAsync("ReceiveMessage", Context.User?.Identity?.Name, message);
}
}
3.4. Protect Against Abuse
Example: throttling middleware for SignalR:
public override async Task OnConnectedAsync()
{
if (TooManyConnections(Context.ConnectionId))
{
Context.Abort();
}
await base.OnConnectedAsync();
}
3.5. Data Validation
Since SignalR uses JSON/MessagePack, validate all incoming data to prevent injection attacks.
3.6. Cross-Origin Security (CORS)
Allow only trusted domains:
builder.Services.AddCors(options =>
{
options.AddPolicy("SignalRCors", policy =>
{
policy.WithOrigins("https://trustedclient.com")
.AllowAnyHeader()
.AllowAnyMethod()
.AllowCredentials();
});
});
app.UseCors("SignalRCors");
4. Common Security Best Practices
Always use TLS for transport security.
Authenticate clients using JWT/OAuth2.
Use authorization attributes at the service/hub level.
Limit message size, rate, and connection count.
Validate all inputs to avoid injection.
Use centralized logging and monitoring (e.g., Application Insights, ELK).
5. Conclusion
Securing gRPC and SignalR in ASP.NET Core requires a layered approach:
Use TLS/mTLS for transport security.
Enforce JWT/OAuth2 authentication at the connection level.
Implement authorization policies for fine-grained access.
Apply limits, validation, and monitoring to detect and block malicious behavior.
By combining these patterns, developers can build secure, resilient, and real-time ASP.NET Core applications that protect both data and infrastructure.