omniauth-cas 1.0.4 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,15 +1,7 @@
1
1
  ---
2
- !binary "U0hBMQ==":
3
- metadata.gz: !binary |-
4
- OTU0MmMyOWM1MWY0YzBiNjMzZDRkZmE4NTljYTA4NTc3M2NmM2FiYg==
5
- data.tar.gz: !binary |-
6
- YjM4MmU1MTAwNThmNjJkNWU2OTJiZjJiMTc5ZDNlYjM0ZDQ2M2E3ZQ==
7
- !binary "U0hBNTEy":
8
- metadata.gz: !binary |-
9
- ZTdkZjEzMDY4ODVjMzY1NDQ2MmUxZTAyMzRkMGUwNzcxYzAyOGM5MzBlNDZi
10
- ZjU1OTk0OWU1ODIzNTIwYTIxNWM5ZDEzNzFiY2UyODJhYzY3NDRkZmM5ODcy
11
- NTBlMGM5YWFhZWU1MDBlMTI2YWQ0NTRmODRkZjhiYmVmMjc2ZDI=
12
- data.tar.gz: !binary |-
13
- OTY0NjU1NTFhZGZmNjdlN2E2OTY5MjNkMTU0NDY5NWQ1ZjQ3N2RiZWFjNmZj
14
- MDA3MmY4M2U1MjMwOThkZmRhNzYwZDI5NzljYjRiYzk5YjY5MWFlNjBjYjY0
15
- NzBhNjE1OWViZjMzMGVmYzkzMWM5MTk5MGNmNjk1MTU3YjYxYWU=
2
+ SHA256:
3
+ metadata.gz: 20d02177b4bdbd637993a8d225133ada4d6d40092b59db98e54b38bbe8aef780
4
+ data.tar.gz: 9143ccd826882b5f1228b7686958cfa62c9527ab1fef041d6ce1bfb39e7e0f6d
5
+ SHA512:
6
+ metadata.gz: a9edd4d3c46a7c7349a0ebf05a67747cb25cfda51fc2c4ebfbc054726e4e8b7034f969291f5f184d609999250507bdfe1da01f659cb43682b837d4fa44292271
7
+ data.tar.gz: e64e3311e11537b2abc77d25189ef38eebdcbb147eb6db53deb7562530371f40851e035eae08370f3621843873c36c47e9690d1e5f2a0678b31ea8dd87f79bca
@@ -0,0 +1,16 @@
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
@@ -1,8 +1,21 @@
1
+ dist: xenial
2
+ os: linux
3
+ language: ruby
1
4
  rvm:
2
- - 1.9.2
3
- - 1.9.3
5
+ - 2.1
6
+ - 2.2
7
+ - 2.3
8
+ - 2.4
9
+ - 2.5
10
+ - 2.6
11
+ - 2.7
12
+ - ruby-edge
4
13
  branches:
5
14
  only:
6
15
  - master
7
16
  before_install:
