ASP.NET 앱 간에 인증 쿠키 공유

작성자: Rick Anderson

웹 사이트는 종종 함께 작동하는 개별 웹앱으로 구성됩니다. SSO(Single Sign-On) 환경을 제공하려면 사이트 내의 웹앱이 인증 쿠키를 공유해야 합니다. 이 시나리오를 지원하기 위해 데이터 보호 스택에서는 Katana cookie 인증 및 ASP.NET Core cookie 인증 티켓을 공유할 수 있습니다.

다음 예제에서는 다음을 수행합니다.

  • 인증 cookie 이름은 .AspNet.SharedCookie의 공통 값으로 설정됩니다.
  • AuthenticationType은 명시적으로 또는 기본적으로 Identity.Application으로 설정됩니다.
  • 일반적인 앱 이름 SharedCookieApp은 데이터 보호 시스템이 데이터 보호 키를 공유할 수 있도록 하는 데 사용됩니다.
  • Identity.Application은 인증 체계로 사용됩니다. 어떤 체계가 사용되었든 간에 기본 체계로 사용하거나 명시적으로 설정하여 공유 cookie 앱 내 또는 전체에서 일관되게 사용되어야 합니다. 이 체계는 쿠키를 암호화하고 암호 해독할 때 사용되므로 앱 간에 일관된 체계를 사용해야 합니다.
  • 공통 데이터 보호 키 스토리지 위치가 사용됩니다.
  • DataProtectionProvider 에는 Microsoft.AspNetCore.DataProtection.Extensions NuGet 패키지가 필요합니다.
  • SetApplicationName은 일반적인 앱 이름을 설정합니다.

ASP.NET Core와 인증 쿠키 공유 Identity

ASP.NET Core Identity을 사용하는 경우:

  • 데이터 보호 키와 앱 이름은 앱 간에 공유되어야 합니다. 공통 키 스토리지 위치는 다음 예제에서 PersistKeysToFileSystem 메서드에 제공됩니다. SetApplicationName을 사용하여 일반적인 공유 앱 이름(다음 예제에서는 SharedCookieApp)을 구성합니다. 자세한 내용은 ASP.NET Core 데이터 보호 구성을 참조하세요.
  • 확장 메서드를 ConfigureApplicationCookie 사용하여 쿠키에 대한 데이터 보호 서비스를 설정합니다.
  • 기본 인증 유형은 Identity.Application입니다.

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

참고: 위의 지침은 ITicketStore(CookieAuthenticationOptions.SessionStore)에서 작동하지 않습니다. 자세한 내용은 해당 GitHub 이슈를 참조하세요.

보안상의 이유로 인증 쿠키는 ASP.NET Core에서 압축되지 않습니다. 인증 쿠키를 사용하는 경우 개발자는 필요한 경우에만 포함된 클레임 정보의 수를 최소화해야 합니다.

ASP.NET Core 없이 인증 쿠키 공유 Identity

ASP.NET Core Identity없이 쿠키를 직접 사용하는 경우 데이터 보호 및 인증을 구성합니다. 다음 예제에서 인증 유형은 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();

보안상의 이유로 인증 쿠키는 ASP.NET Core에서 압축되지 않습니다. 인증 쿠키를 사용하는 경우 개발자는 필요한 경우에만 포함된 클레임 정보의 수를 최소화해야 합니다.

다양한 기본 경로에서 쿠키 공유

인증 cookie는 기본 Cookie.PathHttpRequest.PathBase를 사용합니다. 앱의 cookie를 서로 다른 기본 경로에서 공유해야 하는 경우 Path를 재정의해야 합니다.

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

하위 도메인 간에 쿠키 공유

하위 도메인 간에 쿠키를 공유하는 앱을 호스팅하는 경우 에 공통 도메인을 Cookie지정합니다. 도메인 속성입니다. 와 같은 first_subdomain.contoso.com second_subdomain.contoso.com앱 간에 contoso.com쿠키를 공유하려면 다음을 Cookie.Domain .contoso.com지정합니다.

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

