Partager les authentifications cookies entre les applications ASP.NET

Par Rick Anderson

Les sites Web sont souvent constitués d'applications Web individuelles qui fonctionnent ensemble. Pour fournir une expérience d'authentification unique (SSO), les applications Web d'un site doivent partager des cookies d'authentification. Pour prendre en charge ce scénario, la pile de protection des données permet de partager l'authentification cookie Katana et les tickets d'authentification ASP.NET Core cookie.

Dans les exemples suivants :

  • Le nom d’authentification cookie est défini sur une valeur commune de .AspNet.SharedCookie.
  • Le AuthenticationType est défini sur Identity.Application explicitement ou par défaut.
  • Un nom d'application commun, SharedCookieApp, est utilisé pour permettre au système de protection des données de partager les clés de protection des données.
  • Identity.Application est utilisé comme schéma d'authentification. Quel que soit le schéma utilisé, il doit être utilisé de manière cohérente dans et entre les applications cookie partagées, soit comme schéma par défaut, soit en le définissant explicitement. Le schéma est utilisé lors du chiffrement et du déchiffrement des cookies, donc un schéma cohérent doit être utilisé dans toutes les applications.
  • Un emplacement de stockage de clé de protection des données commun est utilisé.
    • Dans les applications ASP.NET Core, PersistKeysToFileSystem est utilisé pour définir l'emplacement de stockage de la clé.
    • Dans les applications .NET Framework, le Cookie middleware d'authentification utilise une implémentation de DataProtectionProvider. DataProtectionProvider fournit des services de protection des données pour le chiffrement et le déchiffrement des données utiles d'authentification cookie. L'instance DataProtectionProvider est isolée du système de protection des données utilisé par d'autres parties de l'application. DataProtectionProvider.Create(System.IO.DirectoryInfo, Action<IDataProtectionBuilder>) accepte un DirectoryInfo pour spécifier l'emplacement de stockage de la clé de protection des données.
  • DataProtectionProvider nécessite le package NuGet Microsoft.AspNetCore.DataProtection.Extensions :
  • SetApplicationName définit le nom commun de l'application.

Partager les authentifications cookies avec ASP.NET Core Identity

Lors de l'utilisation d'ASP.NET Core Identity :

  • Les clés de protection des données et le nom de l'application doivent être partagés entre les applications. Un emplacement de stockage de clé commun PersistKeysToFileSystem est fourni au procédé dans les exemples suivants. Utilisez SetApplicationName pour configurer un nom d'application partagé commun (SharedCookieApp dans les exemples suivants). Pour plus d’informations, consultez Configurer la protection des données ASP.NET Core.
  • Utilisez la méthode d'extension ConfigureApplicationCookie pour configurer le service de protection des données pour cookies.
  • Le type d'authentification par défaut est Identity.Application.

Dans 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();

Remarque : Les instructions précédentes ne fonctionnent pas avec ITicketStore (CookieAuthenticationOptions.SessionStore). Pour plus d’informations, consultez ce problème GitHub.

Pour des raisons de sécurité, les cookies d’authentification ne sont pas compressés dans ASP.NET Core. Quand vous utilisez des cookies d’authentification, les développeurs doivent limiter les informations de revendication incluses à celles qui sont nécessaires selon leurs besoins.

Partager les authentifications cookies sans ASP.NET Core Identity

Lorsque vous utilisez cookies directement sans ASP.NET Core Identity, configurez la protection des données et l'authentification. Dans l'exemple suivant, le type d'authentification est défini sur 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();

Pour des raisons de sécurité, les cookies d’authentification ne sont pas compressés dans ASP.NET Core. Quand vous utilisez des cookies d’authentification, les développeurs doivent limiter les informations de revendication incluses à celles qui sont nécessaires selon leurs besoins.

Partager des cookies sur différents chemins de base

Une authentification cookie utilise HttpRequest.PathBase comme Cookie.Path par défaut. Si l'application cookie doit être partagée sur différents chemins de base, Path doit être remplacé :

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();

Partager des cookies entre sous-domaines

Lorsque vous hébergez des applications cookies qui partagent des s entre des sous-domaines, spécifiez un domaine commun dans la propriété Cookie.Domain. Pour partager des cookies entre des applications sur contoso.com, telles que first_subdomain.contoso.com et second_subdomain.contoso.com, spécifiez le Cookie.Domain comme .contoso.com :

options.Cookie.Domain = ".contoso.com";

Chiffrer les clés de protection des données au repos

Pour les déploiements de production, configurez le DataProtectionProvider pour chiffrer les clés au repos avec DPAPI ou un X509Certificate. Pour plus d'informations, consultez Chiffrement de clé au repos dans Windows et Azure à l'aide d'ASP.NET Core. Dans l'exemple suivant, une empreinte de certificat est fournie à ProtectKeysWithCertificate :

using Microsoft.AspNetCore.DataProtection;

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddRazorPages();

builder.Services.AddDataProtection()
    .ProtectKeysWithCertificate("{CERTIFICATE THUMBPRINT}");

Utiliser une base de données utilisateur commune

Lorsque les applications utilisent le même schéma Identity (même version de Identity), vérifiez que le système Identity de chaque application pointe vers la même base de données utilisateur. Sinon, le système d'identité produit des échecs lors de l'exécution lorsqu'il tente de faire correspondre les informations de l'authentification cookie avec les informations de sa base de données.

Lorsque le schéma Identity est différent entre les applications, généralement parce que les applications utilisent des versions Identity différentes, le partage d'une base de données commune basée sur la dernière version de Identity n'est pas possible sans remappage et ajout de colonnes dans les schémas d'autres applications Identity. Il est souvent plus efficace de mettre à niveau les autres applications pour utiliser la dernière version Identity afin qu'une base de données commune puisse être partagée par les applications.

Changement de nom de l'application

Dans .NET 6, WebApplicationBuilder normalise le chemin racine du contenu pour qu'il se termine par un DirectorySeparatorChar. La plupart des applications migrées depuis HostBuilder ou WebHostBuilder n'auront pas le même nom d'application car elles ne sont pas normalisées. Pour plus d'informations, voir SetApplicationName

Partager les authentifications cookies entre les applications ASP.NET 4.x et ASP.NET Core

Les applications ASP.NET 4.x qui utilisent le middleware d'Cookieauthentification Microsoft.Owin peuvent être configurées pour générer des authentifications cookies compatibles avec le middleware d'authentification Cookie ASP.NET Core. Cela peut être utile si une application Web se compose à la fois d'applications ASP.NET 4.x et d'applications ASP.NET Core qui doivent partager une expérience d'authentification unique. Un exemple spécifique d'un tel scénario est la migration incrémentielle d'une application Web d'ASP.NET vers ASP.NET Core. Dans de tels scénarios, il est courant que certaines parties d'une application soient servies par l'application ASP.NET d'origine tandis que d'autres sont servies par la nouvelle application ASP.NET Core. Cependant, les utilisateurs ne devraient avoir à se connecter qu'une seule fois. Cela peut être accompli par l'une des approches suivantes :

  • Utilisation de la fonctionnalité d'authentification à distance des adaptateurs System.Web, qui utilise l'application ASP.NET pour connecter les utilisateurs.
  • Configuration de l'application ASP.NET pour utiliser le Cookie middleware d'authentification Microsoft.Owin afin que les authentifications cookies soient partagées avec l'application ASP.NET Core.

Pour configurer ASP.NET Microsoft.Owin Cookie Authentication Middleware pour partager des cookies avec une application ASP.NET Core, suivez les instructions précédentes pour configurer l'application ASP.NET Core afin qu'elle utilise un nom spécifique, un nom d'application cookie et pour conserver les clés de protection des données sur une application ASP.NET Core. emplacement bien connu. Consultez Configurer la protection des données ASP.NET Core pour plus d'informations sur la persistance des clés de protection des données.

Dans l'application ASP.NET, installez le package Microsoft.Owin.Security.Interop.

Mettez à jour l'appel UseCookieAuthentication dans Startup.Auth.cs pour configurer un AspNetTicketDataFormat afin qu'il corresponde aux paramètres de l'application ASP.NET Core :

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()
});

