We are building a new application with Ruby on Rails. Our frontend is in a separate project and we do not make use of Rails' views. Our backend is located on api.app.example.com, whereas the frontend part is located on app.example.com. They are on different infrastructures (one is in AWS ECS, other is in S3). We are having trouble getting the session cookies to save in the browser.
I have done some research and found the domain: :all and tld_length: 4 parameters, however these have been mostly been about same length subdomain, just different names. I have been trying some of the different combinations, but none of them has helped so far:
domain: :all, tld_length: 3
domain: :all, tld_length: 4
domain: '.app.example.com', tld_length: 4
domain: '.example.com'
domain: :all
The Set-Cookie header is received successfully by the browser, however it is not saved, therefor rendering any requests after login Unauthorized.
Is there something that I am forgetting? Can this be solved or should I just move the whole thing to single IP and use /api instead of api.?
Usually, if you are using Rails as an API project session storage is disabled by default. You should do something like this in one of your initializers:
Rails.application.config.session_store :cookie_store, :key => '_namespace'
I don't think subdomain should matter in this case, but I may be wrong.
Related
We have a setup in a way that currently some pages are being served by a Rails 4 app and a Rails 5 app. All the authentication logic resides in the Rails 4 app and we are using Devise for authentication. The session_store.rb on the Rails 4 app looks like this Rails.application.config.session_store :cookie_store, key: '_app_store'. I want to have the current_user accessible in the Rails 5 app as well. Note: Both the apps are under the same domain. Also how should I go about setting devise on my Rails 5 app so that current_user is accessible.
First allow cookie to apply for all of your subdomains:
Rails.application.config.session_store :cookie_store, key: '_app_store', domain: :all
When the browser accesses a website, the website tells the browser to set a cookie. When this happens, it specifies the cookie name, value, domain, and path.
:domain => :all makes a dot in front of the cookie domain (which is whatever host your browser has browsed to), so the cookie applies to all subdomains.
Another good thread about this topic can be found here:
https://stackoverflow.com/a/4065929/1625253
I am having a situation when I am trying to make a RAILS application to be the backend core of my APIs. I am using 'devise' to authenticate the users, which does by putting a session cookie. This is so far perfect. and take in consideration that I am building this on "api.mydomain.com"
Now, I also have a javascript application running on "mydomain.com" which do AJAX calls to the API on the subdomain. I need to have the rails-issued cookie be valid and go on the headers when I make the API calls... It just doesn't.
I tried every single solution that I found on google, where it looks like putting this
Api::Application.config.session_store :cookie_store, key: '_api_session', :domain => ".mydomain.com"
into my config/initializers/session_store.rb was the default answer. this didn't work for me.
I also found some other recommendation on google that I shoudl put that in the environment file. that didn't work either for me.
Help will be appreciated.
Please note: I am running rails 3.2.11 should this matter.
Try using the :domain => :all option.
Source: Railsapps Tutorial on Subdomains (search for "Optional: Allow Sessions To Be Shared Across Subdomains")
I found that there is a better way to do that:
:domain => "*.domain.com"
I have 2 Rails applications (separated but sharing same top level domain). In development, I run the first application under localhost:3000 and the other one under localhost:3500
These two applications have the same users (not really but let's keep it simple).
So, when a user logs into application 1, I want him to be able to go to application 2 without having to sign-in again.
To do this, I changed the initializer, session_store.rb to:
Iview::Application.config.session_store :cookie_store, :key => '_iview_session', :domain => :all
I hoped this would be enough as, in my understanding, when accessing app. 2, the app. would be looking for the cookie of app 1 and assume the user is logged-in but it doesn't do the trick (at least in development).
What do I miss? Thanks!
Have you tried to set the secret_token.rb initializer to the same key?
I have a rails app which supports multiple domains and each domain may have multiple subdomains.
Users visiting mydomain1.com do not receive the same experience as mydomain2.com (although the base behaviour of the apps is the same)
Therefore, if a user is logged in to mydomain1.com, it shouldn't then be logged in to mydomain2.com
If a user is logged in to france.mydomain1.com, it should then be logged in to germany.mydomain1.com
Previously, I've handled this by setting the domain in the session store configs:
MyApp::Application.config.session_store :cookie_store, :key => '_MyApp_session', :domain => APP_CONFIG[:domain]
I'm trying to work out the best way to handle this with multiple domains?
I've tried hacking around ActionDispatch::Callback but the request is not available from within there.
Can anybody suggest a good way of supporting multiple cookies from within one app?
Ideally I'd like to create a fresh cookie for each subdomain.
You should do that:
class ActionDispatch::Session::MultiDomainStore < ActionDispatch::Session::CookieStore
def initialize(app, options = {})
super(app, options.merge!(:domain => compute_domain(app)))
end
def compute_domain(app)
...
end
end
MyApp::Application.config.session_store :multi_domain_store, :key => '_MyApp_session'
I.e. your domain should start with the dot.
It shouldn't be an issue as cookies are only valid per domain. You can have a _MyApp_session for example1.com and one for example2.com. The cookies are managed by the browser and only sent to the host if the domain matches.
Say you visit example1.com and log in and you will get a cookie with the value abcdef123. Then you log into example2.com and you will get another cookie with a random string uvwxyz890.
If you return to example1.com later, the browser will only send the cookies that are valid for this domain to your app. Your app won't have to manage anything and you don't have to hack anything.
I have not been able to find an easy guide for securing a Ruby on Rails app against a Firesheep.
In case you don't know, Firesheep jacks session cookies if your app doesn't force SSL and set the secure flag in the cookie. I had to do some searching to find these two things, so I thought I'd post what I found here and see if there is anything else I'm missing.
Step 1 Force SSL
There are two ways to do this that I found. One is using the ssl_requirement plugin, but this is a pain because you have to specifically specify ssl_required :action1, :action2 in every controller.
The preferable way appears to be by using Rack Middleware, via this post: Force SSL using ssl_requirement in Rails 2 app. Works like a charm.
Step 2 Make cookies secure
For this I followed these directions, which tell you to put the following in your config/environment/production.rb file:
config.action_controller.session = {
:key => 'name_of_session_goes_here',
:secret => 'you need to fill in a fairly long secret here and obviously do not copy paste this one',
:expire_after => 14 * 24 * 3600, #I keep folks logged in for two weeks
:secure => true #The session will now not be sent or received on HTTP requests.
}
This was all pretty straight-forward on my Rails 2.x app. Did I miss anything? Is it different for Rails 3?
Looks pretty good to me. It's pretty similar in Rails 3, though by default the session config is stored in config/initializers/session_store.rb. I usually tweak mine to look something like...
MyApp::Application.config.session_store :cookie_store, :key => '_my_app_session',
:secure => Rails.env == 'production', # Only send cookie over SSL when in production mode
:httponly => true, # Don't allow Javascript to access the cookie (mitigates cookie-based XSS exploits)
:expire_after => 60.minutes
And the secret is held in config/initializers/secret_token.rb:
MyApp::Application.config.secret_token = 'secret secrets are no fun...'
If you have access to your Apache (or whatever) config, you can also force SSL usage at that level. Strikes me as a more appropriate place to do that, but I guess not everyone has that option.
Seeing as this SO post ranks pretty high in Google I thought I'd share the approach I used for securing an app.
If you want to ensure SSL and also ensure secure cookies then you could use a Rack middleware:
https://github.com/tobmatth/rack-ssl-enforcer
I evaluated lots of different options and configuration settings for doing this but the rack middleware felt like the best option with the least amount of config - very easy to deploy. It has some great config options to filter specific rules, hosts, paths etc.
I tested that it does indeed set secure cookies correctly and it does. The one thing I noted was it only did it when logging out and logging in again - but that was using Devise.