Skip to content

Commit 748b368

Browse files
authored
Handle auth schemes in cookie names (#25279)
* Handle auth schemes in cookie names #25266 * With unicode
2 parents 97280fe + f33937f commit 748b368

File tree

10 files changed

+115
-83
lines changed

10 files changed

+115
-83
lines changed

src/Security/Authentication/Cookies/src/PostConfigureCookieAuthenticationOptions.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ public void PostConfigure(string name, CookieAuthenticationOptions options)
3030

3131
if (string.IsNullOrEmpty(options.Cookie.Name))
3232
{
33-
options.Cookie.Name = CookieAuthenticationDefaults.CookiePrefix + name;
33+
options.Cookie.Name = CookieAuthenticationDefaults.CookiePrefix + Uri.EscapeDataString(name);
3434
}
3535
if (options.TicketDataFormat == null)
3636
{

src/Security/Authentication/Core/src/RemoteAuthenticationHandler.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -200,7 +200,7 @@ protected virtual void GenerateCorrelationId(AuthenticationProperties properties
200200

201201
properties.Items[CorrelationProperty] = correlationId;
202202

203-
var cookieName = Options.CorrelationCookie.Name + Scheme.Name + "." + correlationId;
203+
var cookieName = Options.CorrelationCookie.Name + correlationId;
204204

205205
Response.Cookies.Append(cookieName, CorrelationMarker, cookieOptions);
206206
}
@@ -220,7 +220,7 @@ protected virtual bool ValidateCorrelationId(AuthenticationProperties properties
220220

221221
properties.Items.Remove(CorrelationProperty);
222222

223-
var cookieName = Options.CorrelationCookie.Name + Scheme.Name + "." + correlationId;
223+
var cookieName = Options.CorrelationCookie.Name + correlationId;
224224

225225
var correlationCookie = Request.Cookies[cookieName];
226226
if (string.IsNullOrEmpty(correlationCookie))

src/Security/Authentication/test/CookieTests.cs

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -151,6 +151,38 @@ public async Task SignInCausesDefaultCookieToBeCreated()
151151
Assert.Equal("no-cache", transaction.Response.Headers.Pragma.ToString());
152152
}
153153

154+
[Fact]
155+
public async Task CustomAuthSchemeEncodesCookieName()
156+
{
157+
var schemeName = "With spaces and 界";
158+
using var host = await CreateHostWithServices(s => s.AddAuthentication(schemeName).AddCookie(schemeName, o =>
159+
{
160+
o.LoginPath = new PathString("/login");
161+
}), context =>
162+
{
163+
var user = new ClaimsIdentity(new GenericIdentity("Alice", "Cookies"));
164+
user.AddClaim(new Claim("marker", "true"));
165+
return context.SignInAsync(schemeName,
166+
new ClaimsPrincipal(user),
167+
new AuthenticationProperties());
168+
});
169+
170+
using var server = host.GetTestServer();
171+
var transaction = await SendAsync(server, "http://example.com/testpath");
172+
173+
var setCookie = transaction.SetCookie;
174+
Assert.StartsWith(".AspNetCore.With%20spaces%20and%20%E7%95%8C=", setCookie);
175+
Assert.Contains("; path=/", setCookie);
176+
Assert.Contains("; httponly", setCookie);
177+
Assert.Contains("; samesite=", setCookie);
178+
Assert.DoesNotContain("; expires=", setCookie);
179+
Assert.DoesNotContain("; domain=", setCookie);
180+
Assert.DoesNotContain("; secure", setCookie);
181+
Assert.True(transaction.Response.Headers.CacheControl.NoCache);
182+
Assert.True(transaction.Response.Headers.CacheControl.NoStore);
183+
Assert.Equal("no-cache", transaction.Response.Headers.Pragma.ToString());
184+
}
185+
154186
[Fact]
155187
public void SettingCookieExpirationOptionThrows()
156188
{

src/Security/Authentication/test/FacebookTests.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -363,7 +363,7 @@ public async Task CustomUserInfoEndpointHasValidGraphQuery()
363363
using var server = host.GetTestServer();
364364
var transaction = await server.SendAsync(
365365
"https://example.com/signin-facebook?code=TestCode&state=" + UrlEncoder.Default.Encode(state),
366-
$".AspNetCore.Correlation.Facebook.{correlationValue}=N");
366+
$".AspNetCore.Correlation.{correlationValue}=N");
367367
Assert.Equal(HttpStatusCode.Redirect, transaction.Response.StatusCode);
368368
Assert.Equal("/me", transaction.Response.Headers.GetValues("Location").First());
369369
Assert.Equal(1, finalUserInfoEndpoint.Count(c => c == '?'));

src/Security/Authentication/test/GoogleTests.cs

Lines changed: 22 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -133,7 +133,7 @@ public async Task ChallengeWillSetCorrelationCookie()
133133
});
134134
using var server = host.GetTestServer();
135135
var transaction = await server.SendAsync("https://example.com/challenge");
136-
Assert.Contains(transaction.SetCookie, cookie => cookie.StartsWith(".AspNetCore.Correlation.Google."));
136+
Assert.Contains(transaction.SetCookie, cookie => cookie.StartsWith(".AspNetCore.Correlation."));
137137
}
138138

