I have a Rails 6.1 app that uses sessions to store some data.
When I open the app in an iFrame the sessions do not work (I cannot get their value when navigating to another page of the app, still inside the same iFrame)
I read a lot about this and played around with the cookies same_site configurations etc.
I also read about Chrome being the reason but I tried it in Safari with the same issue.
But I do not want to share sessions between the rails app and the page that contains the iFrame. I just want that the app works normally inside the iFrame.
Any ideas what could be the reason?
In order for your session cookie to work inside of an iframe, you need to explicitly set its SameSite setting to None.
Rails version ≥ 6.1
Rails 6.1 introduced a new configuration option, which you can set e.g. in your config/application.rb:
config.action_dispatch.cookies_same_site_protection = :none
The relevant section on the guides is here.
Rails version < 6.1
Your best bet is most likely to use the rails_same_site_cookie gem.
Secure setting
When setting SameSite to None, you must also ensure that your cookies are sent with the Secure setting set to true. This happens when you uncomment the following line in config/environments/production.rb:
config.force_ssl = true
Where is this change from?
The relevant commit for Rails 6.1 is here. It boils down to Rails now explicitly setting SameSite=Lax on every cookie it sends.
Testing
I have found that the best way to locally test a setup such as this one is to run a separate server (e.g. a Middleman instance) to simulate the third party page which embeds your Rails app in an iframe.
Then you can point one browser tab to localhost:3000/my/iframed/page, and the other to lvh.me:4567/my/embedding/page. You should be able to sign in one tab and act as the signed in user in the other.
It is crucial to also test this in a production-like environment.
None vs Lax vs Strict
If you were to set SameSite=Lax, this setup would only work when both tabs are pointing to the same domain, e.g. localhost. With SameSite=Strict, it would not work at all.
When you are testing this, if you switch from e.g. :lax back to :none, you will be logged out from both tabs.
Response headers
Note that changing SameSite's value is not enough to set up your Rails app to work inside of an iframe. You also need to set the right headers in the relevant controller action, like so:
response.set_header("X-Frame-Options", "ALLOW-FROM #{embedding_url}")
response.set_header("Content-Security-Policy", "frame-ancestors 'self' #{embedding_url}")
Where embedding_url can be *, if you'd like anyone to be able to embed your Rails app via an iframe.
For further reading, the nice people over at makandra have compiled a card specifically about the SameSite setting.
Safari support
There is nothing you can do to fix the problem in Safari—besides asking your users to uncheck the Prevent cross-site tracking checkbox in their preferences. In the future, the same is likely to apply to all major browsers (see here for the relevant Chrome blog post).
Related
[Updated - see comment at end]
Google will be changing the behaviour of its Chrome browser so that cookies will no longer work when hosted in another domain's IFRAME unless the cookies are explicityly set to SameSite = None, and Secure.
To this end, we made this change in our ASP.NET MVC code. We have some logic around when to set this (only for partners that we've agreed to work with), so we have this conditional logic:
if (isSameSiteCookieEnforced)
{
cookie.SameSite = SameSiteMode.None;
cookie.Secure = true;
}
We tested this in our DEV, QA, STAGE environments and it works perfectly. In Chrome's developer tools (Application > Cookies), you can inspect the cookies and see that they are all marked as Secure, and have None in the SameSite column.
However, when we rolled this to our PROD environment, we get different results using the same browser: the cookies are marked as Secure, but the SameSite value is empty.
What we checked:
Load Balancer: we isolated this and navigated direct to a single web server, same result
Installed .NET frameworks: in all environments, we've installed 4.7.2 and 4.8
Addressed .NET framework: in all environments, the web.config stipulates 4.7.2
Code: we retrieved the relevant DLL from PROD and inspected with ILSPY. It contains the above code
Currently at a bit of a loss to explain how the cookies could lose the "SameSite" property. Navigating to chrome://flags and filtering on SameSite we're showing the three settings to be "default", so Chrome shouldn't be affecting anything differently from one environment to another.
Update
Our ASP.NET MVC application uses an IHttpModule and as one of the last steps in the EndRequest method we trace out the cookies. You can clearly see that they are set with SameSite=None and Secure=true. But, when they arrive at the browser, the SameSite property has been stripped.
If you are conditioning on whether the new SameSite behavior is enforced, you will want to test the behavior with the chrome://flags entries same-site-by-default-cookies and cookies-without-same-site-must-be-secure set to both "Enabled" and "Disabled". If they are set to "Default", there is no way to tell what the behavior is. It could be on or off, depending on the random seed determined on startup, since the features are currently in a fieldtrial (A/B testing) on Beta. See the second bullet list in "Launch Timeline" here: https://www.chromium.org/updates/same-site
Found the issue - turned out that we were missing a Windows patch.
I'm running Firefox 36.0.4 on Windows 7 32-bit. I've diabled all add-ons, extensions and user scripts before retesting this.
I'd like to step through JavaScript code that is served up in a <script> tag in the HTML document being produced by a Java (Tomcat) web server.
Unfortunately, when I select the HTML document under Debugger > Sources, the source of the page returns to the login page of the application - it appears that session information is not being used to request the source.
I stepped through the server-side code and found that the correct session cookie values were being sent for the real page request and some AJAX requests sent by the page. However, when I tried to load the page source in the JavaScript debugger, I found that an incorrect session cookie was being sent by the JavaScript debugger.
I can replicate this behaviour in other webapps, not just my own. For example, Stack Overflow:
Is this a configuration issue, or a bug in the Firefox Developer Tools?
I can't reproduce your problem using StackOverflow as an example, at least in Firefox Developer Edition ( currently version 38 ):
One thing that might help - try disabling the cache while the toolbox is open - this setting is in the developer tools setting panel ( click on the 'gear' icon at the top right of the toolbox ):
After reviewing canuckistani's answer, I downloaded Firefox Developer Edition. Seemingly, the problem was fixed.
Five minutes in, I became sick of being asked whether to remember passwords and having to manually clear session cookies (I prefer being able to do it by simply closing the browser) - it makes testing easier.
As per usual, I went to Options > Privacy > History to disable this behaviour, by setting the value to Never remember history.
Changing this setting requires the browser to restart. However, upon restarting, I once again saw the same erroneous behaviour - the wrong session cookie was being sent to the web application again.
The workaround here is to not use the Never remember history setting. I have filed a bug report at Mozilla.org Bugzilla.
I have an existing website and suddenly some days ago I can't use Google Chrome anymore for developing. When I use a standard edit and create page, I get the above error. But i'm not getting it in Internet Explorer. I use Windows 10 (all updates installed) and VS2013 with Update 4. The project is the latest MVC version. I even checked the web.config but nothing is changed. I deleted all history, cookies, passwords etc.
Anyone any idea?
I had the same problem. For me the solution was to both clear my browser cookies and to disable Adblock. Other addons may have the same effect. I believe the problem is limited to the Visual Studio / Chrome development environment and will not occur in production regardless of whether the end user has Adblock enabled or not.
Do you have a
<httpCookies requireSSL="true" />
in your Web.config? Change that to false. Then in your transforms files (Web.Prod.config, and other environments that have SSL):
<httpCookies requireSSL="true" xdt:Transform="SetAttributes" />
I'm also having the same issue in recent weeks, but it's also extending cross-browser after originating from Chrome. What's even stranger is that it still works flawlessly with the identical project on a different machine using all browsers.
I have gone so far as to uninstall all extensions, delete all cookies / data, sign out of Chrome completely and re-install it. Problem still persists.
On deployment to Azure websites the problem isn't present on any platform. My current work-around is to Ctrl-F [ValidateAntiForgeryToken] and comment out every occurrence, and re-enable it upon deployment. Annoying, but it works.
This was happening to me in Chrome, and seemed related to using the 'remember me' checkbox on login forms, and closing then re-opening the browser. The token was present on inspecting page source, but was reported as being not present during debugging sessions in visual studio. By clearing the browser cache and not checking the 'remember me' box I did not get the problem - but I don't fully understand why!!
My steps to reproduce the bug in Chrome:
Sign in to your MVC web application, clicking on 'remember me' to make it checked
Close browser
Open browser to your current retained session
Try to sign out - error happens here.
Anyway, the following solution worked for me. Inside your MVC view form, try replacing this:
#Html.AntiForgeryToken()
with:
ViewContext.Writer.Write(Html.AntiForgeryToken().ToHtmlString());
Are you on cloud platform ? chrome emits cookies from cloud domains hence the only way to do it is to map another named domain to your cloud web site
This is probably because browsers like Chrome use the Public Suffix List(https://publicsuffix.org/list/effective_tld_names.dat) to restrict certain cookies. If the domain suffix set on the cookie is shared publicly then the browser may block such a cookie in order to prevent itself from sending "unauthorized" data to other servers running on the same domain.
I am developing an App that uses the AngularJs Router.
So my URLs look like that:
appName/viewOrders
My problem is, when I refresh the browser with F5 I get an 404 Error. (Because there isn't a folder or even file named viewOrders)
I can't redirect it via a config file because I am not able to use one in the environment where I am developing (An Sharepoint 2013 App).
So I came to this idea:
When I click the navigation, the Url doesn't change and stays at
/appName
But the view does it.
How can I achieve it? Have I to use the ui-router?
If you have restricted access and are unable to use the answer #tommyd456 (which it sounds like that may be the case), another option is to omit the url completely using stateProvider (ui-router).
Angular ui-router: Can you change state without changing URL?
Not sure if you've solved this issue but here's a potential solution anyway...
You're using HTML5 mode so you need server-side rewrite as explained here: https://github.com/angular-ui/ui-router/wiki/Frequently-Asked-Questions#how-to-configure-your-server-to-work-with-html5mode
However, it sounds like you've got restricted access to a server so why stop HTML5 mode.
Don't hack at it like you're suggesting - that could get nasty.
I have successfully implemented MVC bundling for my MVC application. There is one problem with the run time which runs under HTTPS.
I am sure there is a problem because when I switch the debug field to false the user gets the warning message "This page contains secure and nonsecure items. Do you wish to proceed?
I know that I can turn this prompt off using the security setting in IE. I would like to know if there is something I can do to the application so that bundled scripts and styles come through the secure pipe.
If you use the Scripts.Render helper to include the bundle it will use the same HTTP scheme as the one used to request the main page. So if the main request was done over HTTPS then this helper will generate a <script> element using HTTPS. You could use the Net tab of FireBug to see which resources are served through HTTP and HTTPS and be able to isolate the problem.
Thank you for this suggestion. I figured out that the problem was coming from modernizr-1.7.js
The strange thing was that this problem only occurs when modernizr is bundled. I removed modernizr because we don't really need it.