Rails, Subdomain based cookies - ruby-on-rails

I have a rails application which is Subdomain based. It also contains REST API which can be publicly accessed to our clients. I have an another client application through which I am accessing the REST API of the main app.
When I am accessing both the apps on the same browser and logged in the main app, I am not able to access the REST API of different Subdomain in client app as cookie get stored according to the domain accessed.
Is there any way to differentiate the cookies based on Subdomain.
Thanks in advance.

You should set cookie's domain as .yourdomain.com so that your cookies are set for main domain and for all subdomains.
Rails 3 on config/initializers/session_store.rb:
Rails.application.config.session_store :cookie_store, :key => '_my_key', :domain => ".yourdomain.com"
Rails 2.3+ on config/environment.rb:
config.action_controller.session = { :key => '_my_key', :domain => '.yourdomain.com' }

Related

Share session between a Rails 4 and a Rails 5 app

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

Rails ActiveRecord Session Store in HTML5 SessionStorage Instead of Cookie

My application has a requirement for users to log into different accounts in separate tabs in their browser (we target Chrome specifically). Because Rails uses cookies to store session info, when the user is logged in, they are logged in on all tabs in the browser. I'm using the ActiveRecord session store method, but even the ID for the session is saved as a cookie.
It seems there's a solution in using HTML5's sessionStorage mechanism, which is limited in scope to the tab or window that the user is logged into. It seems all I have to do is direct Rails to save the session info into the sessionStorage rather than cookies. But I can find no information on this at all.
Assuming there's no way to configure the session store to do this in Rails, is it possible to override the ActiveRecord session saving mechanism? Any pointers on where to look for info about how to go about this?
Unlike cookies, sessionStorage entries cannot be created with response headers, and are not automatically included in request headers. This puts a lot of the workload for managing sessionStorage/localStorage-based authentication on client-side Javascript. All authenticated access would have to be through Javascript XHR requests which explicitly include the authentication token.
If you want the user to be able to have several concurrent sessions, and you don't want to build your site as a SPA, then you will have to take an alternate approach with cookies.
One way would be to use multiple domains to force the cookies into separate subspaces. Set a wildcard DNS record and configure your web server to accept all matching requests regardless of prefix. For example, users might by default be at www.yoursite.com. You would provide a 'create new session' link which opens a new tab to a random subdomain, e.g. 1234abcd.www.yoursite.com. This may create a problem if you are using SSL, however; wildcard SSL certificates tend to be much more expensive.
A simpler way would be to educate users about their browsers' private/icognito modes, which maintain independent cookie stores. However, getting users to read documentation is always a challenge.
You now configure the Cookie-based session store through an initializer, probably in config/initializers/session_store.rb. In Rails 3 the session store is a piece of middleware, and the configuration options are passed in with a single call to config.session_store:
Your::Application.config.session_store :cookie_store, :key => '_session'
You can put any extra options you want in the hash with :key, e.g.
Your::Application.config.session_store :cookie_store, {
:key => '_session_id',
:path => '/',
:domain => nil,
:expire_after => nil,
:secure => false,
:httponly => true,
:cookie_only => true
}

Configuring Rails App to handle multiple subdomains and multiple cookies

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.

How maintain users authentications\sessions through multiple application?

I am using Ruby on Rails 3 and I have 3 web applications:
<site_name>.com
users.<site_name>.com
resources.<site_name>.com
Notice: At this time I have applications on the same server, but in future I can choose to deploy those on separated web servers. So, I would like not use the common solution:
config.session_store :cookie_store, :key => '<whatever key>', :domain => :all
Consider this in your answer.
I would like to handle user authentications\sessions through all those applications so that a user must authenticate himself only one time. That is, I would like to sign in a user on users.<site_name>.com and then maintain its session on browsing other applications.
So, question are:
What do you advice in order to implement these functions? Do that writing own code or using gem(s)\plugin(s)? If the latter, what gem(s)\plugin(s) combination do you advice to use?
I have heard of the OAuth protocoll: in my case (also if at this time I need to authorizate users only through my applications) is it right to use that? If so, what gem(s)\plugin(s) can I use to achieve that?
If you're always going to have these servers on *.<site_name>.com then you could use a cookie written to the <site_name>.com scope to track and authenticate this user. Obviously you do have to be careful about this and make sure that a) the cookie is transferred via HTTPS (secure cookie) and that b) that each server validates the cookie via some sort of web service.
I suggest looking into Warden and the warden_rails gem. On top of this basic well documented authentication foundation you can write "strategies" to validate users using a cookie and read in the session information from a central datasource.
if they all run under the same domain the easiest would be to make sure your cookies are valid for all subdomains. in your production.rb:
config.session_store :cookie_store, :key => '<whatever key>', :domain => :all
the :domain => :all causes your cookies to be valid across all subdomains. just make sure the key and also your session secret token are the same in all apps.

How to handle session domains in a cname forward supporting rails saas software

I have read
How to give cname forward support to saas software
Rails - Multiple top level domains and a single session/cookie
But I am unable to get a solution for the following setup:
A SaaS Webapp in Rails is running under example.com
All users have a sumbdomain e.g. user1.example.com
Users can create a cname forwarding eg. exampleapp.user1.com -> user1.example.com
It is all working until a user tries to log in via exampleapp.user1.com. The SaaS app fails to set the session domain right, because it is configured static on app startup.
config.action_controller.session = {
:session_key => '_example_session',
:domain => ".example.com",
:secret => 'abc'
}
The Request fails with a ActionController::InvalidAuthenticityToken. And that is correct, because the domain changed from .example.com to exampleapp.user1.com.
How do I change the domain config during runtime? I know that the "incoming" domain exampleapp.user1.com belongs to user1, so I want to do something like that in the controller:
session :domain => 'exampleapp.user1.com'
Or can I always set the session domain on the current request domain?
I know that it's possible somehow, because some apps provide that functionality.
Thanks in advance!
:domain => :all on the cookie config may work.
For CNAME'd domains, it will be set to .theirdomain.com
For your custom subdomain, it will go to .yourdomain.com, which may or may not be good
Just don't set the domain, since apparently you don't need to share a session cookie across example.com and user1.example.com. By not specifying a domain, the default cookie behavior is just to be set for the current request domain.

Resources