Cookie authentication has been one of the standard ways to keep users signed in to an ASP.NET Core application.
The model is simple. After a successful login, the server creates an authentication cookie. The browser sends that cookie with later requests, and the application uses it to identify the signed-in user.
The problem is also simple.
If someone steals that cookie, they may be able to use it from another machine.
ASP.NET Core 11 introduces experimental support for Device Bound Session Credentials, commonly called DBSC. The idea is to make a stolen session cookie much less useful by binding session refresh to a private key held by the browser.
Instead of treating the authentication cookie as a credential that can be replayed indefinitely, the application uses a short-lived session cookie and requires the browser to prove that it still owns the associated private key when the session needs to be refreshed.
This article explains how the feature works, how to configure it in ASP.NET Core 11, and what developers should consider before using it in a production application.
The Problem With Traditional Authentication Cookies
Consider a normal cookie-based login.
User logs in
|
v
ASP.NET Core creates authentication cookie
|
v
Browser stores cookie
|
v
Cookie sent with requests
As long as the cookie is valid, the user remains authenticated.
Now imagine that malware, a malicious browser extension, or another attack obtains a copy of the cookie.
The attacker may be able to send that cookie to the application:
Attacker
|
| stolen cookie
v
ASP.NET Core
|
v
Authenticated request
The server normally sees a valid authentication credential.
It does not automatically know whether the request came from the original browser.
This is an important property of bearer-style credentials:
Whoever possesses the credential can potentially use it.
Shorter cookie lifetimes can reduce the attack window, but they do not solve the underlying problem by themselves.
DBSC takes a different approach.
What Is Device Bound Session Credentials?
Device Bound Session Credentials bind session renewal to a private key held by the browser.
The basic idea looks like this:
Browser
|
+-- Private key
|
+-- Public key
|
+-- Short-lived session cookie
The server knows the public key associated with the session.
When the session needs to be refreshed, the browser must prove that it possesses the corresponding private key.
A stolen cookie by itself is therefore not enough to continuously refresh the session.
The important distinction is this:
Traditional cookie
Stolen cookie
|
v
May continue working until expiration
With DBSC:
Stolen session cookie
|
v
Expires relatively quickly
|
X
Cannot be refreshed without browser-held private key
ASP.NET Core 11 provides an experimental server-side implementation through the Microsoft.AspNetCore.Authentication.DeviceBoundSessions package.
How DBSC Works
A simplified DBSC flow looks like this:
1. User signs in
|
v
2. Application establishes authentication
|
v
3. Browser creates or uses a device key
|
v
4. Server associates the session with the public key
|
v
5. Server issues short-lived session credential
|
v
6. Session expires
|
v
7. Browser proves possession of private key
|
v
8. Server issues another short-lived session credential
The private key stays on the browser side.
The server works with the corresponding public key and signed proof.
This is what makes the session different from a normal bearer cookie.
DBSC Uses Existing Cookie Authentication
One useful design choice in ASP.NET Core 11 is that you don't have to replace your existing authentication system.
DBSC wraps an existing cookie authentication scheme.
For example, an application might already have:
builder.Services
.AddAuthentication("Application")
.AddCookie("Application");
DBSC can be added on top of that scheme:
builder.Services
.AddAuthentication("Application")
.AddCookie("Application")
.AddDeviceBoundSession("Application");
You can also configure the short-lived cookie lifetime:
builder.Services
.AddAuthentication("Application")
.AddCookie("Application")
.AddDeviceBoundSession("Application", options =>
{
options.ShortLivedCookieExpiration =
TimeSpan.FromMinutes(10);
});
The default short-lived session cookie expiration is 10 minutes in the current implementation.
The existing application authentication flow can continue using the same source cookie scheme.
Installing the Package
DBSC is provided as a separate package rather than being part of the regular ASP.NET Core authentication package.
Add:
dotnet add package Microsoft.AspNetCore.Authentication.DeviceBoundSessions
The feature is experimental in .NET 11 and remains prerelease while the specification and implementation evolve.
That matters when deciding whether to use it in a production application.
An experimental security API should not be introduced casually into a system that requires long-term API stability.
Basic Configuration
A minimal setup looks like this:
var builder = WebApplication.CreateBuilder(args);
builder.Services
.AddAuthentication("Application")
.AddCookie("Application")
.AddDeviceBoundSession("Application");
var app = builder.Build();
app.UseAuthentication();
app.UseAuthorization();
app.MapControllers();
app.Run();
The DBSC handler sits around the existing cookie authentication scheme.
The application does not need to manually create a separate authentication system for the device-bound session.
Conceptually:
Existing Cookie Authentication
|
v
Device Bound Session
|
v
Short-lived Session
This makes adoption easier for existing ASP.NET Core applications.
Configuring the Session Lifetime
The most obvious option to configure is the lifetime of the short-lived session cookie.
For example:
builder.Services
.AddAuthentication("Application")
.AddCookie("Application")
.AddDeviceBoundSession("Application", options =>
{
options.ShortLivedCookieExpiration =
TimeSpan.FromMinutes(15);
});
A shorter lifetime reduces the amount of time a stolen session credential can remain useful without successful refresh.
But there is a trade-off.
A very short lifetime can increase the frequency of refresh operations.
For example:
5 minutes
|
+-- stronger short-term exposure limit
+-- more frequent refresh
30 minutes
|
+-- fewer refreshes
+-- longer window for a stolen session cookie
There is no universal value that works for every application.
For a banking-style application, the security requirements may justify a shorter lifetime.
For a low-risk internal application, a longer value may be acceptable.
Understanding the Two Cookie Roles
One of the more interesting parts of the implementation is that DBSC does not simply replace the original cookie with another cookie.
The implementation uses separate roles for the long-lived authentication information and the short-lived device-bound session.
Conceptually:
Long-lived cookie
|
+-- Authentication ticket
+-- Public key information
Short-lived session cookie
|
+-- Current authenticated session
The long-lived cookie acts somewhat like the credential that allows the session to be refreshed, while the short-lived cookie is the credential actually used for normal authentication.
The browser's private key is required when refreshing the session.
This means stealing only the short-lived cookie is less valuable than stealing a traditional long-lived authentication cookie.
What Happens When the Session Expires?
Suppose the session cookie expires.
The browser needs to refresh it.
The simplified process is:
Session cookie expired
|
v
Browser sends refresh request
|
v
Browser signs proof with private key
|
v
Server validates proof
|
v
Server issues new session cookie
If the attacker only has the copied session cookie but does not have the corresponding private key:
Attacker
|
+-- Stolen cookie
|
X-- No private key
the attacker cannot perform the same refresh operation.
This is the main security benefit of device binding.
Using DBSC With ASP.NET Core Identity
ASP.NET Core Identity is a particularly useful scenario because Identity already uses cookie authentication.
For example:
builder.Services
.AddDefaultIdentity<IdentityUser>()
.AddEntityFrameworkStores<ApplicationDbContext>();
builder.Services
.AddAuthentication()
.AddDeviceBoundSession(
IdentityConstants.ApplicationScheme);
The existing Identity application cookie can become the source authentication scheme for DBSC.
That means application code such as:
[Authorize]
public class AccountModel : PageModel
{
public void OnGet()
{
var userName = User.Identity?.Name;
}
}
does not need to be rewritten just because DBSC is enabled.
The authentication system handles the additional device-bound session layer.
What About Existing Logged-In Users?
One practical question is what happens when an application already has thousands of authenticated users.
You may not want to force everyone to log in again.
The DBSC implementation provides a mechanism for an application to advertise registration to an already-authenticated browser.
Conceptually:
Existing user
|
v
Already authenticated
|
v
Application offers DBSC registration
|
v
Browser registers device key
|
v
Future sessions use device-bound credentials
The application can use WriteDeviceBoundSessionRegistration for this type of migration.
A simplified example is:
app.Use(async (context, next) =>
{
if (context.User.Identity?.IsAuthenticated == true)
{
context.WriteDeviceBoundSessionRegistration(
IdentityConstants.ApplicationScheme);
}
await next();
});
In a real application, you should not blindly emit a new registration challenge on every response.
The application should control when registration is offered and avoid repeatedly creating new challenges.
The current implementation specifically leaves this idempotency decision to the caller.
Registration and Refresh Endpoints
DBSC uses dedicated endpoints for registration and refresh.
The default paths are:
/.well-known/dbsc/registration
/.well-known/dbsc/refresh
These are handled by the DBSC authentication component.
You can customize them if your application requires different paths:
builder.Services
.AddAuthentication("Application")
.AddCookie("Application")
.AddDeviceBoundSession("Application", options =>
{
options.RegistrationPath =
"/.well-known/dbsc/registration";
options.RefreshPath =
"/.well-known/dbsc/refresh";
});
The implementation expects these paths to be application-local root-relative paths rather than arbitrary full URLs.
HTTPS Is Important
Device-bound authentication depends on secure browser communication.
Do not treat this feature as something that makes plain HTTP authentication safe.
Your application should already be correctly configured for HTTPS.
For example:
if (!app.Environment.IsDevelopment())
{
app.UseHsts();
}
app.UseHttpsRedirection();
Behind a reverse proxy or load balancer, forwarded headers also need to be configured correctly.
A deployment that incorrectly reports HTTP when the original request was HTTPS can cause authentication and security features to behave incorrectly.
For security-sensitive authentication, infrastructure configuration matters just as much as application code.
Device Binding Does Not Replace Authorization
This is an important distinction.
DBSC helps answer:
Is this browser able to prove possession
of the device-bound private key?
It does not answer:
Is this user allowed to delete this customer?
You still need normal authorization:
[Authorize(Policy = "CanDeleteCustomer")]
public async Task<IActionResult> Delete(int id)
{
// Authorization and business rules still apply.
}
Think of the security layers separately:
Authentication
|
v
Who is this user?
Device Binding
|
v
Is this session tied to the expected browser key?
Authorization
|
v
What is this user allowed to do?
DBSC improves the first part of the security chain. It does not eliminate the need for the other parts.
DBSC Is Not a Replacement for Multi-Factor Authentication
Device binding and MFA solve different problems.
MFA helps verify that the person logging in has an additional factor such as:
Authenticator app
Hardware security key
One-time code
Passkey
DBSC helps protect an already-authenticated browser session from cookie theft and replay.
A strong application may use both:
Login
|
+-- Password / Passkey
|
+-- MFA
|
v
Authenticated session
|
v
Device-bound session
Each layer addresses a different part of the threat model.
What Happens If the Device Key Is Lost?
This is one of the operational questions you should consider before deploying DBSC.
The device key belongs to the browser environment.
If the browser profile is removed, the device is reset, or the relevant key becomes unavailable, the user may no longer be able to refresh the device-bound session.
The application therefore needs a recovery path.
A common approach is to allow the user to authenticate again:
DBSC refresh fails
|
v
Require normal sign-in
|
v
Create new device-bound session
This is similar to many other security mechanisms.
A stronger credential usually requires a recovery mechanism.
Handling Sign-Out
Signing out should remove the DBSC-derived credentials as well as the original authentication state.
The application should therefore continue to use the normal authentication APIs rather than manually deleting individual cookies.
For example:
await HttpContext.SignOutAsync("Application");
The DBSC implementation handles its derived session and refresh state as part of the authentication flow.
This is another reason to configure DBSC around the existing authentication scheme instead of manually building a parallel cookie system.
Browser Support Is a Major Consideration
There is one limitation developers need to understand immediately.
The browser must support DBSC.
The ASP.NET Core server implementation cannot create browser support where none exists.
Microsoft currently describes browser support as requiring an experimental DBSC implementation.
That means you should not assume that every client will immediately use device-bound sessions.
Before adopting the feature, test the browsers and environments used by your customers.
This is particularly important for:
Enterprise applications
Older browsers
Embedded web views
Managed corporate devices
Mobile browsers
Automated browser clients
What Happens for Unsupported Browsers?
Your application should have a sensible fallback strategy.
Conceptually:
Browser
|
v
Supports DBSC?
|
+---- Yes ----> Device-bound session
|
+---- No -----> Existing authentication flow
The exact fallback behavior depends on your application's authentication requirements.
For some high-security applications, you may decide that DBSC-capable clients are required.
For a general public website, maintaining normal authentication for unsupported browsers may be more practical.
DBSC and Distributed Applications
A common question is whether device-bound sessions work with multiple application servers.
The important point is that the authentication system still needs to be configured correctly across the deployment.
For example:
Load Balancer
|
+----------+----------+
| |
v v
Server A Server B
| |
+----------+----------+
|
Shared secrets /
key configuration
ASP.NET Core authentication already has requirements around shared Data Protection keys in multi-instance deployments.
DBSC does not remove those requirements.
If different instances cannot validate the same authentication state, users may experience unexpected authentication failures after load balancing.
Test DBSC in an environment that matches the real deployment rather than only testing it on localhost.
Security Benefits
The biggest benefit is reducing the value of a stolen session cookie.
With a traditional long-lived cookie:
Cookie stolen
|
v
Attacker may replay it
|
v
Access continues until expiration/revocation
With DBSC:
Session cookie stolen
|
v
Short expiration
|
v
Refresh required
|
v
Private key required
|
X
Attacker cannot refresh without key
This does not make cookie theft irrelevant.
A stolen short-lived session may still be usable until it expires.
That is why the feature should be understood as reducing the attack window and improving resistance to session replay, not as making session theft impossible.
Common Mistakes
Treating DBSC as a Complete Authentication Solution
It is an additional security mechanism, not a replacement for authorization, MFA, secure cookies, or proper identity management.
Ignoring Browser Compatibility
The server cannot force a browser to support DBSC.
Test the browsers your users actually use.
Making the Session Lifetime Too Long
A very long session lifetime weakens one of the benefits of the design.
Choose a lifetime based on the application's risk level.
Forgetting Recovery
Users can lose browser state.
Make sure there is a safe way to authenticate again and establish a new device-bound session.
Rewriting the Existing Authentication System
DBSC is designed to wrap an existing cookie authentication scheme.
Use that model instead of creating a second independent authentication implementation.
Assuming a Bound Session Means the User Is Authorized
Device binding proves possession of the browser-held key. It does not grant permissions.
Continue enforcing authorization and business rules on every sensitive operation.
When Should You Consider DBSC?
DBSC is particularly interesting for applications where stolen authentication cookies are a meaningful threat.
Examples include:
Banking applications
Financial dashboards
Enterprise administration portals
Cloud management systems
Customer account portals
Internal business systems containing sensitive data
Applications with long-lived login sessions
For a small public website with low-risk data, the additional complexity may not justify adopting an experimental authentication feature yet.
Security should always be evaluated against the application's actual threat model.
A Practical ASP.NET Core 11 Setup
A simple starting configuration can look like this:
var builder = WebApplication.CreateBuilder(args);
builder.Services
.AddAuthentication("Application")
.AddCookie("Application", options =>
{
options.Cookie.HttpOnly = true;
options.Cookie.SecurePolicy =
CookieSecurePolicy.Always;
options.Cookie.SameSite =
SameSiteMode.Lax;
})
.AddDeviceBoundSession("Application", options =>
{
options.ShortLivedCookieExpiration =
TimeSpan.FromMinutes(10);
options.ChallengeMaxAge =
TimeSpan.FromMinutes(5);
});
builder.Services.AddAuthorization();
var app = builder.Build();
app.UseHttpsRedirection();
app.UseAuthentication();
app.UseAuthorization();
app.MapControllers();
app.Run();
Because the DBSC APIs are experimental, your project may need to explicitly suppress the ASP0031 diagnostic when evaluating the feature.
For example:
#pragma warning disable ASP0031
Do this deliberately rather than suppressing all compiler or analyzer warnings globally.
The warning exists because the API is still subject to change.
Production Checklist
Before enabling DBSC in a real application, check these areas:
Confirm the application is fully HTTPS.
Test all supported browsers.
Decide on an appropriate short-lived session lifetime.
Keep authorization checks independent from authentication.
Provide a re-login recovery path.
Test sign-out behavior.
Test password changes and account revocation.
Test multiple application instances.
Verify Data Protection configuration across servers.
Test reverse-proxy deployments.
Monitor authentication failures.
Avoid exposing authentication internals in error messages.
Review the DBSC specification and current browser support.
Remember that the .NET 11 API is experimental.
Summary
ASP.NET Core 11's Device Bound Session Credentials support addresses a real weakness of traditional cookie authentication: a stolen cookie can otherwise be replayed from another device.
DBSC changes the model by using a browser-held private key to protect session refresh. The application can issue a short-lived session cookie, and the browser must prove that it still owns the associated private key when the session needs to continue.
The good part for ASP.NET Core developers is that DBSC works around an existing cookie authentication scheme. You do not need to throw away your current Identity or cookie-based authentication setup.
There are still important limitations. Browser support is experimental, the ASP.NET Core package itself is experimental, and applications need proper recovery, authorization, HTTPS, and multi-server configuration.
For applications where session-cookie theft is a serious concern, DBSC is an interesting security improvement to evaluate. But because the API and browser ecosystem are still evolving, it should be introduced carefully rather than treated as a drop-in replacement for every authentication system.
Join the conversation! Your thoughts help the community grow.