You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
description: Comprehensive guide covering key aspects of ASP.NET Core Data Protection.
4
+
date: 2026-03-26T08:20:20+02:00
5
+
sidebar:
6
+
label: Data Protection
7
+
order: 9
8
+
redirect_from:
9
+
- /dataprotection/
10
+
---
11
+
12
+
Any Duende server-side application, like IdentityServer or BFF, is developed and deployed as an ASP.NET Core application. While there are a lot of decisions to make, this also means that your implementation can be built, deployed, hosted, and managed with the same technology you're using for any other ASP.NET applications you have.
13
+
14
+
It is important to correctly configure ASP.NET Core Data Protection in your application.
15
+
16
+
:::tip
17
+
Some of our most common support requests are related to [Data Protection Keys](#data-protection-keys). We strongly encourage you to review the rest of this page before deploying to production.
18
+
:::
19
+
20
+
## About ASP.NET Core Data Protection
21
+
22
+
Duende's SDKs, like IdentityServer and BFF, make extensive use of ASP.NET's [data protection](https://docs.microsoft.com/en-us/aspnet/core/security/data-protection/) feature. It is crucial that you configure data protection correctly when deploying your application in production.
23
+
24
+
In local development, ASP.NET automatically creates data protection keys, but in a deployed environment, you will need
25
+
to ensure that your data protection keys are stored in a persistent way and shared across all load balanced instances of
26
+
your implementation. This means you'll need to choose where to store and how to protect the data
27
+
protection keys, as appropriate for your environment. Microsoft has [extensive
28
+
documentation on data protection](https://learn.microsoft.com/en-us/aspnet/core/security/data-protection/configuration/overview)
29
+
describing how to configure storage and protection of data protection keys.
30
+
31
+
A typical implementation should include data protection configuration code, like this:
32
+
33
+
```csharp
34
+
// Program.cs
35
+
builder.Services.AddDataProtection()
36
+
// Choose an extension method for key persistence, such as
// Explicitly set an application name to prevent issues with
45
+
// key isolation.
46
+
.SetApplicationName("My.Duende.IdentityServer");
47
+
```
48
+
49
+
:::danger[Ensure data protection keys are persisted]
50
+
Always make sure data protection is configured to persist data protection keys to storage, using `.PersistKeysTo...()`
51
+
for your storage mechanism. If you lose your data protection keys, all data protected with those keys is no longer be readable.
52
+
53
+
Additionally, ensure the storage mechanism itself is durable. For example, if you are using the default file system
54
+
based key store, make sure that the configured path is not stored on ephemeral storage. If you are using Redis to store
55
+
data protection keys using `PersistKeysToStackExchangeRedis()`, ensure that your Redis service is configured to persist
56
+
data to a database backup or append-only file. Otherwise, you will lose all data protection keys when your Redis instance reboots.
57
+
58
+
For a more advanced setup, you can create a [key escrow sink](https://learn.microsoft.com/en-us/aspnet/core/security/data-protection/extensibility/key-management?view=aspnetcore-10.0#xmlkeymanager), allowing you to store new data protection keys into
59
+
a secure storage (e.g., Azure Key Vault) before the new keys are encrypted.
60
+
This enables you to restore existing data protection keys in case they become corrupted or lost.
61
+
:::
62
+
63
+
## Common Problems
64
+
65
+
Common data protection problems occur when data is protected with a key that is not available when the data is later
66
+
read. A common symptom is `CryptographicException`s in the application logs. For example, when IdentityServer's automatic key
67
+
management fails to read its signing keys due to a data protection failure, it will log an error message
68
+
such as `"Error unprotecting key with kid {Signing Key ID}."`, and log the underlying
69
+
`System.Security.Cryptography.CryptographicException`, with a message like `"The key {Data Protection Key ID} was not
70
+
found in the key ring."`
71
+
72
+
Failures to read automatic signing keys are often the first place where a data protection problem manifests, but any of
73
+
many places where ASP.NET uses data protection might also throw `CryptographicException`s.
74
+
75
+
There are several ways that data protection problems can occur:
76
+
77
+
1. In load balanced environments, every instance of a Duende server-side app needs to be configured to share data protection keys.
78
+
Without shared data protection keys, each load balanced instance will only be able to read the data that it writes.
79
+
2. Data protected data could be generated in a development environment and then accidentally included into the build
80
+
output. This is most commonly the case for automatically managed signing keys that are stored on disk. If you are
81
+
using automatic signing key management with the default file system based key store, you should exclude the `~/keys`
82
+
directory from source control and make sure keys are not included in your builds. Note that if you are using our
83
+
Entity Framework based implementation of the operational data stores, then the keys will instead be stored in the
84
+
database.
85
+
3. Data protection derives keys isolated per application name from the generated key material. If you don't specify a name,
86
+
the content root path of the application will be used. In .NET 6.0, Microsoft introduced a breaking change: they changed
87
+
how ASP.NET Core sets the content root path, which can cause Data Protection issues. This change was reverted in .NET 7.0,
88
+
and Microsoft has [documented a workaround in case your application has to restore the correct application name](https://learn.microsoft.com/en-us/aspnet/core/security/data-protection/configuration/overview#set-the-application-name-setapplicationname).
89
+
A better solution is to always specify an explicit application name, but know that changing the application name will
90
+
cause all existing data protected with the previous application name to become unreadable.
91
+
4. When hosting your web application on Microsoft IIS, [special configuration may be required for data protection](https://learn.microsoft.com/en-us/aspnet/core/host-and-deploy/iis/advanced#data-protection).
92
+
In most default deployments, IIS falls back to using an ephemeral storage for data protection keys, which means that
93
+
new keys are generated every time the application pool restarts. We recommend storing data protection keys in a shared location,
94
+
such as a protected file share or database, and configuring IIS to use that location for data protection.
describing how to configure storage and protection of data protection keys.
98
+
The recommended practices for setting up and using ASP.NET Core Data Protection for Duende IdentityServer are the same as for other server-side products, like BFF. See the [general ASP.NET Core Data Protection page](/general/data-protection).
105
99
106
-
A typical IdentityServer implementation should include data protection configuration code, like this:
107
-
108
-
```csharp
109
-
// Program.cs
110
-
builder.Services.AddDataProtection()
111
-
// Choose an extension method for key persistence, such as
// Explicitly set an application name to prevent issues with
120
-
// key isolation.
121
-
.SetApplicationName("IdentityServer");
122
-
```
123
-
124
-
:::danger[Ensure data protection keys are persisted]
125
-
Always make sure data protection is configured to persist data protection keys to storage, using `.PersistKeys...()`
126
-
for your storage mechanism.
127
-
128
-
In addition, make sure the storage mechanism itself is durable. For example, if you are using the default file system
129
-
based key store, make sure that the configured path is not stored on ephemeral storage. If you are using Redis to store
130
-
data protection keys using `PersistKeysToStackExchangeRedis`, ensure that your Redis service is configured to persist
131
-
data to a database backup or append-only file. Otherwise, when your Redis instance reboots, you will lose all data
132
-
protection keys.
133
-
134
-
If you lose your data protection keys, all data protected with those keys to no longer be readable.
135
-
:::
136
-
137
-
### Data Protection Keys and IdentityServer's Signing Keys
100
+
### ASP.NET Data Protection Keys and IdentityServer Signing Keys
138
101
139
102
ASP.NET's data protection keys are sometimes confused with IdentityServer's signing keys, but the two are completely
140
103
separate keys with different purposes. IdentityServer implementations need both to function correctly.
141
104
142
-
#### Data Protection Keys
105
+
#### ASP.NET Data Protection Keys
143
106
144
-
Data protection is a cryptographic library that is part of the ASP.NET framework. Data protection uses private key
107
+
Data protection is a cryptographic library that is part of ASP.NET Core. Data protection uses private key
145
108
cryptography to encrypt and sign sensitive data to ensure that it is only written and read by the application. The
146
109
framework uses data protection to secure data that is commonly used by IdentityServer implementations, such as
147
110
authentication cookies and anti-forgery tokens. In addition, IdentityServer itself uses data protection to protect
@@ -150,7 +113,7 @@ context objects passed to pages in the UI. The data protection keys are critical
150
113
implementation because they encrypt a great deal of sensitive data at rest and prevent sensitive data that is
151
114
round-tripped through the browser from being tampered with.
152
115
153
-
#### IdentityServer Signing Key
116
+
#### The IdentityServer Signing Key
154
117
155
118
Separately, IdentityServer needs cryptographic keys, called [signing keys](/identityserver/fundamentals/key-management.md), to
156
119
sign tokens such as JWT access tokens and id tokens. The signing keys use public key cryptography to allow client
@@ -159,56 +122,7 @@ through [discovery](/identityserver/reference/endpoints/discovery.md). The priva
159
122
also critical secrets for IdentityServer because a valid signature provides integrity and non-repudiation guarantees
160
123
that allow client applications and APIs to trust those tokens.
161
124
162
-
### Common Problems
163
-
164
-
Common data protection problems occur when data is protected with a key that is not available when the data is later
165
-
read. A common symptom is `CryptographicException`s in the IdentityServer logs. For example, when automatic key
166
-
management fails to read its signing keys due to a data protection failure, IdentityServer will log an error message
167
-
such as "Error unprotecting key with kid {Signing Key ID}.", and log the underlying
168
-
`System.Security.Cryptography.CryptographicException`, with a message like "The key {Data Protection Key ID} was not
169
-
found in the key ring."
170
-
171
-
Failures to read automatic signing keys are often the first place where a data protection problem manifests, but any of
172
-
many places where IdentityServer and ASP.NET use data protection might also throw `CryptographicException`s.
173
-
174
-
There are several ways that data protection problems can occur:
175
-
176
-
1. In load balanced environments, every instance of IdentityServer needs to be configured to share data protection keys.
177
-
Without shared data protection keys, each load balanced instance will only be able to read the data that it writes.
178
-
2. Data protected data could be generated in a development environment and then accidentally included into the build
179
-
output. This is most commonly the case for automatically managed signing keys that are stored on disk. If you are
180
-
using automatic signing key management with the default file system based key store, you should exclude the `~/keys`
181
-
directory from source control and make sure keys are not included in your builds. Note that if you are using our
182
-
Entity Framework based implementation of the operational data stores, then the keys will instead be stored in the
183
-
database.
184
-
3. Data protection creates keys isolated by application name. If you don't specify a name, the content root path of the
185
-
application will be used. But, beginning in .NET 6.0 Microsoft changed how they handle the path, which can cause data
186
-
protection keys to break. Their docs on the problem
187
-
are [here](https://learn.microsoft.com/en-us/aspnet/core/security/data-protection/configuration/overview#setapplicationname),
188
-
including a work-around where you de-normalize the path. Then, in .NET 7.0, this change was reverted. The solution is
189
-
always to specify an explicit application name, and if you have old keys that were generated without an explicit
190
-
application name, you need to set your application name to match the default behavior that produced the keys you want
191
-
to be able to read.
192
-
4. If your IdentityServer is hosted by IIS, special configuration is needed for data protection. In most default
193
-
deployments, IIS lacks the permissions required to persist data protection keys, and falls back to using an ephemeral
194
-
key generated every time the site starts up. Microsoft's docs on this issue
195
-
are [here](https://learn.microsoft.com/en-us/aspnet/core/host-and-deploy/iis/advanced?view=aspnetcore-7.0#data-protection).
196
-
197
-
### Identity Server's Usage of Data Protection
198
-
199
-
Duende IdentityServer's features that rely on data protection include
200
-
201
-
* protecting signing keys at rest (
202
-
if [automatic key management](/identityserver/fundamentals/key-management.md#automatic-key-management) is used and enabled)
203
-
* protecting [persisted grants](/identityserver/data/operational.md#persisted-grant-service) at rest (if enabled)
204
-
* protecting [server-side session](/identityserver/ui/server-side-sessions/index.md) data at rest (if enabled)
205
-
* protecting [the state parameter](/identityserver/ui/login/external.md#state-url-length-and-isecuredataformat) for
206
-
external OIDC providers (if enabled)
207
-
* protecting message payloads sent between pages in the UI (
208
-
e.g. [logout context](/identityserver/ui/logout/logout-context.md) and [error context](/identityserver/ui/error.md)).
209
-
* session management (because the ASP.NET Core cookie authentication handler requires it)
210
-
211
-
## IdentityServer Data Stores
125
+
### IdentityServer Data Stores
212
126
213
127
IdentityServer itself is stateless and does not require server affinity - but there is data that needs to be shared between in multi-instance deployments.
214
128
@@ -233,6 +147,18 @@ You can either use a traditional database for storing operational data, or use a
233
147
234
148
Duende IdentityServer includes storage implementations for above data using EntityFramework, and you can build your own. See the [data stores](/identityserver/data) section for more information.
235
149
150
+
### IdentityServer Features Using Data Protection
151
+
152
+
Duende IdentityServer's features that rely on data protection include:
153
+
154
+
* protecting signing keys at rest (if [automatic key management](/identityserver/fundamentals/key-management.md#automatic-key-management) is used and enabled)
155
+
* protecting [persisted grants](/identityserver/data/operational.md#persisted-grant-service) at rest (if enabled)
156
+
* protecting [server-side session](/identityserver/ui/server-side-sessions/index.md) data at rest (if enabled)
157
+
* protecting [the state parameter](/identityserver/ui/login/external.md#state-url-length-and-isecuredataformat) for
158
+
external OIDC providers (if enabled)
159
+
* protecting message payloads sent between pages in the UI (e.g. [logout context](/identityserver/ui/logout/logout-context.md) and [error context](/identityserver/ui/error.md)).
160
+
* session management (because the ASP.NET Core cookie authentication handler requires it)
161
+
236
162
## Distributed Caching
237
163
238
164
Some optional features rely on ASP.NET Core distributed caching:
0 commit comments