omniauth-openid-connector 1.1.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 67ab07bdc7de6392ea111c03ce898b0d4f9309de
4
+ data.tar.gz: 0351d132a18e0259a8bb4632766878cc794dde03
5
+ SHA512:
6
+ metadata.gz: 8d2e5d1d3ea9aa808f32280471f019bebeef2d85c9a631aadbbf6571c5a034b8f6f661ee340d5993b6f8b6448ceb40e172417d2530070883583da6f429664234
7
+ data.tar.gz: 77e63ee5d19773c83c888f911b39b1a0eb2c299465c66edbad4810f3c1f9c03258c9d750b24e52755c39d25235732b777b821920ac02f9d9122e2d52d391fec6
@@ -0,0 +1,17 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ InstalledFiles
7
+ _yardoc
8
+ coverage
9
+ doc/
10
+ lib/bundler/man
11
+ pkg
12
+ rdoc
13
+ spec/reports
14
+ test/tmp
15
+ test/version_tmp
16
+ tmp
17
+ .ruby-version
@@ -0,0 +1,10 @@
1
+ before_install:
2
+ - gem update bundler
3
+ rvm:
4
+ - 1.9.3
5
+ - 2.0.0
6
+ - 2.1.0
7
+ - 2.2.0
8
+ - 2.3.0
9
+ - 2.3.3
10
+ - rbx
data/Gemfile ADDED
@@ -0,0 +1,2 @@
1
+ source 'https://rubygems.org'
2
+ gemspec
@@ -0,0 +1,14 @@
1
+ # A sample Guardfile
2
+ # More info at https://github.com/guard/guard#readme
3
+
4
+ guard 'minitest' do
5
+ # with Minitest::Unit
6
+ watch(%r|^test/(.*)\/(.*)_test\.rb|)
7
+ watch(%r|^lib/(.*)\.rb|) { |m| "test/lib/#{m[1]}_test.rb" }
8
+ watch(%r|^test/test_helper\.rb|) { "test" }
9
+ end
10
+
11
+ guard :bundler do
12
+ watch('Gemfile')
13
+ watch(/^.+\.gemspec/)
14
+ end
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2014 John Bohn
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,71 @@
1
+ # OmniAuth::OpenIDConnect
2
+
3
+ OpenID Connect strategy for OmniAuth
4
+ [![Gem Version](https://badge.fury.io/rb/omniauth-openid-connector.png)](http://badge.fury.io/rb/omniauth-openid-connector)
5
+ [![Build Status](https://travis-ci.org/jjbohn/omniauth-openid-connector.png?branch=master)](https://travis-ci.org/doberg/omniauth-openid-connector)
6
+ [![Coverage Status](https://coveralls.io/repos/doberg/omniauth-openid-connector/badge.png?branch=master)](https://coveralls.io/r/doberg/omniauth-openid-connector?branch=master)
7
+ [![Code Climate](https://codeclimate.com/github/doberg/omniauth-openid-connector.png)](https://codeclimate.com/github/doberg/omniauth-openid-connector)
8
+
9
+ ## Installation
10
+
11
+ Add this line to your application's Gemfile:
12
+
13
+ gem 'omniauth-openid-connector'
14
+
15
+ And then execute:
16
+
17
+ $ bundle
18
+
19
+ Or install it yourself as:
20
+
21
+ $ gem install omniauth-openid-connector
22
+
23
+ ## Usage
24
+
25
+ Example configuration
26
+ ```ruby
27
+ config.omniauth :openid_connect, {
28
+ name: :my_provider,
29
+ scope: [:openid, :email, :profile, :address],
30
+ response_type: :code,
31
+ client_options: {
32
+ port: 443,
33
+ scheme: "https",
34
+ host: "myprovider.com",
35
+ identifier: ENV["OP_CLIENT_ID"],
36
+ secret: ENV["OP_SECRET_KEY"],
37
+ redirect_uri: "http://myapp.com/users/auth/openid_connect/callback",
38
+ },
39
+ }
40
+ ```
41
+
42
+ Configuration details:
43
+ * `name` is arbitrary, I recommend using the name of your provider. The name
44
+ configuration exists because you could be using multiple OpenID Connect
45
+ providers in a single app.
46
+ * Although `response_type` is an available option, currently, only `:code`
47
+ is valid. There are plans to bring in implicit flow and hybrid flow at some
48
+ point, but it hasn't come up yet for me. Those flows aren't best practive for
49
+ server side web apps anyway and are designed more for native/mobile apps.
50
+ * If you want to pass `state` paramete by yourself. You can set Proc Object.
51
+ e.g. `state: Proc.new{ SecureRandom.hex(32) }`
52
+ * `nonce` is optional. If don't want to pass "nonce" parameter to provider, You should specify
53
+ `false` to `send_nonce` option. (default true)
54
+ * Support for other client authentication methods. If don't specified
55
+ `:client_auth_method` option, automatically set `:basic`.
56
+ * Use "OpenID Connect Discovery", You should specify `true` to `discovery` option. (default false)
57
+ * In "OpenID Connect Discovery", generally provider should have Webfinger endpoint.
58
+ If provider does not have Webfinger endpoint, You can specify "Issuer" to option.
59
+ e.g. `issuer: "https://myprovider.com"`
60
+ It means to get configuration from "https://myprovider.com/.well-known/openid-configuration".
61
+
62
+ For the full low down on OpenID Connect, please check out
63
+ [the spec](http://openid.net/specs/openid-connect-core-1_0.html).
64
+
65
+ ## Contributing
66
+
67
+ 1. Fork it ( http://github.com/jjbohn/omniauth-openid-connector/fork )
68
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
69
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
70
+ 4. Push to the branch (`git push origin my-new-feature`)
71
+ 5. Create new Pull Request
@@ -0,0 +1,10 @@
1
+ require 'bundler/gem_tasks'
2
+ require 'rake/testtask'
3
+
4
+ Rake::TestTask.new do |t|
5
+ t.libs << 'lib/omniauth-openid-connect'
6
+ t.test_files = FileList['test/lib/omniauth/**/*_test.rb']
7
+ t.verbose = true
8
+ end
9
+
10
+ task default: :test
@@ -0,0 +1 @@
1
+ require "omniauth/openid_connect"
@@ -0,0 +1,3 @@
1
+ require "omniauth/openid_connect/errors"
2
+ require "omniauth/openid_connect/version"
3
+ require "omniauth/strategies/openid_connect"
@@ -0,0 +1,6 @@
1
+ module OmniAuth
2
+ module OpenIDConnect
3
+ class Error < RuntimeError; end
4
+ class MissingCodeError < Error; end
5
+ end
6
+ end
@@ -0,0 +1,5 @@
1
+ module OmniAuth
2
+ module OpenIDConnect
3
+ VERSION = "1.1.2"
4
+ end
5
+ end
@@ -0,0 +1,251 @@
1
+ require 'addressable/uri'
2
+ require 'timeout'
3
+ require 'net/http'
4
+ require 'open-uri'
5
+ require 'omniauth'
6
+ require 'openid_connect'
7
+
8
+ module OmniAuth
9
+ module Strategies
10
+ class OpenIDConnect
11
+ include OmniAuth::Strategy
12
+
13
+ option :client_options, {
14
+ identifier: nil,
15
+ secret: nil,
16
+ redirect_uri: nil,
17
+ scheme: "https",
18
+ host: nil,
19
+ port: 443,
20
+ authorization_endpoint: "/authorize",
21
+ token_endpoint: "/token",
22
+ userinfo_endpoint: "/userinfo",
23
+ jwks_uri: '/jwk'
24
+ }
25
+ option :issuer
26
+ option :discovery, false
27
+ option :client_signing_alg
28
+ option :client_jwk_signing_key
29
+ option :client_x509_signing_key
30
+ option :scope, [:openid]
31
+ option :response_type, "code"
32
+ option :state
33
+ option :response_mode
34
+ option :display, nil #, [:page, :popup, :touch, :wap]
35
+ option :prompt, nil #, [:none, :login, :consent, :select_account]
36
+ option :hd, nil
37
+ option :max_age
38
+ option :ui_locales
39
+ option :id_token_hint
40
+ option :login_hint
41
+ option :acr_values
42
+ option :send_nonce, true
43
+ option :send_scope_to_token_endpoint, true
44
+ option :client_auth_method
45
+
46
+ uid { user_info.sub }
47
+
48
+ info do
49
+ {
50
+ name: user_info.name,
51
+ email: user_info.email,
52
+ nickname: user_info.preferred_username,
53
+ first_name: user_info.given_name,
54
+ last_name: user_info.family_name,
55
+ gender: user_info.gender,
56
+ image: user_info.picture,
57
+ phone: user_info.phone_number,
58
+ urls: { website: user_info.website }
59
+ }
60
+ end
61
+
62
+ extra do
63
+ {raw_info: user_info.raw_attributes}
64
+ end
65
+
66
+ credentials do
67
+ {
68
+ id_token: access_token.id_token,
69
+ token: access_token.access_token,
70
+ refresh_token: access_token.refresh_token,
71
+ expires_in: access_token.expires_in,
72
+ scope: access_token.scope
73
+ }
74
+ end
75
+
76
+ def client
77
+ @client ||= ::OpenIDConnect::Client.new(client_options)
78
+ end
79
+
80
+ def config
81
+ @config ||= ::OpenIDConnect::Discovery::Provider::Config.discover!(options.issuer)
82
+ end
83
+
84
+ def request_phase
85
+ options.issuer = issuer if options.issuer.blank?
86
+ discover! if options.discovery
87
+ redirect authorize_uri
88
+ end
89
+
90
+ def callback_phase
91
+ error = request.params['error_reason'] || request.params['error']
92
+ if error
93
+ raise CallbackError.new(request.params['error'], request.params['error_description'] || request.params['error_reason'], request.params['error_uri'])
94
+ elsif request.params['state'].to_s.empty? || request.params['state'] != stored_state
95
+ return Rack::Response.new(['401 Unauthorized'], 401).finish
96
+ elsif !request.params["code"]
97
+ return fail!(:missing_code, OmniAuth::OpenIDConnect::MissingCodeError.new(request.params["error"]))
98
+ else
99
+ options.issuer = issuer if options.issuer.blank?
100
+ discover! if options.discovery
101
+ client.redirect_uri = client_options.redirect_uri
102
+ client.authorization_code = authorization_code
103
+ access_token
104
+ super
105
+ end
106
+ rescue CallbackError => e
107
+ fail!(:invalid_credentials, e)
108
+ rescue ::Timeout::Error, ::Errno::ETIMEDOUT => e
109
+ fail!(:timeout, e)
110
+ rescue ::SocketError => e
111
+ fail!(:failed_to_connect, e)
112
+ end
113
+
114
+
115
+ def authorization_code
116
+ request.params["code"]
117
+ end
118
+
119
+ def authorize_uri
120
+ client.redirect_uri = client_options.redirect_uri
121
+ opts = {
122
+ response_type: options.response_type,
123
+ scope: options.scope,
124
+ state: new_state,
125
+ nonce: (new_nonce if options.send_nonce),
126
+ hd: options.hd,
127
+ }
128
+ client.authorization_uri(opts.reject{|k,v| v.nil?})
129
+ end
130
+
131
+ def public_key
132
+ if options.discovery
133
+ config.jwks
134
+ else
135
+ key_or_secret
136
+ end
137
+ end
138
+
139
+ private
140
+
141
+ def issuer
142
+ resource = "#{client_options.scheme}://#{client_options.host}" + ((client_options.port) ? ":#{client_options.port.to_s}" : '')
143
+ ::OpenIDConnect::Discovery::Provider.discover!(resource).issuer
144
+ end
145
+
146
+ def discover!
147
+ client_options.authorization_endpoint = config.authorization_endpoint
148
+ client_options.token_endpoint = config.token_endpoint
149
+ client_options.userinfo_endpoint = config.userinfo_endpoint
150
+ client_options.jwks_uri = config.jwks_uri
151
+ end
152
+
153
+ def user_info
154
+ @user_info ||= access_token.userinfo!
155
+ end
156
+
157
+ def access_token
158
+ @access_token ||= lambda {
159
+ _access_token = client.access_token!(
160
+ scope: (options.scope if options.send_scope_to_token_endpoint),
161
+ client_auth_method: options.client_auth_method
162
+ )
163
+ _id_token = decode_id_token _access_token.id_token
164
+ _id_token.verify!(
165
+ issuer: options.issuer,
166
+ client_id: client_options.identifier,
167
+ nonce: stored_nonce
168
+ )
169
+ _access_token
170
+ }.call()
171
+ end
172
+
173
+ def decode_id_token(id_token)
174
+ ::OpenIDConnect::ResponseObject::IdToken.decode(id_token, public_key)
175
+ end
176
+
177
+
178
+ def client_options
179
+ options.client_options
180
+ end
181
+
182
+ def new_state
183
+ state = options.state.call if options.state.respond_to? :call
184
+ session['omniauth.state'] = state || SecureRandom.hex(16)
185
+ end
186
+
187
+ def stored_state
188
+ session.delete('omniauth.state')
189
+ end
190
+
191
+ def new_nonce
192
+ session['omniauth.nonce'] = SecureRandom.hex(16)
193
+ end
194
+
195
+ def stored_nonce
196
+ session.delete('omniauth.nonce')
197
+ end
198
+
199
+ def session
200
+ @env.nil? ? {} : super
201
+ end
202
+
203
+ def key_or_secret
204
+ case options.client_signing_alg
205
+ when :HS256, :HS384, :HS512
206
+ return client_options.secret
207
+ when :RS256, :RS384, :RS512
208
+ if options.client_jwk_signing_key
209
+ return parse_jwk_key(options.client_jwk_signing_key)
210
+ elsif options.client_x509_signing_key
211
+ return parse_x509_key(options.client_x509_signing_key)
212
+ end
213
+ else
214
+ end
215
+ end
216
+
217
+ def parse_x509_key(key)
218
+ OpenSSL::X509::Certificate.new(key).public_key
219
+ end
220
+
221
+ def parse_jwk_key(key)
222
+ json = JSON.parse(key)
223
+ if json.has_key?('keys')
224
+ JSON::JWK::Set.new json['keys']
225
+ else
226
+ JSON::JWK.new json
227
+ end
228
+ end
229
+
230
+ def decode(str)
231
+ UrlSafeBase64.decode64(str).unpack('B*').first.to_i(2).to_s
232
+ end
233
+
234
+ class CallbackError < StandardError
235
+ attr_accessor :error, :error_reason, :error_uri
236
+
237
+ def initialize(error, error_reason=nil, error_uri=nil)
238
+ self.error = error
239
+ self.error_reason = error_reason
240
+ self.error_uri = error_uri
241
+ end
242
+
243
+ def message
244
+ [error, error_reason, error_uri].compact.join(' | ')
245
+ end
246
+ end
247
+ end
248
+ end
249
+ end
250
+
251
+ OmniAuth.config.add_camelization 'openid_connect', 'OpenIDConnect'
@@ -0,0 +1,35 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'omniauth/openid_connect/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "omniauth-openid-connector"
8
+ spec.version = OmniAuth::OpenIDConnect::VERSION
9
+ spec.authors = ["Danial Oberg"]
10
+ spec.email = ["doberg@verisys.com"]
11
+ spec.summary = %q{OpenID Connect Strategy for OmniAuth}
12
+ spec.description = %q{OpenID Connect Strategy for OmniAuth}
13
+ spec.homepage = "https://github.com/doberg/omniauth-openid-connector"
14
+ spec.license = "MIT"
15
+
16
+ spec.files = `git ls-files -z`.split("\x0")
17
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
+ spec.require_paths = ["lib"]
20
+
21
+ spec.add_dependency 'omniauth', '~> 1.6.1'
22
+ spec.add_dependency 'openid_connect', '~> 1.1.2'
23
+ spec.add_dependency 'addressable', '~> 2.4'
24
+ spec.add_development_dependency "bundler", "~> 1.15.1"
25
+ spec.add_development_dependency "minitest"
26
+ spec.add_development_dependency "mocha"
27
+ spec.add_development_dependency "guard"
28
+ spec.add_development_dependency "guard-minitest"
29
+ spec.add_development_dependency "guard-bundler"
30
+ spec.add_development_dependency "rake"
31
+ spec.add_development_dependency "simplecov"
32
+ spec.add_development_dependency "pry"
33
+ spec.add_development_dependency "coveralls"
34
+ spec.add_development_dependency "faker"
35
+ end
@@ -0,0 +1 @@
1
+ eyJhbGciOiJSUzI1NiIsImtpZCI6IjFlOWdkazcifQ.ewogImlzcyI6ICJodHRwOi8vc2VydmVyLmV4YW1wbGUuY29tIiwKICJzdWIiOiAiMjQ4Mjg5NzYxMDAxIiwKICJhdWQiOiAiczZCaGRSa3F0MyIsCiAibm9uY2UiOiAibi0wUzZfV3pBMk1qIiwKICJleHAiOiAxMzExMjgxOTcwLAogImlhdCI6IDEzMTEyODA5NzAKfQ.ggW8hZ1EuVLuxNuuIJKX_V8a_OMXzR0EHR9R6jgdqrOOF4daGU96Sr_P6qJp6IcmD3HP99Obi1PRs-cwh3LO-p146waJ8IhehcwL7F09JdijmBqkvPeB2T9CJNqeGpe-gccMg4vfKjkM8FcGvnzZUN4_KSP0aAp1tOJ1zZwgjxqGByKHiOtX7TpdQyHE5lcMiKPXfEIQILVq0pc_E2DzL7emopWoaoZTF_m0_N0YzFC6g6EJbOEoRoSK5hoDalrcvRYLSrQAZZKflyuVCyixEoV9GfNQC3_osjzw2PAithfubEEBLuVVk4XUVrWOLrLl0nx7RkKU8NXNHq-rvKMzqg
@@ -0,0 +1,8 @@
1
+ {"keys": [{
2
+ "kty": "RSA",
3
+ "n": "0vx7agoebGcQSuuPiLJXZptN9nndrQmbXEps2aiAFbWhM78LhWx4cbbfAAtVT86zwu1RK7aPFFxuhDR1L6tSoc_BJECPebWKRXjBZCiFV4n3oknjhMstn64tZ_2W-5JsGY4Hc5n9yBXArwl93lqt7_RN5w6Cf0h4QyQ5v-65YGjQR0_FDW2QvzqY368QQMicAtaSqzs8KJZgnYb9c7d0zgdAZHzu6qMQvRL5hajrn1n91CbOpbISD08qNLyrdkt-bFTWhAI4vMQFh6WeZu0fM4lFd2NcRwr3XPksINHaQ-G_xBniIqbw0Ls1jF44-csFCur-kEgU8awapJzKnqDKgw",
4
+ "e": "AQAB",
5
+ "alg": "RS256",
6
+ "kid": "1e9gdk7"
7
+ }]
8
+ }
@@ -0,0 +1,19 @@
1
+ -----BEGIN CERTIFICATE-----
2
+ MIIDJDCCAgwCCQC57Ob2JfXb+DANBgkqhkiG9w0BAQUFADBUMQswCQYDVQQGEwJK
3
+ UDEOMAwGA1UECBMFVG9reW8xITAfBgNVBAoTGEludGVybmV0IFdpZGdpdHMgUHR5
4
+ IEx0ZDESMBAGA1UEAxMJbG9jYWxob3N0MB4XDTE0MDgwMTA4NTAxM1oXDTE1MDgw
5
+ MTA4NTAxM1owVDELMAkGA1UEBhMCSlAxDjAMBgNVBAgTBVRva3lvMSEwHwYDVQQK
6
+ ExhJbnRlcm5ldCBXaWRnaXRzIFB0eSBMdGQxEjAQBgNVBAMTCWxvY2FsaG9zdDCC
7
+ ASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAN+7czSGHN2087T+oX2kBCY/
8
+ XN6UOS/mdU2Gn//omZlyxsQXIqvgBLNWeCVt4QdlFUbgPLggfXUelECV/RUOCIIi
9
+ F2Th4t3x1LviN2XkUiva0DZBnOycqEaJdkyreEuGL1CLVZgZjKmSzNqLl0Yci3D0
10
+ zgVsXFZSadQebietm4CCmfJYREt9NJxXcrLxVDgat/Xm/KJBsohs3f+cbBT8EXer
11
+ 7+2oZjZoVUgw1hu0alaOvAfE4mxsVwjn3g2mjDqRJLbbuWqgDobjMHah+d4zwJvN
12
+ ePK8E0hfaz/XBLsJ4e6bQA3M3bANEgSvsicup/qb/0th4gUdc/kj4aJGj0RP7oEC
13
+ AwEAATANBgkqhkiG9w0BAQUFAAOCAQEADuVec/8u2qJiq6K2W/gSLGYCBZq64OrA
14
+ s7L2+S82m9/3gAb62wGcDNZjIGFDQubXmO6RhHv7JUT5YZqv9/kRGTJcHDUrwwoN
15
+ IE99CIPizp7VfnrZ6GsYeszSsw3m+mKTETm+6ELmaSDbYAsrCg4IpGwUF0L88ATv
16
+ CJ8QzW4X7b9dYVc7UAYyCie2N65GXfesBbRlSwFLuVqIzZfMdNpNijTIUwUqGSME
17
+ b8IjLYzvekP53CO4wEBRrAVIPNXgftorxIE30OLWua2Qw3y6Pn+Qp5fLe47025S7
18
+ Lcec18/FbHG0Vbq0qO9cKQw80XyK31N6z556wr2GN2WyixkzVRddXA==
19
+ -----END CERTIFICATE-----
@@ -0,0 +1,7 @@
1
+ require_relative '../../../test_helper'
2
+
3
+ class OmniAuth::OpenIDConnect::VersionTest < MiniTest::Test
4
+ def test_version_defined
5
+ refute_nil OmniAuth::OpenIDConnect::VERSION
6
+ end
7
+ end
@@ -0,0 +1,344 @@
1
+ require_relative '../../../test_helper'
2
+
3
+ class OmniAuth::Strategies::OpenIDConnectTest < StrategyTestCase
4
+ def test_client_options_defaults
5
+ assert_equal 'https', strategy.options.client_options.scheme
6
+ assert_equal 443, strategy.options.client_options.port
7
+ assert_equal '/authorize', strategy.options.client_options.authorization_endpoint
8
+ assert_equal '/token', strategy.options.client_options.token_endpoint
9
+ end
10
+
11
+ def test_request_phase
12
+ expected_redirect = /^https:\/\/example\.com\/authorize\?client_id=1234&nonce=[\w\d]{32}&response_type=code&scope=openid&state=[\w\d]{32}$/
13
+ strategy.options.issuer = 'example.com'
14
+ strategy.options.client_options.host = 'example.com'
15
+ strategy.expects(:redirect).with(regexp_matches(expected_redirect))
16
+ strategy.request_phase
17
+ end
18
+
19
+ def test_request_phase_with_discovery
20
+ expected_redirect = /^https:\/\/example\.com\/authorization\?client_id=1234&nonce=[\w\d]{32}&response_type=code&scope=openid&state=[\w\d]{32}$/
21
+ strategy.options.client_options.host = 'example.com'
22
+ strategy.options.discovery = true
23
+
24
+ issuer = stub('OpenIDConnect::Discovery::Issuer')
25
+ issuer.stubs(:issuer).returns('https://example.com/')
26
+ ::OpenIDConnect::Discovery::Provider.stubs(:discover!).returns(issuer)
27
+
28
+ config = stub('OpenIDConnect::Discovery::Provder::Config')
29
+ config.stubs(:authorization_endpoint).returns('https://example.com/authorization')
30
+ config.stubs(:token_endpoint).returns('https://example.com/token')
31
+ config.stubs(:userinfo_endpoint).returns('https://example.com/userinfo')
32
+ config.stubs(:jwks_uri).returns('https://example.com/jwks')
33
+ ::OpenIDConnect::Discovery::Provider::Config.stubs(:discover!).with('https://example.com/').returns(config)
34
+
35
+ strategy.expects(:redirect).with(regexp_matches(expected_redirect))
36
+ strategy.request_phase
37
+
38
+ assert_equal strategy.options.issuer, 'https://example.com/'
39
+ assert_equal strategy.options.client_options.authorization_endpoint, 'https://example.com/authorization'
40
+ assert_equal strategy.options.client_options.token_endpoint, 'https://example.com/token'
41
+ assert_equal strategy.options.client_options.userinfo_endpoint, 'https://example.com/userinfo'
42
+ assert_equal strategy.options.client_options.jwks_uri, 'https://example.com/jwks'
43
+ end
44
+
45
+ def test_uid
46
+ assert_equal user_info.sub, strategy.uid
47
+ end
48
+
49
+ def test_callback_phase(session = {}, params = {})
50
+ code = SecureRandom.hex(16)
51
+ state = SecureRandom.hex(16)
52
+ nonce = SecureRandom.hex(16)
53
+ request.stubs(:params).returns({'code' => code,'state' => state})
54
+ request.stubs(:path_info).returns('')
55
+
56
+ strategy.options.issuer = 'example.com'
57
+ strategy.options.client_signing_alg = :RS256
58
+ strategy.options.client_jwk_signing_key = File.read('test/fixtures/jwks.json')
59
+
60
+ id_token = stub('OpenIDConnect::ResponseObject::IdToken')
61
+ id_token.stubs(:verify!).with({:issuer => strategy.options.issuer, :client_id => @identifier, :nonce => nonce}).returns(true)
62
+ ::OpenIDConnect::ResponseObject::IdToken.stubs(:decode).returns(id_token)
63
+
64
+ strategy.unstub(:user_info)
65
+ access_token = stub('OpenIDConnect::AccessToken')
66
+ access_token.stubs(:access_token)
67
+ access_token.stubs(:refresh_token)
68
+ access_token.stubs(:expires_in)
69
+ access_token.stubs(:scope)
70
+ access_token.stubs(:id_token).returns(File.read('test/fixtures/id_token.txt'))
71
+ client.expects(:access_token!).at_least_once.returns(access_token)
72
+ access_token.expects(:userinfo!).returns(user_info)
73
+
74
+ strategy.call!({'rack.session' => {'omniauth.state' => state, 'omniauth.nonce' => nonce}})
75
+ strategy.callback_phase
76
+ end
77
+
78
+ def test_callback_phase_with_discovery
79
+ code = SecureRandom.hex(16)
80
+ state = SecureRandom.hex(16)
81
+ nonce = SecureRandom.hex(16)
82
+ jwks = JSON::JWK::Set.new(JSON.parse(File.read('test/fixtures/jwks.json'))['keys'])
83
+
84
+ request.stubs(:params).returns({'code' => code,'state' => state})
85
+ request.stubs(:path_info).returns('')
86
+
87
+ strategy.options.client_options.host = 'example.com'
88
+ strategy.options.discovery = true
89
+
90
+ issuer = stub('OpenIDConnect::Discovery::Issuer')
91
+ issuer.stubs(:issuer).returns('https://example.com/')
92
+ ::OpenIDConnect::Discovery::Provider.stubs(:discover!).returns(issuer)
93
+
94
+ config = stub('OpenIDConnect::Discovery::Provder::Config')
95
+ config.stubs(:authorization_endpoint).returns('https://example.com/authorization')
96
+ config.stubs(:token_endpoint).returns('https://example.com/token')
97
+ config.stubs(:userinfo_endpoint).returns('https://example.com/userinfo')
98
+ config.stubs(:jwks_uri).returns('https://example.com/jwks')
99
+ config.stubs(:jwks).returns(jwks)
100
+
101
+ ::OpenIDConnect::Discovery::Provider::Config.stubs(:discover!).with('https://example.com/').returns(config)
102
+
103
+ id_token = stub('OpenIDConnect::ResponseObject::IdToken')
104
+ id_token.stubs(:verify!).with({:issuer => 'https://example.com/', :client_id => @identifier, :nonce => nonce}).returns(true)
105
+ ::OpenIDConnect::ResponseObject::IdToken.stubs(:decode).returns(id_token)
106
+
107
+ strategy.unstub(:user_info)
108
+ access_token = stub('OpenIDConnect::AccessToken')
109
+ access_token.stubs(:access_token)
110
+ access_token.stubs(:refresh_token)
111
+ access_token.stubs(:expires_in)
112
+ access_token.stubs(:scope)
113
+ access_token.stubs(:id_token).returns(File.read('test/fixtures/id_token.txt'))
114
+ client.expects(:access_token!).at_least_once.returns(access_token)
115
+ access_token.expects(:userinfo!).returns(user_info)
116
+
117
+ strategy.call!({'rack.session' => {'omniauth.state' => state, 'omniauth.nonce' => nonce}})
118
+ strategy.callback_phase
119
+ end
120
+
121
+ def test_callback_phase_with_error
122
+ state = SecureRandom.hex(16)
123
+ nonce = SecureRandom.hex(16)
124
+ request.stubs(:params).returns({'error' => 'invalid_request'})
125
+ request.stubs(:path_info).returns('')
126
+
127
+ strategy.call!({'rack.session' => {'omniauth.state' => state, 'omniauth.nonce' => nonce}})
128
+ strategy.expects(:fail!)
129
+ strategy.callback_phase
130
+ end
131
+
132
+ def test_callback_phase_with_invalid_state
133
+ code = SecureRandom.hex(16)
134
+ state = SecureRandom.hex(16)
135
+ nonce = SecureRandom.hex(16)
136
+ request.stubs(:params).returns({'code' => code,'state' => 'foobar'})
137
+ request.stubs(:path_info).returns('')
138
+
139
+ strategy.call!({'rack.session' => {'omniauth.state' => state, 'omniauth.nonce' => nonce}})
140
+ result = strategy.callback_phase
141
+
142
+ assert result.kind_of?(Array)
143
+ assert result.first == 401, "Expecting unauthorized"
144
+ end
145
+
146
+ def test_callback_phase_with_timeout
147
+ code = SecureRandom.hex(16)
148
+ state = SecureRandom.hex(16)
149
+ nonce = SecureRandom.hex(16)
150
+ request.stubs(:params).returns({'code' => code,'state' => state})
151
+ request.stubs(:path_info).returns('')
152
+
153
+ strategy.options.issuer = 'example.com'
154
+
155
+ strategy.stubs(:access_token).raises(::Timeout::Error.new('error'))
156
+ strategy.call!({'rack.session' => {'omniauth.state' => state, 'omniauth.nonce' => nonce}})
157
+ strategy.expects(:fail!)
158
+ strategy.callback_phase
159
+ end
160
+
161
+ def test_callback_phase_with_etimeout
162
+ code = SecureRandom.hex(16)
163
+ state = SecureRandom.hex(16)
164
+ nonce = SecureRandom.hex(16)
165
+ request.stubs(:params).returns({'code' => code,'state' => state})
166
+ request.stubs(:path_info).returns('')
167
+
168
+ strategy.options.issuer = 'example.com'
169
+
170
+ strategy.stubs(:access_token).raises(::Errno::ETIMEDOUT.new('error'))
171
+ strategy.call!({'rack.session' => {'omniauth.state' => state, 'omniauth.nonce' => nonce}})
172
+ strategy.expects(:fail!)
173
+ strategy.callback_phase
174
+ end
175
+
176
+ def test_callback_phase_with_socket_error
177
+ code = SecureRandom.hex(16)
178
+ state = SecureRandom.hex(16)
179
+ nonce = SecureRandom.hex(16)
180
+ request.stubs(:params).returns({'code' => code,'state' => state})
181
+ request.stubs(:path_info).returns('')
182
+
183
+ strategy.options.issuer = 'example.com'
184
+
185
+ strategy.stubs(:access_token).raises(::SocketError.new('error'))
186
+ strategy.call!({'rack.session' => {'omniauth.state' => state, 'omniauth.nonce' => nonce}})
187
+ strategy.expects(:fail!)
188
+ strategy.callback_phase
189
+ end
190
+
191
+ def test_info
192
+ info = strategy.info
193
+ assert_equal user_info.name, info[:name]
194
+ assert_equal user_info.email, info[:email]
195
+ assert_equal user_info.preferred_username, info[:nickname]
196
+ assert_equal user_info.given_name, info[:first_name]
197
+ assert_equal user_info.family_name, info[:last_name]
198
+ assert_equal user_info.gender, info[:gender]
199
+ assert_equal user_info.picture, info[:image]
200
+ assert_equal user_info.phone_number, info[:phone]
201
+ assert_equal({ website: user_info.website }, info[:urls])
202
+ end
203
+
204
+ def test_extra
205
+ assert_equal({ raw_info: user_info.as_json }, strategy.extra)
206
+ end
207
+
208
+ def test_credentials
209
+ strategy.options.issuer = 'example.com'
210
+ strategy.options.client_signing_alg = :RS256
211
+ strategy.options.client_jwk_signing_key = File.read('test/fixtures/jwks.json')
212
+
213
+ id_token = stub('OpenIDConnect::ResponseObject::IdToken')
214
+ id_token.stubs(:verify!).returns(true)
215
+ ::OpenIDConnect::ResponseObject::IdToken.stubs(:decode).returns(id_token)
216
+
217
+ access_token = stub('OpenIDConnect::AccessToken')
218
+ access_token.stubs(:access_token).returns(SecureRandom.hex(16))
219
+ access_token.stubs(:refresh_token).returns(SecureRandom.hex(16))
220
+ access_token.stubs(:expires_in).returns(Time.now)
221
+ access_token.stubs(:scope).returns('openidconnect')
222
+ access_token.stubs(:id_token).returns(File.read('test/fixtures/id_token.txt'))
223
+
224
+ client.expects(:access_token!).returns(access_token)
225
+ access_token.expects(:refresh_token).returns(access_token.refresh_token)
226
+ access_token.expects(:expires_in).returns(access_token.expires_in)
227
+
228
+ assert_equal({ id_token: access_token.id_token,
229
+ token: access_token.access_token,
230
+ refresh_token: access_token.refresh_token,
231
+ expires_in: access_token.expires_in,
232
+ scope: access_token.scope
233
+ }, strategy.credentials)
234
+ end
235
+
236
+ def test_option_send_nonce
237
+ strategy.options.client_options[:host] = "foobar.com"
238
+
239
+ assert(strategy.authorize_uri =~ /nonce=/, "URI must contain nonce")
240
+
241
+ strategy.options.send_nonce = false
242
+ assert(!(strategy.authorize_uri =~ /nonce=/), "URI must not contain nonce")
243
+ end
244
+
245
+ def test_failure_endpoint_redirect
246
+ OmniAuth.config.stubs(:failure_raise_out_environments).returns([])
247
+ strategy.stubs(:env).returns({})
248
+ request.stubs(:params).returns({"error" => "access denied"})
249
+
250
+ result = strategy.callback_phase
251
+
252
+ assert(result.is_a? Array)
253
+ assert(result[0] == 302, "Redirect")
254
+ assert(result[1]["Location"] =~ /\/auth\/failure/)
255
+ end
256
+
257
+ def test_state
258
+ strategy.options.state = lambda { 42 }
259
+ session = { "state" => 42 }
260
+
261
+ expected_redirect = /&state=/
262
+ strategy.options.issuer = 'example.com'
263
+ strategy.options.client_options.host = "example.com"
264
+ strategy.expects(:redirect).with(regexp_matches(expected_redirect))
265
+ strategy.request_phase
266
+
267
+ # this should succeed as the correct state is passed with the request
268
+ test_callback_phase(session, { "state" => 42 })
269
+
270
+ # the following should fail because the wrong state is passed to the callback
271
+ code = SecureRandom.hex(16)
272
+ request.stubs(:params).returns({"code" => code, "state" => 43})
273
+ request.stubs(:path_info).returns("")
274
+ strategy.call!({"rack.session" => session})
275
+
276
+ result = strategy.callback_phase
277
+
278
+ assert result.kind_of?(Array)
279
+ assert result.first == 401, "Expecting unauthorized"
280
+ end
281
+
282
+ def test_option_client_auth_method
283
+ code = SecureRandom.hex(16)
284
+ state = SecureRandom.hex(16)
285
+ nonce = SecureRandom.hex(16)
286
+
287
+ opts = strategy.options.client_options
288
+ opts[:host] = "foobar.com"
289
+ strategy.options.issuer = "foobar.com"
290
+ strategy.options.client_auth_method = :not_basic
291
+ strategy.options.client_signing_alg = :RS256
292
+ strategy.options.client_jwk_signing_key = File.read('test/fixtures/jwks.json')
293
+
294
+ json_response = {access_token: 'test_access_token',
295
+ id_token: File.read('test/fixtures/id_token.txt'),
296
+ token_type: 'Bearer',
297
+ }.to_json
298
+ success = Struct.new(:status, :body).new(200, json_response)
299
+
300
+ request.stubs(:path_info).returns('')
301
+ strategy.call!({'rack.session' => {'omniauth.state' => state, 'omniauth.nonce' => nonce}})
302
+
303
+ id_token = stub('OpenIDConnect::ResponseObject::IdToken')
304
+ id_token.stubs(:verify!).with({:issuer => strategy.options.issuer, :client_id => @identifier, :nonce => nonce}).returns(true)
305
+ ::OpenIDConnect::ResponseObject::IdToken.stubs(:decode).returns(id_token)
306
+
307
+ HTTPClient.any_instance.stubs(:post).with(
308
+ "#{opts.scheme}://#{opts.host}:#{opts.port}#{opts.token_endpoint}",
309
+ {scope: 'openid', :grant_type => :client_credentials, :client_id => @identifier, :client_secret => @secret},
310
+ {}
311
+ ).returns(success)
312
+
313
+ assert(strategy.send :access_token)
314
+ end
315
+
316
+ def test_public_key_with_jwks
317
+ strategy.options.client_signing_alg = :RS256
318
+ strategy.options.client_jwk_signing_key = File.read('./test/fixtures/jwks.json')
319
+
320
+ assert_equal JSON::JWK::Set, strategy.public_key.class
321
+ end
322
+
323
+ def test_public_key_with_jwk
324
+ strategy.options.client_signing_alg = :RS256
325
+ jwks_str = File.read('./test/fixtures/jwks.json')
326
+ jwks = JSON.parse(jwks_str)
327
+ jwk = jwks['keys'].first
328
+ strategy.options.client_jwk_signing_key = jwk.to_json
329
+
330
+ assert_equal JSON::JWK, strategy.public_key.class
331
+ end
332
+
333
+ def test_public_key_with_x509
334
+ strategy.options.client_signing_alg = :RS256
335
+ strategy.options.client_x509_signing_key = File.read('./test/fixtures/test.crt')
336
+ assert_equal OpenSSL::PKey::RSA, strategy.public_key.class
337
+ end
338
+
339
+ def test_public_key_with_hmac
340
+ strategy.options.client_options.secret = 'secret'
341
+ strategy.options.client_signing_alg = :HS256
342
+ assert_equal strategy.options.client_options.secret, strategy.public_key
343
+ end
344
+ end
@@ -0,0 +1,66 @@
1
+ require 'simplecov'
2
+ SimpleCov.command_name 'test'
3
+ SimpleCov.start
4
+
5
+ require 'coveralls'
6
+ Coveralls.wear!
7
+
8
+ require 'minitest/autorun'
9
+ require 'mocha/mini_test'
10
+ require 'faker'
11
+ require 'active_support'
12
+ require_relative '../lib/omniauth-openid-connect'
13
+
14
+ OmniAuth.config.test_mode = true
15
+
16
+ class StrategyTestCase < MiniTest::Test
17
+ class DummyApp
18
+ def call(env); end
19
+ end
20
+
21
+ attr_accessor :identifier, :secret
22
+
23
+ def setup
24
+ @identifier = "1234"
25
+ @secret = "1234asdgat3"
26
+ end
27
+
28
+ def client
29
+ strategy.client
30
+ end
31
+
32
+ def user_info
33
+ @user_info ||= OpenIDConnect::ResponseObject::UserInfo.new(
34
+ sub: SecureRandom.hex(16),
35
+ name: Faker::Name.name,
36
+ email: Faker::Internet.email,
37
+ nickname: Faker::Name.first_name,
38
+ preferred_username: Faker::Internet.user_name,
39
+ given_name: Faker::Name.first_name,
40
+ family_name: Faker::Name.last_name,
41
+ gender: 'female',
42
+ picture: Faker::Internet.url + ".png",
43
+ phone_number: Faker::PhoneNumber.phone_number,
44
+ website: Faker::Internet.url,
45
+ )
46
+ end
47
+
48
+ def request
49
+ @request ||= stub('Request').tap do |request|
50
+ request.stubs(:params).returns({})
51
+ request.stubs(:cookies).returns({})
52
+ request.stubs(:env).returns({})
53
+ request.stubs(:scheme).returns({})
54
+ request.stubs(:ssl?).returns(false)
55
+ end
56
+ end
57
+
58
+ def strategy
59
+ @strategy ||= OmniAuth::Strategies::OpenIDConnect.new(DummyApp.new).tap do |strategy|
60
+ strategy.options.client_options.identifier = @identifier
61
+ strategy.options.client_options.secret = @secret
62
+ strategy.stubs(:request).returns(request)
63
+ strategy.stubs(:user_info).returns(user_info)
64
+ end
65
+ end
66
+ end
metadata ADDED
@@ -0,0 +1,266 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: omniauth-openid-connector
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.1.2
5
+ platform: ruby
6
+ authors:
7
+ - Danial Oberg
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2017-07-07 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: omniauth
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: 1.6.1
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: 1.6.1
27
+ - !ruby/object:Gem::Dependency
28
+ name: openid_connect
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: 1.1.2
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: 1.1.2
41
+ - !ruby/object:Gem::Dependency
42
+ name: addressable
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '2.4'
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '2.4'
55
+ - !ruby/object:Gem::Dependency
56
+ name: bundler
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: 1.15.1
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: 1.15.1
69
+ - !ruby/object:Gem::Dependency
70
+ name: minitest
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: mocha
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'
97
+ - !ruby/object:Gem::Dependency
98
+ name: guard
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - ">="
102
+ - !ruby/object:Gem::Version
103
+ version: '0'
104
+ type: :development
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - ">="
109
+ - !ruby/object:Gem::Version
110
+ version: '0'
111
+ - !ruby/object:Gem::Dependency
112
+ name: guard-minitest
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'
125
+ - !ruby/object:Gem::Dependency
126
+ name: guard-bundler
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: rake
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'
153
+ - !ruby/object:Gem::Dependency
154
+ name: simplecov
155
+ requirement: !ruby/object:Gem::Requirement
156
+ requirements:
157
+ - - ">="
158
+ - !ruby/object:Gem::Version
159
+ version: '0'
160
+ type: :development
161
+ prerelease: false
162
+ version_requirements: !ruby/object:Gem::Requirement
163
+ requirements:
164
+ - - ">="
165
+ - !ruby/object:Gem::Version
166
+ version: '0'
167
+ - !ruby/object:Gem::Dependency
168
+ name: pry
169
+ requirement: !ruby/object:Gem::Requirement
170
+ requirements:
171
+ - - ">="
172
+ - !ruby/object:Gem::Version
173
+ version: '0'
174
+ type: :development
175
+ prerelease: false
176
+ version_requirements: !ruby/object:Gem::Requirement
177
+ requirements:
178
+ - - ">="
179
+ - !ruby/object:Gem::Version
180
+ version: '0'
181
+ - !ruby/object:Gem::Dependency
182
+ name: coveralls
183
+ requirement: !ruby/object:Gem::Requirement
184
+ requirements:
185
+ - - ">="
186
+ - !ruby/object:Gem::Version
187
+ version: '0'
188
+ type: :development
189
+ prerelease: false
190
+ version_requirements: !ruby/object:Gem::Requirement
191
+ requirements:
192
+ - - ">="
193
+ - !ruby/object:Gem::Version
194
+ version: '0'
195
+ - !ruby/object:Gem::Dependency
196
+ name: faker
197
+ requirement: !ruby/object:Gem::Requirement
198
+ requirements:
199
+ - - ">="
200
+ - !ruby/object:Gem::Version
201
+ version: '0'
202
+ type: :development
203
+ prerelease: false
204
+ version_requirements: !ruby/object:Gem::Requirement
205
+ requirements:
206
+ - - ">="
207
+ - !ruby/object:Gem::Version
208
+ version: '0'
209
+ description: OpenID Connect Strategy for OmniAuth
210
+ email:
211
+ - doberg@verisys.com
212
+ executables: []
213
+ extensions: []
214
+ extra_rdoc_files: []
215
+ files:
216
+ - ".gitignore"
217
+ - ".travis.yml"
218
+ - Gemfile
219
+ - Guardfile
220
+ - LICENSE.txt
221
+ - README.md
222
+ - Rakefile
223
+ - lib/omniauth-openid-connect.rb
224
+ - lib/omniauth/openid_connect.rb
225
+ - lib/omniauth/openid_connect/errors.rb
226
+ - lib/omniauth/openid_connect/version.rb
227
+ - lib/omniauth/strategies/openid_connect.rb
228
+ - omniauth-openid-connector.gemspec
229
+ - test/fixtures/id_token.txt
230
+ - test/fixtures/jwks.json
231
+ - test/fixtures/test.crt
232
+ - test/lib/omniauth/openid_connect/version_test.rb
233
+ - test/lib/omniauth/strategies/openid_connect_test.rb
234
+ - test/test_helper.rb
235
+ homepage: https://github.com/doberg/omniauth-openid-connector
236
+ licenses:
237
+ - MIT
238
+ metadata: {}
239
+ post_install_message:
240
+ rdoc_options: []
241
+ require_paths:
242
+ - lib
243
+ required_ruby_version: !ruby/object:Gem::Requirement
244
+ requirements:
245
+ - - ">="
246
+ - !ruby/object:Gem::Version
247
+ version: '0'
248
+ required_rubygems_version: !ruby/object:Gem::Requirement
249
+ requirements:
250
+ - - ">="
251
+ - !ruby/object:Gem::Version
252
+ version: '0'
253
+ requirements: []
254
+ rubyforge_project:
255
+ rubygems_version: 2.4.5.1
256
+ signing_key:
257
+ specification_version: 4
258
+ summary: OpenID Connect Strategy for OmniAuth
259
+ test_files:
260
+ - test/fixtures/id_token.txt
261
+ - test/fixtures/jwks.json
262
+ - test/fixtures/test.crt
263
+ - test/lib/omniauth/openid_connect/version_test.rb
264
+ - test/lib/omniauth/strategies/openid_connect_test.rb
265
+ - test/test_helper.rb
266
+ has_rdoc: