omniauth-realme 0.1.0 → 0.2.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.
@@ -2,3 +2,50 @@
2
2
 
3
3
  require 'omniauth/realme/version'
4
4
  require 'omniauth/strategies/realme'
5
+
6
+ module OmniAuth
7
+ module Realme # :nodoc:
8
+ class Error < StandardError; end
9
+
10
+ ##
11
+ # Generates SAML SP metadata XML using the same settings you used to
12
+ # configure the OmniAuth strategy. This XML is suitable for uploading to
13
+ # Realme at https://mts.realme.govt.nz/logon-mts/metadataupdate
14
+ #
15
+ # @param [Hash] options - An optional Hash of options to configure the
16
+ # strategy. This is convenient for testing but is
17
+ # not required during normal operation because the
18
+ # strategy will already be configured by the Rails
19
+ # initializer.
20
+ # @return [String] SP metadata serialized as an XML string
21
+ #
22
+ def self.generate_metadata_xml(options: {})
23
+ meta = OneLogin::RubySaml::Metadata.new
24
+
25
+ # OmniAuth strategies are Rack middlewares. When an instance of a rack
26
+ # middleware is created it is given a reference to the next rack
27
+ # app/middleware in the chain. We are only interested here in getting the
28
+ # SAML settings out of the strategy. We don't hit any code paths which
29
+ # would require a real rack app/middleware so `nil` works just fine.
30
+ rack_app = nil
31
+
32
+ # The Rails initializer calls `OmniAuth::Strategies::Realme.configure`
33
+ # which merges the provided block into the default options for
34
+ # `OmniAuth::Strategies::Realme` - use
35
+ # `OmniAuth::Strategies::Realme.default_options` to inspect the current
36
+ # state of these options.
37
+ #
38
+ # This means that the `options` we pass in here will be merged into (and
39
+ # override) those default options.
40
+ #
41
+ # When this method is called by app code, we want to use the options set
42
+ # by the Rails initializer so pass an empty hash as `options`. When this
43
+ # method is called by its specs, no Rails initializer has run so we need
44
+ # to pass in some options.
45
+ #
46
+ strategy = OmniAuth::Strategies::Realme.new(rack_app, options)
47
+
48
+ meta.generate(strategy.saml_settings)
49
+ end
50
+ end
51
+ end
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- module Omniauth
3
+ module OmniAuth
4
4
  module Realme
5
- VERSION = '0.1.0'
5
+ VERSION = '0.2.0'
6
6
  end
7
7
  end
@@ -6,47 +6,268 @@ require 'ruby-saml'
6
6
  module OmniAuth
7
7
  module Strategies
8
8
  class Realme
9
+ class Error < StandardError; end
10
+ class RelayStateTooLongError < Error; end
11
+
12
+ ##
13
+ # Create an exception for each documented Realme error
14
+ # (https://developers.realme.govt.nz/how-realme-works/realme-saml-exception-handling/).
15
+ #
16
+ # All the errors we raise inherit from `OmniAuth::Strategies::Realme::Error`
17
+ # so a caller can rescue that if they want to rescue all exceptions from
18
+ # this class.
19
+ #
20
+ class RealmeAuthnFailedError < Error; end
21
+ class RealmeInternalError < Error; end
22
+ class RealmeInternalError < Error; end
23
+ class RealmeNoAvailableIDPError < Error; end
24
+ class RealmeNoPassiveError < Error; end
25
+ class RealmeRequestDeniedError < Error; end
26
+ class RealmeRequestUnsupportedError < Error; end
27
+ class RealmeTimeoutError < Error; end
28
+ class RealmeUnknownPrincipalError < Error; end
29
+ class RealmeUnrecognisedError < Error; end
30
+ class RealmeUnsupportedBindingError < Error; end
31
+
9
32
  include OmniAuth::Strategy
