Rails - Multiple top level domains and a single session/cookie - ruby-on-rails

I've been struggling with this for quite awhile and haven't been able to
find a solution. I need a user to be able to view multiple top level
domains with a single login.
My understanding is that this needs to be set in environment.rb and
called with before_dispatch. This is what I've come up with:
require 'activesupport'
require 'dispatcher'
module ActionController
class Dispatcher
def set_session_domain
ActionController::Base.session_options.update :session_domain => "#{#request.host}"
end
before_dispatch :set_session_domain
end
end
However, this does not seem to be working when I try and pull the values
from session[:session_domain].
Any help is greatly appreciated.

This one is a bit tricky. Since cookies can only be assigned to (and retrieved from) the current domain ("forms.example.com", say) and parent domains (".example.com", but not ".com"), but NOT to other domains ("othersite.com"), you'll have to find yourself another solution. This has nothing to do with Rails, but with how cookies work.
EDIT: Sessions rely on a client-specific handle, stored in a cookie, which is why sessions also don't work cross-domain.
This site has one possible solution for creating a cross-domain cookie, and it's the cleanest way I know of, although it may have some security implications. A more complicated version would have the servers communicate directly through some secure channel.
If you're looking for a more general-purpose single-login service, try implementing some form of OpenID.

For sub-domains in Rails 2.3
ActionController::Base.session = { :domain => ".mydomain.com" }
For top-level domains try this middleware.
I've been playing with the above middleware at the moment and it does not quite work as expected. If you do use the middleware you do not need the above code as it handles sub-domains as well.

You will probably need something like RubyCAS if you want authentication across domains regardless of whether they're top-level or subdomains.

Your question is not really precise enough IMHO. Do you want a single cookie for all Rails apps you have or is it within the context of a single one? If the former, you want to look at solutions using database-backed sessions or something along the line of RubyCAS to implement the CAS protocol.

Both Keltia and zuk are right, Answer is rubyCAS, We have do that integration and it allows
SSI - Single sign -in
You sign to one site and you are automatically signed to the other
SSO - Single Sign Out
You sign out from one site and automatically you signed out from the other
For us this is a proven solution and not a hard one to implement
we are using it in
http://www.cabslk.com and www.ticketslk.com
cheers,
Sameera

Related

Single sign-on, multiple domains on same server, ruby on rails

If I have a single server with multiple domains, what is the preferred method for implementing a single-sign-on solution on the same domain. I am currently using devise, have a few million cookies in place on separate domains, and am stuck. On top of just implementing SSO, I also need to migrate the various cookies to a central domain. Regarding the various servers, they only have one single page that requires me to show different states depending on whether or not the user is logged in.
I have tried the following:
CORS: pick one domain as the central auth hub. From all other domains make cross domain checks to see if the user is logged in. For migrating cookies, detect if there's a "current_user" object, send it to the client, make a CORS request, sign the user in and kill the token. Works Great! BUT... After building it for 2-3 weeks, it TOTALLY FAILS in IE. Even IE11, I'm noticing the default setting is disabling this behavior.
tried tinkering with the session store at
Rails.application.config.session_store
with no luck.
I am currently experimenting with the following:
JSONP: I have someone right now trying to convert the above to JSONP instead while I try some other options:
Set up a custom OAUTH provider. Like before, it will be the "central domain" if the person is signed in, return to the requested domain with a token from which the users can make requests. https://github.com/songkick/oauth2-provider
Looking at this but it looks outdated? https://github.com/rubycas/rubycas-client. I also get the feeling this could have been a solution if I rolled this out from the get-go, but given how far we are into the project, it's unclear to me how I'd transfer the existing cookies. Also it's unclear if this requires two applications for me to get up and running ( one for client(s), one for auth server)
As I go through each of these possibilities, if anyone has had any experience doing what I'm doing, please do inform me and save me a whole lot of work :)
The best way unless this is a toy app is probably to set up an oauth provider.
We use Doorkeeper with Devise for this and it works great. It will be worth your time to set a little time aside to read through the documentation and watch a talk or two on youtube if you're not already familiar with the strategy but once you understand the core concepts its actually pretty simple to set up with the help of this gem.
There is a quick video run down on http://railscasts.com/episodes/353-oauth-with-doorkeeper

