Home C# / .NET ASP.NET Core Data Protection: Secure Your App's Secrets
Advanced 3 min · July 13, 2026

ASP.NET Core Data Protection: Secure Your App's Secrets

Learn ASP.NET Core Data Protection API: encrypt, decrypt, and manage keys.

N
Naren Founder & Principal Engineer

20+ years shipping production .NET services in enterprise systems. Written from production experience, not tutorials.

Follow
Production
production tested
July 13, 2026
last updated
2,043
articles · all by Naren
Before you start⏱ 15-20 min read
  • Basic knowledge of C# and ASP.NET Core
  • Familiarity with dependency injection in ASP.NET Core
  • Understanding of cryptographic concepts (encryption, hashing)
 ● Production Incident 🔎 Debug Guide ⚙ Triage Commands
Quick Answer

ASP.NET Core Data Protection provides cryptographic APIs to encrypt and decrypt sensitive data, manage key storage and rotation, and protect against tampering. It's essential for securing cookies, tokens, and other application secrets.

✦ Definition~90s read
What is Data Protection in ASP.NET Core?

ASP.NET Core Data Protection is a cryptographic API that lets you encrypt and decrypt sensitive data in your application, with automatic key management and rotation.

Think of Data Protection as a secure vault with a master key that changes over time.
Plain-English First

Think of Data Protection as a secure vault with a master key that changes over time. You put your secrets inside, lock it, and only you can open it later. Even if someone steals the vault, they can't open it without the current key, and the vault automatically updates its lock periodically.

⚙ Browser compatibility
Latest versions — ✓ supported
ChromeFirefoxSafariEdge

In modern web applications, you often need to store sensitive data temporarily—like authentication cookies, anti-forgery tokens, or temporary user secrets. Storing them in plaintext is a security risk; encrypting them yourself is error-prone. ASP.NET Core's Data Protection stack provides a robust, built-in solution that handles encryption, key management, and key rotation automatically. It's used internally by ASP.NET Core features like authentication, session state, and CSRF protection, but you can also use it directly to protect your own data. This tutorial will walk you through the core concepts, practical usage, and production considerations. You'll learn how to configure the system, manage keys, and avoid common pitfalls. By the end, you'll be able to integrate Data Protection into your applications confidently.

What is ASP.NET Core Data Protection?

ASP.NET Core Data Protection is a cryptographic API designed to protect sensitive data in web applications. It replaces the older <machineKey> element in ASP.NET and provides a more flexible, secure, and easy-to-use system. The core concept is a 'data protector' that can encrypt (Protect) and decrypt (Unprotect) data. The system manages cryptographic keys, handles key rotation, and ensures that data can be decrypted even if the key used to encrypt it has been rotated out (as long as the old key is still available). It also provides integrity checking to detect tampering. Under the hood, it uses authenticated encryption (AES-256-CBC or AES-256-GCM) and keyed hash algorithms (HMACSHA256) for integrity. The system is designed to be transparent: you don't need to worry about key management in most cases, but you have full control when needed.

BasicUsage.csCSHARP
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
using Microsoft.AspNetCore.DataProtection;

public class DataProtectionService
{
    private readonly IDataProtector _protector;

    public DataProtectionService(IDataProtectionProvider provider)
    {
        _protector = provider.CreateProtector("MyApp.Purpose.v1");
    }

    public string Protect(string plaintext)
    {
        return _protector.Protect(plaintext);
    }

    public string Unprotect(string protectedData)
    {
        try
        {
            return _protector.Unprotect(protectedData);
        }
        catch (CryptographicException ex)
        {
            // Handle decryption failure (e.g., tampered data)
            throw new InvalidOperationException("Data integrity check failed.", ex);
        }
    }
}
🔥Purpose Strings
📊 Production Insight
In production, always configure a persistent key store and protect keys at rest (e.g., DPAPI or Azure Key Vault).
🎯 Key Takeaway
Data Protection provides a simple Protect/Unprotect API with automatic key management and integrity.

Configuring Data Protection

To use Data Protection, you must register it in the service collection. The default configuration stores keys in a temporary folder ( %LOCALAPPDATA%/ASP.NET/DataProtection-Keys ) which is not suitable for production. You should configure a persistent key store and optionally protect the keys. Common stores include file system, Azure Blob Storage, Redis, and network shares. You can also protect keys with DPAPI (Windows only), X.509 certificates, or Azure Key Vault. Additionally, you can set the application name to isolate keys between applications. Here's how to configure it in Program.cs:

Program.csCSHARP
1
2
3
4
5
6
7
8
9
10
11
12
using Microsoft.AspNetCore.DataProtection;

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddDataProtection()
    .PersistKeysToFileSystem(new DirectoryInfo(@"C:\Keys")) // Persistent store
    .ProtectKeysWithDpapi() // Protect keys at rest (Windows only)
    .SetApplicationName("MyApplication"); // Isolate keys

var app = builder.Build();

app.Run();
⚠ Key Protection on Linux
📊 Production Insight
For cloud deployments, prefer Azure Blob Storage for key persistence and Azure Key Vault for key encryption. This ensures keys survive restarts and scale across instances.
🎯 Key Takeaway
Always configure a persistent key store and protect keys at rest. Use SetApplicationName to avoid key collisions between apps.

Key Management and Rotation

Data Protection automatically generates new keys periodically (default 90 days) and keeps old keys for decryption until they expire (default 90 additional days). You can configure these lifetimes. When a key expires, it can no longer be used for encryption, but it remains available for decryption. The system automatically selects the most recent key for encryption. You can also manually revoke keys if a compromise is suspected. Revoked keys are not used for encryption or decryption. Here's how to configure key lifetimes:

KeyLifetimeConfig.csCSHARP
1
2
3
4
5
6
7
8
9
10
using Microsoft.AspNetCore.DataProtection;
using Microsoft.Extensions.DependencyInjection;

builder.Services.AddDataProtection()
    .SetDefaultKeyLifetime(TimeSpan.FromDays(30)) // New key every 30 days
    .SetKeyEscrowSink(new MyKeyEscrowSink()); // Optional: escrow keys

// To revoke a key manually:
// var keyManager = serviceProvider.GetService<IKeyManager>();
// keyManager.RevokeKey(keyId, "Key compromised");
💡Key Escrow
📊 Production Insight
Set key lifetime shorter than the maximum lifetime of your encrypted data. For example, if cookies last 14 days, set key lifetime to 7 days so that a compromised key only affects a short window.
🎯 Key Takeaway
Key rotation is automatic, but you can configure lifetimes and manually revoke keys. Old keys are kept for decryption until they expire.

Using Data Protection in Controllers and Services

To use Data Protection in your application, inject IDataProtectionProvider into your services or controllers. Create a protector with a specific purpose string. Always use the same purpose for Protect and Unprotect. Here's an example in a controller:

HomeController.csCSHARP
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
using Microsoft.AspNetCore.DataProtection;
using Microsoft.AspNetCore.Mvc;

public class HomeController : Controller
{
    private readonly IDataProtector _protector;

    public HomeController(IDataProtectionProvider provider)
    {
        _protector = provider.CreateProtector("HomeController.Index.v1");
    }

    public IActionResult Index()
    {
        string sensitiveData = "user-email@example.com";
        string protectedData = _protector.Protect(sensitiveData);
        // Store protectedData in cookie, hidden field, etc.
        return View();
    }

    public IActionResult Decrypt(string protectedData)
    {
        try
        {
            string plaintext = _protector.Unprotect(protectedData);
            return Content("Decrypted: " + plaintext);
        }
        catch (CryptographicException)
        {
            return BadRequest("Invalid data.");
        }
    }
}
🔥Dependency Injection
📊 Production Insight
Avoid storing protected data in logs or error messages. If decryption fails, log the error but do not expose the protected payload.
🎯 Key Takeaway
Inject IDataProtectionProvider and create protectors with unique purpose strings. Handle CryptographicException for tampered data.

Protecting Cookies and Tokens

ASP.NET Core uses Data Protection internally for authentication cookies, anti-forgery tokens, and session state. You can also use it to protect custom cookies or tokens. For example, to protect a cookie that stores a user's email:

CookieProtection.csCSHARP
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
public IActionResult SetCookie()
{
    var protector = _provider.CreateProtector("Cookie.Email.v1");
    string email = "user@example.com";
    string protectedEmail = protector.Protect(email);

    Response.Cookies.Append("UserEmail", protectedEmail, new CookieOptions
    {
        HttpOnly = true,
        Secure = true,
        SameSite = SameSiteMode.Strict
    });
    return Ok();
}

public IActionResult GetCookie()
{
    if (Request.Cookies.TryGetValue("UserEmail", out string protectedEmail))
    {
        var protector = _provider.CreateProtector("Cookie.Email.v1");
        try
        {
            string email = protector.Unprotect(protectedEmail);
            return Content("Email: " + email);
        }
        catch (CryptographicException)
        {
            return BadRequest("Cookie tampered.");
        }
    }
    return NotFound();
}
⚠ Cookie Security
📊 Production Insight
For authentication cookies, ASP.NET Core already protects them. Only use custom protection for additional data you store in cookies.
🎯 Key Takeaway
Use Data Protection to encrypt sensitive cookie values. Combine with secure cookie flags for defense in depth.