10
- autoload :AuthRequest, 'omniauth/strategies/realme/auth_request'
33
+
34
+ RCMS_LAT_NAME = 'urn:nzl:govt:ict:stds:authn:safeb64:logon_attributes_jwt'
35
+
36
+ # The SAML spec says the maximum length of the RelayState is 80
37
+ # bytes. See section 3.4.3 of
38
+ # http://docs.oasis-open.org/security/saml/v2.0/saml-bindings-2.0-os.pdf
39
+ MAX_LENGTH_OF_RELAY_STATE = 80 # bytes
11
40
 
12
41
  # Fixed OmniAuth options
13
42
  option :provider, 'realme'
14
43
 
15
44
  def request_phase
45
+ req_options = { 'SigAlg' => 'http://www.w3.org/2001/04/xmldsig-more#rsa-sha256' }
46
+
47
+ ##
48
+ # If we recieved a `relay_state` param e.g. we were invoked like:
49
+ #
50
+ # redirect_to user_realme_omniauth_authorize_path(relay_state: 'some_value')
51
+ #
52
+ # then we pass it to Realme (via RubySaml). Realme (as a SAML IdP)
53
+ # should return that value unaltered when it redirects back to this
54
+ # application and `#callback_phase` below is executed.
55
+ #
56
+ if request.params['relay_state']
57
+ if request.params['relay_state'].length > MAX_LENGTH_OF_RELAY_STATE
58
+ ex = RelayStateTooLongError.new('RelayState exceeds SAML spec max length of 80 bytes')
59
+
60
+ # fail!() returns a rack response which this callback must also
61
+ # return if OmniAuth error handling is to work correctly.
62
+ return fail!(create_label_for(ex), ex)
63
+ end
64
+
65
+ req_options['RelayState'] = request.params['relay_state']
66
+ end
67
+
16
68
  req = OneLogin::RubySaml::Authrequest.new
17
- redirect req.create(saml_settings, 'SigAlg' => 'http://www.w3.org/2001/04/xmldsig-more#rsa-sha256')
69
+ redirect req.create(saml_settings, req_options)
18
70
  end
19
71
 
20
- def callback_phase
21
- response = ::OneLogin::RubySaml::Response.new(request.params['SAMLResponse'], settings: saml_settings)
72
+ def callback_phase # rubocop:disable Metrics/PerceivedComplexity, Metrics/CyclomaticComplexity, Metrics/MethodLength, Metrics/AbcSize
73
+ response = ::OneLogin::RubySaml::Response.new(request.params['SAMLResponse'],
74
+ settings: saml_settings,
75
+ allowed_clock_drift: allowed_clock_drift)
76
+
77
+ ##
78
+ # `RelayState` is an arbitrary string (length < 80 characters). If we
79
+ # sent it to Realme with the SAMLRequest then Realme will return it unaltered.
80
+ #
81
+ # If we receive any relay state then we save it.
82
+ #
83
+ @relay_state = request.params['RelayState'] if request.params['RelayState']
22
84
 
85
+ # If the Realme Context Mapping Service (RCMS) is enabled in Realme
86
+ # for our app then we will get a RCMS Login Access Token in the
87
+ # SAMLResponse.
88
+ #
89
+ # We save the token if it exists. See
90
+ # https://developers.realme.govt.nz/how-realme-works/whats-realme-rcms/
91
+ #
23
92
  if response.is_valid?
24
- session[:uid] = response.nameid
93
+ @realme_cms_lat = response.attributes[RCMS_LAT_NAME] if response.attributes[RCMS_LAT_NAME]
94
+ end
95
+
96
+ if legacy_rails_session_behaviour_enabled?
97
+ OmniAuth.logger.info "Deprecation: omniauth-realme will stop putting values via Rails `session` in a future version. Use request.env['omniauth.auth'] instead." # rubocop:disable Layout/LineLength
98
+
99
+ if response.is_valid?
100
+ session[:uid] = response.nameid
101
+ else
102
+ session[:realme_error] = {
103
+ error: response.errors.join[/=> (\S+) ->/, 1],
104
+ message: default_error_messages_for_rails_session(response.errors.join)
105
+ }
106
+ end
25
107
  else