139139
[Fact]
@@ -392,7 +392,7 @@ public async Task ReplyPathWithAccessDeniedErrorFails(bool redirect)
392392
});
393393
using var server = host.GetTestServer();
394394
var sendTask = server.SendAsync("https://example.com/signin-google?error=access_denied&error_description=SoBad&error_uri=foobar&state=protected_state",
395-
".AspNetCore.Correlation.Google.correlationId=N");
395+
".AspNetCore.Correlation.correlationId=N");
396396
if (redirect)
397397
{
398398
var transaction = await sendTask;
@@ -431,7 +431,7 @@ public async Task ReplyPathWithAccessDeniedError_AllowsCustomizingPath()
431431
});
432432
using var server = host.GetTestServer();
433433
var transaction = await server.SendAsync("https://example.com/signin-google?error=access_denied&error_description=SoBad&error_uri=foobar&state=protected_state",
434-
".AspNetCore.Correlation.Google.correlationId=N");
434+
".AspNetCore.Correlation.correlationId=N");
435435
Assert.Equal(HttpStatusCode.Redirect, transaction.Response.StatusCode);
436436
Assert.Equal("https://example.com/custom-denied-page?rurl=http%3A%2F%2Fwww.google.com%2F", transaction.Response.Headers.GetValues("Location").First());
437437
}
@@ -474,7 +474,7 @@ public async Task ReplyPathWithAccessDeniedErrorAndNoAccessDeniedPath_FallsBackT
474474
});
475475
using var server = host.GetTestServer();
476476
var transaction = await server.SendAsync("https://example.com/signin-google?error=access_denied&error_description=whyitfailed&error_uri=https://example.com/fail&state=protected_state",
477-
".AspNetCore.Correlation.Google.correlationId=N");
477+
".AspNetCore.Correlation.correlationId=N");
478478
Assert.Equal(HttpStatusCode.Redirect, transaction.Response.StatusCode);
479479
Assert.StartsWith("/error?FailureMessage=", transaction.Response.Headers.GetValues("Location").First());
480480
Assert.True(accessDeniedCalled);
@@ -510,7 +510,7 @@ public async Task ReplyPathWithErrorFails(bool redirect)
510510
});
511511
using var server = host.GetTestServer();
512512
var sendTask = server.SendAsync("https://example.com/signin-google?error=itfailed&error_description=whyitfailed&error_uri=https://example.com/fail&state=protected_state",
513-
".AspNetCore.Correlation.Google.correlationId=N");
513+
".AspNetCore.Correlation.correlationId=N");
514514
if (redirect)
515515
{
516516
var transaction = await sendTask;
@@ -552,11 +552,11 @@ public async Task ReplyPathWillAuthenticateValidAuthorizeCodeAndState(string cla
552552
using var server = host.GetTestServer();
553553
var transaction = await server.SendAsync(
554554
"https://example.com/signin-google?code=TestCode&state=" + UrlEncoder.Default.Encode(state),
555-
$".AspNetCore.Correlation.Google.{correlationValue}=N");
555+
$".AspNetCore.Correlation.{correlationValue}=N");
556556
Assert.Equal(HttpStatusCode.Redirect, transaction.Response.StatusCode);
557557
Assert.Equal("/me", transaction.Response.Headers.GetValues("Location").First());
558558
Assert.Equal(2, transaction.SetCookie.Count);
559-
Assert.Contains($".AspNetCore.Correlation.Google.{correlationValue}", transaction.SetCookie[0]);
559+
Assert.Contains($".AspNetCore.Correlation.{correlationValue}", transaction.SetCookie[0]);
560560
Assert.Contains(".AspNetCore." + TestExtensions.CookieAuthenticationScheme, transaction.SetCookie[1]);
561561

562562
var authCookie = transaction.AuthenticationCookieValue;
@@ -619,7 +619,7 @@ public async Task ReplyPathWillThrowIfCodeIsInvalid(bool redirect)
619619
using var server = host.GetTestServer();
620620
var sendTask = server.SendAsync(
621621
"https://example.com/signin-google?code=TestCode&state=" + UrlEncoder.Default.Encode(state),
622-
$".AspNetCore.Correlation.Google.{correlationValue}=N");
622+
$".AspNetCore.Correlation.{correlationValue}=N");
623623
if (redirect)
624624
{
625625
var transaction = await sendTask;
@@ -671,7 +671,7 @@ public async Task ReplyPathWillRejectIfAccessTokenIsMissing(bool redirect)
671671
using var server = host.GetTestServer();
672672
var sendTask = server.SendAsync(
673673
"https://example.com/signin-google?code=TestCode&state=" + UrlEncoder.Default.Encode(state),
674-
$".AspNetCore.Correlation.Google.{correlationValue}=N");
674+
$".AspNetCore.Correlation.{correlationValue}=N");
675675
if (redirect)
676676
{
677677
var transaction = await sendTask;
@@ -715,11 +715,11 @@ public async Task AuthenticatedEventCanGetRefreshToken()
715715
using var server = host.GetTestServer();
716716
var transaction = await server.SendAsync(
717717
"https://example.com/signin-google?code=TestCode&state=" + UrlEncoder.Default.Encode(state),
718-
$".AspNetCore.Correlation.Google.{correlationValue}=N");
718+
$".AspNetCore.Correlation.{correlationValue}=N");
719719
Assert.Equal(HttpStatusCode.Redirect, transaction.Response.StatusCode);
720720
Assert.Equal("/me", transaction.Response.Headers.GetValues("Location").First());
721721
Assert.Equal(2, transaction.SetCookie.Count);
722-
Assert.Contains($".AspNetCore.Correlation.Google.{correlationValue}", transaction.SetCookie[0]);
722+
Assert.Contains($".AspNetCore.Correlation.{correlationValue}", transaction.SetCookie[0]);
723723
Assert.Contains(".AspNetCore." + TestExtensions.CookieAuthenticationScheme, transaction.SetCookie[1]);
724724

