Skip to content

Commit dc6aeb7

Browse files
committed
add benchmark for csrf
1 parent 42e7dba commit dc6aeb7

4 files changed

Lines changed: 83 additions & 20 deletions

File tree

build/trend-scenarios.yml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,10 @@ parameters:
9999
arguments: --scenario antiforgery-validation $(antiforgeryJobs) --property scenario=AntiforgeryTokenValidation
100100
- displayName: Antiforgery Token Generation
101101
arguments: --scenario antiforgery-generation $(antiforgeryJobs) --property scenario=AntiforgeryTokenGeneration
102+
- displayName: CSRF Accepted
103+
arguments: --scenario csrf-accepted $(antiforgeryJobs) --property scenario=CsrfAccepted
104+
- displayName: CSRF Rejected
105+
arguments: --scenario csrf-rejected $(antiforgeryJobs) --property scenario=CsrfRejected
102106

103107
# TLS
104108

scenarios/antiforgery.benchmarks.yml

Lines changed: 27 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ imports:
55
variables:
66
serverPort: 5000
77
serverScheme: http
8+
scenario: antiforgery
89

910
jobs:
1011
antiforgerybenchmarks:
@@ -13,7 +14,7 @@ jobs:
1314
branchOrCommit: main
1415
project: src/BenchmarksApps/Antiforgery/Antiforgery.csproj
1516
readyStateText: Application started.
16-
arguments: "--urls {{serverScheme}}://{{serverAddress}}:{{serverPort}}"
17+
arguments: "--urls {{serverScheme}}://{{serverAddress}}:{{serverPort}} --scenario {{scenario}}"
1718

1819
scenarios:
1920

@@ -45,4 +46,28 @@ scenarios:
4546
load:
4647
job: wrk
4748
variables:
48-
path: /noOp
49+
path: /noOp
50+
51+
csrf-accepted:
52+
application:
53+
job: antiforgerybenchmarks
54+
variables:
55+
scenario: csrf
56+
load:
57+
job: wrk
58+
variables:
59+
path: /csrf
60+
script: https://raw.githubusercontent.com/aspnet/Benchmarks/main/src/BenchmarksApps/Antiforgery/scripts/wrk-csrf.lua
61+
scriptArguments: same-origin
62+
63+
csrf-rejected:
64+
application:
65+
job: antiforgerybenchmarks
66+
variables:
67+
scenario: csrf
68+
load:
69+
job: wrk
70+
variables:
71+
path: /csrf
72+
script: https://raw.githubusercontent.com/aspnet/Benchmarks/main/src/BenchmarksApps/Antiforgery/scripts/wrk-csrf.lua
73+
scriptArguments: cross-site

src/BenchmarksApps/Antiforgery/Program.cs

Lines changed: 41 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -2,32 +2,55 @@
22

33
var builder = WebApplication.CreateBuilder(args);
44
builder.Logging.ClearProviders();
5-
builder.Services.AddAntiforgery(options => options.HeaderName = "XSRF-TOKEN");
5+
6+
// "csrf" exercises the auto-injected cross-origin (Sec-Fetch) CSRF protection in isolation,
7+
// so the token-based antiforgery services/middleware are left out to avoid overriding its verdict.
8+
var scenario = builder.Configuration["scenario"] ?? "antiforgery";
9+
var tokenAntiforgeryEnabled = !string.Equals(scenario, "csrf", StringComparison.OrdinalIgnoreCase);
10+
11+
if (tokenAntiforgeryEnabled)
12+
{
13+
builder.Services.AddAntiforgery(options => options.HeaderName = "XSRF-TOKEN");
14+
}
615

716
var app = builder.Build();
8-
app.UseAntiforgery();
17+
18+
if (tokenAntiforgeryEnabled)
19+
{
20+
app.UseAntiforgery();
21+
}
922

1023
app.MapGet("/", () => Results.Ok("hello world!"));
11-
app.MapGet("/noOp", (HttpContext ctx, IAntiforgery antiforgery) => Results.Ok());
1224

13-
// GET https://localhost:55471/auth
14-
app.MapGet("/auth", (HttpContext ctx, IAntiforgery antiforgery) =>
15-
{
16-
var token = antiforgery.GetAndStoreTokens(ctx);
17-
ctx.Response.Headers.Append("XSRF-TOKEN", token.RequestToken!);
18-
return Results.Ok();
19-
});
25+
// POST endpoint guarded only by the auto-injected cross-origin CSRF protection.
26+
// Sec-Fetch-Site: same-origin/none => 200; cross-site/same-site => 400.
27+
app.MapPost("/csrf", () => Results.Ok());
2028

21-
// POST https://localhost:55471/validateToken
22-
app.MapPost("/validateToken", async (HttpContext ctx, IAntiforgery antiforgery) =>
29+
// Token-based antiforgery endpoints. These depend on IAntiforgery, which is only
30+
// registered when the token-based antiforgery services are added above.
31+
if (tokenAntiforgeryEnabled)
2332
{
24-
// HttpContext is expected to have 2 headers:
25-
// 1) antiforgery token ("XSRF-TOKEN");
26-
// 2) cookie token ("Cookie") with value of `.AspNetCore.Antiforgery.<unique-sequence>=<cookie_header>`
33+
app.MapGet("/noOp", (HttpContext ctx, IAntiforgery antiforgery) => Results.Ok());
34+
35+
// GET https://localhost:55471/auth
36+
app.MapGet("/auth", (HttpContext ctx, IAntiforgery antiforgery) =>
37+
{
38+
var token = antiforgery.GetAndStoreTokens(ctx);
39+
ctx.Response.Headers.Append("XSRF-TOKEN", token.RequestToken!);
40+
return Results.Ok();
41+
});
42+
43+
// POST https://localhost:55471/validateToken
44+
app.MapPost("/validateToken", async (HttpContext ctx, IAntiforgery antiforgery) =>
45+
{
46+
// HttpContext is expected to have 2 headers:
47+
// 1) antiforgery token ("XSRF-TOKEN");
48+
// 2) cookie token ("Cookie") with value of `.AspNetCore.Antiforgery.<unique-sequence>=<cookie_header>`
2749

28-
await antiforgery.ValidateRequestAsync(ctx);
29-
return Results.Ok();
30-
});
50+
await antiforgery.ValidateRequestAsync(ctx);
51+
return Results.Ok();
52+
});
53+
}
3154

3255
await app.StartAsync();
3356
Console.WriteLine("Application started.");
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
-- The header value is taken from the first script argument (wrk ... -- <value>),
2+
-- e.g. "same-origin" (accepted) or "cross-site" (rejected). Defaults to same-origin.
3+
4+
wrk.method = "POST"
5+
6+
local secFetchSite = "same-origin"
7+
if arg and arg[1] then
8+
secFetchSite = arg[1]
9+
end
10+
11+
wrk.headers["Sec-Fetch-Site"] = secFetchSite

0 commit comments

Comments
 (0)