Search code examples
c#cookiesiframeasp.net-coreidentityserver4

Iframe wont respect login cookies


I have a very strange issue that i have been trying to debug for more then a week now. I am out of ideas as to what the problem could be. I am hoping someone here may have run into this same problem before and be able to give me an idea what the issue could be and how to fix it.

I a asp .net core 2.0 application. It runs fine when hosted stand alone.

  1. Main controller requires authentication.
  2. Logs into Identity server 4. (hybrid granttype)
  3. Returns to application fetches data and displays it.

Now when i try and add this application as a plugin in the main application it doesnt work. It actually loops around. Plugins are displayed in the main application in an iFrame.

<iframe src="https://XXXXX" sandbox="allow-same-origin allow-scripts allow-forms allow-popups allow-popups-to-escape-sandbox" width="500" height="500"></iframe>

Watching the logs. I can see it being forwarded to the Identity server logging returning to the plugin sight were i can see that it

OnSignedIn: IsAuthenticated = True

I can see that the plugin has an access token. Then the loop starts. It goes back to the identity server asks for access again and the whole thing continues endlessly.

What i can see that is diffrent between running standalone and running as a plugin is this line is missing in the log

Microsoft.AspNetCore.Authentication.Cookies.CookieAuthenticationHandler[10]
AuthenticationScheme: Cookies signed in.

I can also see in the headers on the requests that the Identity server returns the cookie headers and tells it to do a setcookie but it is never set.

Why is the cookie not set when in an Iframe?

What i have tried

 options.Cookie.SameSite = SameSiteMode.Lax;
 options.Cookie.SecurePolicy = CookieSecurePolicy.None;

Content-Security-Policy headers includes both the identity server, the plugin site and the main web application sites.

Why isnt the cookie being set?

Plugin auth code.

 services.AddAuthentication(options =>
            {
                options.DefaultScheme = "Cookies";
                options.DefaultChallengeScheme = "oidc";


            })
            .AddCookie("Cookies", options =>
            {
                options.Cookie.SameSite = SameSiteMode.Lax;
                options.Cookie.SecurePolicy = CookieSecurePolicy.None;
                options.SessionStore = new MemoryCacheTicketStore();                   
            })
            .AddOpenIdConnect("oidc", options =>
            {
                options.SignInScheme = "Cookies";

                options.Authority = Configuration["ServiceSettings:IdentityServerEndpoint"];
                options.RequireHttpsMetadata = false;

                options.ClientId = Configuration["ServiceSettings:ClientId"];
                options.ClientSecret = Configuration["ServiceSettings:secret"];
                options.ResponseType = "code id_token";

                options.SaveTokens = true;
                options.GetClaimsFromUserInfoEndpoint = true;

                options.Scope.Add("profile");
                options.Scope.Add("testapi");

            });
    }

headers

 app.Use(async (ctx, next) =>
        {
            ctx.Response.Headers.Add("Content-Security-Policy", Configuration["DefaultApplicationSettings:ContentSecurityPolicy"]);

            await next();
        });

settings

 "DefaultApplicationSettings": {
"ContentSecurityPolicy": "default-src 'self' plugin webapp; style-src 'self' 'unsafe-inline' https://fonts.googleapis.com/ webapp; font-src 'self' https://fonts.gstatic.com/ webapp; frame-ancestors 'self' webapp"  },

Urls changed due to company privacy.


Solution

  • After a lot of searching one of my cowkers found a comment in the identity server 4 source code

    IdentityServerBuilderExtensions.cs

     // we need to disable to allow iframe for authorize requests
     cookie.Cookie.SameSite = AspNetCore.Http.SameSiteMode.None;
    

    as soon as i changed

    options.Cookie.SameSite = SameSiteMode.Lax;
    

    to

    options.Cookie.SameSite = SameSiteMode.None;
    

    It worked.

    Indicates whether the browser should allow the cookie to be attached to same-site requests only (SameSiteMode.Strict) or cross-site requests using safe HTTP methods and same-site requests (SameSiteMode.Lax). When set to SameSiteMode.None, the cookie header value isn't set. Note that Cookie Policy Middleware might overwrite the value that you provide. To support OAuth authentication, the default value is SameSiteMode.Lax. For more information, see OAuth authentication broken due to SameSite cookie policy.

    Why this works i am still not clear but it it works.