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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: 09cce5081c4f84323fdc73cc34324fd597d78424
4
- data.tar.gz: 9a70b93dee51a38340bd07630f83179992f254b1
2
+ SHA256:
3
+ metadata.gz: 2600fefe7682305731ccd7117312c394c148c9d3d2812da453ebbb3a3c0a294a
4
+ data.tar.gz: 96b0f898f502ff223c5b3430ad308daec92914152a8ffead39e09d597f1cac02
5
5
  SHA512:
6
- metadata.gz: 436b7b6a87016de8dd0b4c0e8d89697a5570f17d88662bd73b1ee407f9edb3cf8b058d523c1863e5ecaef9aba9ebaf3c52457005119a547398f7fb761f4949a0
7
- data.tar.gz: d2e434a790244adbe2c83fdfc9900785acbf48f3f9592911a580ce3fefa35eca3e8561906898c4c134895fbcd6614ce2f019ecada702cf56d9a1a453ef9b8457
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](http://keepachangelog.com/) and this
6
- project adheres to [Semantic Versioning](http://semver.org/)
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][travis_status]][travis]
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.png
4
- [version]: http://badge.fury.io/rb/omniauth-cas
5
- [travis]: http://travis-ci.org/dlindahl/omniauth-cas
6
- [travis_status]: https://secure.travis-ci.org/dlindahl/omniauth-cas.png
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.0 compatible port of the previously available
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. `http://example.org:8080`)
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
- fetch_raw_info: lambda { |strategy, options, ticket, user_info|
69
- ExternalService.get(user_info[:user]).attributes
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
- service_validate_url: '/cas/serviceValidate'
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]: http://dlindahl.github.com/omniauth-cas/
122
- [net_http]: http://ruby-doc.org/stdlib-1.9.3/libdoc/net/http/rdoc/Net/HTTP.html
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
@@ -1,5 +1,7 @@
1
- module Omniauth
1
+ # frozen_string_literal: true
2
+
3
+ module OmniAuth
2
4
  module Cas
3
- VERSION = '1.1.1'
5
+ VERSION = '3.0.0.beta.1'
4
6
  end
5
7
  end
data/lib/omniauth/cas.rb CHANGED
@@ -1,2 +1,4 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'omniauth/cas/version'
2
- require 'omniauth/strategies/cas'
4
+ require 'omniauth/strategies/cas'
@@ -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, @request = strategy, request
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 => err
15
- return @strategy.fail! :logout_request, err
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
- private
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
- private
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.kind_of?(Nokogiri::XML::Text) || node_name == 'proxies'
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
- alias_method :user_info, :raw_info
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, Proc.new {}
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, Proc.new { Hash.new }
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
- AuthHashSchemaKeys = %w{name email nickname first_name last_name location image phone}
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
- name: raw_info[options[:name_key].to_s],
54
- email: raw_info[options[:email_key].to_s],
55
- nickname: raw_info[options[:nickname_key].to_s],
56
- first_name: raw_info[options[:first_name_key].to_s],
57
- last_name: raw_info[options[:last_name_key].to_s],
58
- location: raw_info[options[:location_key].to_s],
59
- image: raw_info[options[:image_key].to_s],
60
- phone: raw_info[options[:phone_key].to_s]
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
- prune!(
66
- raw_info.delete_if{ |k,v| AuthHashSchemaKeys.include?(k) }
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
- ["You are being redirected to CAS for sign-in."]
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.has_key?('logoutRequest')
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
- if options.host.nil? || options.login_url.nil?
139
- raise ArgumentError.new(":host and :login_url MUST be provided")
140
- end
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
- service: service_url.to_s,
157
- ticket: ticket
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.each { |k,v| v = Rack::Utils.escape(v) }
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
- private
196
+ private
190
197
 
191
198
  def fetch_raw_info(ticket)
192
- ticket_user_info = validate_service_ticket(ticket).user_info
193
- custom_user_info = options.fetch_raw_info.call(self, options, ticket, ticket_user_info)
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
@@ -1 +1,3 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'omniauth/cas'
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: 1.1.1
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: 2016-09-26 00:00:00.000000000 Z
11
+ date: 2024-01-12 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
- name: omniauth
14
+ name: addressable
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
17
  - - "~>"
18
18
  - !ruby/object:Gem::Version
19
- version: '1.2'
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: '1.2'
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.5'
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.5'
40
+ version: '1.12'
41
41
  - !ruby/object:Gem::Dependency
42
- name: addressable
42
+ name: omniauth
43
43
  requirement: !ruby/object:Gem::Requirement
44
44
  requirements:
45
45
  - - "~>"
46
46
  - !ruby/object:Gem::Version
47
- version: '2.3'
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.3'
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
- post_install_message:
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
- rubyforge_project:
174
- rubygems_version: 2.2.2
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
@@ -1,21 +0,0 @@
1
- *.gem
2
- *.rbc
3
- .bundle
4
- .config
5
- .yardoc
6
- Gemfile.lock
7
- InstalledFiles
8
- _yardoc
9
- coverage
10
- doc/
11
- lib/bundler/man
12
- pkg
13
- rdoc
14
- spec/reports
15
- test/tmp
16
- test/version_tmp
17
- tmp
18
- vendor
19
-
20
- # RSpec
21
- .rspec
data/.ruby-version DELETED
@@ -1 +0,0 @@
1
- 2.1.2
data/.travis.yml DELETED
@@ -1,9 +0,0 @@
1
- rvm:
2
- - 2.1
3
- - 2.2
4
- - 2.3.1
5
- branches:
6
- only:
7
- - master
8
- before_install:
9
- - gem install bundler
data/Gemfile DELETED
@@ -1,9 +0,0 @@
1
- source 'https://rubygems.org'
2
-
3
- # Specify your gem's dependencies in omniauth-cas.gemspec
4
- gemspec
5
-
6
- if RUBY_VERSION < "2.2.2"
7
- # Rack 2 needs Ruby 2.2.2+
8
- gem 'rack', '< 2'
9
- end
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,4 +0,0 @@
1
- <cas:serviceResponse xmlns:cas='http://www.yale.edu/tp/cas'>
2
- <cas:authenticationFailure>
3
- </cas:authenticationFailure>
4
- </cas:serviceResponse>
@@ -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' )