Difference between revisions of "Auth Module"

m (UmlautAuth Module moved to Auth Module: Properly reflect name of the module.)
 
(23 intermediate revisions by one other user not shown)
Line 1: Line 1:
== Umlaut Auth Module (Developer Notes) ==
+
[[Category:Umlaut]]
The Auth module extends functionality available from the [Authlogic|http://github.com/binarylogic/authlogic] (version 2.1.0) gem and included in the lib directory based on the [Authlogic OpenID add-on|http://github.com/binarylogic/authlogic_openid].
+
  
=== Core Umlaut Files Added or Updated ===
+
=WARNING: This is Outdated Documentation!!!!=
Several core Umlaut files were updated in order to develop the Auth module.
+
 
 +
'''THIS IS OUTDATED DOCUMENTATION''' See new Umlaut documentation at http://github.com/team-umlaut/umlaut/wiki
 +
---------
 +
 
 +
== Auth Module (Developer Notes) ==
 +
The Auth module extends functionality available from the [Authlogic|http://github.com/binarylogic/authlogic] (version 2.1.0) gem and included in the lib directory based on the [Authlogic OpenID add-on|http://github.com/binarylogic/authlogic_openid].'
 +
 
 +
The idea is to allow services to be customized based on a logged in user's attributes.
 +
Some examples could be:
 +
* Store a user's mobile phone number or email address to default the txt/email values for those services.
 +
* Provide extended request or paging functionality that is only available to a subset of patrons.
 +
* Allow faculty members to place items on reserve from the Umlaut screen.
 +
 
 +
Currently the Auth module requires existing Umlaut users to install the authlogic gem and perform a rails migration to update the user model to work with authlogic and the auth module.  After these two steps have been taken, the auth module should only take effect if a particular instance has defined a auth module in their local config.
 +
 
 +
=== Umlaut Files Added or Updated ===
 +
Several core Umlaut files were added and updated in order to support the Auth module.
 
==== app/controller/application.rb ====
 
==== app/controller/application.rb ====
The application controller was updated to filter passwords and provide two methods for accessing the current user session and the current user.  The method current_user_session (aliased as has_logged_in_user) returns nil if no user session has been established.  The method current_user (aliased as logged_in_user) return either nil or the current logged in user.
+
The '''ApplicationController''' filters passwords and provides two methods for accessing the current user session and the current user.   
 +
# '''current_user_session''' (aliased as has_logged_in_user) - returns nil if no user session has been established
 +
# '''current_user''' (aliased as logged_in_user) - returns either nil or the current logged in user
 +
The application calls '''current_user_session''' as a before filter on every request.
 
==== app/controllers/user_sessions_controller.rb ====
 
==== app/controllers/user_sessions_controller.rb ====
The user sessions controller manages the routing of user session requests. Three methods are available:
+
The '''UserSessionsController''' manages the routing of user session requests and provides three methods.
# new - renders the login screen or redirects to external login screen
+
# '''new''' - renders the login screen or redirects to external login screen
# validate - validates the user upon login
+
# '''validate''' - validates the user upon login
# destroy - processes logout
+
# '''destroy''' - processes logout
 
==== app/controllers/users_controller.rb ====
 
==== app/controllers/users_controller.rb ====
The users controller manages the routing of user related requests. Two methods are available:
+
The '''UsersController''' manages the routing of user related requests and provides two methods.
# edit (also called from show) - renders the user preferences screen.
+
# '''edit''' (also called from show) - renders the user preferences screen
# update - processes updates to user preferences.
+
# '''update''' - processes updates to user preferences (not yet implemented)
  app/models/user_sessions
+
==== app/models/user_sessions.rb ====
Extends Authlogic::Session::Base
+
'''UserSessions''' extends Authlogic::Session::Base
==== app/models/user ====
+
==== app/models/user.rb ====
Serializes user_attributes and adds acts_as_authentic functionality to leverage the Authlogic gem.  Also sets to_param to username rather than id for prettier urls.
+
'''User''' serializes user_attributes and adds acts_as_authentic functionality to leverage the Authlogic gem.  Also sets to_param to username rather than id for prettier urls.
==== app/views/user_sessions/new ====
+
==== app/views/user_sessions/new.html.rb ====
The default login screen
+
The default login screen, doesn't currently do anything.
==== app/views/users/edit ====
+
==== app/views/users/edit.html.rb ====
The default user preferences screen.  Users can update mobile phone numbers and the like.
+
The default user preferences screen.  Users can update mobile phone numbers and the like (not yet implemented)
 
==== config/environment.rb ====
 
==== config/environment.rb ====
 
Added authlogic gem:   
 
Added authlogic gem:   
 
<pre>
 
<pre>
 
#require 'authlogic'
 
#require 'authlogic'
config.gem 'authlogic', :version => "= 2.1.0"</pre>
+
config.gem 'authlogic', :version => "= 2.1.0"
 +
</pre>
 
==== config/routes.rb ====
 
==== config/routes.rb ====
 
Added url routes:
 
Added url routes:
Line 38: Line 57:
 
</pre>
 
</pre>
 
==== db/schema.rb ====
 
==== db/schema.rb ====
Modified the user table to use with authlogic.  Included column for mobile phone and user attributes.
+
Modified the user table to use with authlogic.  Included column for mobile phone, user attributes and a refreshed_at date to track age of a particular record for better performance.  By default, data expires after 1 week.
 +
==== lib/service.rb ====
 +
Make the user accessible from a particular user via the session_user method.
 +
<pre>
 +
  # Returns the currently logged in user, if available, based on the user_credentials_id in the
 +
  # session from AuthLogic.  May want to make this more sophisticated and check user_credentials
 +
  # against db.
 +
  def session_user
 +
    return User.find(session["user_credentials_id"]) unless session["user_credentials_id"].nil?
 +
  end
 +
</pre>
 +
 
 +
=== Auth Module ===
 +
The following files makeup the Auth module to extend the functionality of Authlogic for our purposes. 
 +
==== lib/auth/acts_as_authentic.rb ====
 +
The '''ActsAsAuthentic''' module extends the authlogic user model to ignore passwords, reset_persistence_token when the username changes, manage stale data (via refreshed_at date), and handle user attributes hash.
 +
==== lib/auth/session.rb ====
 +
The '''Session''' module establishes the Auth module callback functions and can serve as a template for further localizations.
 +
Callback functions to be overridden locally as appropriate:
 +
# '''before_login''' - called when a new user session is being established, before the actual login is called
 +
# '''login_url''' - called if before_login isn't defined or returns false, convenience method for redirecting to an external login url
 +
# '''after_login''' - called after login user has been validated, provides mechanism for authorization
 +
# '''before_logout''' - called before current user session is destroyed
 +
# '''after_logout''' - called after current user session is destroyed
 +
# '''on_every_request''' - called on every request
 +
The module also has two private methods for use in extended local classes.
 +
# '''validate_url''' - generates the return url to send to external logins services
 +
# '''session_user''' - facilitates saving user attributes to the user model
 +
 
 +
== Configuring Local Auth Modules ==
 +
 
 +
=== Auth Module Example ===
 +
AuthPDS was developed at NYU as an example of generating a plugin and populating the stub methods provided.
 +
 
 +
At NYU we're currently using the Auth module in our holdings table to offer request functionality based on "patron status".  We display a request button, if the patron has the appropriate status to be able to request/page items and use a custom controller to provide this functionality seamlessly.  Screenshots of this functionality can be seen below.
 +
 
 +
==== lib/auth/local/auth_pds.rb ====
 +
The AuthPDS module gets mixed in with the Session module to log in via PDS (customized for NYU).  It implements the following callback functions:
 +
# '''login_url''' - provides PDS login URL to redirect to
 +
# '''after_login''' - checks authorization, stores some cookies to improve performance, saves some user data when appropriate
 +
# '''logout_url''' - provides PDS logout URL
 +
# '''after_logout''' - destroys some cookies that were stored to improve performance
 +
# '''on_every_request''' - checks if the user has logged in (e.g. from another PDS SSO system)
 +
 
 +
==== config/umlaut_config/environment.rb ====
 +
The auth configuration settings are added to the local environment.rb to establish the appropriate class to mix in and to pass various options to the module.
 +
<pre>
 +
  config.app_config.login = {
 +
    # File name
 +
    :id => "auth_pds",
 +
    # Class name
 +
    :module => :AuthPDS,
 +
    :options => {
 +
      # Make expiration date configurable
 +
      :expiration_date => lambda {return 1.week.ago},
 +
      # OpenSSO URL, specific to NYU's implementation of PDS.
 +
      # Could easily be removed to make the local PDS module more generic.
 +
      :opensso_path => "https://login.nyu.edu:443/sso",
 +
      # PDS URL
 +
      :pds_url => "https://pds.library.institution.edu:443/",
 +
      # System name since the module is used in many different contexts and different apps
 +
      :system_name => :umlaut,
 +
      # Cookie name that is used to help with performance since the module is used in
 +
      # many different contexts and different apps
 +
      :cookie_name => :nyulibrary_opensso_umlaut,
 +
      :additional_user_attributes => lambda do |user_session|
 +
        h = {}
 +
        # NYU is using this module for several of our ruby apps
 +
        # and this mechanism allows us to include different user attributes per system.
 +
        # It's included here to give an idea of the flexibility of the module.
 +
        return h
 +
      end
 +
    }
 +
  }
 +
</pre>
 +
==== Screenshots of Request Functionality ====
 +
===== Not logged in, no request =====
 +
No request button because generally patrons can't request available items.
  
=== UmlautAuth Plugin ===
+
[[Image:Umlaut_no_request.png]]
The following files makeup the UmlautAuth module to extend the functionality of Authlogic for our purposes.  They could probably be moved into the UserSession module, but may be useful as a template for further localization.
+
==== vendor/plugins/umlaut_auth/lib/acts_as_authentic.rb ====
+
Extends the authlogic user model to ignore passwords, reset_persistence_token when the username changes, manage stale data (via expiration date), and handle user attributes hash.
+
==== vendor/plugins/umlaut_auth/lib/session.rb ====
+
Establishes callback functions before_login, after_login, before_logout, after_logout, on_every_request as well as public methods login_url, logout_url for setting external login and logouts.  The after_login callback is a bit of a hack since it only runs when the controller action is "validate."  It also has private methods validate_url (for sending to external logins) and session_user (for setting the session_user attributes).
+
==== vendor/plugins/umlaut_auth/umlaut_auth.rb ====
+
Loads the relevant auth modules from configuration. (Only tested with one auth module.  Probably won't work yet for multiple auto modules.)
+
==== vendor/plugins/umlaut_auth/generators/umlaut_auth/umlaut_auth_generator.rb ====
+
Uses the umlaut_auth template to create stubs for UmlautAuth localization.
+
  
== Generating Local UmlautAuth Plugins ==
+
===== Logged in, request =====
The following steps will generate a stub module for populating for local Auth needs (assumes authlogic version 2.1.0 is installed and user table is up to date).
+
Now the request button appears because I have permission to request available items.
#  script/generate UmlautAuth YourModuleName
+
[[Image:Umlaut_request.png]]
#  put  your code in the generated stub methods in vendor/plugins/your_module_name/lib/your_module_name.rb
+
#  add the following to config/umlaut_config/environment.rb:
+
<pre>config.app_config.login_modules = [{:id => "your_module_name", :module => :YourModuleName, :default => true }] #default => true doesn't do anything yet</pre>
+
  
=== UmlautAuth Plugin Example ===
+
===== Pretty jQuery modal dialog =====
UmlautAuthOpenSSO was developed at NYU as an example of generating a plugin and populating the stub methods provided.
+
You get the modal dialog upon clicking the request button
* /vendor/plugins/umlaut_auth_open_sso
+
[[Image:Umlaut_request_modal.png]]

Latest revision as of 16:17, 19 June 2012


WARNING: This is Outdated Documentation!!!!

THIS IS OUTDATED DOCUMENTATION See new Umlaut documentation at http://github.com/team-umlaut/umlaut/wiki


Auth Module (Developer Notes)

The Auth module extends functionality available from the [Authlogic|http://github.com/binarylogic/authlogic] (version 2.1.0) gem and included in the lib directory based on the [Authlogic OpenID add-on|http://github.com/binarylogic/authlogic_openid].'

The idea is to allow services to be customized based on a logged in user's attributes. Some examples could be:

  • Store a user's mobile phone number or email address to default the txt/email values for those services.
  • Provide extended request or paging functionality that is only available to a subset of patrons.
  • Allow faculty members to place items on reserve from the Umlaut screen.

Currently the Auth module requires existing Umlaut users to install the authlogic gem and perform a rails migration to update the user model to work with authlogic and the auth module. After these two steps have been taken, the auth module should only take effect if a particular instance has defined a auth module in their local config.

Umlaut Files Added or Updated

Several core Umlaut files were added and updated in order to support the Auth module.

app/controller/application.rb

The ApplicationController filters passwords and provides two methods for accessing the current user session and the current user.

  1. current_user_session (aliased as has_logged_in_user) - returns nil if no user session has been established
  2. current_user (aliased as logged_in_user) - returns either nil or the current logged in user

The application calls current_user_session as a before filter on every request.

app/controllers/user_sessions_controller.rb

The UserSessionsController manages the routing of user session requests and provides three methods.

  1. new - renders the login screen or redirects to external login screen
  2. validate - validates the user upon login
  3. destroy - processes logout

app/controllers/users_controller.rb

The UsersController manages the routing of user related requests and provides two methods.

  1. edit (also called from show) - renders the user preferences screen
  2. update - processes updates to user preferences (not yet implemented)

app/models/user_sessions.rb

UserSessions extends Authlogic::Session::Base

app/models/user.rb

User serializes user_attributes and adds acts_as_authentic functionality to leverage the Authlogic gem. Also sets to_param to username rather than id for prettier urls.

app/views/user_sessions/new.html.rb

The default login screen, doesn't currently do anything.

app/views/users/edit.html.rb

The default user preferences screen. Users can update mobile phone numbers and the like (not yet implemented)

config/environment.rb

Added authlogic gem:

#require 'authlogic'
config.gem 'authlogic', :version => "= 2.1.0"

config/routes.rb

Added url routes:

  map.login "login", :controller => "user_sessions", :action => "new"
  map.logout "logout", :controller => "user_sessions", :action => "destroy"
  map.validate "validate", :controller => "user_sessions", :action => "validate"
  map.resources :user_sessions
  map.resources :users

db/schema.rb

Modified the user table to use with authlogic. Included column for mobile phone, user attributes and a refreshed_at date to track age of a particular record for better performance. By default, data expires after 1 week.

lib/service.rb

Make the user accessible from a particular user via the session_user method.

  # Returns the currently logged in user, if available, based on the user_credentials_id in the 
  # session from AuthLogic.  May want to make this more sophisticated and check user_credentials
  # against db.
  def session_user
    return User.find(session["user_credentials_id"]) unless session["user_credentials_id"].nil?
  end

Auth Module

The following files makeup the Auth module to extend the functionality of Authlogic for our purposes.

lib/auth/acts_as_authentic.rb

The ActsAsAuthentic module extends the authlogic user model to ignore passwords, reset_persistence_token when the username changes, manage stale data (via refreshed_at date), and handle user attributes hash.

lib/auth/session.rb

The Session module establishes the Auth module callback functions and can serve as a template for further localizations. Callback functions to be overridden locally as appropriate:

  1. before_login - called when a new user session is being established, before the actual login is called
  2. login_url - called if before_login isn't defined or returns false, convenience method for redirecting to an external login url
  3. after_login - called after login user has been validated, provides mechanism for authorization
  4. before_logout - called before current user session is destroyed
  5. after_logout - called after current user session is destroyed
  6. on_every_request - called on every request

The module also has two private methods for use in extended local classes.

  1. validate_url - generates the return url to send to external logins services
  2. session_user - facilitates saving user attributes to the user model

Configuring Local Auth Modules

Auth Module Example

AuthPDS was developed at NYU as an example of generating a plugin and populating the stub methods provided.

At NYU we're currently using the Auth module in our holdings table to offer request functionality based on "patron status". We display a request button, if the patron has the appropriate status to be able to request/page items and use a custom controller to provide this functionality seamlessly. Screenshots of this functionality can be seen below.

lib/auth/local/auth_pds.rb

The AuthPDS module gets mixed in with the Session module to log in via PDS (customized for NYU). It implements the following callback functions:

  1. login_url - provides PDS login URL to redirect to
  2. after_login - checks authorization, stores some cookies to improve performance, saves some user data when appropriate
  3. logout_url - provides PDS logout URL
  4. after_logout - destroys some cookies that were stored to improve performance
  5. on_every_request - checks if the user has logged in (e.g. from another PDS SSO system)

config/umlaut_config/environment.rb

The auth configuration settings are added to the local environment.rb to establish the appropriate class to mix in and to pass various options to the module.

  config.app_config.login = {
    # File name
    :id => "auth_pds",
    # Class name
    :module => :AuthPDS,
    :options => {
      # Make expiration date configurable
      :expiration_date => lambda {return 1.week.ago},
      # OpenSSO URL, specific to NYU's implementation of PDS.
      # Could easily be removed to make the local PDS module more generic.
      :opensso_path => "https://login.nyu.edu:443/sso",
      # PDS URL
      :pds_url => "https://pds.library.institution.edu:443/",
      # System name since the module is used in many different contexts and different apps
      :system_name => :umlaut,
      # Cookie name that is used to help with performance since the module is used in 
      # many different contexts and different apps
      :cookie_name => :nyulibrary_opensso_umlaut,
      :additional_user_attributes => lambda do |user_session|
        h = {}
        # NYU is using this module for several of our ruby apps 
        # and this mechanism allows us to include different user attributes per system.
        # It's included here to give an idea of the flexibility of the module.
        return h
      end
    }
  }

Screenshots of Request Functionality

Not logged in, no request

No request button because generally patrons can't request available items.

Umlaut no request.png

Logged in, request

Now the request button appears because I have permission to request available items. Umlaut request.png

Pretty jQuery modal dialog

You get the modal dialog upon clicking the request button Umlaut request modal.png