.NET Data Protection and Authentication Cookies
The ASP.NET Core Data Protection stack is an essential component for encrypting and tamper-proofing sensitive data such as authentication cookies and CSRF tokens. This document explains the role of Data Protection Keys (key rings) in authentication cookies, how to manage them, and emergency response measures in the event of an authentication server leak.
Overview of Data Protection API (DPAPI)
The ASP.NET Core Data Protection API provides a simple API for applications to encrypt and decrypt data.
Role in Authentication Cookies
ASP.NET Core Identity and Cookie authentication middleware create an authentication ticket containing the user's ID and claims, which is then encrypted and stored in a cookie. This encryption uses the Data Protection Key (Key Ring).
- Create Authentication Ticket: Create an authentication ticket from user information (ClaimsPrincipal).
- Serialize and Protect: Serialize the ticket and encrypt/sign it using the Data Protection Provider.
- Issue Cookie: Send the protected payload to the client as a cookie (e.g.,
.AspNetCore.Cookies).
When the cookie is sent back from the client, the server uses the same key ring to decrypt the cookie and verify that it has not been tampered with.
Handling Data Protection in .NET
By default, ASP.NET Core automatically manages keys based on the local file system or environment variables, but explicit configuration is required for production environments (especially multi-instance configurations).
Basic Configuration (Program.cs)
using Microsoft.AspNetCore.DataProtection;
var builder = WebApplication.CreateBuilder(args);
// Configure Data Protection
builder.Services.AddDataProtection()
// Key storage location (e.g., Azure Blob Storage)
.PersistKeysToAzureBlobStorage(new Uri("https://<storage-account>.blob.core.windows.net/keys/keys.xml"), new DefaultAzureCredential())
// Key encryption (e.g., Azure Key Vault)
.ProtectKeysWithAzureKeyVault(new Uri("https://<key-vault>.vault.azure.net/keys/dataprotection"), new DefaultAzureCredential())
// Application Identifier (to share keys between different instances of the same app)
.SetApplicationName("MyApplication");
var app = builder.Build();
Key Persistence and Sharing
In a multi-server configuration behind a load balancer (Web Farm) or container environment (Kubernetes), all instances must share the same key ring.
- Key Storage Location: Store in shared storage (Azure Blob Storage, AWS S3, Redis, SQL Server) rather than local disk.
- Encryption at Rest: It is recommended to encrypt the keys themselves when stored (Azure Key Vault, X.509 certificate, etc.).
If each server has a different key, server B cannot decrypt the cookie of a user who logged in on server A, and the login state will not be maintained.
Response to OpenID Connect (OIDC) Auth Server Compromise
If user information from an OAuth 2.0 / OpenID Connect compliant authentication server (IdP) is leaked externally, or if the signing key is compromised, prompt action is required on the Relying Party (RP) Web application side as well.
Potential Risks
- Token Forgery: If the signing key is leaked, an attacker could potentially issue ID tokens or access tokens impersonating any user.
- Existing Session Hijacking: Valid authentication cookies and refresh tokens could be abused.
Response Flow
-
Response on the Authentication Server Side (IdP)
- Rotation of the compromised signing key (revocation and new issuance).
- Password reset and session invalidation for known leaked accounts.
-
Response on the Web Application Side (RP)
- Update OIDC Settings: Re-acquire the latest public key from the IdP's metadata endpoint (
.well-known/openid-configuration) (usually automatic, but beware of caching periods). - Force Logout for All Users: Invalidate all currently valid authentication cookies.
- Update OIDC Settings: Re-acquire the latest public key from the IdP's metadata endpoint (
Force Logout by Invalidating Data Protection Keys
One of the most reliable and powerful means of forced logout is to revoke the current Data Protection Key. This makes all authentication cookies encrypted with the old key undecryptable, putting all users immediately into an unauthenticated state.
How to Invalidate Keys
The ASP.NET Core IDataProtectionProvider manages keys through an IXmlRepository. While there is no direct API exposed by default to invalidate a specific key, operational methods include:
1. Delete/Back up Key Files (File System/Blob)
Delete or move the XML file on the storage where the keys are kept, and restart the application.
- Impact: All past protected data (authentication cookies, CSRF tokens, etc.) becomes unreadable.
- Behavior: The application generates a new key upon startup, and subsequent logins use the new key.
2. Change Application Name
Changing the identifier in .SetApplicationName("MyApplication") creates a logical separation, making data protected with the previous application name undecryptable.
// Before change
// .SetApplicationName("MyApp_v1");
// After change
.SetApplicationName("MyApp_v2_Revoked20240301");
- Pros: Completed with just a code change and deployment.
- Cons: Other persisted data (e.g., if you encrypted data with DPAPI and stored it in a DB) will also become unreadable, so scope assessment is necessary. Effective when targeting only authentication cookies.
3. Programmatic Revocation using IKeyManager (Advanced)
Using the Microsoft.AspNetCore.DataProtection.KeyManagement.IKeyManager interface allows you to revoke specific keys programmatically, but this is less common in typical Web App implementations.
Best Practice: Regular Key Rotation
Key rotation occurs automatically during normal operation (default is 90 days), not just in emergencies. It is recommended to document the following steps as part of your compromise response plan.
- Incident Occurrence: Receive compromise notification from IdP.
- Identify Scope: Confirm if only authentication sessions are affected or if stored data is also involved.
- Execute Key Revocation:
- Change
ApplicationNamefor the entire Web Farm and redeploy. - Or, archive the key file on shared storage and recycle the app pool.
- Change
- Notify Users: Inform all users that re-login is required for security reasons.
Summary
- Data Protection is the cornerstone of ASP.NET Core security, ensuring the safety of authentication cookies.
- In case of external IdP compromise, session invalidation is required on the RP side as well as the IdP side.
- Invlidating Keys (changing ApplicationName, etc.) acts as a powerful kill switch to force logout all users.
- In production environments, properly configuring Persistence and Protection of keys to maintain consistency across instances is crucial.