omniauth-cas 1.1.1 → 3.0.0.beta.1
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.
- checksums.yaml +5 -5
- data/CHANGELOG.md +25 -2
- data/README.md +19 -13
- data/lib/omniauth/cas/version.rb +4 -2
- data/lib/omniauth/cas.rb +3 -1
- data/lib/omniauth/strategies/cas/logout_request.rb +11 -8
- data/lib/omniauth/strategies/cas/service_ticket_validator.rb +20 -4
- data/lib/omniauth/strategies/cas.rb +38 -28
- data/lib/omniauth-cas.rb +2 -0
- metadata +24 -109
- data/.editorconfig +0 -16
- data/.gitignore +0 -21
- data/.ruby-version +0 -1
- data/.travis.yml +0 -9
- data/Gemfile +0 -9
- data/Rakefile +0 -15
- data/omniauth-cas.gemspec +0 -28
- data/spec/fixtures/cas_failure.xml +0 -4
- data/spec/fixtures/cas_success.xml +0 -14
- data/spec/fixtures/cas_success_jasig.xml +0 -16
- data/spec/omniauth/strategies/cas/logout_request_spec.rb +0 -103
- data/spec/omniauth/strategies/cas/service_ticket_validator_spec.rb +0 -55
- data/spec/omniauth/strategies/cas_spec.rb +0 -250
- data/spec/spec_helper.rb +0 -13
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
|
-
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
2
|
+
SHA256:
|
|
3
|
+
metadata.gz: 2600fefe7682305731ccd7117312c394c148c9d3d2812da453ebbb3a3c0a294a
|
|
4
|
+
data.tar.gz: 96b0f898f502ff223c5b3430ad308daec92914152a8ffead39e09d597f1cac02
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: a35c9f0cbb2d2d061d9de0497156b8565eef5994cb59a4ef97e72ed3722558d205d2d329b7b1cb206ff16774ef0109488b5ac2e079b53f87f574fb2c5804a84a
|
|
7
|
+
data.tar.gz: 7016220b6d2dabeb565a5a90d2b2a008bcbeb36c68c256cba6d2b549295477bf3aa42a442ff11d893c1f8eaa088e69965831122bd2ce2015acf67986c37027a7
|
data/CHANGELOG.md
CHANGED
|
@@ -2,8 +2,31 @@
|
|
|
2
2
|
|
|
3
3
|
All notable changes to this project will be documented in this file.
|
|
4
4
|
|
|
5
|
-
The format is based on [Keep a Changelog](
|
|
6
|
-
project adheres to [Semantic Versioning](
|
|
5
|
+
The format is based on [Keep a Changelog](https://keepachangelog.com/) and this
|
|
6
|
+
project adheres to [Semantic Versioning](https://semver.org/)
|
|
7
|
+
|
|
8
|
+
## 3.0.0.beta.1 - 2024-01-12
|
|
9
|
+
|
|
10
|
+
### Changed
|
|
11
|
+
|
|
12
|
+
* Breaking change: Support OmniAuth 2 (#82).
|
|
13
|
+
* Potential breaking change: case of `Omniauth::Cas::VERSION` module (#76).
|
|
14
|
+
|
|
15
|
+
### Removed
|
|
16
|
+
|
|
17
|
+
* Compatibility with EOL Ruby versions (#73).
|
|
18
|
+
|
|
19
|
+
## 2.0.0 - 2010-11-14
|
|
20
|
+
|
|
21
|
+
### Added
|
|
22
|
+
|
|
23
|
+
* Add support for multivalued attributes ([#59](https://github.com/dlindahl/omniauth-cas/pull/59))
|
|
24
|
+
* Successfully test against Ruby 2.4 and up ([#60](https://github.com/dlindahl/omniauth-cas/pull/60))
|
|
25
|
+
|
|
26
|
+
### Changed
|
|
27
|
+
|
|
28
|
+
* Forward success response to `fetch_raw_info` callback ([#51](https://github.com/dlindahl/omniauth-cas/pull/51))
|
|
29
|
+
* Relax development dependencies to the latest versions
|
|
7
30
|
|
|
8
31
|
## 1.1.1 - 2016-09-19
|
|
9
32
|
|
data/README.md
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
|
-
# OmniAuth CAS Strategy [![Gem Version][version_badge]][version] [![Build Status][
|
|
1
|
+
# OmniAuth CAS Strategy [![Gem Version][version_badge]][version] [![Build Status][github_actions_status]][github_actions]
|
|
2
2
|
|
|
3
|
-
[version_badge]: https://badge.fury.io/rb/omniauth-cas.
|
|
4
|
-
[version]:
|
|
5
|
-
[
|
|
6
|
-
[
|
|
3
|
+
[version_badge]: https://badge.fury.io/rb/omniauth-cas.svg
|
|
4
|
+
[version]: https://badge.fury.io/rb/omniauth-cas
|
|
5
|
+
[github_actions]: https://github.com/dlindahl/omniauth-cas/actions
|
|
6
|
+
[github_actions_status]: https://github.com/dlindahl/omniauth-cas/actions/workflows/ci.yml/badge.svg
|
|
7
7
|
[releases]: https://github.com/dlindahl/omniauth-cas/releases
|
|
8
8
|
|
|
9
|
-
This is a OmniAuth 1
|
|
9
|
+
This is a [OmniAuth][omniauth] 2.1+ compatible port of the previously available
|
|
10
10
|
[OmniAuth CAS strategy][old_omniauth_cas] that was bundled with OmniAuth 0.3.
|
|
11
11
|
|
|
12
12
|
* [View the documentation][document_up]
|
|
@@ -42,7 +42,7 @@ end
|
|
|
42
42
|
|
|
43
43
|
OmniAuth CAS requires at least one of the following two configuration options:
|
|
44
44
|
|
|
45
|
-
* `url` - Defines the URL of your CAS server (i.e. `
|
|
45
|
+
* `url` - Defines the URL of your CAS server (i.e. `https://example.org:8080`)
|
|
46
46
|
* `host` - Defines the host of your CAS server (i.e. `example.org`).
|
|
47
47
|
|
|
48
48
|
#### Optional
|
|
@@ -58,6 +58,7 @@ Other configuration options:
|
|
|
58
58
|
* `uid_field` - The user data attribute to use as your user's unique identifier. Defaults to `'user'` (which usually contains the user's login name).
|
|
59
59
|
* `ca_path` - Optional when `ssl` is `true`. Sets path of a CA certification directory. See [Net::HTTP][net_http] for more details.
|
|
60
60
|
* `disable_ssl_verification` - Optional when `ssl` is true. Disables verification.
|
|
61
|
+
* `merge_multivalued_attributes` - When set to `true` returns attributes with multiple values as arrays. Defaults to `false` and returns the last value as a string.
|
|
61
62
|
* `on_single_sign_out` - Optional. Callback used when a [CAS 3.1 Single Sign Out][sso]
|
|
62
63
|
request is received.
|
|
63
64
|
* `fetch_raw_info` - Optional. Callback used to return additional "raw" user
|
|
@@ -65,9 +66,13 @@ Other configuration options:
|
|
|
65
66
|
|
|
66
67
|
```ruby
|
|
67
68
|
provider :cas,
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
69
|
+
fetch_raw_info: Proc.new { |strategy, opts, ticket, user_info, rawxml|
|
|
70
|
+
return {} if user_info.empty? || rawxml.nil? # Auth failed
|
|
71
|
+
|
|
72
|
+
extra_info = ExternalService.get(user_info[:user]).attributes
|
|
73
|
+
extra_info.merge!({'roles' => rawxml.xpath('//cas:roles').map(&:text)})
|
|
74
|
+
extra_info
|
|
75
|
+
}
|
|
71
76
|
```
|
|
72
77
|
|
|
73
78
|
Configurable options for values returned by CAS:
|
|
@@ -96,7 +101,7 @@ Your new settings should look similar to this:
|
|
|
96
101
|
provider :cas,
|
|
97
102
|
host: 'cas.example.com',
|
|
98
103
|
login_url: '/cas/login',
|
|
99
|
-
|
|
104
|
+
service_validate_url: '/cas/serviceValidate'
|
|
100
105
|
```
|
|
101
106
|
|
|
102
107
|
If you encounter problems wih SSL certificates you may want to set the `ca_path` parameter or activate `disable_ssl_verification` (not recommended).
|
|
@@ -117,7 +122,8 @@ Special thanks go out to the following people
|
|
|
117
122
|
* Elber Ribeiro (@dynaum) for Ubuntu SSL configuration support
|
|
118
123
|
* @rbq for README updates and OmniAuth 0.3 migration guide
|
|
119
124
|
|
|
125
|
+
[omniauth]: https://github.com/omniauth/omniauth
|
|
120
126
|
[old_omniauth_cas]: https://github.com/intridea/omniauth/blob/0-3-stable/oa-enterprise/lib/omniauth/strategies/cas.rb
|
|
121
|
-
[document_up]:
|
|
122
|
-
[net_http]:
|
|
127
|
+
[document_up]: https://dlindahl.github.io/omniauth-cas/
|
|
128
|
+
[net_http]: https://ruby-doc.org/stdlib-1.9.3/libdoc/net/http/rdoc/Net/HTTP.html
|
|
123
129
|
[sso]: https://wiki.jasig.org/display/CASUM/Single+Sign+Out
|
data/lib/omniauth/cas/version.rb
CHANGED
data/lib/omniauth/cas.rb
CHANGED
|
@@ -1,9 +1,12 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
module OmniAuth
|
|
2
4
|
module Strategies
|
|
3
5
|
class CAS
|
|
4
6
|
class LogoutRequest
|
|
5
7
|
def initialize(strategy, request)
|
|
6
|
-
@strategy
|
|
8
|
+
@strategy = strategy
|
|
9
|
+
@request = request
|
|
7
10
|
end
|
|
8
11
|
|
|
9
12
|
def call(options = {})
|
|
@@ -11,10 +14,10 @@ module OmniAuth
|
|
|
11
14
|
|
|
12
15
|
begin
|
|
13
16
|
result = single_sign_out_callback.call(*logout_request)
|
|
14
|
-
rescue StandardError =>
|
|
15
|
-
|
|
17
|
+
rescue StandardError => e
|
|
18
|
+
@strategy.fail! :logout_request, e
|
|
16
19
|
else
|
|
17
|
-
result = [200,{},'OK'] if result == true || result.nil?
|
|
20
|
+
result = [200, {}, 'OK'] if result == true || result.nil?
|
|
18
21
|
ensure
|
|
19
22
|
return unless result
|
|
20
23
|
|
|
@@ -22,18 +25,18 @@ module OmniAuth
|
|
|
22
25
|
# when Rack::Response#new wants [body,status,headers]? Additionally,
|
|
23
26
|
# why does Rack::Response differ in argument order from the usual
|
|
24
27
|
# Rack-like [status,headers,body] array?
|
|
25
|
-
return Rack::Response.new(result[2],result[0],result[1]).finish
|
|
28
|
+
return Rack::Response.new(result[2], result[0], result[1]).finish
|
|
26
29
|
end
|
|
27
30
|
end
|
|
28
31
|
|
|
29
|
-
|
|
32
|
+
private
|
|
30
33
|
|
|
31
34
|
def logout_request
|
|
32
35
|
@logout_request ||= begin
|
|
33
36
|
saml = Nokogiri.parse(@request.params['logoutRequest'])
|
|
34
37
|
name_id = saml.xpath('//saml:NameID').text
|
|
35
38
|
sess_idx = saml.xpath('//samlp:SessionIndex').text
|
|
36
|
-
inject_params(name_id:name_id, session_index:sess_idx)
|
|
39
|
+
inject_params(name_id: name_id, session_index: sess_idx)
|
|
37
40
|
@request
|
|
38
41
|
end
|
|
39
42
|
end
|
|
@@ -42,7 +45,7 @@ module OmniAuth
|
|
|
42
45
|
rack_input = @request.env['rack.input'].read
|
|
43
46
|
params = Rack::Utils.parse_query(rack_input, '&').merge new_params
|
|
44
47
|
@request.env['rack.input'] = StringIO.new(Rack::Utils.build_query(params))
|
|
45
|
-
rescue
|
|
48
|
+
rescue StandardError
|
|
46
49
|
# A no-op intended to ensure that the ensure block is run
|
|
47
50
|
raise
|
|
48
51
|
ensure
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
require 'net/http'
|
|
2
4
|
require 'net/https'
|
|
3
5
|
require 'nokogiri'
|
|
@@ -6,7 +8,9 @@ module OmniAuth
|
|
|
6
8
|
module Strategies
|
|
7
9
|
class CAS
|
|
8
10
|
class ServiceTicketValidator
|
|
9
|
-
VALIDATION_REQUEST_HEADERS = { 'Accept' => '*/*' }
|
|
11
|
+
VALIDATION_REQUEST_HEADERS = { 'Accept' => '*/*' }.freeze
|
|
12
|
+
|
|
13
|
+
attr_reader :success_body
|
|
10
14
|
|
|
11
15
|
# Build a validator from a +configuration+, a
|
|
12
16
|
# +return_to+ URL, and a +ticket+.
|
|
@@ -38,19 +42,30 @@ module OmniAuth
|
|
|
38
42
|
parse_user_info(@success_body)
|
|
39
43
|
end
|
|
40
44
|
|
|
41
|
-
|
|
45
|
+
private
|
|
46
|
+
|
|
47
|
+
# Merges attributes with multiple values into an array if support is
|
|
48
|
+
# enabled (disabled by default)
|
|
49
|
+
def attribute_value(user_info, attribute, value)
|
|
50
|
+
if @options.merge_multivalued_attributes && user_info.key?(attribute)
|
|
51
|
+
Array(user_info[attribute]).push(value)
|
|
52
|
+
else
|
|
53
|
+
value
|
|
54
|
+
end
|
|
55
|
+
end
|
|
42
56
|
|
|
43
57
|
# turns an `<cas:authenticationSuccess>` node into a Hash;
|
|
44
58
|
# returns nil if given nil
|
|
45
59
|
def parse_user_info(node)
|
|
46
60
|
return nil if node.nil?
|
|
61
|
+
|
|
47
62
|
{}.tap do |hash|
|
|
48
63
|
node.children.each do |e|
|
|
49
64
|
node_name = e.name.sub(/^cas:/, '')
|
|
50
|
-
unless e.
|
|
65
|
+
unless e.is_a?(Nokogiri::XML::Text) || node_name == 'proxies'
|
|
51
66
|
# There are no child elements
|
|
52
67
|
if e.element_children.count == 0
|
|
53
|
-
hash[node_name] = e.content
|
|
68
|
+
hash[node_name] = attribute_value(hash, node_name, e.content)
|
|
54
69
|
elsif e.element_children.count
|
|
55
70
|
# JASIG style extra attributes
|
|
56
71
|
if node_name == 'attributes'
|
|
@@ -70,6 +85,7 @@ module OmniAuth
|
|
|
70
85
|
# if the passed body is nil or if there is no such node.
|
|
71
86
|
def find_authentication_success(body)
|
|
72
87
|
return nil if body.nil? || body == ''
|
|
88
|
+
|
|
73
89
|
begin
|
|
74
90
|
doc = Nokogiri::XML(body)
|
|
75
91
|
begin
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
require 'omniauth'
|
|
2
4
|
require 'addressable/uri'
|
|
3
5
|
|
|
@@ -14,7 +16,7 @@ module OmniAuth
|
|
|
14
16
|
autoload :LogoutRequest, 'omniauth/strategies/cas/logout_request'
|
|
15
17
|
|
|
16
18
|
attr_accessor :raw_info
|
|
17
|
-
|
|
19
|
+
alias user_info raw_info
|
|
18
20
|
|
|
19
21
|
option :name, :cas # Required property by OmniAuth::Strategy
|
|
20
22
|
|
|
@@ -22,10 +24,11 @@ module OmniAuth
|
|
|
22
24
|
option :port, nil
|
|
23
25
|
option :path, nil
|
|
24
26
|
option :ssl, true
|
|
27
|
+
option :merge_multivalued_attributes, false
|
|
25
28
|
option :service_validate_url, '/serviceValidate'
|
|
26
29
|
option :login_url, '/login'
|
|
27
30
|
option :logout_url, '/logout'
|
|
28
|
-
option :on_single_sign_out,
|
|
31
|
+
option :on_single_sign_out, proc {}
|
|
29
32
|
# A Proc or lambda that returns a Hash of additional user info to be
|
|
30
33
|
# merged with the info returned by the CAS server.
|
|
31
34
|
#
|
|
@@ -34,7 +37,7 @@ module OmniAuth
|
|
|
34
37
|
# @param [Hash] The user info for the Service Ticket returned by the CAS server
|
|
35
38
|
#
|
|
36
39
|
# @return [Hash] Extra user info
|
|
37
|
-
option :fetch_raw_info,
|
|
40
|
+
option :fetch_raw_info, proc { {} }
|
|
38
41
|
# Make all the keys configurable with some defaults set here
|
|
39
42
|
option :uid_field, 'user'
|
|
40
43
|
option :name_key, 'name'
|
|
@@ -47,24 +50,26 @@ module OmniAuth
|
|
|
47
50
|
option :phone_key, 'phone'
|
|
48
51
|
|
|
49
52
|
# As required by https://github.com/intridea/omniauth/wiki/Auth-Hash-Schema
|
|
50
|
-
|
|
53
|
+
AUTH_HASH_SCHEMA_KEYS = %w[name email nickname first_name last_name location image phone].freeze
|
|
51
54
|
info do
|
|
52
55
|
prune!({
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
56
|
+
name: raw_info[options[:name_key].to_s],
|
|
57
|
+
email: raw_info[options[:email_key].to_s],
|
|
58
|
+
nickname: raw_info[options[:nickname_key].to_s],
|
|
59
|
+
first_name: raw_info[options[:first_name_key].to_s],
|
|
60
|
+
last_name: raw_info[options[:last_name_key].to_s],
|
|
61
|
+
location: raw_info[options[:location_key].to_s],
|
|
62
|
+
image: raw_info[options[:image_key].to_s],
|
|
63
|
+
phone: raw_info[options[:phone_key].to_s]
|
|
64
|
+
})
|
|
62
65
|
end
|
|
63
66
|
|
|
64
67
|
extra do
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
+
if skip_info?
|
|
69
|
+
{}
|
|
70
|
+
else
|
|
71
|
+
prune!(raw_info.dup.delete_if { |k, _v| AUTH_HASH_SCHEMA_KEYS.include?(k) })
|
|
72
|
+
end
|
|
68
73
|
end
|
|
69
74
|
|
|
70
75
|
uid do
|
|
@@ -81,8 +86,10 @@ module OmniAuth
|
|
|
81
86
|
else
|
|
82
87
|
@ticket = request.params['ticket']
|
|
83
88
|
return fail!(:no_ticket, MissingCASTicket.new('No CAS Ticket')) unless @ticket
|
|
89
|
+
|
|
84
90
|
fetch_raw_info(@ticket)
|
|
85
91
|
return fail!(:invalid_ticket, InvalidCASTicket.new('Invalid CAS Ticket')) if raw_info.empty?
|
|
92
|
+
|
|
86
93
|
super
|
|
87
94
|
end
|
|
88
95
|
end
|
|
@@ -96,12 +103,12 @@ module OmniAuth
|
|
|
96
103
|
'Location' => login_url(service_url),
|
|
97
104
|
'Content-Type' => 'text/plain'
|
|
98
105
|
},
|
|
99
|
-
[
|
|
106
|
+
['You are being redirected to CAS for sign-in.']
|
|
100
107
|
]
|
|
101
108
|
end
|
|
102
109
|
|
|
103
110
|
def on_sso_path?
|
|
104
|
-
request.post? && request.params.
|
|
111
|
+
request.post? && request.params.key?('logoutRequest')
|
|
105
112
|
end
|
|
106
113
|
|
|
107
114
|
def single_sign_out_phase
|
|
@@ -135,9 +142,9 @@ module OmniAuth
|
|
|
135
142
|
end
|
|
136
143
|
|
|
137
144
|
def validate_cas_setup
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
145
|
+
return unless options.host.nil? || options.login_url.nil?
|
|
146
|
+
|
|
147
|
+
raise ArgumentError, ':host and :login_url MUST be provided'
|
|
141
148
|
end
|
|
142
149
|
|
|
143
150
|
# Build a service-validation URL from +service+ and +ticket+.
|
|
@@ -153,9 +160,9 @@ module OmniAuth
|
|
|
153
160
|
service_url = Addressable::URI.parse(service_url)
|
|
154
161
|
service_url.query_values = service_url.query_values.tap { |qs| qs.delete('ticket') }
|
|
155
162
|
cas_url + append_params(options.service_validate_url, {
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
163
|
+
service: service_url.to_s,
|
|
164
|
+
ticket: ticket
|
|
165
|
+
})
|
|
159
166
|
end
|
|
160
167
|
|
|
161
168
|
# Build a CAS login URL from +service+.
|
|
@@ -174,7 +181,7 @@ module OmniAuth
|
|
|
174
181
|
#
|
|
175
182
|
# @return [String] the new joined URL.
|
|
176
183
|
def append_params(base, params)
|
|
177
|
-
params = params.
|
|
184
|
+
params = params.each_value { |v| Rack::Utils.escape(v) }
|
|
178
185
|
Addressable::URI.parse(base).tap do |base_uri|
|
|
179
186
|
base_uri.query_values = (base_uri.query_values || {}).merge(params)
|
|
180
187
|
end.to_s
|
|
@@ -186,11 +193,14 @@ module OmniAuth
|
|
|
186
193
|
ServiceTicketValidator.new(self, options, callback_url, ticket).call
|
|
187
194
|
end
|
|
188
195
|
|
|
189
|
-
|
|
196
|
+
private
|
|
190
197
|
|
|
191
198
|
def fetch_raw_info(ticket)
|
|
192
|
-
|
|
193
|
-
|
|
199
|
+
validator = validate_service_ticket(ticket)
|
|
200
|
+
ticket_user_info = validator.user_info
|
|
201
|
+
ticket_success_body = validator.success_body
|
|
202
|
+
custom_user_info = options.fetch_raw_info.call(self,
|
|
203
|
+
options, ticket, ticket_user_info, ticket_success_body)
|
|
194
204
|
self.raw_info = ticket_user_info.merge(custom_user_info)
|
|
195
205
|
end
|
|
196
206
|
|
data/lib/omniauth-cas.rb
CHANGED
metadata
CHANGED
|
@@ -1,127 +1,57 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: omniauth-cas
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version:
|
|
4
|
+
version: 3.0.0.beta.1
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Derek Lindahl
|
|
8
|
-
autorequire:
|
|
8
|
+
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date:
|
|
11
|
+
date: 2024-01-12 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
|
-
name:
|
|
14
|
+
name: addressable
|
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
|
16
16
|
requirements:
|
|
17
17
|
- - "~>"
|
|
18
18
|
- !ruby/object:Gem::Version
|
|
19
|
-
version: '
|
|
19
|
+
version: '2.8'
|
|
20
20
|
type: :runtime
|
|
21
21
|
prerelease: false
|
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
|
23
23
|
requirements:
|
|
24
24
|
- - "~>"
|
|
25
25
|
- !ruby/object:Gem::Version
|
|
26
|
-
version: '
|
|
26
|
+
version: '2.8'
|
|
27
27
|
- !ruby/object:Gem::Dependency
|
|
28
28
|
name: nokogiri
|
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
|
30
30
|
requirements:
|
|
31
31
|
- - "~>"
|
|
32
32
|
- !ruby/object:Gem::Version
|
|
33
|
-
version: '1.
|
|
33
|
+
version: '1.12'
|
|
34
34
|
type: :runtime
|
|
35
35
|
prerelease: false
|
|
36
36
|
version_requirements: !ruby/object:Gem::Requirement
|
|
37
37
|
requirements:
|
|
38
38
|
- - "~>"
|
|
39
39
|
- !ruby/object:Gem::Version
|
|
40
|
-
version: '1.
|
|
40
|
+
version: '1.12'
|
|
41
41
|
- !ruby/object:Gem::Dependency
|
|
42
|
-
name:
|
|
42
|
+
name: omniauth
|
|
43
43
|
requirement: !ruby/object:Gem::Requirement
|
|
44
44
|
requirements:
|
|
45
45
|
- - "~>"
|
|
46
46
|
- !ruby/object:Gem::Version
|
|
47
|
-
version: '2.
|
|
47
|
+
version: '2.1'
|
|
48
48
|
type: :runtime
|
|
49
49
|
prerelease: false
|
|
50
50
|
version_requirements: !ruby/object:Gem::Requirement
|
|
51
51
|
requirements:
|
|
52
52
|
- - "~>"
|
|
53
53
|
- !ruby/object:Gem::Version
|
|
54
|
-
version: '2.
|
|
55
|
-
- !ruby/object:Gem::Dependency
|
|
56
|
-
name: rake
|
|
57
|
-
requirement: !ruby/object:Gem::Requirement
|
|
58
|
-
requirements:
|
|
59
|
-
- - "~>"
|
|
60
|
-
- !ruby/object:Gem::Version
|
|
61
|
-
version: '10.0'
|
|
62
|
-
type: :development
|
|
63
|
-
prerelease: false
|
|
64
|
-
version_requirements: !ruby/object:Gem::Requirement
|
|
65
|
-
requirements:
|
|
66
|
-
- - "~>"
|
|
67
|
-
- !ruby/object:Gem::Version
|
|
68
|
-
version: '10.0'
|
|
69
|
-
- !ruby/object:Gem::Dependency
|
|
70
|
-
name: webmock
|
|
71
|
-
requirement: !ruby/object:Gem::Requirement
|
|
72
|
-
requirements:
|
|
73
|
-
- - "~>"
|
|
74
|
-
- !ruby/object:Gem::Version
|
|
75
|
-
version: 1.19.0
|
|
76
|
-
type: :development
|
|
77
|
-
prerelease: false
|
|
78
|
-
version_requirements: !ruby/object:Gem::Requirement
|
|
79
|
-
requirements:
|
|
80
|
-
- - "~>"
|
|
81
|
-
- !ruby/object:Gem::Version
|
|
82
|
-
version: 1.19.0
|
|
83
|
-
- !ruby/object:Gem::Dependency
|
|
84
|
-
name: rspec
|
|
85
|
-
requirement: !ruby/object:Gem::Requirement
|
|
86
|
-
requirements:
|
|
87
|
-
- - "~>"
|
|
88
|
-
- !ruby/object:Gem::Version
|
|
89
|
-
version: 3.1.0
|
|
90
|
-
type: :development
|
|
91
|
-
prerelease: false
|
|
92
|
-
version_requirements: !ruby/object:Gem::Requirement
|
|
93
|
-
requirements:
|
|
94
|
-
- - "~>"
|
|
95
|
-
- !ruby/object:Gem::Version
|
|
96
|
-
version: 3.1.0
|
|
97
|
-
- !ruby/object:Gem::Dependency
|
|
98
|
-
name: rack-test
|
|
99
|
-
requirement: !ruby/object:Gem::Requirement
|
|
100
|
-
requirements:
|
|
101
|
-
- - "~>"
|
|
102
|
-
- !ruby/object:Gem::Version
|
|
103
|
-
version: '0.6'
|
|
104
|
-
type: :development
|
|
105
|
-
prerelease: false
|
|
106
|
-
version_requirements: !ruby/object:Gem::Requirement
|
|
107
|
-
requirements:
|
|
108
|
-
- - "~>"
|
|
109
|
-
- !ruby/object:Gem::Version
|
|
110
|
-
version: '0.6'
|
|
111
|
-
- !ruby/object:Gem::Dependency
|
|
112
|
-
name: awesome_print
|
|
113
|
-
requirement: !ruby/object:Gem::Requirement
|
|
114
|
-
requirements:
|
|
115
|
-
- - ">="
|
|
116
|
-
- !ruby/object:Gem::Version
|
|
117
|
-
version: '0'
|
|
118
|
-
type: :development
|
|
119
|
-
prerelease: false
|
|
120
|
-
version_requirements: !ruby/object:Gem::Requirement
|
|
121
|
-
requirements:
|
|
122
|
-
- - ">="
|
|
123
|
-
- !ruby/object:Gem::Version
|
|
124
|
-
version: '0'
|
|
54
|
+
version: '2.1'
|
|
125
55
|
description: CAS Strategy for OmniAuth
|
|
126
56
|
email:
|
|
127
57
|
- dlindahl@customink.com
|
|
@@ -129,33 +59,26 @@ executables: []
|
|
|
129
59
|
extensions: []
|
|
130
60
|
extra_rdoc_files: []
|
|
131
61
|
files:
|
|
132
|
-
- ".editorconfig"
|
|
133
|
-
- ".gitignore"
|
|
134
|
-
- ".ruby-version"
|
|
135
|
-
- ".travis.yml"
|
|
136
62
|
- CHANGELOG.md
|
|
137
|
-
- Gemfile
|
|
138
63
|
- LICENSE
|
|
139
64
|
- README.md
|
|
140
|
-
- Rakefile
|
|
141
65
|
- lib/omniauth-cas.rb
|
|
142
66
|
- lib/omniauth/cas.rb
|
|
143
67
|
- lib/omniauth/cas/version.rb
|
|
144
68
|
- lib/omniauth/strategies/cas.rb
|
|
145
69
|
- lib/omniauth/strategies/cas/logout_request.rb
|
|
146
70
|
- lib/omniauth/strategies/cas/service_ticket_validator.rb
|
|
147
|
-
- omniauth-cas.gemspec
|
|
148
|
-
- spec/fixtures/cas_failure.xml
|
|
149
|
-
- spec/fixtures/cas_success.xml
|
|
150
|
-
- spec/fixtures/cas_success_jasig.xml
|
|
151
|
-
- spec/omniauth/strategies/cas/logout_request_spec.rb
|
|
152
|
-
- spec/omniauth/strategies/cas/service_ticket_validator_spec.rb
|
|
153
|
-
- spec/omniauth/strategies/cas_spec.rb
|
|
154
|
-
- spec/spec_helper.rb
|
|
155
71
|
homepage: https://github.com/dlindahl/omniauth-cas
|
|
156
72
|
licenses: []
|
|
157
|
-
metadata:
|
|
158
|
-
|
|
73
|
+
metadata:
|
|
74
|
+
bug_tracker_uri: https://github.com/dlindahl/omniauth-cas/issues
|
|
75
|
+
changelog_uri: https://github.com/dlindahl/omniauth-cas/blob/master/CHANGELOG.md
|
|
76
|
+
documentation_uri: https://dlindahl.github.io/omniauth-cas/
|
|
77
|
+
homepage_uri: https://github.com/dlindahl/omniauth-cas
|
|
78
|
+
rubygems_mfa_required: 'true'
|
|
79
|
+
source_code_uri: https://github.com/dlindahl/omniauth-cas
|
|
80
|
+
wiki_uri: https://github.com/dlindahl/omniauth-cas/wiki
|
|
81
|
+
post_install_message:
|
|
159
82
|
rdoc_options: []
|
|
160
83
|
require_paths:
|
|
161
84
|
- lib
|
|
@@ -163,23 +86,15 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
|
163
86
|
requirements:
|
|
164
87
|
- - ">="
|
|
165
88
|
- !ruby/object:Gem::Version
|
|
166
|
-
version: '0'
|
|
89
|
+
version: '3.0'
|
|
167
90
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
168
91
|
requirements:
|
|
169
92
|
- - ">="
|
|
170
93
|
- !ruby/object:Gem::Version
|
|
171
94
|
version: '0'
|
|
172
95
|
requirements: []
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
signing_key:
|
|
96
|
+
rubygems_version: 3.5.3
|
|
97
|
+
signing_key:
|
|
176
98
|
specification_version: 4
|
|
177
99
|
summary: CAS Strategy for OmniAuth
|
|
178
|
-
test_files:
|
|
179
|
-
- spec/fixtures/cas_failure.xml
|
|
180
|
-
- spec/fixtures/cas_success.xml
|
|
181
|
-
- spec/fixtures/cas_success_jasig.xml
|
|
182
|
-
- spec/omniauth/strategies/cas/logout_request_spec.rb
|
|
183
|
-
- spec/omniauth/strategies/cas/service_ticket_validator_spec.rb
|
|
184
|
-
- spec/omniauth/strategies/cas_spec.rb
|
|
185
|
-
- spec/spec_helper.rb
|
|
100
|
+
test_files: []
|
data/.editorconfig
DELETED
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
# EditorConfig helps developers define and maintain consistent
|
|
2
|
-
# coding styles between different editors and IDEs
|
|
3
|
-
# editorconfig.org
|
|
4
|
-
|
|
5
|
-
root = true
|
|
6
|
-
|
|
7
|
-
[*]
|
|
8
|
-
# Change these settings to your own preference
|
|
9
|
-
indent_style = space
|
|
10
|
-
indent_size = 2
|
|
11
|
-
|
|
12
|
-
# We recommend you to keep these unchanged
|
|
13
|
-
end_of_line = lf
|
|
14
|
-
charset = utf-8
|
|
15
|
-
trim_trailing_whitespace = true
|
|
16
|
-
insert_final_newline = true
|
data/.gitignore
DELETED
data/.ruby-version
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
2.1.2
|
data/.travis.yml
DELETED
data/Gemfile
DELETED
data/Rakefile
DELETED
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env rake
|
|
2
|
-
require 'bundler/gem_tasks'
|
|
3
|
-
|
|
4
|
-
require 'rspec/core/rake_task'
|
|
5
|
-
desc 'Default: run specs.'
|
|
6
|
-
task default: :spec
|
|
7
|
-
|
|
8
|
-
desc 'Run specs'
|
|
9
|
-
RSpec::Core::RakeTask.new(:spec) do |t|
|
|
10
|
-
t.rspec_opts = '--require spec_helper --color --order rand'
|
|
11
|
-
end
|
|
12
|
-
|
|
13
|
-
task :test do
|
|
14
|
-
fail %q{This application uses RSpec. Try running "rake spec"}
|
|
15
|
-
end
|
data/omniauth-cas.gemspec
DELETED
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
# -*- encoding: utf-8 -*-
|
|
2
|
-
require File.expand_path('../lib/omniauth/cas/version', __FILE__)
|
|
3
|
-
|
|
4
|
-
Gem::Specification.new do |gem|
|
|
5
|
-
gem.authors = ["Derek Lindahl"]
|
|
6
|
-
gem.email = ["dlindahl@customink.com"]
|
|
7
|
-
gem.summary = %q{CAS Strategy for OmniAuth}
|
|
8
|
-
gem.description = gem.summary
|
|
9
|
-
gem.homepage = "https://github.com/dlindahl/omniauth-cas"
|
|
10
|
-
|
|
11
|
-
gem.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
|
12
|
-
gem.files = `git ls-files`.split("\n")
|
|
13
|
-
gem.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
|
14
|
-
gem.name = "omniauth-cas"
|
|
15
|
-
gem.require_paths = ["lib"]
|
|
16
|
-
gem.version = Omniauth::Cas::VERSION
|
|
17
|
-
|
|
18
|
-
gem.add_dependency 'omniauth', '~> 1.2'
|
|
19
|
-
gem.add_dependency 'nokogiri', '~> 1.5'
|
|
20
|
-
gem.add_dependency 'addressable', '~> 2.3'
|
|
21
|
-
|
|
22
|
-
gem.add_development_dependency 'rake', '~> 10.0'
|
|
23
|
-
gem.add_development_dependency 'webmock', '~> 1.19.0'
|
|
24
|
-
gem.add_development_dependency 'rspec', '~> 3.1.0'
|
|
25
|
-
gem.add_development_dependency 'rack-test', '~> 0.6'
|
|
26
|
-
|
|
27
|
-
gem.add_development_dependency 'awesome_print'
|
|
28
|
-
end
|
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
<cas:serviceResponse xmlns:cas='http://www.yale.edu/tp/cas'>
|
|
2
|
-
<cas:authenticationSuccess>
|
|
3
|
-
<cas:user>psegel</cas:user>
|
|
4
|
-
<cas:employeeid>54</cas:employeeid>
|
|
5
|
-
<cas:first_name>P. Segel</cas:first_name>
|
|
6
|
-
<cas:first_name>Peter</cas:first_name>
|
|
7
|
-
<cas:last_name>Segel</cas:last_name>
|
|
8
|
-
<cas:email>psegel@intridea.com</cas:email>
|
|
9
|
-
<cas:location>Washington, D.C.</cas:location>
|
|
10
|
-
<cas:image>/images/user.jpg</cas:image>
|
|
11
|
-
<cas:phone>555-555-5555</cas:phone>
|
|
12
|
-
<cas:hire_date>2004-07-13</cas:hire_date>
|
|
13
|
-
</cas:authenticationSuccess>
|
|
14
|
-
</cas:serviceResponse>
|
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
<cas:serviceResponse xmlns:cas='http://www.yale.edu/tp/cas'>
|
|
2
|
-
<cas:authenticationSuccess>
|
|
3
|
-
<cas:user>psegel</cas:user>
|
|
4
|
-
<cas:attributes>
|
|
5
|
-
<cas:employeeid>54</cas:employeeid>
|
|
6
|
-
<cas:first_name>P. Segel</cas:first_name>
|
|
7
|
-
<cas:first_name>Peter</cas:first_name>
|
|
8
|
-
<cas:last_name>Segel</cas:last_name>
|
|
9
|
-
<cas:email>psegel@intridea.com</cas:email>
|
|
10
|
-
<cas:location>Washington, D.C.</cas:location>
|
|
11
|
-
<cas:image>/images/user.jpg</cas:image>
|
|
12
|
-
<cas:phone>555-555-5555</cas:phone>
|
|
13
|
-
<cas:hire_date>2004-07-13</cas:hire_date>
|
|
14
|
-
</cas:attributes>
|
|
15
|
-
</cas:authenticationSuccess>
|
|
16
|
-
</cas:serviceResponse>
|
|
@@ -1,103 +0,0 @@
|
|
|
1
|
-
require 'spec_helper'
|
|
2
|
-
|
|
3
|
-
describe OmniAuth::Strategies::CAS::LogoutRequest do
|
|
4
|
-
let(:strategy) { double('strategy') }
|
|
5
|
-
let(:env) do
|
|
6
|
-
{ 'rack.input' => StringIO.new('','r') }
|
|
7
|
-
end
|
|
8
|
-
let(:request) { double('request', params:params, env:env) }
|
|
9
|
-
let(:params) { { 'url' => url, 'logoutRequest' => logoutRequest } }
|
|
10
|
-
let(:url) { 'http://notes.dev/signed_in' }
|
|
11
|
-
let(:logoutRequest) do
|
|
12
|
-
%Q[
|
|
13
|
-
<samlp:LogoutRequest xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol" xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion\" ID="123abc-1234-ab12-cd34-1234abcd" Version="2.0" IssueInstant="#{Time.now.to_s}">
|
|
14
|
-
<saml:NameID>@NOT_USED@</saml:NameID>
|
|
15
|
-
<samlp:SessionIndex>ST-123456-123abc456def</samlp:SessionIndex>
|
|
16
|
-
</samlp:LogoutRequest>
|
|
17
|
-
]
|
|
18
|
-
end
|
|
19
|
-
|
|
20
|
-
subject { described_class.new(strategy, request).call(options) }
|
|
21
|
-
|
|
22
|
-
describe 'SAML attributes' do
|
|
23
|
-
let(:callback) { Proc.new{} }
|
|
24
|
-
let(:options) do
|
|
25
|
-
{ on_single_sign_out: callback }
|
|
26
|
-
end
|
|
27
|
-
|
|
28
|
-
before do
|
|
29
|
-
@rack_input = nil
|
|
30
|
-
allow(callback).to receive(:call) do |req|
|
|
31
|
-
@rack_input = req.env['rack.input'].read
|
|
32
|
-
true
|
|
33
|
-
end
|
|
34
|
-
subject
|
|
35
|
-
end
|
|
36
|
-
|
|
37
|
-
it 'are parsed and injected into the Rack Request parameters' do
|
|
38
|
-
expect(@rack_input).to eq 'name_id=%40NOT_USED%40&session_index=ST-123456-123abc456def'
|
|
39
|
-
end
|
|
40
|
-
|
|
41
|
-
context 'that raise when parsed' do
|
|
42
|
-
let(:env) { { 'rack.input' => nil } }
|
|
43
|
-
|
|
44
|
-
before do
|
|
45
|
-
allow(strategy).to receive(:fail!)
|
|
46
|
-
subject
|
|
47
|
-
expect(strategy).to have_received(:fail!)
|
|
48
|
-
end
|
|
49
|
-
|
|
50
|
-
it 'responds with an error' do
|
|
51
|
-
expect(strategy).to have_received(:fail!)
|
|
52
|
-
end
|
|
53
|
-
end
|
|
54
|
-
end
|
|
55
|
-
|
|
56
|
-
describe 'with a configured callback' do
|
|
57
|
-
let(:options) do
|
|
58
|
-
{ on_single_sign_out: callback }
|
|
59
|
-
end
|
|
60
|
-
|
|
61
|
-
context 'that returns TRUE' do
|
|
62
|
-
let(:callback) { Proc.new{true} }
|
|
63
|
-
|
|
64
|
-
it 'responds with OK' do
|
|
65
|
-
expect(subject[0]).to eq 200
|
|
66
|
-
expect(subject[2].body).to eq ['OK']
|
|
67
|
-
end
|
|
68
|
-
end
|
|
69
|
-
|
|
70
|
-
context 'that returns Nil' do
|
|
71
|
-
let(:callback) { Proc.new{} }
|
|
72
|
-
|
|
73
|
-
it 'responds with OK' do
|
|
74
|
-
expect(subject[0]).to eq 200
|
|
75
|
-
expect(subject[2].body).to eq ['OK']
|
|
76
|
-
end
|
|
77
|
-
end
|
|
78
|
-
|
|
79
|
-
context 'that returns a tuple' do
|
|
80
|
-
let(:callback) { Proc.new{ [400,{},'Bad Request'] } }
|
|
81
|
-
|
|
82
|
-
it 'responds with OK' do
|
|
83
|
-
expect(subject[0]).to eq 400
|
|
84
|
-
expect(subject[2].body).to eq ['Bad Request']
|
|
85
|
-
end
|
|
86
|
-
end
|
|
87
|
-
|
|
88
|
-
context 'that raises an error' do
|
|
89
|
-
let(:exception) { RuntimeError.new('error' )}
|
|
90
|
-
let(:callback) { Proc.new{raise exception} }
|
|
91
|
-
|
|
92
|
-
before do
|
|
93
|
-
allow(strategy).to receive(:fail!)
|
|
94
|
-
subject
|
|
95
|
-
end
|
|
96
|
-
|
|
97
|
-
it 'responds with an error' do
|
|
98
|
-
expect(strategy).to have_received(:fail!)
|
|
99
|
-
.with(:logout_request, exception)
|
|
100
|
-
end
|
|
101
|
-
end
|
|
102
|
-
end
|
|
103
|
-
end
|
|
@@ -1,55 +0,0 @@
|
|
|
1
|
-
require 'spec_helper'
|
|
2
|
-
|
|
3
|
-
describe OmniAuth::Strategies::CAS::ServiceTicketValidator do
|
|
4
|
-
let(:strategy) do
|
|
5
|
-
double('strategy',
|
|
6
|
-
service_validate_url: 'https://example.org/serviceValidate'
|
|
7
|
-
)
|
|
8
|
-
end
|
|
9
|
-
let(:provider_options) do
|
|
10
|
-
double('provider_options',
|
|
11
|
-
disable_ssl_verification?: false,
|
|
12
|
-
ca_path: '/etc/ssl/certsZOMG'
|
|
13
|
-
)
|
|
14
|
-
end
|
|
15
|
-
let(:validator) do
|
|
16
|
-
OmniAuth::Strategies::CAS::ServiceTicketValidator.new( strategy, provider_options, '/foo', nil )
|
|
17
|
-
end
|
|
18
|
-
|
|
19
|
-
describe '#call' do
|
|
20
|
-
before do
|
|
21
|
-
stub_request(:get, 'https://example.org/serviceValidate?')
|
|
22
|
-
.to_return(status: 200, body: '')
|
|
23
|
-
end
|
|
24
|
-
|
|
25
|
-
subject { validator.call }
|
|
26
|
-
|
|
27
|
-
it 'returns itself' do
|
|
28
|
-
expect(subject).to eq validator
|
|
29
|
-
end
|
|
30
|
-
|
|
31
|
-
it 'uses the configured CA path' do
|
|
32
|
-
subject
|
|
33
|
-
expect(provider_options).to have_received :ca_path
|
|
34
|
-
end
|
|
35
|
-
end
|
|
36
|
-
|
|
37
|
-
describe '#user_info' do
|
|
38
|
-
let(:ok_fixture) do
|
|
39
|
-
File.expand_path(File.join(File.dirname(__FILE__), '../../../fixtures/cas_success.xml'))
|
|
40
|
-
end
|
|
41
|
-
let(:service_response) { File.read(ok_fixture) }
|
|
42
|
-
|
|
43
|
-
before do
|
|
44
|
-
stub_request(:get, 'https://example.org/serviceValidate?')
|
|
45
|
-
.to_return(status: 200, body:service_response)
|
|
46
|
-
validator.call
|
|
47
|
-
end
|
|
48
|
-
|
|
49
|
-
subject { validator.user_info }
|
|
50
|
-
|
|
51
|
-
it 'parses user info from the response' do
|
|
52
|
-
expect(subject).to include 'user' => 'psegel'
|
|
53
|
-
end
|
|
54
|
-
end
|
|
55
|
-
end
|
|
@@ -1,250 +0,0 @@
|
|
|
1
|
-
require 'spec_helper'
|
|
2
|
-
|
|
3
|
-
describe OmniAuth::Strategies::CAS, type: :strategy do
|
|
4
|
-
include Rack::Test::Methods
|
|
5
|
-
|
|
6
|
-
let(:my_cas_provider) { Class.new(OmniAuth::Strategies::CAS) }
|
|
7
|
-
before do
|
|
8
|
-
stub_const 'MyCasProvider', my_cas_provider
|
|
9
|
-
end
|
|
10
|
-
let(:app) do
|
|
11
|
-
Rack::Builder.new {
|
|
12
|
-
use OmniAuth::Test::PhonySession
|
|
13
|
-
use MyCasProvider, name: :cas, host: 'cas.example.org', ssl: false, port: 8080, uid_field: :employeeid
|
|
14
|
-
run lambda { |env| [404, {'Content-Type' => 'text/plain'}, [env.key?('omniauth.auth').to_s]] }
|
|
15
|
-
}.to_app
|
|
16
|
-
end
|
|
17
|
-
|
|
18
|
-
# TODO: Verify that these are even useful tests
|
|
19
|
-
shared_examples_for 'a CAS redirect response' do
|
|
20
|
-
let(:redirect_params) { 'service=' + Rack::Utils.escape("http://example.org/auth/cas/callback?url=#{Rack::Utils.escape(return_url)}") }
|
|
21
|
-
|
|
22
|
-
before { get url, nil, request_env }
|
|
23
|
-
|
|
24
|
-
subject { last_response }
|
|
25
|
-
|
|
26
|
-
it { should be_redirect }
|
|
27
|
-
|
|
28
|
-
it 'redirects to the CAS server' do
|
|
29
|
-
expect(subject.headers).to include 'Location' => "http://cas.example.org:8080/login?#{redirect_params}"
|
|
30
|
-
end
|
|
31
|
-
end
|
|
32
|
-
|
|
33
|
-
describe '#cas_url' do
|
|
34
|
-
let(:params) { Hash.new }
|
|
35
|
-
let(:provider) { MyCasProvider.new(nil, params) }
|
|
36
|
-
|
|
37
|
-
subject { provider.cas_url }
|
|
38
|
-
|
|
39
|
-
it 'raises an ArgumentError' do
|
|
40
|
-
expect{subject}.to raise_error ArgumentError, %r{:host and :login_url MUST be provided}
|
|
41
|
-
end
|
|
42
|
-
|
|
43
|
-
context 'with an explicit :url option' do
|
|
44
|
-
let(:url) { 'https://example.org:8080/my_cas' }
|
|
45
|
-
let(:params) { super().merge url:url }
|
|
46
|
-
|
|
47
|
-
before { subject }
|
|
48
|
-
|
|
49
|
-
it { should eq url }
|
|
50
|
-
|
|
51
|
-
it 'parses the URL into it the appropriate strategy options' do
|
|
52
|
-
expect(provider.options).to include ssl:true
|
|
53
|
-
expect(provider.options).to include host:'example.org'
|
|
54
|
-
expect(provider.options).to include port:8080
|
|
55
|
-
expect(provider.options).to include path:'/my_cas'
|
|
56
|
-
end
|
|
57
|
-
end
|
|
58
|
-
|
|
59
|
-
context 'with explicit URL component' do
|
|
60
|
-
let(:params) { super().merge host:'example.org', port:1234, ssl:true, path:'/a/path' }
|
|
61
|
-
|
|
62
|
-
before { subject }
|
|
63
|
-
|
|
64
|
-
it { should eq 'https://example.org:1234/a/path' }
|
|
65
|
-
|
|
66
|
-
it 'parses the URL into it the appropriate strategy options' do
|
|
67
|
-
expect(provider.options).to include ssl:true
|
|
68
|
-
expect(provider.options).to include host:'example.org'
|
|
69
|
-
expect(provider.options).to include port:1234
|
|
70
|
-
expect(provider.options).to include path:'/a/path'
|
|
71
|
-
end
|
|
72
|
-
end
|
|
73
|
-
end
|
|
74
|
-
|
|
75
|
-
describe 'defaults' do
|
|
76
|
-
subject { MyCasProvider.default_options.to_hash }
|
|
77
|
-
|
|
78
|
-
it { should include('ssl' => true) }
|
|
79
|
-
end
|
|
80
|
-
|
|
81
|
-
describe 'GET /auth/cas' do
|
|
82
|
-
let(:return_url) { 'http://myapp.com/admin/foo' }
|
|
83
|
-
|
|
84
|
-
context 'with a referer' do
|
|
85
|
-
let(:url) { '/auth/cas' }
|
|
86
|
-
|
|
87
|
-
let(:request_env) { { 'HTTP_REFERER' => return_url } }
|
|
88
|
-
|
|
89
|
-
it_behaves_like 'a CAS redirect response'
|
|
90
|
-
end
|
|
91
|
-
|
|
92
|
-
context 'with an explicit return URL' do
|
|
93
|
-
let(:url) { "/auth/cas?url=#{return_url}" }
|
|
94
|
-
|
|
95
|
-
let(:request_env) { {} }
|
|
96
|
-
|
|
97
|
-
it_behaves_like 'a CAS redirect response'
|
|
98
|
-
end
|
|
99
|
-
end
|
|
100
|
-
|
|
101
|
-
describe 'GET /auth/cas/callback' do
|
|
102
|
-
context 'without a ticket' do
|
|
103
|
-
before { get '/auth/cas/callback' }
|
|
104
|
-
|
|
105
|
-
subject { last_response }
|
|
106
|
-
|
|
107
|
-
it { should be_redirect }
|
|
108
|
-
|
|
109
|
-
it 'redirects with a failure message' do
|
|
110
|
-
expect(subject.headers).to include 'Location' => '/auth/failure?message=no_ticket&strategy=cas'
|
|
111
|
-
end
|
|
112
|
-
end
|
|
113
|
-
|
|
114
|
-
context 'with an invalid ticket' do
|
|
115
|
-
before do
|
|
116
|
-
stub_request(:get, /^http:\/\/cas.example.org:8080?\/serviceValidate\?([^&]+&)?ticket=9391d/).
|
|
117
|
-
to_return( body: File.read('spec/fixtures/cas_failure.xml') )
|
|
118
|
-
get '/auth/cas/callback?ticket=9391d'
|
|
119
|
-
end
|
|
120
|
-
|
|
121
|
-
subject { last_response }
|
|
122
|
-
|
|
123
|
-
it { should be_redirect }
|
|
124
|
-
|
|
125
|
-
it 'redirects with a failure message' do
|
|
126
|
-
expect(subject.headers).to include 'Location' => '/auth/failure?message=invalid_ticket&strategy=cas'
|
|
127
|
-
end
|
|
128
|
-
end
|
|
129
|
-
|
|
130
|
-
describe 'with a valid ticket' do
|
|
131
|
-
shared_examples :successful_validation do
|
|
132
|
-
before do
|
|
133
|
-
stub_request(:get, /^http:\/\/cas.example.org:8080?\/serviceValidate\?([^&]+&)?ticket=593af/)
|
|
134
|
-
.with { |request| @request_uri = request.uri.to_s }
|
|
135
|
-
.to_return( body: File.read("spec/fixtures/#{xml_file_name}") )
|
|
136
|
-
|
|
137
|
-
get "/auth/cas/callback?ticket=593af&url=#{return_url}"
|
|
138
|
-
end
|
|
139
|
-
|
|
140
|
-
it 'strips the ticket parameter from the callback URL' do
|
|
141
|
-
expect(@request_uri.scan('ticket=').size).to eq 1
|
|
142
|
-
end
|
|
143
|
-
|
|
144
|
-
it 'properly encodes the service URL' do
|
|
145
|
-
expect(WebMock).to have_requested(:get, 'http://cas.example.org:8080/serviceValidate')
|
|
146
|
-
.with(query: {
|
|
147
|
-
ticket: '593af',
|
|
148
|
-
service: 'http://example.org/auth/cas/callback?url=' + Rack::Utils.escape('http://127.0.0.10/?some=parameter')
|
|
149
|
-
})
|
|
150
|
-
end
|
|
151
|
-
|
|
152
|
-
context "request.env['omniauth.auth']" do
|
|
153
|
-
subject { last_request.env['omniauth.auth'] }
|
|
154
|
-
|
|
155
|
-
it { should be_kind_of Hash }
|
|
156
|
-
|
|
157
|
-
it 'identifes the provider' do
|
|
158
|
-
expect(subject.provider).to eq :cas
|
|
159
|
-
end
|
|
160
|
-
|
|
161
|
-
it 'returns the UID of the user' do
|
|
162
|
-
expect(subject.uid).to eq '54'
|
|
163
|
-
end
|
|
164
|
-
|
|
165
|
-
context 'the info hash' do
|
|
166
|
-
subject { last_request.env['omniauth.auth']['info'] }
|
|
167
|
-
|
|
168
|
-
it 'includes user info attributes' do
|
|
169
|
-
expect(subject.name).to eq 'Peter Segel'
|
|
170
|
-
expect(subject.first_name).to eq 'Peter'
|
|
171
|
-
expect(subject.last_name).to eq 'Segel'
|
|
172
|
-
expect(subject.nickname).to eq 'psegel'
|
|
173
|
-
expect(subject.email).to eq 'psegel@intridea.com'
|
|
174
|
-
expect(subject.location).to eq 'Washington, D.C.'
|
|
175
|
-
expect(subject.image).to eq '/images/user.jpg'
|
|
176
|
-
expect(subject.phone).to eq '555-555-5555'
|
|
177
|
-
end
|
|
178
|
-
end
|
|
179
|
-
|
|
180
|
-
context 'the extra hash' do
|
|
181
|
-
subject { last_request.env['omniauth.auth']['extra'] }
|
|
182
|
-
|
|
183
|
-
it 'includes additional user attributes' do
|
|
184
|
-
expect(subject.user).to eq 'psegel'
|
|
185
|
-
expect(subject.employeeid).to eq '54'
|
|
186
|
-
expect(subject.hire_date).to eq '2004-07-13'
|
|
187
|
-
end
|
|
188
|
-
end
|
|
189
|
-
|
|
190
|
-
context 'the credentials hash' do
|
|
191
|
-
subject { last_request.env['omniauth.auth']['credentials'] }
|
|
192
|
-
|
|
193
|
-
it 'has a ticket value' do
|
|
194
|
-
expect(subject.ticket).to eq '593af'
|
|
195
|
-
end
|
|
196
|
-
end
|
|
197
|
-
end
|
|
198
|
-
|
|
199
|
-
it 'calls through to the master app' do
|
|
200
|
-
expect(last_response.body).to eq 'true'
|
|
201
|
-
end
|
|
202
|
-
end
|
|
203
|
-
|
|
204
|
-
let(:return_url) { 'http://127.0.0.10/?some=parameter' }
|
|
205
|
-
|
|
206
|
-
context 'with JASIG flavored XML' do
|
|
207
|
-
let(:xml_file_name) { 'cas_success_jasig.xml' }
|
|
208
|
-
|
|
209
|
-
it_behaves_like :successful_validation
|
|
210
|
-
end
|
|
211
|
-
|
|
212
|
-
context 'with classic XML' do
|
|
213
|
-
let(:xml_file_name) { 'cas_success.xml' }
|
|
214
|
-
|
|
215
|
-
it_behaves_like :successful_validation
|
|
216
|
-
end
|
|
217
|
-
end
|
|
218
|
-
end
|
|
219
|
-
|
|
220
|
-
describe 'POST /auth/cas/callback' do
|
|
221
|
-
describe 'with a Single Sign-Out logoutRequest' do
|
|
222
|
-
let(:logoutRequest) do
|
|
223
|
-
%Q[
|
|
224
|
-
<samlp:LogoutRequest xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol" xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion\" ID="123abc-1234-ab12-cd34-1234abcd" Version="2.0" IssueInstant="#{Time.now.to_s}">
|
|
225
|
-
<saml:NameID>@NOT_USED@</saml:NameID>
|
|
226
|
-
<samlp:SessionIndex>ST-123456-123abc456def</samlp:SessionIndex>
|
|
227
|
-
</samlp:LogoutRequest>
|
|
228
|
-
]
|
|
229
|
-
end
|
|
230
|
-
|
|
231
|
-
let(:logout_request) { double('logout_request', call:[200,{},'OK']) }
|
|
232
|
-
|
|
233
|
-
subject do
|
|
234
|
-
post 'auth/cas/callback', logoutRequest:logoutRequest
|
|
235
|
-
end
|
|
236
|
-
|
|
237
|
-
before do
|
|
238
|
-
allow_any_instance_of(MyCasProvider)
|
|
239
|
-
.to receive(:logout_request_service)
|
|
240
|
-
.and_return double('LogoutRequest', new:logout_request)
|
|
241
|
-
|
|
242
|
-
subject
|
|
243
|
-
end
|
|
244
|
-
|
|
245
|
-
it 'initializes a LogoutRequest' do
|
|
246
|
-
expect(logout_request).to have_received :call
|
|
247
|
-
end
|
|
248
|
-
end
|
|
249
|
-
end
|
|
250
|
-
end
|
data/spec/spec_helper.rb
DELETED
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
require 'bundler/setup'
|
|
2
|
-
require 'awesome_print'
|
|
3
|
-
|
|
4
|
-
RSpec.configure do |c|
|
|
5
|
-
c.filter_run focus: true
|
|
6
|
-
c.run_all_when_everything_filtered = true
|
|
7
|
-
end
|
|
8
|
-
|
|
9
|
-
require 'rack/test'
|
|
10
|
-
require 'webmock/rspec'
|
|
11
|
-
require 'omniauth-cas'
|
|
12
|
-
|
|
13
|
-
OmniAuth.config.logger = Logger.new( '/dev/null' )
|