omniauth-cas 1.1.1 → 3.0.0.beta.1

Sign up to get free protection for your applications and to get access to all the features.
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' )