ASP.NET Core 5.0 - Cookie Consent and GDPR
This article will describe the implementation of Microsoft. AspNetCore. CookiePolicy to request user consent for non-essential cookies. I will assume you have downloaded the ASP.NET Core 5.0 - Homegrown Analytics Project or created a new ASP.NET Core 5.0 Razor Pages project. See Tutorial: Get started with Razor Pages in ASP.NET Core.
Homegrown Analytics Project and Article Series
The project is feature complete and will increment the version with updates. The details page includes the version change log. This project is designed and organized to allow easy integration with existing projects. The KenHaggerty. Com. SingleUser NuGet package segregates the user logic. SQL scripts to create the schema, tables, and default data are included in the package. Details, screenshots, and related articles can be found at ASP.NET Core 5.0 - Homegrown Analytics Project.
- ASP.NET Core 5.0 - Homegrown Analytics
- ASP.NET Core 5.0 - Analytics Schema and Integration
- ASP.NET Core 5.0 - Cookie Consent and GDPR
- ASP.NET Core 5.0 - Analytic Data Collection
- ASP.NET Core 5.0 - Not Found Errors
- ASP.NET Core 5.0 - Preferred UserAgents
- ASP.NET Core 5.0 - Analytic Dashboard
- ASP.NET Core 5.0 - Online User Count with SignalR
- ASP.NET Core 5.0 - Is Human with Google reCAPTCHA
- ASP.NET Core 5.0 - Log Maintenance with Hangfire
The project implements a cookie policy banner and CheckConsentNeeded option from Microsoft. AspNetCore. CookiePolicy to request user consent for non-essential cookies. See EU General Data Protection Regulation (GDPR) support in ASP.NET Core. This article will update the implementation of the article I published, ASP.NET Core 3.1 - Cookie Consent to add the use of the non-essential cookies, ScreenSize and TimeOffset.
Configure the CheckConsentNeeded option to check if consent policies should be evaluated on the request.
Startup > ConfigureServices:
services.Configure<CookiePolicyOptions>(options => { // Sets the display of the Cookie Consent banner (/Pages/Shared/_CookieConsentPartial.cshtml). // This lambda determines whether user consent for non-essential cookies is needed for a given request. options.CheckConsentNeeded = context => true; options.MinimumSameSitePolicy = SameSiteMode.Strict; });
Add the UseCookiePolicy extension to apply the CheckConsentNeeded option to the pipeline.
Startup > Configure:
app.UseCookiePolicy();
I moved the _CookieConsentPartial below the RenderBody div in _Layout. cshtml to apply mobile friendly style from site.css.
The project implements a SessionId cookie which expires when the browsing session ends. Because of the confusion and interpretations of the GDPR and other privacy laws, my code includes an option to set the SessionId cookie's essential state. See The 2020 Guide to Google Analytics and GDPR Compliance
The ASP.NET Core 3.1 - Cookie Consent article describes the issue and remedy for the CookieTempDataProvider and consent.
Startup > ConfigureServices:
services.AddRazorPages(options => { options.Conventions.AuthorizeFolder("/Admin"); }) .AddCookieTempDataProvider(options => { options.Cookie.IsEssential = true; });
I improved the way I pass the CanTrack consent flag to JavaScript. I now place the code inside the head tag of _Layout. cshtml.
_Layout. cshtml:
<script> var mustAcceptCookies = false; </script> @{ var consentFeature = Context.Features.Get<ITrackingConsentFeature>(); if (!consentFeature?.CanTrack ?? false) { <script> mustAcceptCookies = true; </script> } }
Now, mustAcceptCookies is always declared and a global variable. It defaults to false. If the consent feature is implemented and the user has not consented, it is set true. I use mustAcceptCookies in site.js to determine if I can set non-essential cookies.
site.js:
window.setCookie = function (cname, cvalue, exdays, path = '/', samesite = 'strict') { let d = new Date(); d.setTime(d.getTime() + (exdays * 24 * 60 * 60 * 1000)); document.cookie = cname + '=' + cvalue + ';expires=' + d.toUTCString() + ';path=' + path + '; samesite=' + samesite + ';'; } window.getCookie = function (cname) { let name = cname + '='; let ca = document.cookie.split(';'); for (let i = 0; i < ca.length; i++) { let c = ca[i]; while (c.charAt(0) === ' ') c = c.substring(1); if (c.indexOf(name) === 0) return c.substring(name.length, c.length); } return ''; } document.addEventListener('DOMContentLoaded', function () { if (!mustAcceptCookies) { // client timezone if (getCookie('HomegrownAnalytics.TimeOffset') === '') { setCookie('HomegrownAnalytics.TimeOffset', new Date().getTimezoneOffset(), 1, '/', 'strict'); } // client screen width and height if (getCookie('HomegrownAnalytics.ScreenSize') === '') { setCookie('HomegrownAnalytics.ScreenSize', window.screen.availWidth.toString() + 'X' + window.screen.availHeight.toString(), 365, '/', 'strict'); } } });
Comments(0)