Difference between revisions of "Auth Module"

From Code4Lib
Jump to: navigation, search
(UmlautAuth Plugin)
 
(27 intermediate revisions by one other user not shown)
Line 1: Line 1:
== UmlautAuth Module (Developer Notes) ==
+
[[Category:Umlaut]]
The UmlautAuth module extends functionality available from the [Authlogic|http://github.com/binarylogic/authlogic] (version 2.1.0) gem and configured as a plugin 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 UmlautAuth 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 }] #(the 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.

Error creating thumbnail: Unable to save thumbnail to destination
Logged in, request

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

Error creating thumbnail: Unable to save thumbnail to destination
Pretty jQuery modal dialog

You get the modal dialog upon clicking the request button

Error creating thumbnail: Unable to save thumbnail to destination