Les éléments importants configurés ici incluent :

  • Le nom cookie est défini sur le même nom que dans l'application ASP.NET Core.
  • Un fournisseur de protection des données est créé à l'aide du même chemin de trousseau de clés. Notez que dans ces exemples, les clés de protection des données sont stockées sur disque, mais d'autres fournisseurs de protection des données peuvent être utilisés. Par exemple, Redis ou Stockage Blob Azure peuvent être utilisés pour les fournisseurs de protection des données tant que la configuration correspond entre les applications. Consultez Configurer la protection des données ASP.NET Core pour plus d'informations sur la persistance des clés de protection des données.
  • Le nom de l'application est défini pour être le même que le nom de l'application utilisé dans l'application ASP.NET Core.
  • Le type d'authentification est défini sur le nom du schéma d'authentification dans l'application ASP.NET Core.
  • System.Web.Helpers.AntiForgeryConfig.UniqueClaimTypeIdentifier est défini sur une revendication de l'identité ASP.NET Core qui sera unique pour un utilisateur.

Étant donné que le type d'authentification a été modifié pour correspondre au schéma d'authentification de l'application ASP.NET Core, il est également nécessaire de mettre à jour la manière dont l'application ASP.NET génère de nouvelles identités pour utiliser le même nom. Cela se fait généralement dans 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;
    }
}

Avec ces modifications, les applications ASP.NET et ASP.NET Core peuvent utiliser les mêmes authentifications cookies afin que les utilisateurs qui se connectent ou se déconnectent d'une application soient reflétés dans l'autre application.

Notez qu'en raison des différences entre les schémas de base de données ASP.NET Identity et ASP.NET Core Identity, il est recommandé aux utilisateurs de se connecter uniquement à l'aide de l'une des applications, soit l'application ASP.NET ou ASP.NET Core. Une fois les utilisateurs connectés, les étapes décrites dans cette section permettront à l'authentification cookie d'être utilisée par l'une ou l'autre des applications et les deux applications devraient pouvoir déconnecter les utilisateurs.

Ressources supplémentaires

Dans les exemples suivants :

  • Le nom d’authentification cookie est défini sur une valeur commune de .AspNet.SharedCookie.
  • Le AuthenticationType est défini sur Identity.Application explicitement ou par défaut.
  • Un nom d'application commun est utilisé pour permettre au système de protection des données de partager les clés de protection des données (SharedCookieApp).
  • Identity.Application est utilisé comme schéma d'authentification. Quel que soit le schéma utilisé, il doit être utilisé de manière cohérente dans et entre les applications cookie partagées, soit comme schéma par défaut, soit en le définissant explicitement. Le schéma est utilisé lors du chiffrement et du déchiffrement des cookies, donc un schéma cohérent doit être utilisé dans toutes les applications.
  • Un emplacement de stockage de clé de protection des données commun est utilisé.
    • Dans les applications ASP.NET Core, PersistKeysToFileSystem est utilisé pour définir l'emplacement de stockage de la clé.
    • Dans les applications .NET Framework, le Cookie middleware d'authentification utilise une implémentation de DataProtectionProvider. DataProtectionProvider fournit des services de protection des données pour le chiffrement et le déchiffrement des données utiles d'authentification cookie. L'instance DataProtectionProvider est isolée du système de protection des données utilisé par d'autres parties de l'application. DataProtectionProvider.Create(System.IO.DirectoryInfo, Action<IDataProtectionBuilder>) accepte un DirectoryInfo pour spécifier l'emplacement de stockage de la clé de protection des données.
  • DataProtectionProvider nécessite le package NuGet Microsoft.AspNetCore.DataProtection.Extensions :
  • SetApplicationName définit le nom commun de l'application.

Partager les authentifications cookies avec ASP.NET Core Identity

Lors de l'utilisation d'ASP.NET Core Identity :

  • Les clés de protection des données et le nom de l'application doivent être partagés entre les applications. Un emplacement de stockage de clé commun PersistKeysToFileSystem est fourni au procédé dans les exemples suivants. Utilisez SetApplicationName pour configurer un nom d'application partagé commun (SharedCookieApp dans les exemples suivants). Pour plus d’informations, consultez Configurer la protection des données ASP.NET Core.
  • Utilisez la méthode d'extension ConfigureApplicationCookie pour configurer le service de protection des données pour cookies.
  • Le type d'authentification par défaut est Identity.Application.