Password protecting pages simply with rails - what should I do?

I'm now on level 7 of Hartl's rails tutorial book and I'm starting to think about my application in deployment. It's an app that allows about 12 social workers to communicate collaboratively and privately. Thus, I need to password protect it.
However, it also needs to be easy to use, very easy to use. A few of these people haven't used a computer before, and having logging on and sign-up processes would put them off completely.
Thus I want to create a landing page, where they have to type a password in (the same password for everybody), then it redirects to the 'discussion pages.' My first idea was to use some obfuscated javascript such that upon typing in the password, it redirects them to the discussion pages, but this doesn't sound very secure.
Can anyone recommend me a better way to do this in rails? Ideally they would only have to type it in once, and then it would authenticate them for all the pages automatically (by setting a cookie?) and anyone trying to access a page directly would be redirected to the authentication page.
Cheers in advance
A very simple authentication option is available to you in this situation. I would suggest you watch the Ruby on Railscast episode 270. I think it just maybe what you are looking for.
If you want really simple, you can use authenticate_or_request_with_http_basic
It's not a replacement for a real authentication system, e.g. Devise or AuthLogic however.
I started to use the lockup gem for this purpose:
https://github.com/gblakeman/lockup
It is super easy to setup and almost every user accessing the site should be able to use it.

RESTful web services with complex actions (verbs)

I am attempting to construct a web app in which the back end is a complete RESTful web service. I.e. the models (business logic) would be completely accessible via HTTP. For example:
GET /api/users/
GET /api/users/1
POST /api/users
PUT /api/users/1
DELETE /api/users/1
Whats the proper way to provide more methods that aren't CRUD (verbs/actions)? Is this considered more of a RPC-api domain? How would one properly design the RPC api to run on top of the RESTful api?
For example, how would I elegantly implement a forgot password method for a user.
POST (?) /api/users/1/forgot
The application (Controllers/View) would then use a https requests (HMVC like) to access the models and methods. What would be the best for authentication? OAuth, Basic Auth over HTTPs?
Although this is "best practice" for scalability later on, am I over engineering this task? Is it best to just follow the typical MVC model and provide a very basic API?
This question has been mostly inspired by ASP.NET's MVC 4 (WebAPI) and a NodeJS module https://github.com/marak/webservice.js
Thanks in advance
I recently started learning REST, and when developing a new web service I think you're doing the right thing to consider it.
You are correct in your assumptions about the custom verbs. REST acknowledges that some actions need to be handled in a different way, and custom verbs don't violate the requirements. You should use POST when communicating with the server, but the verbs are normally written in imperative. Instead of forgot, I'd probably use remind or something similar. I.e., you should give instructions on what to do, rather than describe what happened without clearly indicating what you expect as a result.
Furthermore, the preferred way to construct the service is to include api into the domain name, and drop it from the path. I'd write your particular example like this:
POST /users/1/remind HTTP/1.1
Host: api.myservice.example.com
Session handling in REST is a bit tricky. The cleanest way of doing it would probably be to authenticate with username and password on every single request, using Basic access authentication. However, I believe that it's rarely done like that. You should read this question (and its accepted answer): OAuth's tokens and sessions in REST
EDIT: I'd also drop the trailing forward slash in the GET request in your example. If the service is truly RESTful, then the resource is not supposed to be accessibly from both /users/ and /users. A particular resource should have one and only one URL pointing to it. A URL with a trailing slash is actually distinct from one without. REST promotes dropping it, and a RESTful web service should not accept both (which in the case of GET means responding with 200 OK), although it may redirect from one to the other. Otherwise, it might lead to confusion about the proper URL, duplicate caching, weeping and gnashing of teeth. :)
EDIT 2: In RESTful Web Services by Richardson & Ruby you're discouraged from putting the new verb in the path. Instead, you could append something like ?_method=remind. It's up to you which one you choose, but please remember that you're not supposed to handle these requests with GET, regardless of what you choose. A GET must not change the resource, and should not cause side effects if the user browses back and forth in the history. Otherwise, you might end up resending the password several times. Use POST instead.

