Skip to content

Handle auth schemes in cookie names #25279

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Aug 28, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ public void PostConfigure(string name, CookieAuthenticationOptions options)

if (string.IsNullOrEmpty(options.Cookie.Name))
{
options.Cookie.Name = CookieAuthenticationDefaults.CookiePrefix + name;
options.Cookie.Name = CookieAuthenticationDefaults.CookiePrefix + Uri.EscapeDataString(name);
}
if (options.TicketDataFormat == null)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -200,7 +200,7 @@ protected virtual void GenerateCorrelationId(AuthenticationProperties properties

properties.Items[CorrelationProperty] = correlationId;

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

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

properties.Items.Remove(CorrelationProperty);

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

var correlationCookie = Request.Cookies[cookieName];
if (string.IsNullOrEmpty(correlationCookie))
Expand Down
32 changes: 32 additions & 0 deletions src/Security/Authentication/test/CookieTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,38 @@ public async Task SignInCausesDefaultCookieToBeCreated()
Assert.Equal("no-cache", transaction.Response.Headers.Pragma.ToString());
}

[Fact]
public async Task CustomAuthSchemeEncodesCookieName()
{
var schemeName = "With spaces and 界";
using var host = await CreateHostWithServices(s => s.AddAuthentication(schemeName).AddCookie(schemeName, o =>
{
o.LoginPath = new PathString("/login");
}), context =>
{
var user = new ClaimsIdentity(new GenericIdentity("Alice", "Cookies"));
user.AddClaim(new Claim("marker", "true"));
return context.SignInAsync(schemeName,
new ClaimsPrincipal(user),
new AuthenticationProperties());
});

using var server = host.GetTestServer();
var transaction = await SendAsync(server, "http://example.com/testpath");

var setCookie = transaction.SetCookie;
Assert.StartsWith(".AspNetCore.With%20spaces%20and%20%E7%95%8C=", setCookie);
Assert.Contains("; path=/", setCookie);
Assert.Contains("; httponly", setCookie);
Assert.Contains("; samesite=", setCookie);
Assert.DoesNotContain("; expires=", setCookie);
Assert.DoesNotContain("; domain=", setCookie);
Assert.DoesNotContain("; secure", setCookie);
Assert.True(transaction.Response.Headers.CacheControl.NoCache);
Assert.True(transaction.Response.Headers.CacheControl.NoStore);
Assert.Equal("no-cache", transaction.Response.Headers.Pragma.ToString());
}

[Fact]
public void SettingCookieExpirationOptionThrows()
{
Expand Down
2 changes: 1 addition & 1 deletion src/Security/Authentication/test/FacebookTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -363,7 +363,7 @@ public async Task CustomUserInfoEndpointHasValidGraphQuery()
using var server = host.GetTestServer();
var transaction = await server.SendAsync(
"https://example.com/signin-facebook?code=TestCode&state=" + UrlEncoder.Default.Encode(state),
$".AspNetCore.Correlation.Facebook.{correlationValue}=N");
$".AspNetCore.Correlation.{correlationValue}=N");
Assert.Equal(HttpStatusCode.Redirect, transaction.Response.StatusCode);
Assert.Equal("/me", transaction.Response.Headers.GetValues("Location").First());
Assert.Equal(1, finalUserInfoEndpoint.Count(c => c == '?'));
Expand Down
44 changes: 22 additions & 22 deletions src/Security/Authentication/test/GoogleTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,7 @@ public async Task ChallengeWillSetCorrelationCookie()
});
using var server = host.GetTestServer();
var transaction = await server.SendAsync("https://example.com/challenge");
Assert.Contains(transaction.SetCookie, cookie => cookie.StartsWith(".AspNetCore.Correlation.Google."));
Assert.Contains(transaction.SetCookie, cookie => cookie.StartsWith(".AspNetCore.Correlation."));
}