725725
var authCookie = transaction.AuthenticationCookieValue;
@@ -755,11 +755,11 @@ public async Task NullRedirectUriWillRedirectToSlash()
755755
using var server = host.GetTestServer();
756756
var transaction = await server.SendAsync(
757757
"https://example.com/signin-google?code=TestCode&state=" + UrlEncoder.Default.Encode(state),
758-
$".AspNetCore.Correlation.Google.{correlationValue}=N");
758+
$".AspNetCore.Correlation.{correlationValue}=N");
759759
Assert.Equal(HttpStatusCode.Redirect, transaction.Response.StatusCode);
760760
Assert.Equal("/", transaction.Response.Headers.GetValues("Location").First());
761761
Assert.Equal(2, transaction.SetCookie.Count);
762-
Assert.Contains($".AspNetCore.Correlation.Google.{correlationValue}", transaction.SetCookie[0]);
762+
Assert.Contains($".AspNetCore.Correlation.{correlationValue}", transaction.SetCookie[0]);
763763
Assert.Contains(".AspNetCore." + TestExtensions.CookieAuthenticationScheme, transaction.SetCookie[1]);
764764
}
765765

@@ -802,7 +802,7 @@ public async Task ValidateAuthenticatedContext()
802802
using var server = host.GetTestServer();
803803
var transaction = await server.SendAsync(
804804
"https://example.com/signin-google?code=TestCode&state=" + UrlEncoder.Default.Encode(state),
805-
$".AspNetCore.Correlation.Google.{correlationValue}=N");
805+
$".AspNetCore.Correlation.{correlationValue}=N");
806806

