Share via


Compartir cookies de autenticación entre aplicaciones de ASP.NET

Por Rick Anderson

A menudo, los sitios web constan de aplicaciones web individuales que funcionan en conjunto. Para proporcionar una experiencia de inicio de sesión único (SSO), las aplicaciones web dentro de un sitio deben compartir cookies de autenticación. Para admitir este escenario, la pila de protección de datos permite compartir cookie de autenticación de Katana y vales de autenticación de cookie de ASP.NET Core.

En los ejemplos siguientes:

  • El nombre de la cookie de autenticación se establece en un valor común de .AspNet.SharedCookie.
  • AuthenticationType se establece en Identity.Application de manera explícita o predeterminada.
  • Se usa un nombre de aplicación común, SharedCookieApp, para permitir que el sistema de protección de datos comparta las claves de protección de datos.
  • Identity.Application se usa como el esquema de autenticación. Cualquier esquema que se use, se debe usar de forma coherente dentro y en las aplicaciones de cookie compartidas, ya sea como el esquema predeterminado o estableciendo explícitamente. El esquema se usa al cifrar y descifrar cookie, por lo que se debe usar un esquema coherente en todas las aplicaciones.
  • Se usa una ubicación de almacenamiento de clave de protección de datos común.
    • En las aplicaciones de ASP.NET Core, PersistKeysToFileSystem se usa para establecer la ubicación del almacenamiento de claves.
    • En las aplicaciones de .NET Framework, el middleware de autenticación de Cookie usa una implementación de DataProtectionProvider. DataProtectionProvider proporciona servicios de protección de datos para el cifrado y descifrado de los datos de carga de autenticación de cookie. La instancia DataProtectionProvider está aislada del sistema de protección de datos que usan otras partes de la aplicación. DataProtectionProvider.Create(System.IO.DirectoryInfo, Action<IDataProtectionBuilder>) acepta DirectoryInfo para especificar la ubicación del almacenamiento de claves de protección de datos.
  • DataProtectionProvider requiere el paquete NuGet Microsoft.AspNetCore.DataProtection.Extensions:
  • SetApplicationName establece el nombre de la aplicación común.

Compartir cookies de autenticación con ASP.NET Core Identity

Al usar ASP.NET Core Identity:

  • Las claves de protección de datos y el nombre de la aplicación se deben compartir entre las aplicaciones. En los ejemplos siguientes se proporciona una ubicación de almacenamiento de claves común al método PersistKeysToFileSystem. Use SetApplicationName para configurar un nombre de aplicación compartido común (SharedCookieApp en los ejemplos siguientes). Para más información, vea Configurar la protección de datos en ASP.NET Core.
  • Use el método de extensión ConfigureApplicationCookie para configurar el servicio de protección de datos para cookie.
  • El tipo de autenticación predeterminado es Identity.Application.

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

Nota: Las instrucciones anteriores no funcionan con ITicketStore (CookieAuthenticationOptions.SessionStore). Para más información, consulte este problema de GitHub.

Por motivos de seguridad, las autenticaciones cookie no se comprimen en ASP.NET Core. Cuando se usan las autenticaciones cookie, los desarrolladores deben minimizar el número de información de notificaciones que se incluye solo para sus necesidades.

Compartir cookies de autenticación sin ASP.NET Core Identity

Cuando se usan cookies directamente sin ASP.NET Core Identity, configure la autenticación y la protección de datos. En el ejemplo siguiente, el tipo de autenticación se establece en 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();

Por motivos de seguridad, las autenticaciones cookie no se comprimen en ASP.NET Core. Cuando se usan las autenticaciones cookie, los desarrolladores deben minimizar el número de información de notificaciones que se incluye solo para sus necesidades.

Compartir cookies entre diferentes rutas de acceso base

Una autenticación cookie usa HttpRequest.PathBase como el valor de Cookie.Path predeterminado. Si cookie de la aplicación debe compartirse entre diferentes rutas de acceso base, Path debe invalidarse:

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