26
- authorize_failure
108
+ if response.is_valid? # rubocop:disable Style/IfInsideElse
109
+ @uid = response.nameid
110
+ else
111
+ ex = create_exception_for(status_code: response.status_code, message: response.status_message.strip)
112
+
113
+ # fail!() returns a rack response which this callback must also
114
+ # return if OmniAuth error handling is to work correctly.
115
+ return fail!(create_label_for(ex), ex)
116
+ end
27
117
  end
28
118
 
29
- @raw_info = response
30
119
  super
31
120
  end
32
121
 
33
- private
122
+ ##
123
+ # The `credentials` Hash will be placed within the `request["omniauth.auth"]`
124
+ # Hash that `OmniAuth::Strategy` builds. See
125
+ # https://github.com/omniauth/omniauth/wiki/Auth-Hash-Schema
126
+ #
127
+ # `credentials` contains any extra credentials information about the user
128
+ # that we received from the authentication service (Realme) e.g. an RCMS
129
+ # token if it exists.
130
+ #
131
+ credentials do
132
+ output = {}
133
+ output[:realme_cms_lat] = @realme_cms_lat if @realme_cms_lat
134
+ output
135
+ end
136
+
137
+ ##
138
+ # The `extra` Hash will be placed within the `request["omniauth.auth"]`
139
+ # Hash that `OmniAuth::Strategy` builds. See
140
+ # https://github.com/omniauth/omniauth/wiki/Auth-Hash-Schema
141
+ #
142
+ # `extra` contains anything which isn't information about the user or a
143
+ # user credential.
144
+ #
145
+ extra do
146
+ output = {}
147
+ output[:relay_state] = @relay_state if @relay_state
148
+ output
149
+ end
150
+
151
+ ##
152
+ # Return the `uid` (User ID) value in a way that allows
153
+ # OmniAuth::Strategy to place it in the `request["omniauth.auth"]` Hash
154
+ # that it builds. See
155
+ # https://github.com/omniauth/omniauth/wiki/Auth-Hash-Schema
156
+ #
157
+ uid do
158
+ @uid
159
+ end
34
160
 
35
- def saml_settings
161
+ def saml_settings # rubocop:disable Metrics/AbcSize
36
162
  idp_metadata_parser = OneLogin::RubySaml::IdpMetadataParser.new
37
163
  settings = idp_metadata_parser.parse(File.read(options.fetch('idp_service_metadata')))
38
164
 
39
- settings.issuer = options.fetch('issuer')
40
- settings.assertion_consumer_service_url = options.fetch('assertion_consumer_service_url')
41
- settings.private_key = options.fetch('private_key')
42
- settings.authn_context = options.fetch('auth_strenght', 'urn:nzl:govt:ict:stds:authn:deployment:GLS:SAML:2.0:ac:classes:LowStrength')
43
- settings.protocol_binding = "urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST"
44
- settings.assertion_consumer_service_binding = "urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST"
45
- settings.soft = false
165
+ settings.issuer = options.fetch('issuer')
166
+ settings.assertion_consumer_service_url = options.fetch('assertion_consumer_service_url')
167
+ settings.attributes_index = options.fetch('attributes_index', '0')
168
+ settings.private_key = options.fetch('private_key')
169
+ settings.authn_context = options.fetch('auth_strength', 'urn:nzl:govt:ict:stds:authn:deployment:GLS:SAML:2.0:ac:classes:LowStrength')
170
+ settings.protocol_binding = 'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST'
171
+ settings.assertion_consumer_service_binding = 'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST'
172
+ settings.soft = !options.fetch('raise_exceptions_for_saml_validation_errors', false)
173
+
174
+ settings.security[:authn_requests_signed] = true
175
+
176
+ ##
177
+ # Realme error if this is missing from the metadata
178
+ #
179
+ # WantAssertionsSigned must be true (MTS-002)
180
+ #
181
+ settings.security[:want_assertions_signed] = true
182
+
183
+ ##
184
+ # Realme MTS requires our Metadata XML to have both:
185
+ #
186
+ # <md:KeyDescriptor use="signing">...</md:KeyDescriptor>
187
+ # <md:KeyDescriptor use="encryption">...</md:KeyDescriptor>
188
+ #
189
+ # in the metadata XML we submit. We need to set a certificate **and**
190
+ # set `:want_assertions_encrypted` for ruby-saml to include these
191
+ # elements.
192
+ #
193
+ settings.certificate = options.fetch('certificate')
194
+ settings.security[:want_assertions_encrypted] = true
195
+
196
+ settings
197
+ end
46
198
 