807807
Assert.Equal(HttpStatusCode.Redirect, transaction.Response.StatusCode);
808808
Assert.Equal("/foo", transaction.Response.Headers.GetValues("Location").First());
@@ -876,11 +876,11 @@ public async Task AuthenticateAutomaticWhenAlreadySignedInSucceeds()
876876
using var server = host.GetTestServer();
877877
var transaction = await server.SendAsync(
878878
"https://example.com/signin-google?code=TestCode&state=" + UrlEncoder.Default.Encode(state),
879-
$".AspNetCore.Correlation.Google.{correlationValue}=N");
879+
$".AspNetCore.Correlation.{correlationValue}=N");
880880
Assert.Equal(HttpStatusCode.Redirect, transaction.Response.StatusCode);
881881
Assert.Equal("/me", transaction.Response.Headers.GetValues("Location").First());
882882
Assert.Equal(2, transaction.SetCookie.Count);
883-
Assert.Contains($".AspNetCore.Correlation.Google.{correlationValue}", transaction.SetCookie[0]); // Delete
883+
Assert.Contains($".AspNetCore.Correlation.{correlationValue}", transaction.SetCookie[0]); // Delete
884884
Assert.Contains(".AspNetCore." + TestExtensions.CookieAuthenticationScheme, transaction.SetCookie[1]);
885885

886886
var authCookie = transaction.AuthenticationCookieValue;
@@ -920,11 +920,11 @@ public async Task AuthenticateGoogleWhenAlreadySignedInSucceeds()
920920
using var server = host.GetTestServer();
921921
var transaction = await server.SendAsync(
922922
"https://example.com/signin-google?code=TestCode&state=" + UrlEncoder.Default.Encode(state),
923-
$".AspNetCore.Correlation.Google.{correlationValue}=N");
923+
$".AspNetCore.Correlation.{correlationValue}=N");
924924
Assert.Equal(HttpStatusCode.Redirect, transaction.Response.StatusCode);
925925
Assert.Equal("/me", transaction.Response.Headers.GetValues("Location").First());
926926
Assert.Equal(2, transaction.SetCookie.Count);
927-
Assert.Contains($".AspNetCore.Correlation.Google.{correlationValue}", transaction.SetCookie[0]); // Delete
927+
Assert.Contains($".AspNetCore.Correlation.{correlationValue}", transaction.SetCookie[0]); // Delete
928928
Assert.Contains(".AspNetCore." + TestExtensions.CookieAuthenticationScheme, transaction.SetCookie[1]);
929929

930930
var authCookie = transaction.AuthenticationCookieValue;
@@ -964,11 +964,11 @@ public async Task AuthenticateFacebookWhenAlreadySignedWithGoogleReturnsNull()
964964
using var server = host.GetTestServer();
965965
var transaction = await server.SendAsync(
966966
"https://example.com/signin-google?code=TestCode&state=" + UrlEncoder.Default.Encode(state),
967-
$".AspNetCore.Correlation.Google.{correlationValue}=N");
967+
$".AspNetCore.Correlation.{correlationValue}=N");
968968
Assert.Equal(HttpStatusCode.Redirect, transaction.Response.StatusCode);
969969
Assert.Equal("/me", transaction.Response.Headers.GetValues("Location").First());
970970
Assert.Equal(2, transaction.SetCookie.Count);
971-
Assert.Contains($".AspNetCore.Correlation.Google.{correlationValue}", transaction.SetCookie[0]); // Delete
971+
Assert.Contains($".AspNetCore.Correlation.{correlationValue}", transaction.SetCookie[0]); // Delete
972972
Assert.Contains(".AspNetCore." + TestExtensions.CookieAuthenticationScheme, transaction.SetCookie[1]);
973973

974974
var authCookie = transaction.AuthenticationCookieValue;
@@ -1001,11 +1001,11 @@ public async Task ChallengeFacebookWhenAlreadySignedWithGoogleSucceeds()
10011001
using var server = host.GetTestServer();
10021002
var transaction = await server.SendAsync(
10031003
"https://example.com/signin-google?code=TestCode&state=" + UrlEncoder.Default.Encode(state),
1004-
$".AspNetCore.Correlation.Google.{correlationValue}=N");
1004+
$".AspNetCore.Correlation.{correlationValue}=N");
10051005
Assert.Equal(HttpStatusCode.Redirect, transaction.Response.StatusCode);
10061006
Assert.Equal("/me", transaction.Response.Headers.GetValues("Location").First());
10071007
Assert.Equal(2, transaction.SetCookie.Count);
1008-
Assert.Contains($".AspNetCore.Correlation.Google.{correlationValue}", transaction.SetCookie[0]); // Delete
1008+
Assert.Contains($".AspNetCore.Correlation.{correlationValue}", transaction.SetCookie[0]); // Delete
10091009
Assert.Contains(".AspNetCore." + TestExtensions.CookieAuthenticationScheme, transaction.SetCookie[1]);
10101010

10111011
var authCookie = transaction.AuthenticationCookieValue;