Compartir cookies entre subdominios

Al hospedar aplicaciones que comparten cookie entre subdominios, especifique un dominio común en la propiedad Cookie.Domain. Para compartir cookies entre aplicaciones en contoso.com, como first_subdomain.contoso.com y second_subdomain.contoso.com, especifique Cookie.Domain como .contoso.com:

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

Cifrado de claves de protección de datos en reposo

En el caso de las implementaciones de producción, configure DataProtectionProvider para cifrar las claves en reposo con DPAPI o X509Certificate. Para obtener más información, consulte Cifrado de claves en reposo en Windows y Azure mediante ASP.NET Core. En el ejemplo siguiente, se proporciona una huella digital de certificado a ProtectKeysWithCertificate:

using Microsoft.AspNetCore.DataProtection;

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddRazorPages();

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

Uso de una base de datos de usuario común

Cuando las aplicaciones usan el mismo esquema de Identity (misma versión de Identity), confirme que el sistema Identity de cada aplicación apunta a la misma base de datos de usuario. De lo contrario, el sistema de identidad genera errores en tiempo de ejecución cuando intenta buscar coincidencias con la información de la cookie de autenticación en la información de su base de datos.

Cuando el esquema Identity es diferente entre las aplicaciones, normalmente porque las aplicaciones usan versiones de Identity diferentes, compartir una base de datos común basada en la versión más reciente de Identity no es posible sin reasignar ni agregar columnas en los esquemas Identity de otra aplicación. A menudo, es más eficaz actualizar las demás aplicaciones para que usen la versión más reciente de Identity para que las aplicaciones puedan compartir una base de datos común.

Cambio del nombre de la aplicación

En .NET 6, WebApplicationBuilder normaliza la ruta de acceso raíz del contenido para finalizar con DirectorySeparatorChar. La mayoría de las aplicaciones que migran desde HostBuilder o WebHostBuilder no tendrán el mismo nombre de aplicación porque no se normalizan. Para obtener más información, consulte SetApplicationName

Compartir cookies de autenticación entre aplicaciones de ASP.NET 4.x y ASP.NET Core

Las aplicaciones de ASP.NET 4.x que usan middleware de autenticación de Cookie de Microsoft.Owin se pueden configurar para generar cookie de autenticación compatibles con el middleware de autenticación de Cookie de ASP.NET Core. Esto puede ser útil si una aplicación web consta de aplicaciones de ASP.NET 4.x y aplicaciones de ASP.NET Core que deben compartir una experiencia de inicio de sesión único. Un ejemplo específico de este escenario es migrar incrementalmente una aplicación web de ASP.NET a ASP.NET Core. En estos escenarios, es habitual que algunas partes de una aplicación las sirva la aplicación de ASP.NET original, mientras que otras son servidas por la nueva aplicación de ASP.NET Core. Sin embargo, los usuarios solo deben iniciar sesión una vez. Para ello, puede usar cualquiera de los enfoques siguientes:

  • Con la característica de autenticación remota de los adaptadores System.Web, que usa la aplicación de ASP.NET para iniciar la sesión de los usuarios.
  • Configuración de la aplicación de ASP.NET para usar el middleware de autenticación de Cookie de Microsoft.Owin para que las cookie de autenticación se compartan con la aplicación de ASP.NET Core.

Para configurar el middleware de autenticación de Cookie de Microsoft.Owin de ASP.NET para compartir cookie con una aplicación de ASP.NET Core, siga las instrucciones anteriores para configurar la aplicación de ASP.NET Core para usar un nombre de cookie específico, un nombre de aplicación y conservar las claves de protección de datos en una ubicación conocida. Consulte Configuración la protección de datos de ASP.NET Core para obtener más información sobre la conservación de claves de protección de datos.

En la aplicación de ASP.NET, instale el paquete Microsoft.Owin.Security.Interop.