Dans Startup.ConfigureServices :

services.AddDataProtection()
    .PersistKeysToFileSystem("{PATH TO COMMON KEY RING FOLDER}")
    .SetApplicationName("SharedCookieApp");

services.ConfigureApplicationCookie(options => {
    options.Cookie.Name = ".AspNet.SharedCookie";
});

Remarque : Les instructions précédentes ne fonctionnent pas avec ITicketStore (CookieAuthenticationOptions.SessionStore). Pour plus d’informations, consultez ce problème GitHub.

Pour des raisons de sécurité, les cookies d’authentification ne sont pas compressés dans ASP.NET Core. Quand vous utilisez des cookies d’authentification, les développeurs doivent limiter les informations de revendication incluses à celles qui sont nécessaires selon leurs besoins.

Partager les authentifications cookies sans ASP.NET Core Identity

Lorsque vous utilisez cookies directement sans ASP.NET Core Identity, configurez la protection des données et l'authentification dans Startup.ConfigureServices. Dans l'exemple suivant, le type d'authentification est défini sur 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";
    });

Pour des raisons de sécurité, les cookies d’authentification ne sont pas compressés dans ASP.NET Core. Quand vous utilisez des cookies d’authentification, les développeurs doivent limiter les informations de revendication incluses à celles qui sont nécessaires selon leurs besoins.

Partager des cookies sur différents chemins de base

Une authentification cookie utilise HttpRequest.PathBase comme Cookie.Path par défaut. Si l'application cookie doit être partagée sur différents chemins de base, Path doit être remplacé :

services.AddDataProtection()
    .PersistKeysToFileSystem("{PATH TO COMMON KEY RING FOLDER}")
    .SetApplicationName("SharedCookieApp");

services.ConfigureApplicationCookie(options => {
    options.Cookie.Name = ".AspNet.SharedCookie";
    options.Cookie.Path = "/";
});

Partager des cookies entre sous-domaines

Lorsque vous hébergez des applications cookies qui partagent des s entre des sous-domaines, spécifiez un domaine commun dans la propriété Cookie.Domain. Pour partager des cookies entre des applications sur contoso.com, telles que first_subdomain.contoso.com et second_subdomain.contoso.com, spécifiez le Cookie.Domain comme .contoso.com :

options.Cookie.Domain = ".contoso.com";

Chiffrer les clés de protection des données au repos

Pour les déploiements de production, configurez le DataProtectionProvider pour chiffrer les clés au repos avec DPAPI ou un X509Certificate. Pour plus d'informations, consultez Chiffrement de clé au repos dans Windows et Azure à l'aide d'ASP.NET Core. Dans l'exemple suivant, une empreinte de certificat est fournie à ProtectKeysWithCertificate :

services.AddDataProtection()
    .ProtectKeysWithCertificate("{CERTIFICATE THUMBPRINT}");

Partager les authentifications cookies entre les applications ASP.NET 4.x et ASP.NET Core

Les applications ASP.NET 4.x qui utilisent le middleware d'Cookieauthentification Katana peuvent être configurées pour générer des authentifications cookies compatibles avec le middleware d'authentification Cookie ASP.NET Core. Pour plus d'informations, consultez Partager les authentifications cookies entre les applications ASP.NET 4.x et ASP.NET Core (dotnet/AspNetCore.Docs #21987).

Utiliser une base de données utilisateur commune

Lorsque les applications utilisent le même schéma Identity (même version de Identity), vérifiez que le système Identity de chaque application pointe vers la même base de données utilisateur. Sinon, le système d'identité produit des échecs lors de l'exécution lorsqu'il tente de faire correspondre les informations de l'authentification cookie avec les informations de sa base de données.

Lorsque le schéma Identity est différent entre les applications, généralement parce que les applications utilisent des versions Identity différentes, le partage d'une base de données commune basée sur la dernière version de Identity n'est pas possible sans remappage et ajout de colonnes dans les schémas d'autres applications Identity. Il est souvent plus efficace de mettre à niveau les autres applications pour utiliser la dernière version Identity afin qu'une base de données commune puisse être partagée par les applications.

Ressources supplémentaires