47
- settings.security[:authn_requests_signed] = true
199
+ private
48
200
 
49
- settings
201
+ ##
202
+ # Realme documents the various error conditions it can return:
203
+ #
204
+ # https://developers.realme.govt.nz/how-realme-works/realme-saml-exception-handling/
205
+ #
206
+ def create_exception_for(status_code:, message:) # rubocop:disable Metrics/MethodLength, Metrics/CyclomaticComplexity
207
+ case status_code
208
+ when /status:Timeout\z/
209
+ RealmeTimeoutError.new(message)
210
+ when /status:InternalError\z/
211
+ RealmeInternalError.new(message)
212
+ when /status:AuthnFailed\z/
213
+ RealmeAuthnFailedError.new(message)
214
+ when /status:NoAvailableIDP\z/
215
+ RealmeNoAvailableIDPError.new(message)
216
+ when /status:NoPassive\z/
217
+ RealmeNoPassiveError.new(message)
218
+ when /status:RequestDenied\z/
219
+ RealmeRequestDeniedError.new(message)
220
+ when /status:RequestUnsupported\z/
221
+ RealmeRequestUnsupportedError.new(message)
222
+ when /status:UnknownPrincipal\z/
223
+ RealmeUnknownPrincipalError.new(message)
224
+ when /status:UnsupportedBinding\z/
225
+ RealmeUnsupportedBindingError.new(message)
226
+ else
227
+ RealmeUnrecognisedError.new("Realme login service returned an unrecognised error. status_code=#{status_code} message=#{message}")
228
+ end
229
+ end
230
+
231
+ ##
232
+ # The OmniAuth failure endpoint requires us to pass an instance of an
233
+ # Exception and a String|Symbol describing the error. This method builds
234
+ # a simple description based on class of the exception.
235
+ #
236
+ # This gem can be used in any Rack environment so we don't use any Rails
237
+ # specific text wrangling methods
238
+ #
239
+ # @param [Exception] exception The exception to describe
240
+ # @return [String] The label describing the exception
241
+ #
242
+ def create_label_for(exception)
243
+ exception.class.to_s.gsub('::', '_')
244
+ end
245
+
246
+ def allowed_clock_drift
247
+ options.fetch('allowed_clock_drift', 0)
248
+ end
249
+
250
+ def legacy_rails_session_behaviour_enabled?
251
+ options.fetch('legacy_rails_session_behaviour_enabled', true)
252
+ end
253
+
254
+ def default_error_messages_for_rails_session(error)
255
+ case error
256
+ when /Timeout/
257
+ '<p>Your RealMe session has expired due to inactivity.</p>'
258
+ when /NoAvailableIDP/
259
+ "<p>RealMe reported that the TXT service, Google Authenticator or the RealMe token service is not available.</p>
260
+ <p>You may try again later. If the problem persists, please contact RealMe Help <a href='tel:'0800664774>0800 664 774</a>.</p>"
261
+ when /AuthnFailed/
262
+ '<p>You have chosen to leave the RealMe login screen without completing the login process.</p>'
263
+ when /InternalError/
264
+ "<p>RealMe was unable to process your request due to a RealMe internal error.</p>
265
+ <p>Please try again. If the problem persists, please contact RealMe Help Desk on <a href='tel:'0800664774>0800 664 774</a>.</p>"
266
+ else
267
+ "<p>RealMe reported a serious application error with the message:</p>
268
+ <p>#{error}</p>
269
+ <p>Please try again later. If the problem persists, please contact RealMe Help Desk on <a href='tel:'0800664774>0800 664 774</a>.</p>"
270
+ end
50
271
  end