Actualice la llamada UseCookieAuthentication en Startup.Auth.cs para configurar aspNetTicketDataFormat para que coincida con la configuración de la aplicación de 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()
});

Entre los elementos importantes configurados aquí se incluyen:

  • El nombre de cookie se establece en el mismo nombre que en la aplicación de ASP.NET Core.
  • Se crea un proveedor de protección de datos con la misma ruta de acceso del anillo de claves. Tenga en cuenta que en estos ejemplos, las claves de protección de datos se almacenan en el disco, pero se pueden usar otros proveedores de protección de datos. Por ejemplo, Redis o Azure Blob Storage se pueden usar para proveedores de protección de datos siempre que la configuración coincida entre las aplicaciones. Consulte Configuración la protección de datos de ASP.NET Core para obtener más información sobre la conservación de claves de protección de datos.
  • El nombre de la aplicación se establece para que sea el mismo que el nombre de la aplicación que se usa en la aplicación de ASP.NET Core.
  • El tipo de autenticación se establece en el nombre del esquema de autenticación en la aplicación de ASP.NET Core.
  • System.Web.Helpers.AntiForgeryConfig.UniqueClaimTypeIdentifier se establece en una notificación de la identidad de ASP.NET Core que será única para un usuario.

Dado que el tipo de autenticación se cambió para que coincida con el esquema de autenticación de la aplicación de ASP.NET Core, también es necesario actualizar cómo la aplicación de ASP.NET genera nuevas identidades para usar ese mismo nombre. Normalmente, esto se hace en 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;
    }
}

Con estos cambios, las aplicaciones de ASP.NET y ASP.NET Core pueden usar las mismas cookie de autenticación para que los usuarios que inicien o cierren sesión de una aplicación se reflejan en la otra aplicación.

Tenga en cuenta que, dado que hay diferencias entre los esquemas de base de datos de ASP.NET Identity y ASP.NET Core Identity, se recomienda que los usuarios solo inicien sesión con una de las aplicaciones, ya sea la aplicación de ASP.NET o ASP.NET Core. Una vez que los usuarios hayan iniciado sesión, los pasos documentados en esta sección permitirán que la aplicación pueda usar la cookie de autenticación y ambas aplicaciones deberían poder cerrar la sesión de los usuarios.

Recursos adicionales

En los ejemplos siguientes:

  • El nombre de la cookie de autenticación se establece en un valor común de .AspNet.SharedCookie.
  • AuthenticationType se establece en Identity.Application de manera explícita o predeterminada.
  • Se usa un nombre de aplicación común para permitir que el sistema de protección de datos comparta las claves de protección de datos (SharedCookieApp).
  • Identity.Application se usa como el esquema de autenticación. Cualquier esquema que se use, se debe usar de forma coherente dentro y en las aplicaciones de cookie compartidas, ya sea como el esquema predeterminado o estableciendo explícitamente. El esquema se usa al cifrar y descifrar cookie, por lo que se debe usar un esquema coherente en todas las aplicaciones.
  • Se usa una ubicación de almacenamiento de clave de protección de datos común.
    • En las aplicaciones de ASP.NET Core, PersistKeysToFileSystem se usa para establecer la ubicación del almacenamiento de claves.
    • En las aplicaciones de .NET Framework, el middleware de autenticación de Cookie usa una implementación de DataProtectionProvider. DataProtectionProvider proporciona servicios de protección de datos para el cifrado y descifrado de los datos de carga de autenticación de cookie. La instancia DataProtectionProvider está aislada del sistema de protección de datos que usan otras partes de la aplicación. DataProtectionProvider.Create(System.IO.DirectoryInfo, Action<IDataProtectionBuilder>) acepta DirectoryInfo para especificar la ubicación del almacenamiento de claves de protección de datos.
  • DataProtectionProvider requiere el paquete NuGet Microsoft.AspNetCore.DataProtection.Extensions:
  • SetApplicationName establece el nombre de la aplicación común.

Compartir cookies de autenticación con ASP.NET Core Identity

