rack-casual 0.0.1 → 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/README.md +31 -30
- data/examples/sinatra_app.rb +67 -0
- data/lib/rack/casual/authentication.rb +50 -27
- data/lib/rack/casual/client.rb +130 -0
- data/lib/rack/casual/controller.rb +1 -0
- data/lib/rack/casual/user_factory.rb +39 -34
- data/lib/rack/casual.rb +92 -60
- data/lib/rack-casual.rb +0 -1
- metadata +37 -12
data/README.md
CHANGED
@@ -6,16 +6,25 @@ It kicks in whenever a 401 response is returned from the server.
|
|
6
6
|
|
7
7
|
The plugin has only been tested using ActiveRecord and Rails 3.
|
8
8
|
|
9
|
+
|
9
10
|
Installation
|
10
11
|
============
|
11
12
|
|
13
|
+
### Sinatra
|
14
|
+
|
15
|
+
$ gem install 'rack-casual'
|
16
|
+
|
17
|
+
See examples/sinatra_app.rb for a sample app.
|
18
|
+
|
19
|
+
### Rails 3
|
20
|
+
|
12
21
|
Add this to your Gemfile:
|
13
22
|
|
14
|
-
|
23
|
+
$ gem 'rack-casual'
|
15
24
|
|
16
25
|
Run bundle install, and add a configuration file:
|
17
26
|
|
18
|
-
|
27
|
+
$ rails generate rack_casual
|
19
28
|
|
20
29
|
This creates a config/initializers/rack-casual.rb file.
|
21
30
|
Make sure base_url points to your CAS server.
|
@@ -27,9 +36,9 @@ For Rails3, you can add this to your config/application.rb
|
|
27
36
|
|
28
37
|
Finally, to authenticate your users, add a before_filter to your controller:
|
29
38
|
|
30
|
-
|
31
|
-
|
32
|
-
|
39
|
+
class ApplicationController < ActionController::Base
|
40
|
+
before_filter :authenticate!
|
41
|
+
end
|
33
42
|
|
34
43
|
|
35
44
|
Usage
|
@@ -62,25 +71,19 @@ If there are no users with that token, the client just receives the 401 error.
|
|
62
71
|
It does not fallback to CAS or create a user automatically (doh).
|
63
72
|
|
64
73
|
|
65
|
-
|
74
|
+
Authorization
|
66
75
|
=============
|
67
76
|
|
68
|
-
|
69
|
-
|
70
|
-
config.authentication_scope = :active
|
77
|
+
Rack::Casual calls active? on your user model if that method exists to determine whether the user can log in or not.
|
78
|
+
So just add this to control whether authenticated users can log in or not.
|
71
79
|
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
80
|
+
# app/models/user.rb
|
81
|
+
class User < ActiveRecord::Base
|
82
|
+
def active?
|
83
|
+
# i'm sure you can figure something out...
|
84
|
+
end
|
76
85
|
end
|
77
|
-
end
|
78
86
|
|
79
|
-
Then Rack::Casual will only search among users where active is true.
|
80
|
-
A side effect of this is that Rack::Casual will try to create a user that already exists.
|
81
|
-
However, this should not be a problem as long as your User model validates the uniqueness of the username.
|
82
|
-
|
83
|
-
The default scope to use is
|
84
87
|
|
85
88
|
Extra attributes
|
86
89
|
================
|
@@ -89,17 +92,17 @@ When creating users automatically, Rack::Casual can also add extra attributes if
|
|
89
92
|
For this to work your User model must have a cas_extra_attributes= instance method.
|
90
93
|
Here's an example:
|
91
94
|
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
95
|
+
class User < ActiveRecord::Base
|
96
|
+
def cas_extra_attributes=(extra_attributes)
|
97
|
+
extra_attributes.each do |name, value|
|
98
|
+
case name.to_sym
|
99
|
+
when :name then self.name = value
|
100
|
+
when :email then self.email = value
|
101
|
+
when :phone then self.phone = value
|
102
|
+
end
|
99
103
|
end
|
100
104
|
end
|
101
105
|
end
|
102
|
-
end
|
103
106
|
|
104
107
|
|
105
108
|
Tracking
|
@@ -114,8 +117,6 @@ These variables will be updated if they are present in your User model:
|
|
114
117
|
TODO
|
115
118
|
====
|
116
119
|
|
117
|
-
|
118
|
-
2. Replace ruby-cas with something "lighter", like casual, but casual doesn't seem to support extra attributes...
|
119
|
-
Note to self: http://rubycas-client.rubyforge.org/classes/CASClient/ValidationResponse.src/M000044.html
|
120
|
+
More tests dammit.
|
120
121
|
|
121
122
|
Copyright (c) 2010 Gudleik Rasch <gudleik@gmail.com>, released under the MIT license
|
@@ -0,0 +1,67 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
require 'rubygems'
|
3
|
+
require 'sinatra'
|
4
|
+
require 'rack-casual'
|
5
|
+
|
6
|
+
##
|
7
|
+
## This is an example Sinatra app using Rack::Casual for authentication
|
8
|
+
##
|
9
|
+
## Start with ruby sinatra_app.rb
|
10
|
+
## If you go to http://localhost:4567 you should be redirected to the CAS server.
|
11
|
+
## Or if you enter http://localhost:4567?auth_token=secret you're authenticated.
|
12
|
+
##
|
13
|
+
|
14
|
+
use Rack::Lint
|
15
|
+
use Rack::Casual::Authentication
|
16
|
+
|
17
|
+
Rack::Casual.setup do |config|
|
18
|
+
config.cas_url = "http://localhost:8080"
|
19
|
+
config.auth_token = "auth_token"
|
20
|
+
config.session_key = "user"
|
21
|
+
config.create_user = false
|
22
|
+
end
|
23
|
+
|
24
|
+
# User class with a few activerecord-ish methods to make Rack::Casual work properly.
|
25
|
+
# Didn't want to roll in a full activerecord orchestra for this example purpose.
|
26
|
+
class User
|
27
|
+
attr_accessor :last_login_ip, :last_login_at, :login_count
|
28
|
+
|
29
|
+
# This is used by Rack::Casual to locate the user.
|
30
|
+
def self.where(conditions)
|
31
|
+
if conditions["auth_token"] == "secret" # find by auth_token
|
32
|
+
[ User.new("foobar") ]
|
33
|
+
elsif conditions["username"] == "foobar" # find by username
|
34
|
+
[ User.new("foobar") ]
|
35
|
+
else
|
36
|
+
[] # Must return an empty array to satisfy Rack::Casual (it uses .first)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
def id
|
41
|
+
42
|
42
|
+
end
|
43
|
+
|
44
|
+
def active?
|
45
|
+
false
|
46
|
+
end
|
47
|
+
|
48
|
+
def save
|
49
|
+
# Just print out some info to see that these
|
50
|
+
puts "Last login IP: #{@last_login_ip}"
|
51
|
+
end
|
52
|
+
|
53
|
+
def initialize(username)
|
54
|
+
@username = username
|
55
|
+
@login_count = 0
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
set :sessions, true
|
60
|
+
|
61
|
+
before do
|
62
|
+
halt 401, 'Forbidden dammit' unless session["user"]
|
63
|
+
end
|
64
|
+
|
65
|
+
get '/' do
|
66
|
+
%{Hello, your user-id is #{session["user"]}}
|
67
|
+
end
|
@@ -1,7 +1,21 @@
|
|
1
|
+
# encoding: utf-8
|
1
2
|
module Rack
|
2
3
|
|
3
4
|
module Casual
|
4
|
-
|
5
|
+
|
6
|
+
# How it works
|
7
|
+
#
|
8
|
+
# 1. Request enters app
|
9
|
+
# 2. Is params[:ticket] present with a valid CAS ticket
|
10
|
+
# 3. `- Validate ticket
|
11
|
+
# If valid find or create user
|
12
|
+
# User not ok? -- show bad info, don't redirect back to cas
|
13
|
+
# User ok? -- set user.id in session and continue
|
14
|
+
# 5. Is response a 401?
|
15
|
+
# 6. `- Authenticate using auth_token if auth_token is present
|
16
|
+
# `- Or redirect to CAS
|
17
|
+
# 7. Done
|
18
|
+
#
|
5
19
|
class Authentication
|
6
20
|
|
7
21
|
def initialize(app)
|
@@ -10,67 +24,76 @@ module Rack
|
|
10
24
|
|
11
25
|
def call(env)
|
12
26
|
@request = Rack::Request.new(env)
|
13
|
-
@response = @app.call(env)
|
14
27
|
@env = env
|
15
28
|
|
16
|
-
process_request_from_cas
|
17
|
-
|
29
|
+
unless process_request_from_cas
|
30
|
+
@app.call(env)
|
31
|
+
else
|
32
|
+
handle_401(@app.call(env))
|
33
|
+
end
|
18
34
|
end
|
19
35
|
|
20
36
|
private
|
21
37
|
|
38
|
+
# This handles requests from CAS
|
39
|
+
# CAS requests must include a ticket in the params.
|
40
|
+
# Only returns true if a CAS ticket was processed but returned no users
|
22
41
|
def process_request_from_cas
|
23
42
|
if ticket = read_ticket
|
24
|
-
if user = UserFactory.authenticate_with_cas_ticket(ticket, @request)
|
25
|
-
|
26
|
-
@request.session[Rack::Casual.session_key_user] = user.id
|
43
|
+
if user = UserFactory.authenticate_with_cas_ticket(ticket, service_url, @request.ip)
|
44
|
+
set_session(user)
|
27
45
|
else
|
28
|
-
|
46
|
+
return false
|
29
47
|
end
|
30
48
|
end
|
49
|
+
|
50
|
+
true
|
31
51
|
end
|
32
52
|
|
33
|
-
|
34
|
-
|
53
|
+
# This handles 401 responses by either authenticating using a token if present in params,
|
54
|
+
# or redirects to CAS login
|
55
|
+
def handle_401(response)
|
56
|
+
return response unless response[0] == 401
|
35
57
|
|
36
|
-
if Rack::Casual.
|
37
|
-
authenticate_with_token
|
58
|
+
if Rack::Casual.auth_token && token = @request.params[Rack::Casual.auth_token]
|
59
|
+
authenticate_with_token(token)
|
38
60
|
else
|
39
61
|
redirect_to_cas
|
40
62
|
end
|
41
63
|
end
|
42
64
|
|
43
|
-
|
44
|
-
|
45
|
-
@request.
|
65
|
+
# Authenticate user by a token
|
66
|
+
def authenticate_with_token(token)
|
67
|
+
set_session UserFactory.authenticate_with_token(token, @request.ip)
|
46
68
|
@app.call(@env)
|
47
69
|
end
|
48
|
-
|
70
|
+
|
71
|
+
# Stores user.id in the session key configured in Rack::Casual.session_key
|
72
|
+
def set_session(user)
|
73
|
+
@request.session[Rack::Casual.session_key] = user.id if user
|
74
|
+
end
|
75
|
+
|
76
|
+
# Redirects to CAS
|
49
77
|
def redirect_to_cas
|
50
|
-
url = Rack::Casual.cas_client.add_service_to_login_url(service_url)
|
51
78
|
[ 302,
|
52
79
|
{
|
53
|
-
"Location" =>
|
80
|
+
"Location" => Client.login_url(service_url),
|
54
81
|
"Content-Type" => "text/plain"
|
55
82
|
},
|
56
83
|
"Redirecting to CAS for authentication"
|
57
84
|
]
|
58
85
|
end
|
59
|
-
|
86
|
+
|
87
|
+
# Return the service url for this application (minus the ticket parameter)
|
60
88
|
def service_url
|
61
89
|
@request.url.sub(/[\?&]#{Rack::Casual.ticket_param}=[^\?&]+/, '')
|
62
90
|
end
|
63
91
|
|
64
|
-
# Read ticket from params and
|
92
|
+
# Read ticket from params and return a string if a CAS ticket is present.
|
93
|
+
# Otherwise returns nil
|
65
94
|
def read_ticket
|
66
95
|
ticket = @request.params[Rack::Casual.ticket_param]
|
67
|
-
|
68
|
-
|
69
|
-
if ticket =~ /^PT-/
|
70
|
-
::CASClient::ProxyTicket.new(ticket, service_url, @request.params[:renew])
|
71
|
-
else
|
72
|
-
::CASClient::ServiceTicket.new(ticket, service_url, @request.params[:renew])
|
73
|
-
end
|
96
|
+
ticket =~ /^(S|P)T-/ ? ticket : nil
|
74
97
|
end
|
75
98
|
|
76
99
|
end
|
@@ -0,0 +1,130 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require 'nokogiri'
|
4
|
+
require 'open-uri'
|
5
|
+
require 'net/http'
|
6
|
+
require 'net/https'
|
7
|
+
|
8
|
+
# This is a über simple CAS client responsible for validating a ticket.
|
9
|
+
class Rack::Casual::Client
|
10
|
+
attr_accessor :username, :extra_attributes
|
11
|
+
|
12
|
+
# Returns login url as string
|
13
|
+
def self.login_url(service_url)
|
14
|
+
new(service_url).login_url.to_s
|
15
|
+
end
|
16
|
+
|
17
|
+
# Creates a new object
|
18
|
+
def initialize(service_url, ticket=nil)
|
19
|
+
raise(ArgumentError, "Base URL must be configured") if Rack::Casual.cas_url.nil?
|
20
|
+
|
21
|
+
@service_url = service_url
|
22
|
+
@ticket = ticket
|
23
|
+
@result = nil
|
24
|
+
end
|
25
|
+
|
26
|
+
# Return the URL to the CAS login page
|
27
|
+
def login_url
|
28
|
+
cas_url(:login)
|
29
|
+
end
|
30
|
+
|
31
|
+
# URL to the CAS ticket validation service
|
32
|
+
def validation_url
|
33
|
+
cas_url(:validate)
|
34
|
+
end
|
35
|
+
|
36
|
+
# Validate the ticket we got from CAS
|
37
|
+
#
|
38
|
+
# On ticket validation success:
|
39
|
+
# <cas:serviceResponse xmlns:cas='http://www.yale.edu/tp/cas'>
|
40
|
+
# <cas:authenticationSuccess>
|
41
|
+
# <cas:user>username</cas:user>
|
42
|
+
# <cas:proxyGrantingTicket>PGTIOU-84678-8a9d...
|
43
|
+
# </cas:proxyGrantingTicket>
|
44
|
+
# </cas:authenticationSuccess>
|
45
|
+
# </cas:serviceResponse>
|
46
|
+
#
|
47
|
+
# On ticket validation failure:
|
48
|
+
# <cas:serviceResponse xmlns:cas='http://www.yale.edu/tp/cas'>
|
49
|
+
# <cas:authenticationFailure code="INVALID_TICKET">
|
50
|
+
# Ticket ST-1856339-aA5Yuvrxzpv8Tau1cYQ7 not recognized
|
51
|
+
# </cas:authenticationFailure>
|
52
|
+
# </cas:serviceResponse>
|
53
|
+
#
|
54
|
+
#
|
55
|
+
def validate_ticket
|
56
|
+
url = validation_url
|
57
|
+
http = Net::HTTP.new(url.host, url.port)
|
58
|
+
http.use_ssl = (url.scheme == "https")
|
59
|
+
|
60
|
+
result = Nokogiri.parse(http.get(url.request_uri).body)
|
61
|
+
|
62
|
+
# set username and extra attributes
|
63
|
+
find_username(result)
|
64
|
+
find_attributes(result) if @username
|
65
|
+
|
66
|
+
!@username.nil?
|
67
|
+
end
|
68
|
+
|
69
|
+
def find_username(xml)
|
70
|
+
@username = xml.search("//cas:authenticationSuccess //cas:user").first.text rescue nil
|
71
|
+
end
|
72
|
+
|
73
|
+
def find_attributes(xml)
|
74
|
+
@extra_attributes = {}
|
75
|
+
xml.search("//cas:authenticationSuccess/*").each do |el|
|
76
|
+
# puts " * Attribute #{el.name} = #{el.content}"
|
77
|
+
@extra_attributes[el.name] = el.content
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
# For testing purposes only
|
82
|
+
#
|
83
|
+
# Fetch login ticket from the CAS login page
|
84
|
+
# def acquire_login_ticket(service_url=nil)
|
85
|
+
# Nokogiri.parse(open(login_url(service_url)).read).search('input[@name=lt]').first.attr('value') rescue nil
|
86
|
+
# end
|
87
|
+
#
|
88
|
+
# def authenticate(username, password, ticket, service_url=nil)
|
89
|
+
# ticket = acquire_login_ticket(service_url)
|
90
|
+
# url = login_url(service_url)
|
91
|
+
#
|
92
|
+
# query = url.query ? url.query : ""
|
93
|
+
# query += "&" + build_query(:username => username, :password => password, :lt => ticket, :service => service_url)
|
94
|
+
#
|
95
|
+
# req = Net::HTTP.new(url.host, url.port)
|
96
|
+
# res = req.post url.path, query
|
97
|
+
#
|
98
|
+
# res.is_a?(Net::HTTPSuccess)
|
99
|
+
# end
|
100
|
+
|
101
|
+
#
|
102
|
+
# Returns a CAS url
|
103
|
+
# if action is :login or :validate, then the appropriate login and service-validation actions are used.
|
104
|
+
# Otherwise the argument is used as the first action.
|
105
|
+
#
|
106
|
+
# Options is a hash that is appended to the url.
|
107
|
+
#
|
108
|
+
# Return value is a URI object.
|
109
|
+
#
|
110
|
+
# Examples:
|
111
|
+
#
|
112
|
+
# cas_url :login # => http://localhost/login
|
113
|
+
# cas_url :validate, :ticket => "T123" # => http://localhost/serviceValidate?ticket=T123
|
114
|
+
#
|
115
|
+
def cas_url(action=nil, options = nil)
|
116
|
+
url = Rack::Casual.cas_url.sub(/\/+$/, '')
|
117
|
+
|
118
|
+
url << case action
|
119
|
+
when :login then "/login"
|
120
|
+
when :validate then "/serviceValidate"
|
121
|
+
else
|
122
|
+
action.to_s
|
123
|
+
end
|
124
|
+
|
125
|
+
url += "?service=#{@service_url}"
|
126
|
+
url += "&ticket=#{@ticket}" if @ticket
|
127
|
+
URI.parse(url)
|
128
|
+
end
|
129
|
+
|
130
|
+
end
|
@@ -4,45 +4,60 @@ module Rack
|
|
4
4
|
|
5
5
|
class UserFactory
|
6
6
|
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
7
|
+
#
|
8
|
+
# Authenticate user by CAS.
|
9
|
+
#
|
10
|
+
# If ticket is valid it will search for user with the given username.
|
11
|
+
# If no user is found it will be automatically created if +Rack::Casual.create_user+ is set.
|
12
|
+
#
|
13
|
+
# Returns the user or nil if user not found
|
14
|
+
#
|
15
|
+
def self.authenticate_with_cas_ticket(ticket, service_url, ip)
|
16
|
+
user = nil
|
17
|
+
client = Client.new(service_url, ticket)
|
18
|
+
|
19
|
+
if client.validate_ticket
|
20
|
+
# find or create the user
|
21
|
+
user = find(client.username)
|
16
22
|
if user.nil? && Rack::Casual.create_user
|
17
|
-
user = make(
|
23
|
+
user = make(client.username)
|
18
24
|
end
|
19
25
|
|
20
|
-
return nil
|
26
|
+
return nil if user.nil? || user_not_active(user)
|
21
27
|
|
28
|
+
# Set extra attributes if supported by user
|
22
29
|
if user.respond_to?(:cas_extra_attributes=)
|
23
|
-
user.cas_extra_attributes =
|
30
|
+
user.cas_extra_attributes = client.extra_attributes
|
24
31
|
end
|
25
32
|
|
26
|
-
update_tracking(user,
|
33
|
+
update_tracking(user, ip)
|
27
34
|
end
|
28
35
|
|
29
|
-
user
|
36
|
+
user
|
30
37
|
end
|
31
38
|
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
39
|
+
#
|
40
|
+
# Find user by authentication token.
|
41
|
+
# If user exists and tracking is enabled, tracking info is updated.
|
42
|
+
# Returns user or nil if user not found.
|
43
|
+
#
|
44
|
+
def self.authenticate_with_token(token, ip)
|
45
|
+
user = resource.where(Rack::Casual.auth_token => token).first
|
46
|
+
return nil if user_not_active(user)
|
47
|
+
update_tracking(user, ip) if user
|
37
48
|
user
|
38
49
|
end
|
50
|
+
|
51
|
+
def self.user_not_active(user)
|
52
|
+
user.respond_to?(:active?) && user.send(:active?) == false
|
53
|
+
end
|
39
54
|
|
40
55
|
# Update tracking info (last logged in at / ip) if tracking_enabled is set.
|
41
56
|
# Saves the user regardless of whether tracking was updated or not.
|
42
|
-
def self.update_tracking(user,
|
57
|
+
def self.update_tracking(user, ip)
|
43
58
|
if Rack::Casual.tracking_enabled
|
44
59
|
user.last_login_at = Time.now if user.respond_to?(:last_login_at)
|
45
|
-
user.last_login_ip =
|
60
|
+
user.last_login_ip = ip if user.respond_to?(:last_login_ip)
|
46
61
|
user.login_count += 1 if user.respond_to?(:login_count)
|
47
62
|
end
|
48
63
|
user.save
|
@@ -50,7 +65,7 @@ module Rack
|
|
50
65
|
|
51
66
|
# Find user by username
|
52
67
|
def self.find(username)
|
53
|
-
|
68
|
+
resource.where(Rack::Casual.username => username).first
|
54
69
|
end
|
55
70
|
|
56
71
|
# Initializes a new user
|
@@ -60,19 +75,9 @@ module Rack
|
|
60
75
|
|
61
76
|
# Returns the user class
|
62
77
|
def self.resource
|
63
|
-
Rack::Casual.user_class.constantize
|
78
|
+
# Rack::Casual.user_class.constantize
|
79
|
+
Kernel.const_get(Rack::Casual.user_class)
|
64
80
|
end
|
65
|
-
|
66
|
-
# Returns the scope used to find users
|
67
|
-
def self.authentication_scope
|
68
|
-
if Rack::Casual.authentication_scope
|
69
|
-
puts "Authentication scope is kinda broken and should be avoided"
|
70
|
-
resource.send(Rack::Casual.authentication_scope)
|
71
|
-
else
|
72
|
-
resource.scoped
|
73
|
-
end
|
74
|
-
end
|
75
|
-
|
76
81
|
end
|
77
82
|
|
78
83
|
end
|
data/lib/rack/casual.rb
CHANGED
@@ -6,75 +6,107 @@ module Rack
|
|
6
6
|
module Casual
|
7
7
|
|
8
8
|
autoload :Authentication, 'rack/casual/authentication'
|
9
|
+
autoload :Client, 'rack/casual/client'
|
9
10
|
autoload :UserFactory, 'rack/casual/user_factory'
|
10
11
|
autoload :Controller, 'rack/casual/controller'
|
12
|
+
|
13
|
+
# Default options
|
14
|
+
defaults = {
|
15
|
+
:cas_url => nil, # CAS URL
|
16
|
+
:session_key => "user", # Name of session key to store the user-id in
|
17
|
+
:ticket_param => "ticket", # Name of parameter for the CAS ticket
|
18
|
+
:create_user => true, # Automatic user creation
|
19
|
+
:user_class => "User", # Name of user model
|
20
|
+
:username => "username", # Name of username attribute in User model
|
21
|
+
:auth_token => "auth_token", # Name of authentication token attribute in User model
|
22
|
+
:tracking_enabled => true, # Enable tracking on user
|
23
|
+
}
|
24
|
+
|
25
|
+
# Create attribute accessors for each key/value pair in options.
|
26
|
+
defaults.each do |key, value|
|
27
|
+
# value = value.is_a?(String) ? "'#{value}'" : %Q{"#{value}"}
|
28
|
+
class_eval <<-EOS
|
29
|
+
@@#{key} = nil unless defined? @@#{key}
|
30
|
+
|
31
|
+
def self.#{key}
|
32
|
+
@@#{key}
|
33
|
+
end
|
34
|
+
|
35
|
+
def self.#{key}=(value)
|
36
|
+
@@#{key} = value
|
37
|
+
end
|
38
|
+
EOS
|
39
|
+
|
40
|
+
# set the default value
|
41
|
+
self.send("#{key}=", value)
|
42
|
+
end
|
11
43
|
|
12
|
-
#
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
#
|
17
|
-
#
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
#
|
22
|
-
#
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
#
|
27
|
-
#
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
#
|
32
|
-
#
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
#
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
#
|
41
|
-
#
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
#
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
#
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
#
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
#
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
#
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
# Default way to setup Devise. Run rails generate devise_install to create
|
44
|
+
# # URI to CAS login
|
45
|
+
# # Default is base_url/login
|
46
|
+
# def self.login_url; @@login_url; end
|
47
|
+
# def self.login_url=(login_url)
|
48
|
+
#
|
49
|
+
# mattr_accessor :login_url
|
50
|
+
# @@login_url = nil
|
51
|
+
#
|
52
|
+
# # URI to CAS logout
|
53
|
+
# # Default is base_url/logout
|
54
|
+
# mattr_accessor :logout_url
|
55
|
+
# @@logout_url = nil
|
56
|
+
#
|
57
|
+
# # URI to service validation
|
58
|
+
# # Default is base_url/serviceValidate
|
59
|
+
# mattr_accessor :validate_url
|
60
|
+
# @@validate_url = nil
|
61
|
+
#
|
62
|
+
# # Name of authentication token to use in params
|
63
|
+
# # Set to nil to disable token authentication
|
64
|
+
# mattr_accessor :auth_token_key
|
65
|
+
# @@auth_token_key = "auth_token"
|
66
|
+
#
|
67
|
+
# # Name of the ticket parameter used by CAS
|
68
|
+
# mattr_accessor :ticket_param
|
69
|
+
# @@ticket_param = "ticket"
|
70
|
+
#
|
71
|
+
# # Name of key to store user id
|
72
|
+
# # Default is 'user' => session[:user]
|
73
|
+
# mattr_accessor :session_key_user
|
74
|
+
# @@session_key_user = "user"
|
75
|
+
#
|
76
|
+
# # Use this scope when finding users
|
77
|
+
# mattr_accessor :authentication_scope
|
78
|
+
# @@authentication_scope = nil
|
79
|
+
#
|
80
|
+
# # Set to true to auto-create users
|
81
|
+
# mattr_accessor :create_user
|
82
|
+
# @@create_user = true
|
83
|
+
#
|
84
|
+
# # Name of the User class
|
85
|
+
# mattr_accessor :user_class
|
86
|
+
# @@user_class = "User"
|
87
|
+
#
|
88
|
+
# # Username attribute on user
|
89
|
+
# mattr_accessor :username
|
90
|
+
# @@username = "username"
|
91
|
+
#
|
92
|
+
# # Update user with last_login_at and last_login_ip info
|
93
|
+
# mattr_accessor :tracking_enabled
|
94
|
+
# @@tracking_enabled = true
|
95
|
+
|
96
|
+
# Setup Rack::Casual. Run rails generate rack_casual to create
|
66
97
|
# a fresh initializer with all configuration values.
|
67
98
|
def self.setup
|
68
99
|
yield self
|
69
100
|
end
|
70
101
|
|
71
102
|
def self.cas_client
|
72
|
-
@@cas_client ||=
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
103
|
+
@@cas_client ||= Client.new
|
104
|
+
# @@cas_client ||= ::CASClient::Client.new(
|
105
|
+
# :cas_base_url => @@base_url,
|
106
|
+
# :login_url => @@login_url,
|
107
|
+
# :logout_url => @@logout_url,
|
108
|
+
# :validate_url => @@validate_url
|
109
|
+
# )
|
78
110
|
end
|
79
111
|
|
80
112
|
end
|
data/lib/rack-casual.rb
CHANGED
metadata
CHANGED
@@ -1,12 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rack-casual
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
+
hash: 27
|
4
5
|
prerelease: false
|
5
6
|
segments:
|
6
7
|
- 0
|
7
|
-
- 0
|
8
8
|
- 1
|
9
|
-
|
9
|
+
- 0
|
10
|
+
version: 0.1.0
|
10
11
|
platform: ruby
|
11
12
|
authors:
|
12
13
|
- Gudleik Rasch
|
@@ -14,39 +15,59 @@ autorequire:
|
|
14
15
|
bindir: bin
|
15
16
|
cert_chain: []
|
16
17
|
|
17
|
-
date: 2010-09-
|
18
|
+
date: 2010-09-03 00:00:00 +02:00
|
18
19
|
default_executable:
|
19
20
|
dependencies:
|
20
21
|
- !ruby/object:Gem::Dependency
|
21
|
-
name:
|
22
|
+
name: nokogiri
|
22
23
|
prerelease: false
|
23
24
|
requirement: &id001 !ruby/object:Gem::Requirement
|
24
25
|
none: false
|
25
26
|
requirements:
|
26
27
|
- - ~>
|
27
28
|
- !ruby/object:Gem::Version
|
29
|
+
hash: 1
|
28
30
|
segments:
|
29
|
-
- 2
|
30
|
-
- 2
|
31
31
|
- 1
|
32
|
-
|
32
|
+
- 4
|
33
|
+
- 3
|
34
|
+
version: 1.4.3
|
33
35
|
type: :runtime
|
34
36
|
version_requirements: *id001
|
35
37
|
- !ruby/object:Gem::Dependency
|
36
|
-
name:
|
38
|
+
name: rspec
|
37
39
|
prerelease: false
|
38
40
|
requirement: &id002 !ruby/object:Gem::Requirement
|
39
41
|
none: false
|
40
42
|
requirements:
|
41
43
|
- - ~>
|
42
44
|
- !ruby/object:Gem::Version
|
45
|
+
hash: 62196427
|
43
46
|
segments:
|
44
|
-
-
|
47
|
+
- 2
|
45
48
|
- 0
|
46
|
-
|
47
|
-
|
49
|
+
- 0
|
50
|
+
- beta
|
51
|
+
- 20
|
52
|
+
version: 2.0.0.beta.20
|
53
|
+
type: :development
|
48
54
|
version_requirements: *id002
|
49
|
-
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: webmock
|
57
|
+
prerelease: false
|
58
|
+
requirement: &id003 !ruby/object:Gem::Requirement
|
59
|
+
none: false
|
60
|
+
requirements:
|
61
|
+
- - ~>
|
62
|
+
- !ruby/object:Gem::Version
|
63
|
+
hash: 9
|
64
|
+
segments:
|
65
|
+
- 1
|
66
|
+
- 3
|
67
|
+
version: "1.3"
|
68
|
+
type: :development
|
69
|
+
version_requirements: *id003
|
70
|
+
description: Rack middleware for authentication using CAS and/or tokens
|
50
71
|
email:
|
51
72
|
- gudleik@gmail.com
|
52
73
|
executables: []
|
@@ -60,12 +81,14 @@ files:
|
|
60
81
|
- lib/generators/templates/initializer.rb
|
61
82
|
- lib/generators/USAGE
|
62
83
|
- lib/rack/casual/authentication.rb
|
84
|
+
- lib/rack/casual/client.rb
|
63
85
|
- lib/rack/casual/controller.rb
|
64
86
|
- lib/rack/casual/user_factory.rb
|
65
87
|
- lib/rack/casual.rb
|
66
88
|
- lib/rack-casual.rb
|
67
89
|
- LICENSE
|
68
90
|
- README.md
|
91
|
+
- examples/sinatra_app.rb
|
69
92
|
has_rdoc: true
|
70
93
|
homepage: http://github.com/gudleik/rack-casual
|
71
94
|
licenses: []
|
@@ -80,6 +103,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
80
103
|
requirements:
|
81
104
|
- - ">="
|
82
105
|
- !ruby/object:Gem::Version
|
106
|
+
hash: 3
|
83
107
|
segments:
|
84
108
|
- 0
|
85
109
|
version: "0"
|
@@ -88,6 +112,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
88
112
|
requirements:
|
89
113
|
- - ">="
|
90
114
|
- !ruby/object:Gem::Version
|
115
|
+
hash: 21
|
91
116
|
segments:
|
92
117
|
- 1
|
93
118
|
- 3
|