mirror of
https://github.com/bitwarden/server.git
synced 2025-05-20 11:04:31 -05:00
rate limiting APIs
This commit is contained in:
parent
ac62d54a7b
commit
17f8d0f677
39
src/Api/Middleware/CustomIpRateLimitMiddleware.cs
Normal file
39
src/Api/Middleware/CustomIpRateLimitMiddleware.cs
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
using AspNetCoreRateLimit;
|
||||||
|
using Bit.Api.Models.Response;
|
||||||
|
using Microsoft.AspNetCore.Http;
|
||||||
|
using Microsoft.Extensions.Logging;
|
||||||
|
using Microsoft.Extensions.Options;
|
||||||
|
using Newtonsoft.Json;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace Bit.Api.Middleware
|
||||||
|
{
|
||||||
|
public class CustomIpRateLimitMiddleware : IpRateLimitMiddleware
|
||||||
|
{
|
||||||
|
private readonly IpRateLimitOptions _options;
|
||||||
|
|
||||||
|
public CustomIpRateLimitMiddleware(
|
||||||
|
RequestDelegate next,
|
||||||
|
IOptions<IpRateLimitOptions> options,
|
||||||
|
IRateLimitCounterStore counterStore,
|
||||||
|
IIpPolicyStore policyStore,
|
||||||
|
ILogger<IpRateLimitMiddleware> logger,
|
||||||
|
IIpAddressParser ipParser = null
|
||||||
|
) : base(next, options, counterStore, policyStore, logger, ipParser)
|
||||||
|
{
|
||||||
|
_options = options.Value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override Task ReturnQuotaExceededResponse(HttpContext httpContext, RateLimitRule rule, string retryAfter)
|
||||||
|
{
|
||||||
|
var message = string.IsNullOrWhiteSpace(_options.QuotaExceededMessage) ?
|
||||||
|
$"Slow down! Too many requests. Try again in {rule.Period}." : _options.QuotaExceededMessage;
|
||||||
|
httpContext.Response.Headers["Retry-After"] = retryAfter;
|
||||||
|
httpContext.Response.StatusCode = _options.HttpStatusCode;
|
||||||
|
|
||||||
|
httpContext.Response.ContentType = "application/json";
|
||||||
|
var errorModel = new ErrorResponseModel { Message = message };
|
||||||
|
return httpContext.Response.WriteAsync(JsonConvert.SerializeObject(errorModel));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -23,6 +23,8 @@ using System.Linq;
|
|||||||
using Microsoft.AspNetCore.Mvc.Formatters;
|
using Microsoft.AspNetCore.Mvc.Formatters;
|
||||||
using Microsoft.Net.Http.Headers;
|
using Microsoft.Net.Http.Headers;
|
||||||
using Newtonsoft.Json.Serialization;
|
using Newtonsoft.Json.Serialization;
|
||||||
|
using AspNetCoreRateLimit;
|
||||||
|
using Bit.Api.Middleware;
|
||||||
|
|
||||||
namespace Bit.Api
|
namespace Bit.Api
|
||||||
{
|
{
|
||||||
@ -61,6 +63,8 @@ namespace Bit.Api
|
|||||||
var globalSettings = new GlobalSettings();
|
var globalSettings = new GlobalSettings();
|
||||||
ConfigurationBinder.Bind(Configuration.GetSection("GlobalSettings"), globalSettings);
|
ConfigurationBinder.Bind(Configuration.GetSection("GlobalSettings"), globalSettings);
|
||||||
services.AddSingleton(s => globalSettings);
|
services.AddSingleton(s => globalSettings);
|
||||||
|
services.Configure<IpRateLimitOptions>(Configuration.GetSection("IpRateLimitOptions"));
|
||||||
|
services.Configure<IpRateLimitPolicies>(Configuration.GetSection("IpRateLimitPolicies"));
|
||||||
|
|
||||||
// Repositories
|
// Repositories
|
||||||
services.AddSingleton<IUserRepository, Repos.UserRepository>();
|
services.AddSingleton<IUserRepository, Repos.UserRepository>();
|
||||||
@ -70,6 +74,13 @@ namespace Bit.Api
|
|||||||
// Context
|
// Context
|
||||||
services.AddScoped<CurrentContext>();
|
services.AddScoped<CurrentContext>();
|
||||||
|
|
||||||
|
// Caching
|
||||||
|
services.AddMemoryCache();
|
||||||
|
|
||||||
|
// Rate limiting
|
||||||
|
services.AddSingleton<IIpPolicyStore, MemoryCacheIpPolicyStore>();
|
||||||
|
services.AddSingleton<IRateLimitCounterStore, MemoryCacheRateLimitCounterStore>();
|
||||||
|
|
||||||
// Identity
|
// Identity
|
||||||
services.AddTransient<ILookupNormalizer, LowerInvariantLookupNormalizer>();
|
services.AddTransient<ILookupNormalizer, LowerInvariantLookupNormalizer>();
|
||||||
services.AddJwtBearerIdentity(options =>
|
services.AddJwtBearerIdentity(options =>
|
||||||
@ -176,6 +187,10 @@ namespace Bit.Api
|
|||||||
globalSettings.Loggr.ApiKey);
|
globalSettings.Loggr.ApiKey);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Rate limiting
|
||||||
|
app.UseMiddleware<CustomIpRateLimitMiddleware>();
|
||||||
|
|
||||||
|
// Insights
|
||||||
app.UseApplicationInsightsRequestTelemetry();
|
app.UseApplicationInsightsRequestTelemetry();
|
||||||
app.UseApplicationInsightsExceptionTelemetry();
|
app.UseApplicationInsightsExceptionTelemetry();
|
||||||
|
|
||||||
|
@ -18,8 +18,10 @@
|
|||||||
"Microsoft.AspNetCore.Diagnostics": "1.0.0",
|
"Microsoft.AspNetCore.Diagnostics": "1.0.0",
|
||||||
"Microsoft.Extensions.Configuration.EnvironmentVariables": "1.0.0",
|
"Microsoft.Extensions.Configuration.EnvironmentVariables": "1.0.0",
|
||||||
"Microsoft.Extensions.Configuration.Binder": "1.0.0",
|
"Microsoft.Extensions.Configuration.Binder": "1.0.0",
|
||||||
|
"Microsoft.Extensions.Options.ConfigurationExtensions": "1.0.0",
|
||||||
"Loggr.Extensions.Logging": "1.0.0",
|
"Loggr.Extensions.Logging": "1.0.0",
|
||||||
"Microsoft.ApplicationInsights.AspNetCore": "1.0.0"
|
"Microsoft.ApplicationInsights.AspNetCore": "1.0.0",
|
||||||
|
"AspNetCoreRateLimit": "1.0.2"
|
||||||
},
|
},
|
||||||
|
|
||||||
"tools": {
|
"tools": {
|
||||||
|
@ -24,5 +24,60 @@
|
|||||||
"gcmApiKey": "SECRET",
|
"gcmApiKey": "SECRET",
|
||||||
"gcmAppPackageName": "com.x8bit.bitwarden"
|
"gcmAppPackageName": "com.x8bit.bitwarden"
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"IpRateLimitOptions": {
|
||||||
|
"EnableEndpointRateLimiting": true,
|
||||||
|
"StackBlockedRequests": false,
|
||||||
|
"RealIpHeader": "X-Forwarded-For",
|
||||||
|
"ClientIdHeader": "X-ClientId",
|
||||||
|
"HttpStatusCode": 429,
|
||||||
|
"IpWhitelist": [],
|
||||||
|
"EndpointWhitelist": [],
|
||||||
|
"ClientWhitelist": [],
|
||||||
|
"GeneralRules": [
|
||||||
|
{
|
||||||
|
"Endpoint": "post:/auth/token",
|
||||||
|
"Period": "1m",
|
||||||
|
"Limit": 10
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Endpoint": "post:/auth/token/two-factor",
|
||||||
|
"Period": "1m",
|
||||||
|
"Limit": 5
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Endpoint": "post:/accounts/register",
|
||||||
|
"Period": "1m",
|
||||||
|
"Limit": 2
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Endpoint": "post:/account/password-hint",
|
||||||
|
"Period": "1m",
|
||||||
|
"Limit": 2
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Endpoint": "post:/account/email-token",
|
||||||
|
"Period": "1m",
|
||||||
|
"Limit": 2
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Endpoint": "post:/account/email",
|
||||||
|
"Period": "1m",
|
||||||
|
"Limit": 5
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Endpoint": "put:/account/email",
|
||||||
|
"Period": "1m",
|
||||||
|
"Limit": 5
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Endpoint": "get:/alive",
|
||||||
|
"Period": "1m",
|
||||||
|
"Limit": 5
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"IpRateLimitPolicies": {
|
||||||
|
"IpRules": []
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user