Al usar ASP.NET Core Identity:

  • Las claves de protección de datos y el nombre de la aplicación se deben compartir entre las aplicaciones. En los ejemplos siguientes se proporciona una ubicación de almacenamiento de claves común al método PersistKeysToFileSystem. Use SetApplicationName para configurar un nombre de aplicación compartido común (SharedCookieApp en los ejemplos siguientes). Para más información, vea Configurar la protección de datos en ASP.NET Core.
  • Use el método de extensión ConfigureApplicationCookie para configurar el servicio de protección de datos para cookie.
  • El tipo de autenticación predeterminado es Identity.Application.

En Startup.ConfigureServices:

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

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

Nota: Las instrucciones anteriores no funcionan con ITicketStore (CookieAuthenticationOptions.SessionStore). Para más información, consulte este problema de GitHub.

Por motivos de seguridad, las autenticaciones cookie no se comprimen en ASP.NET Core. Cuando se usan las autenticaciones cookie, los desarrolladores deben minimizar el número de información de notificaciones que se incluye solo para sus necesidades.

Compartir cookies de autenticación sin ASP.NET Core Identity

Cuando se usan cookie directamente sin ASP.NET Core Identity, configure la autenticación y la protección de datos en Startup.ConfigureServices. En el ejemplo siguiente, el tipo de autenticación se establece en 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";
    });

Por motivos de seguridad, las autenticaciones cookie no se comprimen en ASP.NET Core. Cuando se usan las autenticaciones cookie, los desarrolladores deben minimizar el número de información de notificaciones que se incluye solo para sus necesidades.

Compartir cookies entre diferentes rutas de acceso base

Una autenticación cookie usa HttpRequest.PathBase como el valor de Cookie.Path predeterminado. Si cookie de la aplicación debe compartirse entre diferentes rutas de acceso base, Path debe invalidarse:

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

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

Compartir cookies entre subdominios

Al hospedar aplicaciones que comparten cookie entre subdominios, especifique un dominio común en la propiedad Cookie.Domain. Para compartir cookies entre aplicaciones en contoso.com, como first_subdomain.contoso.com y second_subdomain.contoso.com, especifique Cookie.Domain como .contoso.com:

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

Cifrado de claves de protección de datos en reposo

En el caso de las implementaciones de producción, configure DataProtectionProvider para cifrar las claves en reposo con DPAPI o X509Certificate. Para obtener más información, consulte Cifrado de claves en reposo en Windows y Azure mediante ASP.NET Core. En el ejemplo siguiente, se proporciona una huella digital de certificado a ProtectKeysWithCertificate:

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

Compartir cookies de autenticación entre aplicaciones de ASP.NET 4.x y ASP.NET Core

Las aplicaciones de ASP.NET 4.x que usan el middleware de autenticación de Cookie de Katana se pueden configurar para generar cookies de autenticación compatibles con el middleware de autenticación de Cookie de ASP.NET Core. Para obtener más información, consulte Compartir cookies de autenticación entre aplicaciones de ASP.NET 4.x y ASP.NET Core (dotnet/AspNetCore.Docs #21987).

Uso de una base de datos de usuario común

Cuando las aplicaciones usan el mismo esquema de Identity (misma versión de Identity), confirme que el sistema Identity de cada aplicación apunta a la misma base de datos de usuario. De lo contrario, el sistema de identidad genera errores en tiempo de ejecución cuando intenta buscar coincidencias con la información de la cookie de autenticación en la información de su base de datos.

Cuando el esquema Identity es diferente entre las aplicaciones, normalmente porque las aplicaciones usan versiones de Identity diferentes, compartir una base de datos común basada en la versión más reciente de Identity no es posible sin reasignar ni agregar columnas en los esquemas Identity de otra aplicación. A menudo, es más eficaz actualizar las demás aplicaciones para que usen la versión más reciente de Identity para que las aplicaciones puedan compartir una base de datos común.

Recursos adicionales