에서 데이터 보호 키 암호화 rest

프로덕션 배포의 DataProtectionProvider 경우 DPAPI 또는 X509Certificate를 rest 사용하여 키를 암호화하도록 구성합니다. 자세한 내용은 ASP.NET Core를 사용하여 Windows 및 Azure에서 rest 키 암호화를 참조하세요. 다음 예제에서는 인증서 지문이 ProtectKeysWithCertificate에 제공됩니다.

using Microsoft.AspNetCore.DataProtection;

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddRazorPages();

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

일반 사용자 데이터베이스 사용

앱에서 동일한 Identity 스키마(동일한 버전의 Identity)를 사용하는 경우 각 앱의 Identity 시스템이 동일한 사용자 데이터베이스를 가리키는지 확인합니다. 그렇지 않은 경우 시스템은 데이터베이스의 identity 정보에 대해 인증 cookie 의 정보와 일치시키려고 할 때 런타임에 오류를 생성합니다.

일반적으로 앱이 서로 다른 Identity 버전을 사용하므로 앱 간에 Identity 스키마가 다른 경우 다른 앱의 Identity 스키마에 열을 다시 매핑하고 추가하지 않고는 최신 버전의 Identity를 기반으로 공통 데이터베이스를 공유할 수 없습니다. 일반적으로 앱에서 공통 데이터베이스를 공유할 수 있도록 최신 Identity 버전을 사용하도록 다른 앱을 업그레이드하는 것이 더 효율적입니다.

애플리케이션 이름 변경

.NET 6에서는 WebApplicationBuilder가 콘텐츠 루트 경로를 정규화하여 DirectorySeparatorChar로 끝납니다. HostBuilder 또는 WebHostBuilder에서 마이그레이션하는 대부분의 앱은 정규화되지 않으므로 동일한 앱 이름을 갖지 않습니다. 자세한 내용은 SetApplicationName을 참조하세요.

ASP.NET 4.x와 ASP.NET Core 앱 간에 인증 쿠키 공유

Microsoft.Owin Cookie 인증 미들웨어를 사용하는 ASP.NET 4.x 앱은 ASP.NET Core Cookie 인증 미들웨어와 호환되는 인증 쿠키를 생성하도록 구성할 수 있습니다. 이는 웹 애플리케이션이 ASP.NET 4.x 앱과 Single Sign-On 환경을 공유해야 하는 ASP.NET Core 앱으로 구성된 경우에 유용할 수 있습니다. 이러한 시나리오의 특정 예는 웹앱을 ASP.NET에서 ASP.NET Core로 점진적으로 마이그레이션하는 것입니다. 이러한 시나리오에서는 앱의 일부 부분이 원래 ASP.NET 앱에서 제공되는 반면 다른 부분은 새 ASP.NET Core 앱에서 제공하는 것이 일반적입니다. 하지만 사용자는 한 번만 로그인하면 됩니다. 이 작업은 다음 방법 중 하나를 통해 수행할 수 있습니다.

  • ASP.NET 앱을 사용하여 사용자를 로그인하는 System.Web 어댑터의 원격 인증 기능을 사용합니다.
  • 인증 쿠키가 ASP.NET Core 앱과 공유되도록 Microsoft.Owin Cookie 인증 미들웨어를 사용하도록 ASP.NET 앱을 구성합니다.

ASP.NET Core 앱과 쿠키를 공유하도록 ASP.NET Microsoft.Owin Cookie 인증 미들웨어를 구성하려면 이전 지침에 따라 특정 cookie 이름, 앱 이름을 사용하고 데이터 보호 키를 잘 알려진 위치에 유지하도록 ASP.NET Core 앱을 구성합니다. 데이터 보호 키 유지에 대한 자세한 내용은 ASP.NET Core 데이터 보호 구성을 참조하세요.

ASP.NET 앱에서 Microsoft.Owin.Security.Interop 패키지를 설치합니다.

