omniauth-cas 1.0.4 → 2.0.0

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