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.
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?
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");
});
}
app.Use(async (ctx, next) =>
{
ctx.Response.Headers.Add("Content-Security-Policy", Configuration["DefaultApplicationSettings:ContentSecurityPolicy"]);
await next();
});
"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.
It works in all browsers except for Chrome. Set secure:false or secure:true for the cookie. Set sandbox="allow-same-origin allow-scripts" for the iframe, or remove the sandbox attribute.
src URL in the iframe to have the login credential in the URL. When the second domain loaded in the iframe, it would see the login credential in the URL, grab it, turn it into a cookie value that it wrote on itself and the refresh itself (thus now looking logged in).
Since your content is being loaded into an iframe from a remote domain, it is classed as a third-party cookie. The vast majority of third-party cookies are provided by advertisers (these are usually marked as tracking cookies by anti-malware software) and many people consider them to be an invasion of privacy.
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 toSameSiteMode.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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With