51
272
  end
52
273
  end
@@ -1,33 +1,42 @@
1
-
2
1
  # frozen_string_literal: true
3
2
 
4
- lib = File.expand_path('lib', __dir__)
5
- $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
6
- require 'omniauth/realme/version'
3
+ require_relative 'lib/omniauth/realme/version'
7
4
 
8
5
  Gem::Specification.new do |spec|
9
6
  spec.name = 'omniauth-realme'
10
- spec.version = Omniauth::Realme::VERSION
11
- spec.authors = ['DanHenton']
12
- spec.email = ['Dan.henton@live.com']
7
+ spec.version = OmniAuth::Realme::VERSION
8
+ spec.authors = ['DigitalNZ']
9
+ spec.email = ['info@digitalnz.org']
13
10
 
14
11
  spec.summary = 'Omniauth strategy for New Zealands secure online identity verification service.'
15
12
  spec.description = 'Omniauth strategy for New Zealands secure online identity verification service.'
16
- spec.homepage = 'https://example.com'
13
+ spec.homepage = 'https://github.com/omniauth/omniauth'
17
14
  spec.license = 'GNU'
15
+ spec.required_ruby_version = Gem::Requirement.new('>= 2.3.0')
16
+
17
+ # spec.metadata['allowed_push_host'] = "TODO: Set to 'http://mygemserver.com'"
18
+
19
+ spec.metadata['homepage_uri'] = spec.homepage
20
+ spec.metadata['source_code_uri'] = 'https://github.com/omniauth/omniauth'
18
21
 
