Events
Power BI DataViz World Championships
Feb 14, 4 PM - Mar 31, 4 PM
With 4 chances to enter, you could win a conference package and make it to the LIVE Grand Finale in Las Vegas
Learn moreThis browser is no longer supported.
Upgrade to Microsoft Edge to take advantage of the latest features, security updates, and technical support.
Websites often consist of individual web apps working together. To provide a single sign-on (SSO) experience, web apps within a site must share authentication cookies. To support this scenario, the data protection stack allows sharing Katana cookie authentication and ASP.NET Core cookie authentication tickets.
In the examples that follow:
.AspNet.SharedCookie
.AuthenticationType
is set to Identity.Application
either explicitly or by default.SharedCookieApp
, is used to enable the data protection system to share data protection keys.Identity.Application
is used as the authentication scheme. Whatever scheme is used, it must be used consistently within and across the shared cookie apps either as the default scheme or by explicitly setting it. The scheme is used when encrypting and decrypting cookies, so a consistent scheme must be used across apps.DataProtectionProvider
provides data protection services for the encryption and decryption of authentication cookie payload data. The DataProtectionProvider
instance is isolated from the data protection system used by other parts of the app. DataProtectionProvider.Create(System.IO.DirectoryInfo, Action<IDataProtectionBuilder>) accepts a DirectoryInfo to specify the location for data protection key storage.DataProtectionProvider
requires the Microsoft.AspNetCore.DataProtection.Extensions NuGet package:
When using ASP.NET Core Identity:
SharedCookieApp
in the following examples). For more information, see Configure ASP.NET Core Data Protection.Identity.Application
.In Program.cs
:
using Microsoft.AspNetCore.DataProtection;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddRazorPages();
builder.Services.AddDataProtection()
.PersistKeysToFileSystem(new DirectoryInfo(@"c:\PATH TO COMMON KEY RING FOLDER"))
.SetApplicationName("SharedCookieApp");
builder.Services.ConfigureApplicationCookie(options => {
options.Cookie.Name = ".AspNet.SharedCookie";
});
var app = builder.Build();
Note: The preceding instructions don't work with ITicketStore
(CookieAuthenticationOptions.SessionStore
). For more information, see this GitHub issue.
For security reasons, authentication cookies are not compressed in ASP.NET Core. When using authentication cookies, developers should minimize the number of claim information included to just that necessary for their needs.
When using cookies directly without ASP.NET Core Identity, configure data protection and authentication. In the following example, the authentication type is set to Identity.Application
:
using Microsoft.AspNetCore.DataProtection;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddRazorPages();
builder.Services.AddDataProtection()
.PersistKeysToFileSystem(new DirectoryInfo(@"c:\PATH TO COMMON KEY RING FOLDER"))
.SetApplicationName("SharedCookieApp");
builder.Services.AddAuthentication("Identity.Application")
.AddCookie("Identity.Application", options =>
{
options.Cookie.Name = ".AspNet.SharedCookie";
});
var app = builder.Build();
For security reasons, authentication cookies are not compressed in ASP.NET Core. When using authentication cookies, developers should minimize the number of claim information included to just that necessary for their needs.
An authentication cookie uses the HttpRequest.PathBase as its default Cookie.Path. If the app's cookie must be shared across different base paths, Path
must be overridden:
using Microsoft.AspNetCore.DataProtection;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddRazorPages();
builder.Services.AddDataProtection()
.PersistKeysToFileSystem(new DirectoryInfo(@"c:\PATH TO COMMON KEY RING FOLDER"))
.SetApplicationName("SharedCookieApp");
builder.Services.ConfigureApplicationCookie(options => {
options.Cookie.Name = ".AspNet.SharedCookie";
options.Cookie.Path = "/";
});
var app = builder.Build();
When hosting apps that share cookies across subdomains, specify a common domain in the Cookie.Domain property. To share cookies across apps at contoso.com
, such as first_subdomain.contoso.com
and second_subdomain.contoso.com
, specify the Cookie.Domain
as .contoso.com
:
options.Cookie.Domain = ".contoso.com";
For production deployments, configure the DataProtectionProvider
to encrypt keys at rest with DPAPI or an X509Certificate. For more information, see Key encryption at rest in Windows and Azure using ASP.NET Core. In the following example, a certificate thumbprint is provided to ProtectKeysWithCertificate:
using Microsoft.AspNetCore.DataProtection;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddRazorPages();
builder.Services.AddDataProtection()
.ProtectKeysWithCertificate("{CERTIFICATE THUMBPRINT}");
When apps use the same Identity schema (same version of Identity), confirm that the Identity system for each app is pointed at the same user database. Otherwise, the identity system produces failures at runtime when it attempts to match the information in the authentication cookie against the information in its database.
When the Identity schema is different among apps, usually because apps are using different Identity versions, sharing a common database based on the latest version of Identity isn't possible without remapping and adding columns in other app's Identity schemas. It's often more efficient to upgrade the other apps to use the latest Identity version so that a common database can be shared by the apps.
In .NET 6, WebApplicationBuilder normalizes the content root path to end with a DirectorySeparatorChar. Most apps migrating from HostBuilder or WebHostBuilder won't have the same app name because they aren't normalized. For more information, see SetApplicationName
ASP.NET 4.x apps that use Microsoft.Owin Cookie Authentication Middleware can be configured to generate authentication cookies that are compatible with the ASP.NET Core Cookie Authentication Middleware. This can be useful if a web application consists of both ASP.NET 4.x apps and ASP.NET Core apps that must share a single sign-on experience. A specific example of such a scenario is incrementally migrating a web app from ASP.NET to ASP.NET Core. In such scenarios, it's common for some parts of an app to be served by the original ASP.NET app while others are served by the new ASP.NET Core app. Users should only have to sign in once, though. This can be accomplished by either of the following approaches:
To configure ASP.NET Microsoft.Owin Cookie Authentication Middleware to share cookies with an ASP.NET Core app, follow the preceding instructions to configure the ASP.NET Core app to use a specific cookie name, app name, and to persist data protection keys to a well-known location. See Configure ASP.NET Core Data Protection for more information on persisting data protection keys.
In the ASP.NET app, install the Microsoft.Owin.Security.Interop
package.
Update the UseCookieAuthentication
call in Startup.Auth.cs to configure an AspNetTicketDataFormat to match the ASP.NET Core app's settings:
app.UseCookieAuthentication(new CookieAuthenticationOptions
{
LoginPath = new PathString("/Account/Login"),
Provider = new CookieAuthenticationProvider
{
OnValidateIdentity = SecurityStampValidator.OnValidateIdentity<ApplicationUserManager, ApplicationUser>(
validateInterval: TimeSpan.FromMinutes(30),
regenerateIdentity: (manager, user) => user.GenerateUserIdentityAsync(manager))
},
// Settings to configure shared cookie with ASP.NET Core app
CookieName = ".AspNet.ApplicationCookie",
AuthenticationType = "Identity.Application",
TicketDataFormat = new AspNetTicketDataFormat(
new DataProtectorShim(
DataProtectionProvider.Create(new DirectoryInfo(@"c:\PATH TO COMMON KEY RING FOLDER"),
builder => builder.SetApplicationName("SharedCookieApp"))
.CreateProtector(
"Microsoft.AspNetCore.Authentication.Cookies.CookieAuthenticationMiddleware",
// Must match the Scheme name used in the ASP.NET Core app, i.e. IdentityConstants.ApplicationScheme
"Identity.Application",
"v2"))),
CookieManager = new ChunkingCookieManager()
});
Important items configured here include:
System.Web.Helpers.AntiForgeryConfig.UniqueClaimTypeIdentifier
is set to a claim from the ASP.NET Core identity that will be unique to a user.Because the authentication type was changed to match the authentication scheme of the ASP.NET Core app, it's also necessary to update how the ASP.NET app generates new identities to use that same name. This is typically done in Models/IdentityModels.cs
:
public class ApplicationUser : IdentityUser
{
public async Task<ClaimsIdentity> GenerateUserIdentityAsync(UserManager<ApplicationUser> manager)
{
// Note the authenticationType must match the one defined in CookieAuthenticationOptions.AuthenticationType
var userIdentity = await manager.CreateIdentityAsync(this, "Identity.Application");
// Add custom user claims here
return userIdentity;
}
}
With these changes, the ASP.NET and ASP.NET Core apps are able to use the same authentication cookies so that users signing in or out of one app are reflected in the other app.
Note that because there are differences between ASP.NET Identity and ASP.NET Core Identity's database schemas, it is recommended that users only sign-in using one of the apps - either the ASP.NET or ASP.NET Core app. Once users are signed in, the steps documented in this section will allow the authentication cookie to be used by either app and both apps should be able to log users out.
In the examples that follow:
.AspNet.SharedCookie
.AuthenticationType
is set to Identity.Application
either explicitly or by default.SharedCookieApp
).Identity.Application
is used as the authentication scheme. Whatever scheme is used, it must be used consistently within and across the shared cookie apps either as the default scheme or by explicitly setting it. The scheme is used when encrypting and decrypting cookies, so a consistent scheme must be used across apps.DataProtectionProvider
provides data protection services for the encryption and decryption of authentication cookie payload data. The DataProtectionProvider
instance is isolated from the data protection system used by other parts of the app. DataProtectionProvider.Create(System.IO.DirectoryInfo, Action<IDataProtectionBuilder>) accepts a DirectoryInfo to specify the location for data protection key storage.DataProtectionProvider
requires the Microsoft.AspNetCore.DataProtection.Extensions NuGet package:
When using ASP.NET Core Identity:
SharedCookieApp
in the following examples). For more information, see Configure ASP.NET Core Data Protection.Identity.Application
.In Startup.ConfigureServices
:
services.AddDataProtection()
.PersistKeysToFileSystem("{PATH TO COMMON KEY RING FOLDER}")
.SetApplicationName("SharedCookieApp");
services.ConfigureApplicationCookie(options => {
options.Cookie.Name = ".AspNet.SharedCookie";
});
Note: The preceding instructions don't work with ITicketStore
(CookieAuthenticationOptions.SessionStore
). For more information, see this GitHub issue.
For security reasons, authentication cookies are not compressed in ASP.NET Core. When using authentication cookies, developers should minimize the number of claim information included to just that necessary for their needs.
When using cookies directly without ASP.NET Core Identity, configure data protection and authentication in Startup.ConfigureServices
. In the following example, the authentication type is set to Identity.Application
:
services.AddDataProtection()
.PersistKeysToFileSystem("{PATH TO COMMON KEY RING FOLDER}")
.SetApplicationName("SharedCookieApp");
services.AddAuthentication("Identity.Application")
.AddCookie("Identity.Application", options =>
{
options.Cookie.Name = ".AspNet.SharedCookie";
});
For security reasons, authentication cookies are not compressed in ASP.NET Core. When using authentication cookies, developers should minimize the number of claim information included to just that necessary for their needs.
An authentication cookie uses the HttpRequest.PathBase as its default Cookie.Path. If the app's cookie must be shared across different base paths, Path
must be overridden:
services.AddDataProtection()
.PersistKeysToFileSystem("{PATH TO COMMON KEY RING FOLDER}")
.SetApplicationName("SharedCookieApp");
services.ConfigureApplicationCookie(options => {
options.Cookie.Name = ".AspNet.SharedCookie";
options.Cookie.Path = "/";
});
When hosting apps that share cookies across subdomains, specify a common domain in the Cookie.Domain property. To share cookies across apps at contoso.com
, such as first_subdomain.contoso.com
and second_subdomain.contoso.com
, specify the Cookie.Domain
as .contoso.com
:
options.Cookie.Domain = ".contoso.com";
For production deployments, configure the DataProtectionProvider
to encrypt keys at rest with DPAPI or an X509Certificate. For more information, see Key encryption at rest in Windows and Azure using ASP.NET Core. In the following example, a certificate thumbprint is provided to ProtectKeysWithCertificate:
services.AddDataProtection()
.ProtectKeysWithCertificate("{CERTIFICATE THUMBPRINT}");
ASP.NET 4.x apps that use Katana Cookie Authentication Middleware can be configured to generate authentication cookies that are compatible with the ASP.NET Core Cookie Authentication Middleware. For more information, see Share authentication cookies between ASP.NET 4.x and ASP.NET Core apps (dotnet/AspNetCore.Docs #21987).
When apps use the same Identity schema (same version of Identity), confirm that the Identity system for each app is pointed at the same user database. Otherwise, the identity system produces failures at runtime when it attempts to match the information in the authentication cookie against the information in its database.
When the Identity schema is different among apps, usually because apps are using different Identity versions, sharing a common database based on the latest version of Identity isn't possible without remapping and adding columns in other app's Identity schemas. It's often more efficient to upgrade the other apps to use the latest Identity version so that a common database can be shared by the apps.
ASP.NET Core feedback
ASP.NET Core is an open source project. Select a link to provide feedback:
Events
Power BI DataViz World Championships
Feb 14, 4 PM - Mar 31, 4 PM
With 4 chances to enter, you could win a conference package and make it to the LIVE Grand Finale in Las Vegas
Learn moreTraining
Module
Secure a .NET web app with the ASP.NET Core Identity framework - Training
Learn how to add authentication and authorization to a .NET web app using the ASP.NET Core Identity framework.
Certification
Microsoft Certified: Identity and Access Administrator Associate - Certifications
Demonstrate the features of Microsoft Entra ID to modernize identity solutions, implement hybrid solutions, and implement identity governance.