src/Security/Authentication/test/MicrosoftAccountTests.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -242,11 +242,11 @@ public async Task AuthenticatedEventCanGetRefreshToken()
242242
using var server = host.GetTestServer();
243243
var transaction = await server.SendAsync(
244244
"https://example.com/signin-microsoft?code=TestCode&state=" + UrlEncoder.Default.Encode(state),
245-
$".AspNetCore.Correlation.Microsoft.{correlationValue}=N");
245+
$".AspNetCore.Correlation.{correlationValue}=N");
246246
Assert.Equal(HttpStatusCode.Redirect, transaction.Response.StatusCode);
247247
Assert.Equal("/me", transaction.Response.Headers.GetValues("Location").First());
248248
Assert.Equal(2, transaction.SetCookie.Count);
249-
Assert.Contains($".AspNetCore.Correlation.Microsoft.{correlationValue}", transaction.SetCookie[0]);
249+
Assert.Contains($".AspNetCore.Correlation.{correlationValue}", transaction.SetCookie[0]);
250250
Assert.Contains(".AspNetCore." + TestExtensions.CookieAuthenticationScheme, transaction.SetCookie[1]);
251251

252252
var authCookie = transaction.AuthenticationCookieValue;
@@ -351,7 +351,7 @@ public async Task PkceSentToTokenEndpoint()
351351
Assert.Equal(HttpStatusCode.Redirect, transaction.Response.StatusCode);
352352
Assert.Equal("/me", transaction.Response.Headers.GetValues("Location").First());
353353
Assert.Equal(2, transaction.SetCookie.Count);
354-
Assert.StartsWith(".AspNetCore.Correlation.Microsoft.", transaction.SetCookie[0]);
354+
Assert.StartsWith(".AspNetCore.Correlation.", transaction.SetCookie[0]);
355355
Assert.StartsWith(".AspNetCore." + TestExtensions.CookieAuthenticationScheme, transaction.SetCookie[1]);
356356
}
357357

src/Security/Authentication/test/OAuthTests.cs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -283,7 +283,7 @@ public async Task HandleRequestAsync_RedirectsToAccessDeniedPathWhenExplicitlySe
283283

284284
using var server = host.GetTestServer();
285285
var transaction = await server.SendAsync("https://www.example.com/oauth-callback?error=access_denied&state=protected_state",
286-
".AspNetCore.Correlation.Weblie.correlationId=N");
286+
".AspNetCore.Correlation.correlationId=N");
287287

288288
Assert.Equal(HttpStatusCode.Redirect, transaction.Response.StatusCode);
289289
Assert.Equal("https://www.example.com/access-denied?ReturnUrl=http%3A%2F%2Ftesthost%2Fredirect", transaction.Response.Headers.Location.ToString());
@@ -318,7 +318,7 @@ public async Task HandleRequestAsync_InvokesAccessDeniedEvent()
318318

319319
using var server = host.GetTestServer();
320320
var transaction = await server.SendAsync("https://www.example.com/oauth-callback?error=access_denied&state=protected_state",
321-
".AspNetCore.Correlation.Weblie.correlationId=N");
321+
".AspNetCore.Correlation.correlationId=N");
322322

323323
Assert.Equal(HttpStatusCode.NotAcceptable, transaction.Response.StatusCode);
324324
Assert.Null(transaction.Response.Headers.Location);
@@ -354,7 +354,7 @@ public async Task HandleRequestAsync_InvokesRemoteFailureEventWhenAccessDeniedPa
354354

355355
using var server = host.GetTestServer();
356356
var transaction = await server.SendAsync("https://www.example.com/oauth-callback?error=access_denied&state=protected_state",
357-
".AspNetCore.Correlation.Weblie.correlationId=N");
357+
".AspNetCore.Correlation.correlationId=N");
358358

359359
Assert.Equal(HttpStatusCode.NotAcceptable, transaction.Response.StatusCode);
360360
Assert.Null(transaction.Response.Headers.Location);
@@ -390,7 +390,7 @@ public async Task RemoteAuthenticationFailed_OAuthError_IncludesProperties()
390390

391391
using var server = host.GetTestServer();
392392
var transaction = await server.SendAsync("https://www.example.com/oauth-callback?error=custom_error&state=protected_state",
393-
".AspNetCore.Correlation.Weblie.correlationId=N");
393+
".AspNetCore.Correlation.correlationId=N");
394394

395395
Assert.Equal(HttpStatusCode.NotAcceptable, transaction.Response.StatusCode);
396396
Assert.Null(transaction.Response.Headers.Location);

0 commit comments

Comments
 (0)