19
- spec.files = `git ls-files -z`.split("\x0").reject do |f|
20
- f.match(%r{^(test|spec|features)/})
22
+ # Specify which files should be added to the gem when it is released.
23
+ # The `git ls-files -z` loads the files in the RubyGem that have been added into git.
24
+ spec.files = Dir.chdir(File.expand_path(__dir__)) do
25
+ `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
21
26
  end
22
27
  spec.bindir = 'exe'
23
28
  spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
24
29
  spec.require_paths = ['lib']
25
30
 
26
31
  spec.add_dependency 'omniauth', '~> 1.0'
27
- spec.add_dependency 'uuid', '~> 2.0'
28
32
  spec.add_dependency 'ruby-saml', '~> 1.5'
33
+ spec.add_dependency 'uuid', '~> 2.0'
29
34
 
30
35
  spec.add_development_dependency 'bundler'
36
+ spec.add_development_dependency 'pry-byebug'
37
+ spec.add_development_dependency 'rack-test'
31
38
  spec.add_development_dependency 'rake'
32
39
  spec.add_development_dependency 'rspec'
40
+ spec.add_development_dependency 'rubocop'
41
+ spec.add_development_dependency 'rubocop-rspec'
33
42
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: omniauth-realme
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
- - DanHenton
8
- autorequire:
7
+ - DigitalNZ
8
+ autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2018-11-12 00:00:00.000000000 Z
11
+ date: 2020-09-24 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: omniauth
@@ -25,33 +25,33 @@ dependencies:
25
25
  - !ruby/object:Gem::Version
26
26
  version: '1.0'
27
27
  - !ruby/object:Gem::Dependency
28
- name: uuid
28
+ name: ruby-saml
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
31
  - - "~>"
32
32
  - !ruby/object:Gem::Version
33
- version: '2.0'
33
+ version: '1.5'
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: '2.0'
40
+ version: '1.5'
41
41
  - !ruby/object:Gem::Dependency
42
- name: ruby-saml
42
+ name: uuid
43
43
  requirement: !ruby/object:Gem::Requirement
44
44
  requirements:
45
45
  - - "~>"
46
46
  - !ruby/object:Gem::Version
47
- version: '1.5'
47
+ version: '2.0'
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: '1.5'
54
+ version: '2.0'
55
55
  - !ruby/object:Gem::Dependency
56
56
  name: bundler
57
57
  requirement: !ruby/object:Gem::Requirement
@@ -66,6 +66,34 @@ dependencies:
66
66
  - - ">="
67
67
  - !ruby/object:Gem::Version
68
68
  version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: pry-byebug
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: rack-test
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ">="
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ">="
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
69
97
  - !ruby/object:Gem::Dependency
70
98
  name: rake
71
99
  requirement: !ruby/object:Gem::Requirement
@@ -94,22 +122,50 @@ dependencies:
94
122
  - - ">="
95
123
  - !ruby/object:Gem::Version
96
124
  version: '0'
125
+ - !ruby/object:Gem::Dependency
126
+ name: rubocop
127
+ requirement: !ruby/object:Gem::Requirement
128
+ requirements:
129
+ - - ">="
130
+ - !ruby/object:Gem::Version
131
+ version: '0'
132
+ type: :development
133
+ prerelease: false
134
+ version_requirements: !ruby/object:Gem::Requirement
135
+ requirements:
136
+ - - ">="
137
+ - !ruby/object:Gem::Version
138
+ version: '0'
139
+ - !ruby/object:Gem::Dependency
140
+ name: rubocop-rspec
141
+ requirement: !ruby/object:Gem::Requirement
142
+ requirements:
143
+ - - ">="
144
+ - !ruby/object:Gem::Version
145
+ version: '0'
146
+ type: :development
147
+ prerelease: false
148
+ version_requirements: !ruby/object:Gem::Requirement
149
+ requirements:
150
+ - - ">="
151
+ - !ruby/object:Gem::Version
152
+ version: '0'
97
153
  description: Omniauth strategy for New Zealands secure online identity verification
98
154
  service.
99
155
  email:
100
- - Dan.henton@live.com
156
+ - info@digitalnz.org
101
157
  executables: []
102
158
  extensions: []
103
159
  extra_rdoc_files: []
104
160
  files:
161
+ - ".github/workflows/ci.yml"
105
162
  - ".gitignore"
106
163
  - ".rspec"
107
164
  - ".rubocop.yml"
165
+ - ".rubocop_todo.yml"
108
166
  - ".ruby-version"
109
- - ".travis.yml"
110
167
  - Gemfile
111
168
  - Gemfile.lock
112
- - LICENSE
113
169
  - LICENSE.txt
114
170
  - README.md
115
171
  - Rakefile
@@ -119,11 +175,13 @@ files:
119
175
  - lib/omniauth/realme/version.rb
120
176
  - lib/omniauth/strategies/realme.rb
121
177
  - omniauth-realme.gemspec
122
- homepage: https://example.com
178
+ homepage: https://github.com/omniauth/omniauth
123
179
  licenses:
124
180
  - GNU
125
- metadata: {}
126
- post_install_message:
181
+ metadata:
182
+ homepage_uri: https://github.com/omniauth/omniauth
183
+ source_code_uri: https://github.com/omniauth/omniauth
184
+ post_install_message:
127
185
  rdoc_options: []
128
186
  require_paths:
129
187
  - lib
@@ -131,16 +189,15 @@ required_ruby_version: !ruby/object:Gem::Requirement
131
189
  requirements:
132
190
  - - ">="
133
191
  - !ruby/object:Gem::Version
134
- version: '0'
192
+ version: 2.3.0
135
193
  required_rubygems_version: !ruby/object:Gem::Requirement
136
194
  requirements:
137
195
  - - ">="
138
196
  - !ruby/object:Gem::Version
139
197
  version: '0'
140
198
  requirements: []
141
- rubyforge_project:
142
- rubygems_version: 2.7.7
143
- signing_key:
199
+ rubygems_version: 3.0.3
200
+ signing_key:
144
201
  specification_version: 4
145
202
  summary: Omniauth strategy for New Zealands secure online identity verification service.
146
203
  test_files: []