Time-Limited Data Protection

Sometimes you need data to be decryptable only for a limited time (e.g., password reset tokens). Data Protection supports time-limited protection via the ITimeLimitedDataProtector interface. You can create one from a regular protector and specify a lifetime. After the lifetime expires, decryption fails. This is useful for one-time tokens or temporary links.

TimeLimitedProtection.csCSHARP
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
using Microsoft.AspNetCore.DataProtection;

public class TokenService
{
    private readonly ITimeLimitedDataProtector _protector;

    public TokenService(IDataProtectionProvider provider)
    {
        _protector = provider.CreateProtector("Token.PasswordReset.v1")
            .ToTimeLimitedDataProtector();
    }

    public string GenerateToken(string userId, TimeSpan lifetime)
    {
        return _protector.Protect(userId, lifetime);
    }

    public string ValidateToken(string token)
    {
        try
        {
            return _protector.Unprotect(token);
        }
        catch (CryptographicException)
        {
            // Token expired or tampered
            return null;
        }
    }
}
💡Expiration Check
📊 Production Insight
For password reset tokens, set a short lifetime (e.g., 1 hour). Combine with server-side tracking to prevent reuse.
🎯 Key Takeaway
Use ITimeLimitedDataProtector for tokens that must expire after a set duration. The expiration is embedded in the protected payload.

Testing Data Protection

When unit testing code that uses Data Protection, you can mock IDataProtectionProvider and IDataProtector. However, for integration tests, you can use the real implementation with an in-memory key store. Here's an example using xUnit:

DataProtectionTests.csCSHARP
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
using Microsoft.AspNetCore.DataProtection;
using Microsoft.Extensions.DependencyInjection;
using Xunit;

public class DataProtectionTests
{
    [Fact]
    public void ProtectAndUnprotect_RoundTrip_Success()
    {
        var services = new ServiceCollection();
        services.AddDataProtection()
            .PersistKeysToFileSystem(new DirectoryInfo(Path.GetTempPath()))
            .SetApplicationName("TestApp");
        var provider = services.BuildServiceProvider();
        var dataProtectionProvider = provider.GetRequiredService<IDataProtectionProvider>();
        var protector = dataProtectionProvider.CreateProtector("TestPurpose");

        string original = "sensitive data";
        string protectedData = protector.Protect(original);
        string decrypted = protector.Unprotect(protectedData);

        Assert.Equal(original, decrypted);
    }

    [Fact]
    public void Unprotect_TamperedData_Throws()
    {
        var services = new ServiceCollection();
        services.AddDataProtection();
        var provider = services.BuildServiceProvider();
        var dataProtectionProvider = provider.GetRequiredService<IDataProtectionProvider>();
        var protector = dataProtectionProvider.CreateProtector("TestPurpose");

        string protectedData = protector.Protect("test");
        // Tamper with the data
        char[] chars = protectedData.ToCharArray();
        chars[10] = 'X';
        string tampered = new string(chars);

        Assert.Throws<CryptographicException>(() => protector.Unprotect(tampered));
    }
}
🔥Integration Testing
📊 Production Insight
Include tests that simulate key rotation: protect with an old key, then rotate, and ensure decryption still works with the old key.
🎯 Key Takeaway
Test Protect/Unprotect round trips and verify that tampered data throws CryptographicException.
● Production incidentPOST-MORTEMseverity: high

The Cookie That Wouldn't Decrypt After Deployment

Symptom
After deploying a new version of an ASP.NET Core app, all existing users were logged out. Authentication cookies became invalid, and users saw '401 Unauthorized' or were redirected to login.
Assumption
The developer assumed that authentication cookies would survive a deployment because the app code didn't change the cookie format.
Root cause
The default key storage for Data Protection is a temporary folder on the server. When the app was redeployed to a new server (or the app pool recycled), the old keys were lost. New keys were generated, but they couldn't decrypt cookies encrypted with the old keys.
Fix
Configured a persistent key store (Azure Blob Storage) and set a shared key encryption key (Azure Key Vault). Also set the key lifetime to 90 days with automatic key generation.
Key lesson
  • Always configure a persistent key store for production (file system, Azure Blob, Redis).
  • Use a key encryption mechanism (like DPAPI or Azure Key Vault) to protect keys at rest.
  • Plan for key rotation: old keys should be kept for decryption until all encrypted data expires.
  • Test deployment scenarios in staging to ensure keys survive restarts.
  • Monitor key expiration and ensure your key management strategy aligns with your data lifetime.
