Implement ITrackingConsentFeature.CreateConsentCookie() #1590

This commit is contained in:
Chris Ross (ASP.NET) 2018-01-05 12:34:39 -08:00
parent da066d50e0
commit 1f855f7b06
3 changed files with 119 additions and 4 deletions

View File

@ -68,6 +68,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution
build\Key.snk = build\Key.snk
NuGet.config = NuGet.config
build\repo.props = build\repo.props
build\sources.props = build\sources.props
EndProjectSection
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Authorization.Policy", "src\Microsoft.AspNetCore.Authorization.Policy\Microsoft.AspNetCore.Authorization.Policy.csproj", "{58194599-F07D-47A3-9DF2-E21A22C5EF9E}"

View File

@ -82,6 +82,30 @@ namespace Microsoft.AspNetCore.CookiePolicy
_hasConsent = false;
}
// Note policy will be applied. We don't want to bypass policy because we want HttpOnly, Secure, etc. to apply.
public string CreateConsentCookie()
{
var key = Options.ConsentCookie.Name;
var value = ConsentValue;
var options = Options.ConsentCookie.Build(Context);
ApplyAppendPolicy(ref key, ref value, options);
var setCookieHeaderValue = new Net.Http.Headers.SetCookieHeaderValue(
Uri.EscapeDataString(key),
Uri.EscapeDataString(value))
{
Domain = options.Domain,
Path = options.Path,
Expires = options.Expires,
MaxAge = options.MaxAge,
Secure = options.Secure,
SameSite = (Net.Http.Headers.SameSiteMode)options.SameSite,
HttpOnly = options.HttpOnly
};
return setCookieHeaderValue.ToString();
}
private bool CheckPolicyRequired()
{
return !CanTrack
@ -109,6 +133,14 @@ namespace Microsoft.AspNetCore.CookiePolicy
throw new ArgumentNullException(nameof(options));
}
if (ApplyAppendPolicy(ref key, ref value, options))
{
Cookies.Append(key, value, options);
}
}
private bool ApplyAppendPolicy(ref string key, ref string value, CookieOptions options)
{
var issueCookie = CanTrack || options.IsEssential;
ApplyPolicy(options);
if (Options.OnAppendCookie != null)
@ -126,10 +158,7 @@ namespace Microsoft.AspNetCore.CookiePolicy
issueCookie = context.IssueCookie;
}
if (issueCookie)
{
Cookies.Append(key, value, options);
}
return issueCookie;
}
public void Delete(string key)

View File

@ -542,6 +542,91 @@ namespace Microsoft.AspNetCore.CookiePolicy.Test
Assert.Empty(httpContext.Response.Headers[HeaderNames.SetCookie]);
}
[Fact]
public async Task CreateConsentCookieMatchesGrantConsentCookie()
{
var httpContext = await RunTestAsync(options =>
{
options.CheckConsentNeeded = context => true;
},
requestContext => { },
context =>
{
var feature = context.Features.Get<ITrackingConsentFeature>();
Assert.True(feature.IsConsentNeeded);
Assert.False(feature.HasConsent);
Assert.False(feature.CanTrack);
feature.GrantConsent();
Assert.True(feature.IsConsentNeeded);
Assert.True(feature.HasConsent);
Assert.True(feature.CanTrack);
var cookie = feature.CreateConsentCookie();
context.Response.Headers["ManualCookie"] = cookie;
return Task.CompletedTask;
});
var cookies = SetCookieHeaderValue.ParseList(httpContext.Response.Headers[HeaderNames.SetCookie]);
Assert.Equal(1, cookies.Count);
var consentCookie = cookies[0];
Assert.Equal(".AspNet.Consent", consentCookie.Name);
Assert.Equal("yes", consentCookie.Value);
Assert.Equal(Net.Http.Headers.SameSiteMode.Lax, consentCookie.SameSite);
Assert.NotNull(consentCookie.Expires);
Assert.Equal(httpContext.Response.Headers[HeaderNames.SetCookie], httpContext.Response.Headers["ManualCookie"]);
}
[Fact]
public async Task CreateConsentCookieAppliesPolicy()
{
var httpContext = await RunTestAsync(options =>
{
options.CheckConsentNeeded = context => true;
options.MinimumSameSitePolicy = Http.SameSiteMode.Strict;
options.OnAppendCookie = context =>
{
Assert.Equal(".AspNet.Consent", context.CookieName);
Assert.Equal("yes", context.CookieValue);
Assert.Equal(Http.SameSiteMode.Strict, context.CookieOptions.SameSite);
context.CookieName += "1";
context.CookieValue += "1";
};
},
requestContext => { },
context =>
{
var feature = context.Features.Get<ITrackingConsentFeature>();
Assert.True(feature.IsConsentNeeded);
Assert.False(feature.HasConsent);
Assert.False(feature.CanTrack);
feature.GrantConsent();
Assert.True(feature.IsConsentNeeded);
Assert.True(feature.HasConsent);
Assert.True(feature.CanTrack);
var cookie = feature.CreateConsentCookie();
context.Response.Headers["ManualCookie"] = cookie;
return Task.CompletedTask;
});
var cookies = SetCookieHeaderValue.ParseList(httpContext.Response.Headers[HeaderNames.SetCookie]);
Assert.Equal(1, cookies.Count);
var consentCookie = cookies[0];
Assert.Equal(".AspNet.Consent1", consentCookie.Name);
Assert.Equal("yes1", consentCookie.Value);
Assert.Equal(Net.Http.Headers.SameSiteMode.Strict, consentCookie.SameSite);
Assert.NotNull(consentCookie.Expires);
Assert.Equal(httpContext.Response.Headers[HeaderNames.SetCookie], httpContext.Response.Headers["ManualCookie"]);
}
private Task<HttpContext> RunTestAsync(Action<CookiePolicyOptions> configureOptions, Action<HttpContext> configureRequest, RequestDelegate handleRequest)
{
var builder = new WebHostBuilder()