Search code examples
cookiesasp.net-core-mvcmulti-tenantasp.net-core-7.0

Mixed cookie configuration in a multi-tenant SaaS ASP.NET Core MVC solution


We're developing a multi-tenant SaaS solution based on ASP.NET Core 7 MVC deployed to an Azure App Service. We have a requirement from one customer who needs to embed the application into their ERP product via an iFrame.

We can set up the X-FRAME-OPTIONS and Content Security Policy headers for them, however the site uses ASP.NET Identity with application cookies set to Strict.

This is configured in Startup.cs like this:

var authentication = services.AddAuthentication()
     .AddCookie(options =>
     {
         options.Cookie.SameSite = SameSiteMode.Strict;
         ...
     });

Unfortunately, because this is set at application level, there doesn't appear to be a way to set cookie settings per tenant.

Is there a way to override the default "Strict" mode for a specific customer dynamically?


Solution

  • I found this repo, and I change the HandleSignInAsync method like below. It also could use middleware to implement it.

        /// <summary>
        /// Creates the cookie.
        /// </summary>
        /// <param name="user"></param>
        /// <param name="properties"></param>
        /// <returns></returns>
        protected override async Task HandleSignInAsync(ClaimsPrincipal user, AuthenticationProperties? properties)
        {
            await Task.CompletedTask;
    
            ClaimsIdentity claimsIdentity = (ClaimsIdentity)user.Identity!;
            //if (Options.CheckIpAddress && !user.HasClaim(claim => claim.Type == "IpAddress"))
            //{
            //    var ipAddress = Context.Connection.RemoteIpAddress!.ToString();
            //    claimsIdentity.AddClaim(new Claim("IpAddress", ipAddress));
            //}
    
            //if (Options.CheckUserAgent && !user.HasClaim(claim => claim.Type == "UserAgent"))
            //{
            //    var userAgent = Context.Request.Headers["User-Agent"].ToString();
            //    claimsIdentity.AddClaim(new Claim("UserAgent", userAgent));
            //}
            var tenantId = Context.Request.Headers["TenantId"].ToString();
    
            user.AddIdentity(claimsIdentity);
    
            var ticket = new AuthenticationTicket(user, MyCookieDefaults.AuthenticationScheme);
            string cookieValue = Options.TicketDataFormat.Protect(ticket);
            CookieOptions options;
            if (tenantId == "A-Tenant")
            {
                options = new()
                {
                    HttpOnly = true,
                    Expires = DateTime.UtcNow.Add(Options.ExpireTimeSpan),
                    SameSite = SameSiteMode.Lax
                };
            }
            else {
                options = new()
                {
                    HttpOnly = true,
                    Expires = DateTime.UtcNow.Add(Options.ExpireTimeSpan),
                    SameSite = SameSiteMode.Strict
                };
            }
            Response.Cookies.Append(Options.CookieName, cookieValue, options);
        }