8
- - gem install bundler
17
+ - gem uninstall -v '>= 2' -i $(rvm gemdir)@global -ax bundler || true
18
+ - gem install bundler -v '< 2'
19
+ jobs:
20
+ allow_failures:
21
+ - rvm: ruby-edge
@@ -0,0 +1,27 @@
1
+ # Change Log
2
+
3
+ All notable changes to this project will be documented in this file.
4
+
5
+ The format is based on [Keep a Changelog](http://keepachangelog.com/) and this
6
+ project adheres to [Semantic Versioning](http://semver.org/)
7
+
8
+ ## 2.0.0 - 2010-11-14
9
+
10
+ ### Added
11
+
12
+ * Add support for multivalued attributes ([#59](https://github.com/dlindahl/omniauth-cas/pull/59))
13
+ * Successfully test against Ruby 2.4 and up ([#60](https://github.com/dlindahl/omniauth-cas/pull/60))
14
+
15
+ ### Changed
16
+
17
+ * Forward success response to `fetch_raw_info` callback ([#51](https://github.com/dlindahl/omniauth-cas/pull/51))
18
+ * Relax development dependencies to the latest versions
19
+
20
+ ## 1.1.1 - 2016-09-19
21
+
22
+ ### Changed
23
+
24
+ * Relax gemspec requirements, to add support for Rails 5.
25
+
26
+ Note that the only tested versions of Ruby are now 2.1, 2.2, and 2.3 - older
27
+ versions of Ruby should work, but are no longer officially supported.
data/Gemfile CHANGED
@@ -2,3 +2,8 @@ source 'https://rubygems.org'
2
2
 
3
3
  # Specify your gem's dependencies in omniauth-cas.gemspec
4
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/README.md CHANGED
@@ -1,14 +1,16 @@
1
1
  # OmniAuth CAS Strategy [![Gem Version][version_badge]][version] [![Build Status][travis_status]][travis]
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
+ [travis]: https://travis-ci.org/dlindahl/omniauth-cas
6
+ [travis_status]: https://secure.travis-ci.org/dlindahl/omniauth-cas.svg
7
+ [releases]: https://github.com/dlindahl/omniauth-cas/releases
7
8
 
8
9
  This is a OmniAuth 1.0 compatible port of the previously available
9
10
  [OmniAuth CAS strategy][old_omniauth_cas] that was bundled with OmniAuth 0.3.
10
11
 
11
- [View the documentation][document_up]
12
+ * [View the documentation][document_up]
13
+ * [Changelog][releases]
12
14
 
13
15
  ## Installation
14
16
 
@@ -41,21 +43,49 @@ end
41
43
  OmniAuth CAS requires at least one of the following two configuration options:
42
44
 
43
45
  * `url` - Defines the URL of your CAS server (i.e. `http://example.org:8080`)
44
- * `host` - Defines the host of your CAS server. Optional if using `url`
45
- * `login_url` - Defines the URL used to prompt users for their login information. Defaults to `/login`
46
- If no `host` is configured, the host application's domain will be used.
46
+ * `host` - Defines the host of your CAS server (i.e. `example.org`).
47
47
 
48
48
  #### Optional
49
49
 
50
50
  Other configuration options:
51
51
 
52
- * `port` - The port to use for your configured CAS `host`. Optional if using `url`
53
- * `ssl` - TRUE to connect to your CAS server over SSL. Optional if using `url`
54
- * `service_validate_url` - The URL to use to validate a user. Defaults to `'/serviceValidate'`
55
- * `logout_url` - The URL to use to logout a user. Defaults to `'/logout'`
56
- * `uid_key` - The user data attribute to use as your user's unique identifier. Defaults to `'user'` (which usually contains the user's login name)
57
- * `ca_path` - Optional when `ssl` is `true`. Sets path of a CA certification directory. See [Net::HTTP][net_http] for more details
52
+ * `port` - The port to use for your configured CAS `host`. Optional if using `url`.
53
+ * `ssl` - TRUE to connect to your CAS server over SSL. Optional if using `url`.
54
+ * `service_validate_url` - The URL to use to validate a user. Defaults to `'/serviceValidate'`.
55
+ * `callback_url` - The URL custom URL path which CAS uses to call back to the service. Defaults to `/users/auth/cas/callback`.
56
+ * `logout_url` - The URL to use to logout a user. Defaults to `'/logout'`.
57
+ * `login_url` - Defines the URL used to prompt users for their login information. Defaults to `/login` If no `host` is configured, the host application's domain will be used.
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
+ * `ca_path` - Optional when `ssl` is `true`. Sets path of a CA certification directory. See [Net::HTTP][net_http] for more details.
58
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.
62
+ * `on_single_sign_out` - Optional. Callback used when a [CAS 3.1 Single Sign Out][sso]
63
+ request is received.
64
+ * `fetch_raw_info` - Optional. Callback used to return additional "raw" user
65
+ info from other sources.
66
+
67
+ ```ruby
68
+ provider :cas,
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
+ }
76
+ ```
77
+
78
+ Configurable options for values returned by CAS:
79
+
80
+ * `uid_key` - The user ID data attribute to use as your user's unique identifier. Defaults to `'user'` (which usually contains the user's login name).
81
+ * `name_key` - The data attribute containing user first and last name. Defaults to `'name'`.
82
+ * `email_key` - The data attribute containing user email address. Defaults to `'email'`.
83
+ * `nickname_key` - The data attribute containing user's nickname. Defaults to `'user'`.
84
+ * `first_name_key` - The data attribute containing user first name. Defaults to `'first_name'`.
85
+ * `last_name_key` - The data attribute containing user last name. Defaults to `'last_name'`.
86
+ * `location_key` - The data attribute containing user location/address. Defaults to `'location'`.
87
+ * `image_key` - The data attribute containing user image/picture. Defaults to `'image'`.
88
+ * `phone_key` - The data attribute containing user contact phone number. Defaults to `'phone'`.
59
89
 
60
90
  ## Migrating from OmniAuth 0.3
61
91
 
@@ -93,5 +123,6 @@ Special thanks go out to the following people
93
123
  * @rbq for README updates and OmniAuth 0.3 migration guide
94
124
 
95
125
  [old_omniauth_cas]: https://github.com/intridea/omniauth/blob/0-3-stable/oa-enterprise/lib/omniauth/strategies/cas.rb
96
- [document_up]: http://dlindahl.github.com/omniauth-cas/
97
- [net_http]: http://ruby-doc.org/stdlib-1.9.3/libdoc/net/http/rdoc/Net/HTTP.html
126
+ [document_up]: https://dlindahl.github.io/omniauth-cas/
127
+ [net_http]: https://ruby-doc.org/stdlib-1.9.3/libdoc/net/http/rdoc/Net/HTTP.html
128
+ [sso]: https://wiki.jasig.org/display/CASUM/Single+Sign+Out
@@ -1 +1 @@
1
- require "omniauth/cas"
1
+ require 'omniauth/cas'
@@ -1,5 +1,5 @@
1
1
  module Omniauth
2
2
  module Cas
3
- VERSION = '1.0.4'
3
+ VERSION = '2.0.0'
4
4
  end
5
5
  end
@@ -1,4 +1,4 @@
1
- require 'omniauth/strategy'
1
+ require 'omniauth'
2
2
  require 'addressable/uri'
3
3
 
4
4
  module OmniAuth
@@ -10,8 +10,8 @@ module OmniAuth
10
10
  class MissingCASTicket < StandardError; end
11
11
  class InvalidCASTicket < StandardError; end
12
12
 
13
- autoload :Configuration, 'omniauth/strategies/cas/configuration'
14
13
  autoload :ServiceTicketValidator, 'omniauth/strategies/cas/service_ticket_validator'
14
+ autoload :LogoutRequest, 'omniauth/strategies/cas/logout_request'
15
15
 
16
16
  attr_accessor :raw_info
17
17
  alias_method :user_info, :raw_info
@@ -22,84 +22,125 @@ module OmniAuth
22
22
  option :port, nil
23
23
  option :path, nil
24
24
  option :ssl, true
25
+ option :merge_multivalued_attributes, false
25
26
  option :service_validate_url, '/serviceValidate'
26
27
  option :login_url, '/login'
27
28
  option :logout_url, '/logout'
28
- option :uid_key, 'user'
29
+ option :on_single_sign_out, Proc.new {}
30
+ # A Proc or lambda that returns a Hash of additional user info to be
31
+ # merged with the info returned by the CAS server.
32
+ #
33
+ # @param [Object] An instance of OmniAuth::Strategies::CAS for the current request
34
+ # @param [String] The user's Service Ticket value
35
+ # @param [Hash] The user info for the Service Ticket returned by the CAS server
36
+ #
37
+ # @return [Hash] Extra user info
38
+ option :fetch_raw_info, Proc.new { Hash.new }
39
+ # Make all the keys configurable with some defaults set here
40
+ option :uid_field, 'user'
41
+ option :name_key, 'name'
42
+ option :email_key, 'email'
43
+ option :nickname_key, 'user'
44
+ option :first_name_key, 'first_name'
45
+ option :last_name_key, 'last_name'
46
+ option :location_key, 'location'
47
+ option :image_key, 'image'
48
+ option :phone_key, 'phone'
29
49
 
30
50
  # As required by https://github.com/intridea/omniauth/wiki/Auth-Hash-Schema
31
- AuthHashSchemaKeys = %w{name email first_name last_name location image phone}
51
+ AuthHashSchemaKeys = %w{name email nickname first_name last_name location image phone}
32
52
  info do
33
53
  prune!({
34
- :name => raw_info['name'],
35
- :email => raw_info['email'],
36
- :first_name => raw_info['first_name'],
37
- :last_name => raw_info['last_name'],
38
- :location => raw_info['location'],
39
- :image => raw_info['image'],
40
- :phone => raw_info['phone']
54
+ name: raw_info[options[:name_key].to_s],
55
+ email: raw_info[options[:email_key].to_s],
56
+ nickname: raw_info[options[:nickname_key].to_s],
57
+ first_name: raw_info[options[:first_name_key].to_s],
58
+ last_name: raw_info[options[:last_name_key].to_s],
59
+ location: raw_info[options[:location_key].to_s],
60
+ image: raw_info[options[:image_key].to_s],
61
+ phone: raw_info[options[:phone_key].to_s]
41
62
  })
42
63
  end
43
64
 
44
65
  extra do
45
- prune! raw_info.delete_if{ |k,v| AuthHashSchemaKeys.include?(k) }
66
+ prune!(
67
+ raw_info.delete_if{ |k,v| AuthHashSchemaKeys.include?(k) }
68
+ )
46
69
  end
47
70
 
48
71
  uid do
49
- raw_info[ @options[:uid_key].to_s ]
72
+ raw_info[options[:uid_field].to_s]
50
73
  end
51
74
 
52
75
  credentials do
53
- prune!({
54
- :ticket => @ticket
55
- })
56
- end
57
-
58
- def initialize( app, *args, &block )
59
- super
60
- @configuration = Configuration.new( @options )
76
+ prune!({ ticket: @ticket })
61
77
  end
62
78
 
63
79
  def callback_phase
64
- @ticket = request.params['ticket']
65
-
66
- return fail!(:no_ticket, MissingCASTicket.new('No CAS Ticket')) unless @ticket
67
-
68
- self.raw_info = ServiceTicketValidator.new(self, @options, callback_url, @ticket).user_info
69
-
70
- return fail!(:invalid_ticket, InvalidCASTicket.new('Invalid CAS Ticket')) if raw_info.empty?
71
-
72
- super
80
+ if on_sso_path?
81
+ single_sign_out_phase
82
+ else
83
+ @ticket = request.params['ticket']
84
+ return fail!(:no_ticket, MissingCASTicket.new('No CAS Ticket')) unless @ticket
85
+ fetch_raw_info(@ticket)
86
+ return fail!(:invalid_ticket, InvalidCASTicket.new('Invalid CAS Ticket')) if raw_info.empty?
87
+ super
88
+ end
73
89
  end
74
90
 
75
91
  def request_phase
76
- service_url = append_params( callback_url, return_url )
92
+ service_url = append_params(callback_url, return_url)
77
93
 
78
94
  [
79
95
  302,
80
96
  {
81
- 'Location' => login_url( service_url ),
97
+ 'Location' => login_url(service_url),
82
98
  'Content-Type' => 'text/plain'
83
99
  },
84
100
  ["You are being redirected to CAS for sign-in."]
85
101
  ]
86
102
  end
87
103
 
104
+ def on_sso_path?
105
+ request.post? && request.params.has_key?('logoutRequest')
106
+ end
107
+
108
+ def single_sign_out_phase
109
+ logout_request_service.new(self, request).call(options)
110
+ end
111
+
88
112
  # Build a CAS host with protocol and port
89
113
  #
90
114
  #
91
115
  def cas_url
116
+ extract_url if options['url']
117
+ validate_cas_setup
92
118
  @cas_url ||= begin
93
119
  uri = Addressable::URI.new
94
- uri.host = @options.host
95
- uri.scheme = @options.ssl ? 'https' : 'http'
96
- uri.port = @options.port
97
- uri.path = @options.path
98
-
120
+ uri.host = options.host
121
+ uri.scheme = options.ssl ? 'https' : 'http'
122
+ uri.port = options.port
123
+ uri.path = options.path
99
124
  uri.to_s
100
125
  end
101
126
  end
102
127
 
128
+ def extract_url
129
+ url = Addressable::URI.parse(options.delete('url'))
130
+ options.merge!(
131
+ 'host' => url.host,
132
+ 'port' => url.port,
133
+ 'path' => url.path,
134
+ 'ssl' => url.scheme == 'https'
135
+ )
136
+ end
137
+
138
+ def validate_cas_setup
139
+ if options.host.nil? || options.login_url.nil?
140
+ raise ArgumentError.new(":host and :login_url MUST be provided")
141
+ end
142
+ end
143
+
103
144
  # Build a service-validation URL from +service+ and +ticket+.
104
145
  # If +service+ has a ticket param, first remove it. URL-encode
105
146
  # +service+ and add it and the +ticket+ as paraemters to the
@@ -110,10 +151,12 @@ module OmniAuth
110
151
  #
111
152
  # @return [String] a URL like `http://cas.mycompany.com/serviceValidate?service=...&ticket=...`
112
153
  def service_validate_url(service_url, ticket)
113
- service_url = Addressable::URI.parse( service_url )
154
+ service_url = Addressable::URI.parse(service_url)
114
155
  service_url.query_values = service_url.query_values.tap { |qs| qs.delete('ticket') }
115
-
116
- cas_url + append_params(@options.service_validate_url, { :service => service_url.to_s, :ticket => ticket })
156
+ cas_url + append_params(options.service_validate_url, {
157
+ service: service_url.to_s,
158
+ ticket: ticket
159
+ })
117
160
  end
118
161
 
119
162
  # Build a CAS login URL from +service+.
@@ -122,7 +165,7 @@ module OmniAuth
122
165
  #
123
166
  # @return [String] a URL like `http://cas.mycompany.com/login?service=...`
124
167
  def login_url(service)
125
- cas_url + append_params( @options.login_url, { :service => service })
168
+ cas_url + append_params(options.login_url, { service: service })
126
169
  end
127
170
 
128
171
  # Adds URL-escaped +parameters+ to +base+.
@@ -133,14 +176,28 @@ module OmniAuth
133
176
  # @return [String] the new joined URL.
134
177
  def append_params(base, params)
135
178
  params = params.each { |k,v| v = Rack::Utils.escape(v) }
136
-
137
179
  Addressable::URI.parse(base).tap do |base_uri|
138
- base_uri.query_values = (base_uri.query_values || {}).merge( params )
180
+ base_uri.query_values = (base_uri.query_values || {}).merge(params)
139
181
  end.to_s
140
182
  end
141
183
 
184
+ # Validate the Service Ticket
185
+ # @return [Object] the validated Service Ticket
186
+ def validate_service_ticket(ticket)
187
+ ServiceTicketValidator.new(self, options, callback_url, ticket).call
188
+ end
189
+
142
190
  private
143
191
 
192
+ def fetch_raw_info(ticket)
193
+ validator = validate_service_ticket(ticket)
194
+ ticket_user_info = validator.user_info
195
+ ticket_success_body = validator.success_body
196
+ custom_user_info = options.fetch_raw_info.call(self,
197
+ options, ticket, ticket_user_info, ticket_success_body)
198
+ self.raw_info = ticket_user_info.merge(custom_user_info)
199
+ end
200
+
144
201
  # Deletes Hash pairs with `nil` values.
145
202
  # From https://github.com/mkdynamic/omniauth-facebook/blob/972ed5e3456bcaed7df1f55efd7c05c216c8f48e/lib/omniauth/strategies/facebook.rb#L122-127
146
203
  def prune!(hash)
@@ -152,13 +209,16 @@ module OmniAuth
152
209
 
153
210
  def return_url
154
211
  # If the request already has a `url` parameter, then it will already be appended to the callback URL.
155
- if request.params and request.params['url']
212
+ if request.params && request.params['url']
156
213
  {}
157
214
  else
158
- { :url => request.referer }
215
+ { url: request.referer }
159
216
  end
160
217
  end
161
218
 
219
+ def logout_request_service
220
+ LogoutRequest
221
+ end
162
222
  end
163
223
  end
164
224
  end