.net6 쿠키 로그인시 같은 도메인에서 쿠키를 여러개 만드는게 가능한가요??

도메인은 같으나 path에 따라 개별 세션 쿠키 생성 방식(multi-tenant scheme)에 대해 테스트를 해 봤는데요.
결론부터 말씀드리면, 되는데 보강이 필요합니다.

우선 코드부터 공유 드릴게요.
테스트 코드라서 보안에 취약한 부분이 있습니다.
운영에 그대로 적용하시면 안되세요!

Cookie Scheme 등록

각 path별 Cookie 인증 Scheme을 등록합니다.

builder.Services.AddAuthentication(o =>
       {
           o.RequireAuthenticatedSignIn = false;
       })
       .AddCookie("ACookie", options => 
       {
           options.ExpireTimeSpan = TimeSpan.FromHours(1);
           options.SlidingExpiration = true;
           options.Cookie.Name = "ACookie";
           options.Cookie.Path = "/A";
           options.CookieManager = new CookieManager();
       })
       .AddCookie("BCookie", options =>
       {
           options.ExpireTimeSpan = TimeSpan.FromHours(1);
           options.SlidingExpiration = true;
           options.Cookie.Name = "BCookie";
           options.Cookie.Path = "/B";
           options.CookieManager = new CookieManager();
       })
       .AddCookie("CCookie", options =>
       {
           options.ExpireTimeSpan = TimeSpan.FromHours(1);
           options.SlidingExpiration = true;
           options.Cookie.Name = "CCookie";
           options.Cookie.Path = "/C";
           options.CookieManager = new CookieManager();
       });

Path별 쿠키를 처리할 CookieManager

path 별로 쿠키를 처리할 CookieManager를 별도 구현합니다.

public class CookieManager : ICookieManager
{
    private readonly ICookieManager ConcreteManager;

    private string RemoveSubdomain(string host)
    {
        var splitHostname = host.Split('.');

        //if not localhost
        if (splitHostname.Length > 1)
        {
            return string.Join(".", splitHostname.Skip(1));
        }
        else
        {
            return host;
        }
    }

    public CookieManager()
    {
        ConcreteManager = new ChunkingCookieManager();
    }

    public void AppendResponseCookie(HttpContext context, string key, string value, CookieOptions options)
    {
        options.Domain = RemoveSubdomain(context.Request.Host.Host); //Set the Cookie Domain using the request from host
        ConcreteManager.AppendResponseCookie(context, key, value, options);
    }

    public void DeleteCookie(HttpContext context, string key, CookieOptions options)
    {
        ConcreteManager.DeleteCookie(context, key, options);
    }

    public string GetRequestCookie(HttpContext context, string key)
    {
        var result = ConcreteManager.GetRequestCookie(context, key);
        return result;
    }
}

웹 요청시 Cookie 처리

Scheme별 쿠키 인증을 처리하여 Identity Context를 저장합니다.

app.Use(async (context, next) =>
{
    var principal = new ClaimsPrincipal();
    var result1 = await context.AuthenticateAsync("ACookie");
    if (result1?.Principal != null)
    {
        principal.AddIdentities(result1.Principal.Identities);
    }

    var result2 = await context.AuthenticateAsync("BCookie");
    if (result2?.Principal != null)
    {
        principal.AddIdentities(result2.Principal.Identities);
    }

    var result3 = await context.AuthenticateAsync("CCookie");
    if (result3?.Principal != null)
    {
        principal.AddIdentities(result3.Principal.Identities);
    }

    context.User = principal;

    await next();
});

쿠키 생성

SignInAsync시 tenant에 맞는 쿠키가 생성 되도록 지정합니다.

[HttpPost("session")]
public async Task Session()
{
    var userPrincipal = GetPrincipal("Roh", "a@a.com", "AUser");

    var options = new AuthenticationProperties
    {
        IsPersistent = true
    };
    await HttpContext.SignInAsync("ACookie", userPrincipal, options).ConfigureAwait(false);
}

테스트

Path별 API 리스트

API 테스트

B의 session 쿠키를 위해 POST API를 호출 합니다.
image

B 세션 쿠키가 생성 되었습니다.
image

현재 버전

기대결과에 맞는 모습을 보여줍니다.

  • 쿠키가 path 별로 생성 됩니다.
  • 같은 Path API 호출시 쿠키가 전달됩니다.
  • 다른 Path API 호출시 쿠키가 전달되지 않습니다.

현재 버전 문제점

[Authorize(AuthenticationSchemes = "CCookie")]
[HttpGet("user")]
public UserResult GetCUser()
{
    return GetUserResult();
}

CCookie를 먼저 생성하고, 위와 같이 특정 API에 인증 제약이 적용되지 않아 API 호출에 실패하는 현상을 보였습니다.
아마도, multi-tenant에 걸맞는 Cookie scheme 세부 처리 옵션이나 AuthorizationHandler를 재작성해서 적용해야 될 것 같은데 너무 깊게 들어가는 것 같아서 현재 수준으로 공유 드립니다.
참조하셔서 원하시는 결과 얻으시길 바래요.

참조

6개의 좋아요