Startup.Auth.cs에서 UseCookieAuthentication 호출을 업데이트하여 ASP.NET Core 앱의 설정과 일치하도록 AspNetTicketDataFormat을 구성합니다.

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

여기에 구성된 중요한 항목은 다음과 같습니다.

  • cookie 이름은 ASP.NET Core 앱과 동일한 이름으로 설정됩니다.
  • 데이터 보호 공급업체는 동일한 키 링 경로를 사용하여 만들어집니다. 이러한 예제에서는 데이터 보호 키가 디스크에 저장되지만 다른 데이터 보호 공급업체를 사용할 수 있습니다. 예를 들어 구성이 앱 간에 일치하는 한 데이터 보호 공급업체에 Redis 또는 Azure Blob Storage를 사용할 수 있습니다. 데이터 보호 키 유지에 대한 자세한 내용은 ASP.NET Core 데이터 보호 구성을 참조하세요.
  • 앱 이름은 ASP.NET Core 앱에서 사용되는 앱 이름과 동일하게 설정됩니다.
  • 인증 유형은 ASP.NET Core 앱의 인증 체계 이름으로 설정됩니다.
  • System.Web.Helpers.AntiForgeryConfig.UniqueClaimTypeIdentifier 는 사용자에게 고유한 ASP.NET Core identity 의 클레임으로 설정됩니다.

인증 유형이 ASP.NET Core 앱의 인증 체계와 일치하도록 변경되었으므로 ASP.NET 앱이 동일한 이름을 사용하기 위해 새 ID를 생성하는 방법을 업데이트해야 합니다. 이 작업은 일반적으로 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;
    }
}

이러한 변경으로 ASP.NET 및 ASP.NET Core 앱은 동일한 인증 쿠키를 사용할 수 있으므로 한 앱에서 로그인하거나 로그아웃한 사용자가 다른 앱에 반영됩니다.

ASP.NET 및 ASP.NET Identity Core Identity의 데이터베이스 스키마 간에는 차이가 있으므로 사용자는 ASP.NET 또는 ASP.NET Core 앱 중 하나를 사용하여 로그인 하는 것이 좋습니다. 사용자가 로그인되면 이 섹션에 설명된 단계를 통해 두 앱에서 인증 cookie 을 사용할 수 있으며 두 앱 모두 사용자를 로그아웃할 수 있어야 합니다.

추가 리소스

다음 예제에서는 다음을 수행합니다.

  • 인증 cookie 이름은 .AspNet.SharedCookie의 공통 값으로 설정됩니다.
  • AuthenticationType은 명시적으로 또는 기본적으로 Identity.Application으로 설정됩니다.
  • 일반적인 앱 이름은 데이터 보호 시스템이 데이터 보호 키(SharedCookieApp)를 공유할 수 있도록 하는 데 사용됩니다.
  • Identity.Application은 인증 체계로 사용됩니다. 어떤 체계가 사용되었든 간에 기본 체계로 사용하거나 명시적으로 설정하여 공유 cookie 앱 내 또는 전체에서 일관되게 사용되어야 합니다. 이 체계는 쿠키를 암호화하고 암호 해독할 때 사용되므로 앱 간에 일관된 체계를 사용해야 합니다.
  • 공통 데이터 보호 키 스토리지 위치가 사용됩니다.
  • DataProtectionProvider 에는 Microsoft.AspNetCore.DataProtection.Extensions NuGet 패키지가 필요합니다.
  • SetApplicationName은 일반적인 앱 이름을 설정합니다.

ASP.NET Core와 인증 쿠키 공유 Identity

ASP.NET Core Identity을 사용하는 경우:

  • 데이터 보호 키와 앱 이름은 앱 간에 공유되어야 합니다. 공통 키 스토리지 위치는 다음 예제에서 PersistKeysToFileSystem 메서드에 제공됩니다. SetApplicationName을 사용하여 일반적인 공유 앱 이름(다음 예제에서는 SharedCookieApp)을 구성합니다. 자세한 내용은 ASP.NET Core 데이터 보호 구성을 참조하세요.
  • 확장 메서드를 ConfigureApplicationCookie 사용하여 쿠키에 대한 데이터 보호 서비스를 설정합니다.
  • 기본 인증 유형은 Identity.Application입니다.