Pylons authentication?

Is there a one and true way to add authentication in Pylons? I've seen so many different ways, but most of them are either outdated or too complex. Is there a tutorial somewhere that explains how to add authentication in a good and solid way?
Pylon's official stance appears to be: We don't do authentication, you can plug in whatever authentication system you want.
Authkit works. It is very basic, but, does a relatively simple job rather well.
Repoze.who/Repoze.what works fairly well and is maintained/developed a bit more actively.
You could use RPX along with openid as mentioned on Tony Landis' blog
Or, you could use BlastOff which contains a bit more than just authentication. It comes with registration, user management, forgot my password functionality, etc.
Think about using repoze.who and repoze.what. They provide a strong pattern for authentication and can be customized easily because its customizable in places that matter.
If you don't get why "what" and "who" are two parts of an authentication scheme all one really needs to know is that "who" authenticates (perhaps with a username and password) and provides an identity of your users and "what" is for checking the authorization the user has in a request. If one wanted they could use "what" or "who" alone. But, IMHO it works best if you use just "who" or "who" and "what" together
Basically it works like this; On each request that requires authentication the "who" will be processed (applying its plugins) when the controller gets called - giving you an identity to work with. That is.. If a "what" is required or abort( 401 ) is called then a login page (a challenge) might be shown if the user needs credentials else a 403 Forbidden is displayed. It works well
Here is a tutorial on getting just "who" to work Authentication and Authorization with repoze.who. It outlines a very simple way to get started.
nope, you are free to choose whatever is appropriate for your application. Now, if you consider that turbogears 2.0 is built on pylons and uses repoze.who for authentication, it would seem in that light that repoze.who is pretty popular and could conceivably be the generally accepted way of doing things according to turbogears. If you are looking for guidance.
AuthKit
http://pylonsbook.com/en/1.1/authentication-and-authorization.html#authkit
I tried repoze.who and repoze.what but I didn't like them. Now, I use a variation of the solution described at http://wiki.pylonshq.com/display/pylonscookbook/Simple+Homegrown+Authentication
The decorator based approach works well also: http://wiki.pylonshq.com/display/pylonscookbook/Another+approach+for+authorization+in+pylons+%28decorator+based%2C+repoze.what+like%29

Kerberos Authentication in Rails

Is it possible to use kerberos to authenticate a user under rails? Are there any existing plugins (preferably which extend authlogic's functionality) to do this?
I'm hoping someone else will come around and show us a pure Rails way of doing this. But until then, the easiest way to get things going is by letting your web server handle it.
On that note, I'm going to assume Apache. If this is not the case, please tell us a bit more about your set-up.
Proper Kerberos authentication in browsers is done in the HTTP protocol itself, much like Basic or Digest authentication. In Apache, this can be done with mod_kerb_auth.
Then the next step is to find out how to retrieve the username. It depends a bit on the interface you're using between the web-server and your Rails app. This could be Passenger, FastCGI, mod_proxy, etc.
Many will follow the original CGI standard to some degree, passing along a bunch of environment variables with the request. Try the following in your controller:
username = request.env['REMOTE_USER']
That's as far as I can take you. I've never used authlogic. Though, by the looks of it, it supports plugins. Perhaps you can create a new one that blindly trusts REMOTE_USER if it is set?
If you wanto to switch from authlogic to Omniauth for your authentication there's a module for it:
https://github.com/jgraichen/omniauth-kerberos

Resources