[Fact]
Expand Down Expand Up @@ -392,7 +392,7 @@ public async Task ReplyPathWithAccessDeniedErrorFails(bool redirect)
});
using var server = host.GetTestServer();
var sendTask = server.SendAsync("https://example.com/signin-google?error=access_denied&error_description=SoBad&error_uri=foobar&state=protected_state",
".AspNetCore.Correlation.Google.correlationId=N");
".AspNetCore.Correlation.correlationId=N");
if (redirect)
{
var transaction = await sendTask;
Expand Down Expand Up @@ -431,7 +431,7 @@ public async Task ReplyPathWithAccessDeniedError_AllowsCustomizingPath()
});
using var server = host.GetTestServer();
var transaction = await server.SendAsync("https://example.com/signin-google?error=access_denied&error_description=SoBad&error_uri=foobar&state=protected_state",
".AspNetCore.Correlation.Google.correlationId=N");
".AspNetCore.Correlation.correlationId=N");
Assert.Equal(HttpStatusCode.Redirect, transaction.Response.StatusCode);
Assert.Equal("https://example.com/custom-denied-page?rurl=http%3A%2F%2Fwww.google.com%2F", transaction.Response.Headers.GetValues("Location").First());
}
Expand Down Expand Up @@ -474,7 +474,7 @@ public async Task ReplyPathWithAccessDeniedErrorAndNoAccessDeniedPath_FallsBackT
});
using var server = host.GetTestServer();
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",
".AspNetCore.Correlation.Google.correlationId=N");
".AspNetCore.Correlation.correlationId=N");
Assert.Equal(HttpStatusCode.Redirect, transaction.Response.StatusCode);
Assert.StartsWith("/error?FailureMessage=", transaction.Response.Headers.GetValues("Location").First());
Assert.True(accessDeniedCalled);
Expand Down Expand Up @@ -510,7 +510,7 @@ public async Task ReplyPathWithErrorFails(bool redirect)
});
using var server = host.GetTestServer();
var sendTask = server.SendAsync("https://example.com/signin-google?error=itfailed&error_description=whyitfailed&error_uri=https://example.com/fail&state=protected_state",
".AspNetCore.Correlation.Google.correlationId=N");
".AspNetCore.Correlation.correlationId=N");
if (redirect)
{
var transaction = await sendTask;
Expand Down Expand Up @@ -552,11 +552,11 @@ public async Task ReplyPathWillAuthenticateValidAuthorizeCodeAndState(string cla
using var server = host.GetTestServer();
var transaction = await server.SendAsync(
"https://example.com/signin-google?code=TestCode&state=" + UrlEncoder.Default.Encode(state),
$".AspNetCore.Correlation.Google.{correlationValue}=N");
$".AspNetCore.Correlation.{correlationValue}=N");
Assert.Equal(HttpStatusCode.Redirect, transaction.Response.StatusCode);
Assert.Equal("/me", transaction.Response.Headers.GetValues("Location").First());
Assert.Equal(2, transaction.SetCookie.Count);
Assert.Contains($".AspNetCore.Correlation.Google.{correlationValue}", transaction.SetCookie[0]);
Assert.Contains($".AspNetCore.Correlation.{correlationValue}", transaction.SetCookie[0]);
Assert.Contains(".AspNetCore." + TestExtensions.CookieAuthenticationScheme, transaction.SetCookie[1]);

var authCookie = transaction.AuthenticationCookieValue;
Expand Down Expand Up @@ -619,7 +619,7 @@ public async Task ReplyPathWillThrowIfCodeIsInvalid(bool redirect)
using var server = host.GetTestServer();
var sendTask = server.SendAsync(
"https://example.com/signin-google?code=TestCode&state=" + UrlEncoder.Default.Encode(state),
$".AspNetCore.Correlation.Google.{correlationValue}=N");
$".AspNetCore.Correlation.{correlationValue}=N");
if (redirect)
{
var transaction = await sendTask;
Expand Down Expand Up @@ -671,7 +671,7 @@ public async Task ReplyPathWillRejectIfAccessTokenIsMissing(bool redirect)
using var server = host.GetTestServer();
var sendTask = server.SendAsync(
"https://example.com/signin-google?code=TestCode&state=" + UrlEncoder.Default.Encode(state),
$".AspNetCore.Correlation.Google.{correlationValue}=N");
$".AspNetCore.Correlation.{correlationValue}=N");
if (redirect)
{
var transaction = await sendTask;
Expand Down Expand Up @@ -715,11 +715,11 @@ public async Task AuthenticatedEventCanGetRefreshToken()
using var server = host.GetTestServer();
var transaction = await server.SendAsync(
"https://example.com/signin-google?code=TestCode&state=" + UrlEncoder.Default.Encode(state),
$".AspNetCore.Correlation.Google.{correlationValue}=N");
$".AspNetCore.Correlation.{correlationValue}=N");
Assert.Equal(HttpStatusCode.Redirect, transaction.Response.StatusCode);
Assert.Equal("/me", transaction.Response.Headers.GetValues("Location").First());
Assert.Equal(2, transaction.SetCookie.Count);
Assert.Contains($".AspNetCore.Correlation.Google.{correlationValue}", transaction.SetCookie[0]);
Assert.Contains($".AspNetCore.Correlation.{correlationValue}", transaction.SetCookie[0]);
Assert.Contains(".AspNetCore." + TestExtensions.CookieAuthenticationScheme, transaction.SetCookie[1]);

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

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

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

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

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

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

var authCookie = transaction.AuthenticationCookieValue;
Expand Down
6 changes: 3 additions & 3 deletions src/Security/Authentication/test/MicrosoftAccountTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -242,11 +242,11 @@ public async Task AuthenticatedEventCanGetRefreshToken()
using var server = host.GetTestServer();
var transaction = await server.SendAsync(
"https://example.com/signin-microsoft?code=TestCode&state=" + UrlEncoder.Default.Encode(state),
$".AspNetCore.Correlation.Microsoft.{correlationValue}=N");
$".AspNetCore.Correlation.{correlationValue}=N");
Assert.Equal(HttpStatusCode.Redirect, transaction.Response.StatusCode);
Assert.Equal("/me", transaction.Response.Headers.GetValues("Location").First());
Assert.Equal(2, transaction.SetCookie.Count);
Assert.Contains($".AspNetCore.Correlation.Microsoft.{correlationValue}", transaction.SetCookie[0]);
Assert.Contains($".AspNetCore.Correlation.{correlationValue}", transaction.SetCookie[0]);
Assert.Contains(".AspNetCore." + TestExtensions.CookieAuthenticationScheme, transaction.SetCookie[1]);

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

Expand Down
8 changes: 4 additions & 4 deletions src/Security/Authentication/test/OAuthTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -283,7 +283,7 @@ public async Task HandleRequestAsync_RedirectsToAccessDeniedPathWhenExplicitlySe

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

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

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

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

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

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

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

Assert.Equal(HttpStatusCode.NotAcceptable, transaction.Response.StatusCode);
Assert.Null(transaction.Response.Headers.Location);
Expand Down
Loading