Nefarius.Legacy.DataProtector
1.3.0
Prefix Reserved
dotnet add package Nefarius.Legacy.DataProtector --version 1.3.0
NuGet\Install-Package Nefarius.Legacy.DataProtector -Version 1.3.0
<PackageReference Include="Nefarius.Legacy.DataProtector" Version="1.3.0" />
<PackageVersion Include="Nefarius.Legacy.DataProtector" Version="1.3.0" />
<PackageReference Include="Nefarius.Legacy.DataProtector" />
paket add Nefarius.Legacy.DataProtector --version 1.3.0
#r "nuget: Nefarius.Legacy.DataProtector, 1.3.0"
#:package Nefarius.Legacy.DataProtector@1.3.0
#addin nuget:?package=Nefarius.Legacy.DataProtector&version=1.3.0
#tool nuget:?package=Nefarius.Legacy.DataProtector&version=1.3.0
Nefarius.Legacy.DataProtector
ASP.NET Data Protection key store using EF (Legacy and Core).
Motivation
Recently I was tasked with the challenge of starting migrating an ASP.NET 4 MVC monolith over to the sacred .NET core universe. Since no direct upgrade paths exist, a common strategy is to gradually migrate over app logic to a new backend-frontend-combination while keeping the old app on life support and incorporated with the new software stack. A major pain-point is modernizing authentication and giving users an acceptable SSO experience. One such strategy is shared auth cookies between the ASP.NET Classic and Core apps.
Session cookies are encrypted by default, so both app environments need to have means to decrypt the session details. ASP.NET Core Data Protection is used to offload encryption and decryption, and the key material can be shared by a common filesystem directory or other means.
Since I already had to deal with EF (Core) and an MS SQL Server, I chose to backport an EF-based SQL Server backed key repository consumable both in ASP.NET Classic and Core from a single class library.
Usage
The main advantage is getting SSO via shared cookies to work while not relying on a shared directory, but SQL database instead. The example below assumes you have an ASP.NET Core backend playing reverse proxy to a legacy ASP.NET 4.x app and share the user session via cookie that gets decrypted via the DB-backed keys.
The table name DataProtectionKeys
is hard-coded and needs to be created in the target database.
See SQL_CreateTable.sql
for details.
ASP.NET Core (.NET 8)
builder.Services.AddDbContext<DataProtectionDbContext>(options =>
options.UseSqlServer(builder.Configuration.GetConnectionString("DataProtection")));
builder.Services.AddDataProtection()
.PersistKeysToSqlServer(builder.Configuration.GetConnectionString("DataProtection")!)
.SetApplicationName("iis-app-name");
// example to use SSO via shared cookie with ASP.NET 4
builder.Services.AddAuthentication(options =>
{
options.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
})
// Shared cookie authentication
.AddCookie(options =>
{
options.Cookie.Name = ".AspNet.SharedCookie";
options.Cookie.SameSite = SameSiteMode.Lax;
options.Cookie.Path = "/";
options.Cookie.HttpOnly = true;
options.Cookie.IsEssential = true;
options.ExpireTimeSpan = TimeSpan.FromMinutes(120);
})
ASP.NET 4 (.NET Framework)
If your web app doesn't yet use OWIN you need to add it first (video guide) for this example to work!
// assumes OwinStartup is used
string connectionString = ConfigurationManager.ConnectionStrings["DataProtection"].ConnectionString;
app.UseCookieAuthentication(new CookieAuthenticationOptions
{
AuthenticationType = CookieAuthenticationDefaults.AuthenticationType,
CookieName = ".AspNet.SharedCookie",
CookieSameSite = SameSiteMode.Lax,
SlidingExpiration = true,
ExpireTimeSpan = TimeSpan.FromMinutes(120),
TicketDataFormat = new AspNetTicketDataFormat(
new DataProtectorShim(
SqlDataProtectionProvider.Create(connectionString, "iis-app-name")
.CreateProtector(
"Microsoft.AspNetCore.Authentication.Cookies.CookieAuthenticationMiddleware",
"Cookies",
"v2"))),
CookieManager = new ChunkingCookieManager()
});
The values .AspNet.SharedCookie
and iis-app-name
used here need to match across web projects that share the same
cookie(s)!
Documentation
Sources & 3rd party credits
Product | Versions Compatible and additional computed target framework versions. |
---|---|
.NET | net8.0 is compatible. net8.0-android was computed. net8.0-browser was computed. net8.0-ios was computed. net8.0-maccatalyst was computed. net8.0-macos was computed. net8.0-tvos was computed. net8.0-windows was computed. net9.0 was computed. net9.0-android was computed. net9.0-browser was computed. net9.0-ios was computed. net9.0-maccatalyst was computed. net9.0-macos was computed. net9.0-tvos was computed. net9.0-windows was computed. net10.0 was computed. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
.NET Framework | net472 is compatible. net48 was computed. net481 was computed. |
-
.NETFramework 4.7.2
- EntityFramework (>= 6.5.1)
- Microsoft.AspNetCore.DataProtection (>= 9.0.6)
-
net8.0
- Microsoft.AspNetCore.DataProtection (>= 9.0.6)
- Microsoft.EntityFrameworkCore.SqlServer (>= 9.0.2)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.
Version | Downloads | Last Updated |
---|---|---|
1.3.0 | 105 | 6/28/2025 |
1.3.0-pre005 | 96 | 6/28/2025 |
1.3.0-pre004 | 100 | 6/28/2025 |
1.3.0-pre003 | 93 | 6/28/2025 |
1.3.0-pre002 | 98 | 6/28/2025 |
1.3.0-pre001 | 97 | 6/28/2025 |
1.1.3 | 148 | 5/21/2025 |
1.1.2 | 176 | 2/17/2025 |
1.1.1 | 112 | 2/17/2025 |
1.1.0 | 111 | 2/17/2025 |
1.0.0 | 126 | 2/16/2025 |
1.0.0-pre005 | 97 | 2/16/2025 |
1.0.0-pre004 | 96 | 2/16/2025 |
1.0.0-pre003 | 107 | 2/16/2025 |
1.0.0-pre002 | 97 | 2/16/2025 |
1.0.0-pre001 | 103 | 2/16/2025 |