Startup.ConfigureServices의 경우

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

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

참고: 위의 지침은 ITicketStore(CookieAuthenticationOptions.SessionStore)에서 작동하지 않습니다. 자세한 내용은 해당 GitHub 이슈를 참조하세요.

보안상의 이유로 인증 쿠키는 ASP.NET Core에서 압축되지 않습니다. 인증 쿠키를 사용하는 경우 개발자는 필요한 경우에만 포함된 클레임 정보의 수를 최소화해야 합니다.

ASP.NET Core 없이 인증 쿠키 공유 Identity

ASP.NET Core Identity없이 쿠키를 직접 사용하는 경우 데이터 보호 및 인증을 구성합니다 Startup.ConfigureServices. 다음 예제에서 인증 유형은 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";
    });

보안상의 이유로 인증 쿠키는 ASP.NET Core에서 압축되지 않습니다. 인증 쿠키를 사용하는 경우 개발자는 필요한 경우에만 포함된 클레임 정보의 수를 최소화해야 합니다.

다양한 기본 경로에서 쿠키 공유

인증 cookie는 기본 Cookie.PathHttpRequest.PathBase를 사용합니다. 앱의 cookie를 서로 다른 기본 경로에서 공유해야 하는 경우 Path를 재정의해야 합니다.

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

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

하위 도메인 간에 쿠키 공유

하위 도메인 간에 쿠키를 공유하는 앱을 호스팅하는 경우 에 공통 도메인을 Cookie지정합니다. 도메인 속성입니다. 와 같은 first_subdomain.contoso.com second_subdomain.contoso.com앱 간에 contoso.com쿠키를 공유하려면 다음을 Cookie.Domain .contoso.com지정합니다.

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

에서 데이터 보호 키 암호화 rest

프로덕션 배포의 DataProtectionProvider 경우 DPAPI 또는 X509Certificate를 rest 사용하여 키를 암호화하도록 구성합니다. 자세한 내용은 ASP.NET Core를 사용하여 Windows 및 Azure에서 rest 키 암호화를 참조하세요. 다음 예제에서는 인증서 지문이 ProtectKeysWithCertificate에 제공됩니다.

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

ASP.NET 4.x와 ASP.NET Core 앱 간에 인증 쿠키 공유

Katana Cookie 인증 미들웨어를 사용하는 ASP.NET 4.x 앱은 ASP.NET Core Cookie 인증 미들웨어와 호환되는 인증 쿠키를 생성하도록 구성할 수 있습니다. 자세한 내용은 ASP.NET 4.x와 ASP.NET Core 앱 간의 인증 쿠키 공유(dotnet/AspNetCore.Docs #21987)를 참조하세요.

일반 사용자 데이터베이스 사용

앱에서 동일한 Identity 스키마(동일한 버전의 Identity)를 사용하는 경우 각 앱의 Identity 시스템이 동일한 사용자 데이터베이스를 가리키는지 확인합니다. 그렇지 않은 경우 시스템은 데이터베이스의 identity 정보에 대해 인증 cookie 의 정보와 일치시키려고 할 때 런타임에 오류를 생성합니다.

일반적으로 앱이 서로 다른 Identity 버전을 사용하므로 앱 간에 Identity 스키마가 다른 경우 다른 앱의 Identity 스키마에 열을 다시 매핑하고 추가하지 않고는 최신 버전의 Identity를 기반으로 공통 데이터베이스를 공유할 수 없습니다. 일반적으로 앱에서 공통 데이터베이스를 공유할 수 있도록 최신 Identity 버전을 사용하도록 다른 앱을 업그레이드하는 것이 더 효율적입니다.

추가 리소스