KasperHammer
KasperHammer

Reputation: 11

ASP.NET core iframe authentication cookie

I'm having some trouble with my iframe. Whenever I try to login it seems that my authentication cookie isn't working since I just get redirected back to my login screen. How can I fix this?

The cookie works fine when I'm just running the website normally, but as soon as I display it in iframe it all goes to hell.

Here is my Startup.cs:

public class Startup
    {
        public Startup(IConfiguration configuration)
        {
            Configuration = configuration;
          
        }

        public IConfiguration Configuration { get; }

        // This method gets called by the runtime. Use this method to add services to the container.
        public void ConfigureServices(IServiceCollection services)
        {
            services.AddRazorPages();
            services.AddMvc().AddRazorPagesOptions(o =>
            {
                o.Conventions.ConfigureFilter(new Microsoft.AspNetCore.Mvc.IgnoreAntiforgeryTokenAttribute());
                
            });

            // Here we set some settings for the authentication cookie, with the class CookieAuthenticationOptions which is a part of the Microsoft.AspNetCore.Authentication.Cookies namespace.
            services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme).AddCookie(options =>
            {
                // Here we set the name of the authentication cookie.
                options.Cookie.Name = "AuthCookie";
                // Here we set the cookie to Http Only, because no scripts should have access to change the cookie.
                options.Cookie.HttpOnly = true;
                // Here we set the cookie to be only send over an HTTPS connection.
                options.Cookie.SecurePolicy = CookieSecurePolicy.None;
                // Here we set the SameSite to lax, because not all browser's set cookies without a SameSite value to lax.
                options.Cookie.SameSite = SameSiteMode.Lax;
                // Here we set the path to the Access denied site to our AccessDenied site. The site is shown if a user don't have access to the site he/she/it is trying to visit.
                options.AccessDeniedPath = "/";
                // Here we set the login page. The user is redirected to this site if he/she/it is not logged in and the site require the user to be logged in.
                options.LoginPath = "/";
                // Here we set the log out site.
                options.LogoutPath = "/Logout";
            });

        }

        




        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }
            else
            {
                app.UseExceptionHandler("/Error");
                // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
                app.UseHsts();
            }


            /* app.Use(async (context, next) =>
             {
                 //
                 //context.Response.Headers.Remove("X-Frame-Options");
                 context.Response.Headers.Add("X-Frame-Options", "DENY");
             });*/

            app.Use(async (context, next) =>
            {
                context.Response.Headers.Remove("X-Frame-Options");
                context.Response.Headers.Add("X-Frame-Options", "ALLOWALL");
                //context.Response.Headers.Add("Content-Security-Policy", "frame-ancestors https://kasp151f.000webhostapp.com/");
                await next();
            });

            // app.UseHttpsRedirection();
            // Here I enable authentication capeabilities for the website.
            app.UseAuthentication();
            // Here I enable authorization capeabilities for the website.
            app.UseAuthorization();
            app.UseStaticFiles();

            app.UseRouting();
            
            app.UseAuthorization();
            app.UseEndpoints(endpoints =>
            {
                endpoints.MapRazorPages();
            });
        }

    }

And here is my Iframe:

<iframe width="1280" height="720" frameBorder="0"  scrolling="no"  onload="HandleLocationChange(this, this.contentWindow.location.href)" src="http://kasperssejeside.tk/"></iframe>

Upvotes: 1

Views: 3038

Answers (2)

benk
benk

Reputation: 446

As Halvor suggested, it is indeed a SameSite cookie issue. This article describes a fix: Upcoming SameSite Cookie Changes in ASP.NET and ASP.NET Core

Summary: you need the to set the SameSite option to none to allow the cookie to be used despite the iframe. The catch: it will break for browsers for which this option was not available. For these, you need to leave the option out.

Implementation for asp.net core (taken from the above-mentioned article with small changes): All changes are in Startup.cs. Add this to the body of ConfigureServices(...):

services.Configure<CookiePolicyOptions>(options =>
{
    options.MinimumSameSitePolicy = SameSiteMode.Unspecified;
    options.OnAppendCookie = cookieContext =>
        cookieContext.CookieOptions.SameSite = DisallowsSameSiteNone(cookieContext.Context) ? SameSiteMode.Unspecified : SameSiteMode.None;  
    options.OnDeleteCookie = cookieContext =>
        cookieContext.CookieOptions.SameSite = DisallowsSameSiteNone(cookieContext.Context) ? SameSiteMode.Unspecified : SameSiteMode.None;
    options.Secure = CookieSecurePolicy.Always; // required for chromium-based browsers

});

Add this to the body of Configure(...) before app.UseAuthentication()

app.UseCookiePolicy();

And add this method

private static bool DisallowsSameSiteNone(HttpContext httpContext)
{
    var userAgent = httpContext.Request.Headers["User-Agent"].ToString();

    if (string.IsNullOrEmpty(userAgent))
    {
        return false;
    }

    // Cover all iOS based browsers here. This includes:
    // - Safari on iOS 12 for iPhone, iPod Touch, iPad
    // - WkWebview on iOS 12 for iPhone, iPod Touch, iPad
    // - Chrome on iOS 12 for iPhone, iPod Touch, iPad
    // All of which are broken by SameSite=None, because they use the iOS networking stack
    if (userAgent.Contains("CPU iPhone OS 12") || userAgent.Contains("iPad; CPU OS 12"))
    {
        return true;
    }

    // Cover Mac OS X based browsers that use the Mac OS networking stack. This includes:
    // - Safari on Mac OS X.
    // This does not include:
    // - Chrome on Mac OS X
    // Because they do not use the Mac OS networking stack.
    if (userAgent.Contains("Macintosh; Intel Mac OS X 10_14") &&
        userAgent.Contains("Version/") && userAgent.Contains("Safari"))
    {
        return true;
    }

    // Cover Chrome 50-69, because some versions are broken by SameSite=None, 
    // and none in this range require it.
    // Note: this covers some pre-Chromium Edge versions, 
    // but pre-Chromium Edge does not require SameSite=None.
    if (userAgent.Contains("Chrome/5") || userAgent.Contains("Chrome/6"))
    {
        return true;
    }

    return false;
}

Upvotes: 2

Halvor Sakshaug
Halvor Sakshaug

Reputation: 3475

Sounds more like a SameSite cookie issue. To test this try disabling SameSite settings in Chrome, chrome://flags/#same-site-by-default-cookies, or check if it works in IE.

If this fixes your problem you will need to modify the SameSite flag on one or more cookies.

Upvotes: 0

Related Questions