Production debug guideSymptom to Action4 entries
Symptom · 01
Users are logged out after deployment
Fix
Check if keys are stored persistently. Verify key ring exists in the configured store. Ensure key encryption key is accessible.
Symptom · 02
CryptographicException: Key not found
Fix
Check key ring for the key ID. Ensure key hasn't been revoked or expired. Verify the key store is reachable.
Symptom · 03
DataProtectionProvider.CreateProtector fails
Fix
Check service registration: Ensure services.AddDataProtection() is called. Verify dependencies like IDataProtectionProvider are injected correctly.
Symptom · 04
Decryption returns garbled data
Fix
Check that the same purpose string is used for Protect and Unprotect. Verify the data hasn't been tampered with (integrity check).
★ Quick Debug Cheat SheetCommon Data Protection issues and immediate actions
Keys lost after restart
Immediate action
Configure persistent key store
Commands
services.AddDataProtection().PersistKeysToFileSystem(new DirectoryInfo(@"C:\Keys"))
services.AddDataProtection().ProtectKeysWithDpapi()
Fix now
Move keys to a network share or Azure Blob
Decryption fails with CryptographicException+
Immediate action
Check key ring for the key ID
Commands
Use IDataProtectionProvider to list keys (custom code)
Verify key not revoked
Fix now
If key revoked, re-encrypt data with current key
Different instances cannot decrypt each other's data+
Immediate action
Ensure all instances share the same key ring
Commands
Use shared key store (e.g., Redis, Azure Blob)
Set same application name: SetApplicationName("MyApp")
Fix now
Configure identical key store and application name
FeatureData ProtectionManual Encryption
Key ManagementAutomaticManual
Key RotationAutomaticManual
Integrity CheckingBuilt-inRequires HMAC
Ease of UseSimple APIComplex
Production ReadinessHighLow without expertise
⚙ Quick Reference
7 commands from this guide
FileCommand / CodePurpose
BasicUsage.csusing Microsoft.AspNetCore.DataProtection;What is ASP.NET Core Data Protection?
Program.csusing Microsoft.AspNetCore.DataProtection;Configuring Data Protection
KeyLifetimeConfig.csusing Microsoft.AspNetCore.DataProtection;Key Management and Rotation
HomeController.csusing Microsoft.AspNetCore.DataProtection;Using Data Protection in Controllers and Services
CookieProtection.cspublic IActionResult SetCookie()Protecting Cookies and Tokens
TimeLimitedProtection.csusing Microsoft.AspNetCore.DataProtection;Time-Limited Data Protection
DataProtectionTests.csusing Microsoft.AspNetCore.DataProtection;Testing Data Protection

Key takeaways

1
ASP.NET Core Data Protection provides a secure, easy-to-use API for encrypting and decrypting sensitive data with automatic key management.
2
Always configure a persistent key store and protect keys at rest in production.
3
Use unique purpose strings to isolate protectors and handle CryptographicException for tampered data.
4
Leverage time-limited protection for tokens that need expiration.
5
Test your Data Protection implementation, including key rotation scenarios.

Common mistakes to avoid

3 patterns
×

Using the same purpose string for different types of data.

×

Not configuring a persistent key store in production.

×

Ignoring CryptographicException when unprotecting data.

INTERVIEW PREP · PRACTICE MODE

Interview Questions on This Topic

Q01SENIOR
Explain the purpose of the 'purpose' string in Data Protection.
Q02SENIOR
How does ASP.NET Core Data Protection handle key rotation?
Q03SENIOR
What are the security considerations when deploying Data Protection in a...
Q01 of 03SENIOR

Explain the purpose of the 'purpose' string in Data Protection.

ANSWER
The purpose string isolates different protectors. Data protected with one purpose cannot be unprotected with another. It prevents one part of the application from decrypting data meant for another part, adding a layer of security.
FAQ · 4 QUESTIONS

Frequently Asked Questions

01
What is the difference between Data Protection and ASP.NET Core's Identity?
02
Can I use Data Protection to encrypt database columns?
03
How do I share keys between multiple servers?
04
What happens if a key is revoked?
N
Naren Founder & Principal Engineer

20+ years shipping production .NET services in enterprise systems. Written from production experience, not tutorials.

Follow
Verified
production tested
July 13, 2026
last updated
2,043
articles · all by Naren
🔥

That's ASP.NET. Mark it forged?

3 min read · try the examples if you haven't

Previous
ASP.NET Core Identity Complete Guide
35 / 35 · ASP.NET
Next
Unit Testing in C# with xUnit