require 'janus/hooks/remote_authenticatable' module Janus module Models # = RemoteAuthenticatable # # Keeping a user connected on subdomains is an easy task, all you need to do # is define the session cookie to .example.com for instance. But # keeping a user connected on multiple top level domains is a harder task. # # Hopefully RemoteAuthenticatable takes care of all the hassle. # # == Single Sign In # # The authentication must happen on a single domain, for instance # login.example.com, then other domains must redirect to that # domain's new session url. For instance: # # redirect_to new_user_session_url(:host => "login.example.com") unless user_signed_in? # # And that's it! The user shall be redirected with an unique +remote_token+, # which shall log her in. Actually the user won't be logged in through # Janus::Manager#login but through Janus::Manager#set_user which won't # run the login hooks. This is useful for not tracking the user everytime # it gets authenticated on each remote site. # # == Single Sign Out # # Session state is maintained across domains through the session_token # column of your User model. If a session token is invalid the session # is simply resetted, thus logging out the user on remote domains. Actually # the user is logged out using Janus::Manager#unset_user before # resetting the session. # # == Required columns and models: # # A +session_token+ column (string) is required, as well as a RemoteToken # model like so: # # class RemoteToken < ActiveRecord::Base # include Janus::Models::RemoteToken # # belongs_to :user # validates_presence_of :user # end # # With the associated table: # # create_table :remote_tokens do |t| # t.references :user # t.string :token # t.datetime :created_at # end # # add_index :remote_tokens, :token, :unique => true module RemoteAuthenticatable extend ActiveSupport::Concern included do |klass| attr_protected :session_token klass.class_eval { has_many :remote_tokens } janus_config :remote_authentication_key end # Generates an unique session token. This token will be used to validate # the current session, and must be generated whenever a user signs in on # the main site. # # The token won't be regenerated if it already exists. def generate_session_token! update_attribute(:session_token, self.class.generate_token(:session_token)) unless session_token session_token end # Destroys the session token. This must be called whenever the user signs # out. Doing so will invalidate all sessions using this token at once # --hence single sign out. def destroy_session_token! update_attribute(:session_token, nil) end # Returns a temporary token to be used with find_for_remote_authentication. def generate_remote_token! remote_tokens.create.token end module ClassMethods def find_for_remote_authentication(token) remote_token = ::RemoteToken.where(:token => token).first if remote_token remote_token.destroy remote_token.user unless remote_token.created_at < 30.seconds.ago end end end end end end