authpds 1.1.2 → 1.1.3
Sign up to get free protection for your applications and to get access to all the features.
- data/README.md +168 -0
- data/lib/authpds/acts_as_authentic.rb +1 -1
- data/lib/authpds/acts_as_authentic/core_attributes.rb +11 -8
- data/lib/authpds/acts_as_authentic/expiration.rb +4 -6
- data/lib/authpds/acts_as_authentic/institutions_attributes.rb +35 -11
- data/lib/authpds/controllers/authpds_controller.rb +21 -4
- data/lib/authpds/controllers/authpds_sessions_controller.rb +10 -5
- data/lib/authpds/exlibris/pds.rb +1 -1
- data/lib/authpds/helpers/current_user_helper.rb +17 -0
- data/lib/authpds/helpers/institution/current_institution_helper.rb +44 -0
- data/lib/authpds/helpers/institution/param_helper.rb +19 -0
- data/lib/authpds/helpers/institution/url_helper.rb +18 -0
- data/lib/authpds/session.rb +1 -1
- data/lib/authpds/session/authentication.rb +1 -1
- data/lib/authpds/session/authlogic_callbacks.rb +1 -1
- data/lib/authpds/session/authorization.rb +1 -1
- data/lib/authpds/session/callbacks.rb +1 -1
- data/lib/authpds/session/config.rb +1 -1
- data/lib/authpds/session/core_attributes.rb +1 -1
- data/lib/authpds/session/exception_handling.rb +1 -1
- data/lib/authpds/session/institution_attributes.rb +1 -1
- data/lib/authpds/session/pds_handle.rb +1 -1
- data/lib/authpds/session/pds_user.rb +1 -1
- data/lib/authpds/session/record.rb +1 -1
- data/lib/authpds/session/url_handling.rb +1 -1
- data/lib/authpds/version.rb +1 -1
- metadata +9 -8
- data/README.rdoc +0 -150
- data/lib/authpds/controllers/authpds_controller/core_attributes.rb +0 -24
- data/lib/authpds/controllers/authpds_controller/institution_attributes.rb +0 -63
- data/lib/authpds/controllers/authpds_controller/url_handling.rb +0 -12
data/README.md
ADDED
@@ -0,0 +1,168 @@
|
|
1
|
+
[![Gem Version](https://badge.fury.io/rb/authpds.png)](http://badge.fury.io/rb/authpds)
|
2
|
+
[![Build Status](https://api.travis-ci.org/scotdalton/authpds.png?branch=master)](https://travis-ci.org/scotdalton/authpds)
|
3
|
+
[![Dependency Status](https://gemnasium.com/scotdalton/authpds.png)](http://gemnasium.com/scotdalton/authpds)
|
4
|
+
[![Code Climate](https://codeclimate.com/github/scotdalton/authpds.png)](http://codeclimate.com/github/scotdalton/authpds)
|
5
|
+
[![Coverage Status](https://coveralls.io/repos/scotdalton/authpds/badge.png?branch=master)](https://coveralls.io/r/scotdalton/authpds)
|
6
|
+
|
7
|
+
# Authpds
|
8
|
+
Libraries for authenticating via Ex Libris' Patron Directory Services (PDS) and provides
|
9
|
+
hooks for making authorization decisions based on the user information provided by PDS.
|
10
|
+
It leverages the [authlogic](https://github.com/binarylogic/authlogic) gem and depends
|
11
|
+
on a User-like model.
|
12
|
+
|
13
|
+
## Basics
|
14
|
+
### Generate User-like model
|
15
|
+
$ rails generate model User username:string email:string firstname:string \
|
16
|
+
lastname:string mobile_phone:string crypted_password:string password_salt:string \
|
17
|
+
session_id:string persistence_token:string login_count:integer last_request_at:string \
|
18
|
+
current_login_at:string last_login_at:string last_login_ip:string current_login_ip:string \
|
19
|
+
user_attributes:text refreshed_at:datetime
|
20
|
+
|
21
|
+
### Configure User-like model
|
22
|
+
class User < ActiveRecord::Base
|
23
|
+
serialize :user_attributes
|
24
|
+
|
25
|
+
acts_as_authentic do |c|
|
26
|
+
c.validations_scope = :username
|
27
|
+
c.validate_password_field = false
|
28
|
+
c.require_password_confirmation = false
|
29
|
+
c.disable_perishable_token_maintenance = true
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
### Generate UserSession model
|
34
|
+
$ rails generate authlogic:session user_session
|
35
|
+
|
36
|
+
### Configure UserSession with Authpds options
|
37
|
+
class UserSession < Authlogic::Session::Base
|
38
|
+
pds_url "https://login.library.institution.edu"
|
39
|
+
redirect_logout_url "http://library.institution.edu"
|
40
|
+
calling_system "my_system"
|
41
|
+
|
42
|
+
def expiration_date
|
43
|
+
1.second.ago
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
### Create UserSessions controller
|
48
|
+
$ rails generate controller UserSessions --no-assets --no-helper
|
49
|
+
|
50
|
+
### Configure institutions
|
51
|
+
|
52
|
+
#### Create institutions.yml file
|
53
|
+
Calling the institution "default" will make it the default:
|
54
|
+
|
55
|
+
default:
|
56
|
+
login:
|
57
|
+
code: INST01
|
58
|
+
display_name: My Institution
|
59
|
+
|
60
|
+
An alternative syntax:
|
61
|
+
|
62
|
+
INST01:
|
63
|
+
login:
|
64
|
+
code: INST01
|
65
|
+
default: true
|
66
|
+
display_name: My Institution
|
67
|
+
|
68
|
+
You can create multiple institution listings as follows:
|
69
|
+
|
70
|
+
INST01:
|
71
|
+
login:
|
72
|
+
code: INST01
|
73
|
+
default: true
|
74
|
+
display_name: My Institution
|
75
|
+
INST02:
|
76
|
+
login:
|
77
|
+
code: INST01
|
78
|
+
display_name: Your Institution
|
79
|
+
|
80
|
+
The two separate institutions above share a code in this example.
|
81
|
+
The code attribute determines the institute parameter in the PDS url.
|
82
|
+
|
83
|
+
#### Institution fields
|
84
|
+
| Field | Description |
|
85
|
+
| ----- | ----------- |
|
86
|
+
| `name` | Institution name |
|
87
|
+
| `display_name` | Name to display to users. |
|
88
|
+
| `default` | Boolean indicating whether this is a default Institution. Alternatively, an Institution can be named 'default'.|
|
89
|
+
| `parent_institution` | A parent Institution from which this child will inherit fields. |
|
90
|
+
| `ip_addresses` | IP addresses associated with the Institution. |
|
91
|
+
| `login` | Login configurations associated with the Institution. |
|
92
|
+
| `layouts` | Layout configurations associated with the Institution. |
|
93
|
+
| `views` | View configurations associated with the Institution. |
|
94
|
+
| `controllers` | Controller configurations associated with the Institution. |
|
95
|
+
| `models` | Model configurations associated with the Institution. |
|
96
|
+
|
97
|
+
|
98
|
+
#### Create institution initializer
|
99
|
+
|
100
|
+
Most likely it will just work if you put the config file in
|
101
|
+
|
102
|
+
"#{Rails.root}/config/institutions.yml"
|
103
|
+
|
104
|
+
If you have your institutions config file in another location make sure to
|
105
|
+
change the line below accordingly.
|
106
|
+
|
107
|
+
Institutions.loadpaths << File.join("other", "path")
|
108
|
+
Institutions.filenames << "other_file.yml"
|
109
|
+
|
110
|
+
### Mixin authpds methods into UserSessionsController
|
111
|
+
class UserSessionsController < ApplicationController
|
112
|
+
require 'authpds'
|
113
|
+
include Authpds::Controllers::AuthpdsSessionsController
|
114
|
+
end
|
115
|
+
|
116
|
+
### Mixin authpds methods into ApplicationController
|
117
|
+
class ApplicationController < ActionController::Base
|
118
|
+
protect_from_forgery
|
119
|
+
require 'authpds'
|
120
|
+
include Authpds::Controllers::AuthpdsController
|
121
|
+
end
|
122
|
+
|
123
|
+
### Mixin institution url helpers into ApplicationHelper
|
124
|
+
module ApplicationHelper
|
125
|
+
include Authpds::Helpers::Institution::UrlHelper
|
126
|
+
end
|
127
|
+
|
128
|
+
## Overview
|
129
|
+
The Authpds gem mixes in callbacks to Authlogic for persisting sessions based on a valid PDS handle.
|
130
|
+
The module extends Authlogic and should be compatible with Authlogic configuation.
|
131
|
+
It also provides hooks for custom functionality.
|
132
|
+
The documentation below describes the hooks available for overriding, PDS config methods
|
133
|
+
and further details about the module.
|
134
|
+
|
135
|
+
## Config Accessors Available
|
136
|
+
| Accessor | Description |
|
137
|
+
| -------- | ----------- |
|
138
|
+
| `#pds_url` | Base pds url |
|
139
|
+
| `#calling_system` | Name of the system (authpds) |
|
140
|
+
| `#anonymous` | Does the system allow anonymous access? (true) |
|
141
|
+
| `#pds_attributes` | Mapping of PDS attributes to record attributes |
|
142
|
+
| `#redirect_logout_url` | Custom redirect logout url |
|
143
|
+
| `#login_inaccessible_url` | Custom url to redirect to in case of PDS system outage |
|
144
|
+
| `#pds_record_identifier` | PDS user method to call to identify record |
|
145
|
+
| `#institution_param_key` | Querystring parameter key for the institution value in this system |
|
146
|
+
| `#validate_url_name` | URL name for validation action in routes (validate_url) |
|
147
|
+
|
148
|
+
## Hooks Available for Overriding
|
149
|
+
| Hook | Description |
|
150
|
+
| ---- | ----------- |
|
151
|
+
| `#pds_record_identifier` | Allows for more complex logic in determining what should be used as the record identifier. Defaults to what was set in the `pds_record_identifier` config. Returns a Symbol. |
|
152
|
+
| `#attempt_sso?` | If there is no PDS handle, can we attempt to establish a PDS session based on some other information? Returns a Boolean. |
|
153
|
+
| `#additional_authorization` | Allows for additions to the authorization decision. Returns a Boolean. |
|
154
|
+
| `#additional_attributes` | Allows for additional attributes to be stored in the record. Returns a Hash. |
|
155
|
+
| `#expiration_date` | Indicates when the record information should be refreshed. Defaults to one week ago. Returns a Date or Time. |
|
156
|
+
|
157
|
+
## Further Implementation Details
|
158
|
+
### Persisting a Session in AuthLogic
|
159
|
+
When persisting a Session, Authlogic attempts to create the Session based on information available
|
160
|
+
without having to perform an actual login by calling the `#persisting?` method.
|
161
|
+
Authologic provides several callbacks from the `#persisting?`
|
162
|
+
method, e.g. `#before_persisting`, `#persist`, `#after_persisting`.
|
163
|
+
We're using the `#persist` callback and setting it to `#persist_session`.
|
164
|
+
|
165
|
+
### Access to the controller in Session
|
166
|
+
The class that Session extends, Authologic::Session::Base, has an explicit handle to the current
|
167
|
+
controller via the instance method `#controller`. This gives our custom instance methods access to
|
168
|
+
cookies, session information, loggers, etc. and also allows them to perform redirects and renders.
|
@@ -2,9 +2,7 @@ module Authpds
|
|
2
2
|
module ActsAsAuthentic
|
3
3
|
module CoreAttributes
|
4
4
|
def self.included(klass)
|
5
|
-
klass.class_eval
|
6
|
-
serialize :user_attributes
|
7
|
-
end
|
5
|
+
klass.class_eval { serialize :user_attributes }
|
8
6
|
end
|
9
7
|
|
10
8
|
# Setting the username field also resets the persistence_token if the value changes.
|
@@ -13,12 +11,17 @@ module Authpds
|
|
13
11
|
reset_persistence_token if username_changed?
|
14
12
|
end
|
15
13
|
|
16
|
-
# "Smart" updating of user_attributes.
|
14
|
+
# "Smart" updating of user_attributes.
|
15
|
+
# Maintains user_attributes that are not explicity overwritten.
|
17
16
|
def user_attributes=(new_attributes)
|
18
|
-
|
19
|
-
|
20
|
-
|
17
|
+
if new_attributes.kind_of?(Hash)
|
18
|
+
# Merge new/updated attributes with new attributes taking precedence
|
19
|
+
merged_attributes = (user_attributes || {}).merge(new_attributes)
|
20
|
+
write_attribute(:user_attributes, merged_attributes)
|
21
|
+
else
|
22
|
+
write_attribute(:user_attributes, new_attributes)
|
23
|
+
end
|
21
24
|
end
|
22
25
|
end
|
23
26
|
end
|
24
|
-
end
|
27
|
+
end
|
@@ -2,18 +2,16 @@ module Authpds
|
|
2
2
|
module ActsAsAuthentic
|
3
3
|
module Expiration
|
4
4
|
def self.included(klass)
|
5
|
-
klass.class_eval
|
6
|
-
attr_accessor :expiration_date
|
7
|
-
end
|
5
|
+
klass.class_eval { attr_accessor :expiration_date }
|
8
6
|
end
|
9
7
|
|
10
8
|
# Returns a boolean based on whether the User has been refreshed recently.
|
11
|
-
# If User#refreshed_at is older than User#expiration_date,
|
12
|
-
# may need to be refreshed.
|
9
|
+
# If User#refreshed_at is older than User#expiration_date,
|
10
|
+
# the User is expired and the data may need to be refreshed.
|
13
11
|
def expired?
|
14
12
|
# If the record is older than the expiration date, it is expired.
|
15
13
|
(refreshed_at.nil?) ? true : refreshed_at < expiration_date
|
16
14
|
end
|
17
15
|
end
|
18
16
|
end
|
19
|
-
end
|
17
|
+
end
|
@@ -4,25 +4,49 @@ module Authpds
|
|
4
4
|
require 'institutions'
|
5
5
|
|
6
6
|
def primary_institution
|
7
|
-
|
7
|
+
unless user_attributes.blank?
|
8
|
+
all_institutions[user_attributes[:primary_institution]]
|
9
|
+
end
|
8
10
|
end
|
9
11
|
|
10
12
|
def primary_institution=(new_primary_institution)
|
11
|
-
|
12
|
-
|
13
|
+
if new_primary_institution.is_a?(Institutions::Institution)
|
14
|
+
new_primary_institution = new_primary_institution.code
|
15
|
+
end
|
16
|
+
if new_primary_institution.present?
|
17
|
+
self.user_attributes =
|
18
|
+
{ primary_institution: new_primary_institution.to_sym }
|
19
|
+
end
|
13
20
|
end
|
14
21
|
|
15
22
|
def institutions
|
16
|
-
|
23
|
+
if user_attributes.present?
|
24
|
+
user_attributes[:institutions].collect do |institution|
|
25
|
+
all_institutions[institution]
|
26
|
+
end
|
27
|
+
end
|
17
28
|
end
|
18
29
|
|
19
30
|
def institutions=(new_institutions)
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
31
|
+
unless new_institutions.is_a?(Array)
|
32
|
+
raise ArgumentError.new("Institutions input should be an array.")
|
33
|
+
end
|
34
|
+
# Collect the codes as symbols
|
35
|
+
new_institutions.collect! do |institution|
|
36
|
+
if institution.is_a?(Institutions::Institution)
|
37
|
+
institution.code
|
38
|
+
else
|
39
|
+
institution.to_sym
|
40
|
+
end
|
41
|
+
end
|
42
|
+
# Whitelist the institutions
|
43
|
+
new_institutions = new_institutions.select do |institution|
|
44
|
+
all_institutions[institution].present?
|
45
|
+
end
|
46
|
+
# Add them to the user attributes
|
47
|
+
if new_institutions.present?
|
48
|
+
self.user_attributes = { institutions: new_institutions }
|
49
|
+
end
|
26
50
|
end
|
27
51
|
|
28
52
|
def all_institutions
|
@@ -31,4 +55,4 @@ module Authpds
|
|
31
55
|
private :all_institutions
|
32
56
|
end
|
33
57
|
end
|
34
|
-
end
|
58
|
+
end
|
@@ -1,13 +1,30 @@
|
|
1
1
|
module Authpds
|
2
2
|
module Controllers
|
3
3
|
module AuthpdsController
|
4
|
+
include Authpds::Helpers::CurrentUserHelper
|
5
|
+
include Authpds::Helpers::Institution::CurrentInstitutionHelper
|
6
|
+
include Authpds::Helpers::Institution::UrlHelper
|
7
|
+
|
4
8
|
def self.included(klass)
|
9
|
+
# Include
|
5
10
|
klass.class_eval do
|
6
|
-
|
7
|
-
|
8
|
-
|
11
|
+
helper_method :current_user_session, :current_user
|
12
|
+
helper_method :current_primary_institution
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
# Controller method to generate the Appropriate redirect url
|
17
|
+
def user_session_redirect_url(url)
|
18
|
+
# Work with what we have
|
19
|
+
case
|
20
|
+
when url.present?
|
21
|
+
url
|
22
|
+
when request.referer.present?
|
23
|
+
request.referer
|
24
|
+
else
|
25
|
+
root_url
|
9
26
|
end
|
10
27
|
end
|
11
28
|
end
|
12
29
|
end
|
13
|
-
end
|
30
|
+
end
|
@@ -5,15 +5,20 @@ module Authpds
|
|
5
5
|
# GET /login
|
6
6
|
def new
|
7
7
|
@user_session = UserSession.new(params)
|
8
|
-
|
9
|
-
|
8
|
+
unless @user_session.login_url.blank?
|
9
|
+
redirect_to @user_session.login_url(params)
|
10
|
+
else
|
11
|
+
raise RuntimeError.new( "Error in #{self.class}.\nNo login url defined")
|
12
|
+
end
|
10
13
|
end
|
11
14
|
|
12
15
|
# GET /validate
|
13
16
|
def validate
|
14
17
|
# Only create a new one if it doesn't exist
|
15
18
|
@user_session ||= UserSession.create(params[:user_session])
|
16
|
-
|
19
|
+
# If we have a return url, redirect to that otherwise use the root url
|
20
|
+
redirect_to (params[:return_url].present?) ?
|
21
|
+
params[:return_url] : root_url
|
17
22
|
end
|
18
23
|
|
19
24
|
# DELETE /user_sessions/1
|
@@ -22,8 +27,8 @@ module Authpds
|
|
22
27
|
user_session = UserSession.find
|
23
28
|
logout_url = user_session.logout_url(params) unless user_session.nil?
|
24
29
|
user_session.destroy unless user_session.nil?
|
25
|
-
redirect_to user_session_redirect_url(logout_url)
|
30
|
+
redirect_to user_session_redirect_url(logout_url) unless performed?
|
26
31
|
end
|
27
32
|
end
|
28
33
|
end
|
29
|
-
end
|
34
|
+
end
|
data/lib/authpds/exlibris/pds.rb
CHANGED
@@ -0,0 +1,17 @@
|
|
1
|
+
module Authpds
|
2
|
+
module Helpers
|
3
|
+
module CurrentUserHelper
|
4
|
+
# Get the current UserSession if it exists
|
5
|
+
def current_user_session
|
6
|
+
@current_user_session ||= UserSession.find
|
7
|
+
end
|
8
|
+
|
9
|
+
# Get the current User if there is a UserSession
|
10
|
+
def current_user
|
11
|
+
if current_user_session.present?
|
12
|
+
@current_user ||= current_user_session.record
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
module Authpds
|
2
|
+
module Helpers
|
3
|
+
module Institution
|
4
|
+
module CurrentInstitutionHelper
|
5
|
+
# Include institutional param helper
|
6
|
+
include ParamHelper
|
7
|
+
|
8
|
+
# Determine current primary institution based on:
|
9
|
+
# 0. institutions are not being used (returns nil)
|
10
|
+
# 1. institution query string parameter in URL
|
11
|
+
# 2. institution associated with the client IP
|
12
|
+
# 3. primary institution for the current user
|
13
|
+
# 4. first default institution
|
14
|
+
def current_primary_institution
|
15
|
+
@current_primary_institution ||= case
|
16
|
+
when (institution_param.present? && institutions[institution_param])
|
17
|
+
institutions[institution_param]
|
18
|
+
when primary_institution_from_ip.present?
|
19
|
+
primary_institution_from_ip
|
20
|
+
when (@current_user && current_user.primary_institution)
|
21
|
+
current_user.primary_institution
|
22
|
+
else
|
23
|
+
Institutions.defaults.first
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
# Grab the first institution that matches the client IP
|
28
|
+
def primary_institution_from_ip
|
29
|
+
unless request.nil?
|
30
|
+
@primary_institution_from_ip ||=
|
31
|
+
Institutions.with_ip(request.remote_ip).first
|
32
|
+
end
|
33
|
+
end
|
34
|
+
private :primary_institution_from_ip
|
35
|
+
|
36
|
+
# All institutions
|
37
|
+
def institutions
|
38
|
+
@institutions ||= Institutions.institutions
|
39
|
+
end
|
40
|
+
private :institutions
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module Authpds
|
2
|
+
module Helpers
|
3
|
+
module Institution
|
4
|
+
module ParamHelper
|
5
|
+
# The institution param key as configured in UserSession
|
6
|
+
def institution_param_key
|
7
|
+
@institution_param_key ||= UserSession.institution_param_key
|
8
|
+
end
|
9
|
+
|
10
|
+
# The institution param as a Symbol
|
11
|
+
def institution_param
|
12
|
+
if params["#{institution_param_key}"].present?
|
13
|
+
params["#{institution_param_key}"].to_sym
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
module Authpds
|
2
|
+
module Helpers
|
3
|
+
module Institution
|
4
|
+
module UrlHelper
|
5
|
+
# Include institutional param helper
|
6
|
+
include ParamHelper
|
7
|
+
|
8
|
+
# Override Rails #url_for to add institution
|
9
|
+
def url_for(options={})
|
10
|
+
if institution_param.present? and options.is_a? Hash
|
11
|
+
options[institution_param_key] ||= institution_param
|
12
|
+
end
|
13
|
+
super options
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
data/lib/authpds/session.rb
CHANGED
data/lib/authpds/version.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: authpds
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.1.
|
4
|
+
version: 1.1.3
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2013-12-
|
12
|
+
date: 2013-12-17 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: require_all
|
@@ -167,12 +167,13 @@ files:
|
|
167
167
|
- lib/authpds/acts_as_authentic/expiration.rb
|
168
168
|
- lib/authpds/acts_as_authentic/institutions_attributes.rb
|
169
169
|
- lib/authpds/acts_as_authentic.rb
|
170
|
-
- lib/authpds/controllers/authpds_controller/core_attributes.rb
|
171
|
-
- lib/authpds/controllers/authpds_controller/institution_attributes.rb
|
172
|
-
- lib/authpds/controllers/authpds_controller/url_handling.rb
|
173
170
|
- lib/authpds/controllers/authpds_controller.rb
|
174
171
|
- lib/authpds/controllers/authpds_sessions_controller.rb
|
175
172
|
- lib/authpds/exlibris/pds.rb
|
173
|
+
- lib/authpds/helpers/current_user_helper.rb
|
174
|
+
- lib/authpds/helpers/institution/current_institution_helper.rb
|
175
|
+
- lib/authpds/helpers/institution/param_helper.rb
|
176
|
+
- lib/authpds/helpers/institution/url_helper.rb
|
176
177
|
- lib/authpds/session/authentication.rb
|
177
178
|
- lib/authpds/session/authlogic_callbacks.rb
|
178
179
|
- lib/authpds/session/authorization.rb
|
@@ -191,7 +192,7 @@ files:
|
|
191
192
|
- lib/tasks/pds-auth_tasks.rake
|
192
193
|
- MIT-LICENSE
|
193
194
|
- Rakefile
|
194
|
-
- README.
|
195
|
+
- README.md
|
195
196
|
- test/authpds_controller_test.rb
|
196
197
|
- test/authpds_test.rb
|
197
198
|
- test/authpds_user_sessions_controller_test.rb
|
@@ -227,7 +228,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
227
228
|
version: '0'
|
228
229
|
segments:
|
229
230
|
- 0
|
230
|
-
hash: -
|
231
|
+
hash: -458188680690181348
|
231
232
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
232
233
|
none: false
|
233
234
|
requirements:
|
@@ -236,7 +237,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
236
237
|
version: '0'
|
237
238
|
segments:
|
238
239
|
- 0
|
239
|
-
hash: -
|
240
|
+
hash: -458188680690181348
|
240
241
|
requirements: []
|
241
242
|
rubyforge_project:
|
242
243
|
rubygems_version: 1.8.25
|
data/README.rdoc
DELETED
@@ -1,150 +0,0 @@
|
|
1
|
-
{<img src="https://badge.fury.io/rb/authpds.png" alt="Gem Version" />}[http://badge.fury.io/rb/authpds]
|
2
|
-
{<img src="https://api.travis-ci.org/scotdalton/authpds.png?branch=master" alt="Build Status" />}[https://travis-ci.org/scotdalton/authpds]
|
3
|
-
{<img src="https://gemnasium.com/scotdalton/authpds.png" alt="Dependency Status" />}[https://gemnasium.com/scotdalton/authpds]
|
4
|
-
{<img src="https://codeclimate.com/github/scotdalton/authpds.png" />}[https://codeclimate.com/github/scotdalton/authpds]
|
5
|
-
{<img src="https://coveralls.io/repos/scotdalton/authpds/badge.png?branch=master" alt="Coverage Status" />}[https://coveralls.io/r/scotdalton/authpds]
|
6
|
-
|
7
|
-
= Authpds
|
8
|
-
Libraries for authenticating via Ex Libris' Patron Directory Services (PDS) and provides hooks for making authorization decisions based on the user information provided by PDS. It leverages the authlogic gem and depends on a User-like model.
|
9
|
-
|
10
|
-
== Basics
|
11
|
-
=== Generate User-like model
|
12
|
-
$ rails generate model User username:string email:string firstname:string \
|
13
|
-
lastname:string mobile_phone:string crypted_password:string password_salt:string \
|
14
|
-
session_id:string persistence_token:string login_count:integer last_request_at:string \
|
15
|
-
current_login_at:string last_login_at:string last_login_ip:string current_login_ip:string \
|
16
|
-
user_attributes:text refreshed_at:datetime
|
17
|
-
|
18
|
-
=== Configure User-like model
|
19
|
-
class User < ActiveRecord::Base
|
20
|
-
serialize :user_attributes
|
21
|
-
|
22
|
-
acts_as_authentic do |c|
|
23
|
-
c.validations_scope = :username
|
24
|
-
c.validate_password_field = false
|
25
|
-
c.require_password_confirmation = false
|
26
|
-
c.disable_perishable_token_maintenance = true
|
27
|
-
end
|
28
|
-
end
|
29
|
-
|
30
|
-
=== Generate UserSession model
|
31
|
-
$ rails generate authlogic:session user_session
|
32
|
-
|
33
|
-
=== Configure UserSession with Authpds options
|
34
|
-
class UserSession < Authlogic::Session::Base
|
35
|
-
pds_url "https://login.library.institution.edu"
|
36
|
-
redirect_logout_url "http://library.institution.edu"
|
37
|
-
calling_system "my_system"
|
38
|
-
|
39
|
-
def expiration_date
|
40
|
-
1.second.ago
|
41
|
-
end
|
42
|
-
end
|
43
|
-
|
44
|
-
=== Create UserSessions controller
|
45
|
-
$ rails generate controller UserSessions --no-assets --no-helper
|
46
|
-
|
47
|
-
=== Configure institutions
|
48
|
-
|
49
|
-
==== Create institutions.yml file
|
50
|
-
|
51
|
-
Calling the institution "default" will make it the default:
|
52
|
-
|
53
|
-
default:
|
54
|
-
login:
|
55
|
-
code: INST01
|
56
|
-
display_name: My Institution
|
57
|
-
|
58
|
-
An alternative syntax:
|
59
|
-
|
60
|
-
INST01:
|
61
|
-
login:
|
62
|
-
code: INST01
|
63
|
-
default: true
|
64
|
-
display_name: My Institution
|
65
|
-
|
66
|
-
You can create multiple institution listings as follows:
|
67
|
-
|
68
|
-
INST01:
|
69
|
-
login:
|
70
|
-
code: INST01
|
71
|
-
default: true
|
72
|
-
display_name: My Institution
|
73
|
-
INST02:
|
74
|
-
login:
|
75
|
-
code: INST01
|
76
|
-
display_name: Your Institution
|
77
|
-
|
78
|
-
The two separate institutions above share a code in this example. The code attribute determines the institute parameter in the PDS url.
|
79
|
-
|
80
|
-
==== Institution fields
|
81
|
-
:name:: Institution name
|
82
|
-
:display_name:: Name to display to users.
|
83
|
-
:default:: Boolean indicating whether this is a default Institution. Alternatively, an Institution can be named 'default'.
|
84
|
-
:parent_institution:: A parent Institution from which this child will inherit fields.
|
85
|
-
:ip_addresses:: IP addresses associated with the Institution.
|
86
|
-
:login:: Login configurations associated with the Institution.
|
87
|
-
:layouts:: Layout configurations associated with the Institution.
|
88
|
-
:views:: View configurations associated with the Institution.
|
89
|
-
:controllers:: Controller configurations associated with the Institution.
|
90
|
-
:models:: Model configurations associated with the Institution.
|
91
|
-
|
92
|
-
|
93
|
-
==== Create institution initializer
|
94
|
-
|
95
|
-
Most likely it will just work if you put the config file in
|
96
|
-
"#{Rails.root}/config/institutions.yml"
|
97
|
-
|
98
|
-
If you have your institutions config file in another location make sure to change the line below accordingly.
|
99
|
-
Institutions.loadpaths << File.join("other", "path")
|
100
|
-
Institutions.filenames << "other_file.yml"
|
101
|
-
|
102
|
-
=== Mixin authpds methods into UserSessionsController
|
103
|
-
class UserSessionsController < ApplicationController
|
104
|
-
require 'authpds'
|
105
|
-
include Authpds::Controllers::AuthpdsSessionsController
|
106
|
-
end
|
107
|
-
|
108
|
-
=== Mixin authpds methods into ApplicationController
|
109
|
-
class ApplicationController < ActionController::Base
|
110
|
-
protect_from_forgery
|
111
|
-
require 'authpds'
|
112
|
-
include Authpds::Controllers::AuthpdsController
|
113
|
-
end
|
114
|
-
|
115
|
-
== Overview
|
116
|
-
The Authpds gem mixes in callbacks to Authlogic for persisting
|
117
|
-
sessions based on a valid PDS handle.
|
118
|
-
The module extends Authlogic and should be compatible with Authlogic configuation.
|
119
|
-
It also provides hooks for custom functionality.
|
120
|
-
The documentation below describes the hooks available for overriding, PDS config methods
|
121
|
-
and further details about the module.
|
122
|
-
|
123
|
-
== Config Options Available
|
124
|
-
:pds_url:: Base pds url
|
125
|
-
:calling_system:: Name of the system (authpds)
|
126
|
-
:anonymous:: Does the system allow anonymous access? (true)
|
127
|
-
:pds_attributes:: Mapping of PDS attributes to record attributes
|
128
|
-
:redirect_logout_url:: Custom redirect logout url
|
129
|
-
:login_inaccessible_url:: Custom url to redirect to in case of PDS system outage
|
130
|
-
:pds_record_identifier:: PDS user method to call to identify record
|
131
|
-
:institution_param_key:: Querystring parameter key for the institution value in this system
|
132
|
-
:validate_url_name:: URL name for validation action in routes (validate_url)
|
133
|
-
|
134
|
-
== Hooks Available for Overriding
|
135
|
-
:pds_record_identifier:: Allows for more complex logic in determining what should be used as the record identifier. Defaults to what was set in the pds_record_identifier config. Returns a Symbol.
|
136
|
-
:attempt_sso?:: If there is no PDS handle, can we attempt to establish a PDS session based on some other information? Returns a Boolean.
|
137
|
-
:additional_authorization:: Allows for additions to the authorization decision. Returns a Boolean.
|
138
|
-
:additional_attributes:: Allows for additional attributes to be stored in the record. Returns a Hash.
|
139
|
-
:expiration_date:: Indicates when the record information should be refreshed. Defaults to one week ago. Returns a Date or Time.
|
140
|
-
|
141
|
-
== Further Implementation Details
|
142
|
-
=== Persisting a Session in AuthLogic
|
143
|
-
When persisting a Session, Authlogic attempts to create the Session based on information available
|
144
|
-
without having to perform an actual login by calling the :persisting? method. Authologic provides several callbacks from the :persisting?
|
145
|
-
method, e.g. :before_persisting, :persist, :after_persisting. We're using the :persist callback and setting it to :persist_session.
|
146
|
-
|
147
|
-
=== Access to the controller in Session
|
148
|
-
The class that Session extends, Authologic::Session::Base, has an explicit handle to the current controller via the instance method
|
149
|
-
:controller. This gives our custom instance methods access to cookies, session information, loggers, etc. and also allows them to
|
150
|
-
perform redirects and renders.
|
@@ -1,24 +0,0 @@
|
|
1
|
-
module Authpds
|
2
|
-
module Controllers
|
3
|
-
module AuthpdsController
|
4
|
-
module CoreAttributes
|
5
|
-
# Set helper methods when this module is included.
|
6
|
-
def self.included(klass)
|
7
|
-
klass.class_eval do
|
8
|
-
helper_method :current_user_session, :current_user
|
9
|
-
end
|
10
|
-
end
|
11
|
-
|
12
|
-
# Get the current UserSession if it exists
|
13
|
-
def current_user_session
|
14
|
-
@current_user_session ||= UserSession.find
|
15
|
-
end
|
16
|
-
|
17
|
-
# Get the current User if there is a UserSession
|
18
|
-
def current_user
|
19
|
-
@current_user ||= current_user_session.record unless current_user_session.nil?
|
20
|
-
end
|
21
|
-
end
|
22
|
-
end
|
23
|
-
end
|
24
|
-
end
|
@@ -1,63 +0,0 @@
|
|
1
|
-
module Authpds
|
2
|
-
module Controllers
|
3
|
-
module AuthpdsController
|
4
|
-
module InstitutionAttributes
|
5
|
-
require 'institutions'
|
6
|
-
|
7
|
-
# Set helper methods when this module is included.
|
8
|
-
def self.included(klass)
|
9
|
-
klass.class_eval do
|
10
|
-
helper_method :current_primary_institution
|
11
|
-
helper_method :url_for
|
12
|
-
end
|
13
|
-
end
|
14
|
-
|
15
|
-
# Determine current primary institution based on:
|
16
|
-
# 0. institutions are not being used (returns nil)
|
17
|
-
# 1. institution query string parameter in URL
|
18
|
-
# 2. institution associated with the client IP
|
19
|
-
# 3. primary institution for the current user
|
20
|
-
# 4. first default institution
|
21
|
-
def current_primary_institution
|
22
|
-
@current_primary_institution ||=
|
23
|
-
(institution_param.nil? or all_institutions[institution_param].nil?) ?
|
24
|
-
((primary_institution_from_ip.nil?) ?
|
25
|
-
((@current_user.nil? or current_user.primary_institution.nil?) ?
|
26
|
-
Institutions.defaults.first :
|
27
|
-
current_user.primary_institution) :
|
28
|
-
primary_institution_from_ip) :
|
29
|
-
all_institutions[institution_param]
|
30
|
-
end
|
31
|
-
|
32
|
-
# Override Rails ActionController#url_for to add institution.
|
33
|
-
def url_for(options={})
|
34
|
-
if institution_param.present? and options.is_a? Hash
|
35
|
-
options[institution_param_key] ||= institution_param
|
36
|
-
end
|
37
|
-
super options
|
38
|
-
end
|
39
|
-
|
40
|
-
# Grab the first institution that matches the client IP
|
41
|
-
def primary_institution_from_ip
|
42
|
-
Institutions.with_ip(request.remote_ip).first unless request.nil?
|
43
|
-
end
|
44
|
-
private :primary_institution_from_ip
|
45
|
-
|
46
|
-
def institution_param_key
|
47
|
-
@institution_param_key ||= UserSession.institution_param_key
|
48
|
-
end
|
49
|
-
private :institution_param_key
|
50
|
-
|
51
|
-
def institution_param
|
52
|
-
params["#{institution_param_key}"].to_sym unless params["#{institution_param_key}"].nil?
|
53
|
-
end
|
54
|
-
private :institution_param
|
55
|
-
|
56
|
-
def all_institutions
|
57
|
-
@all_institutions ||= Institutions.institutions
|
58
|
-
end
|
59
|
-
private :all_institutions
|
60
|
-
end
|
61
|
-
end
|
62
|
-
end
|
63
|
-
end
|
@@ -1,12 +0,0 @@
|
|
1
|
-
module Authpds
|
2
|
-
module Controllers
|
3
|
-
module AuthpdsController
|
4
|
-
module UrlHandling
|
5
|
-
# Controller method to generate the Appropriate redirect url
|
6
|
-
def user_session_redirect_url(url)
|
7
|
-
(url.nil? or url.empty?) ? (request.referer.nil?) ? root_url : request.referer : url
|
8
|
-
end
|
9
|
-
end
|
10
|
-
end
|
11
|
-
end
|
12
|
-
end
|