omniauth-pixelpin 1.1.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: f4ac8e3dfdcf06437d1cc683672babbc3b591bbf
4
+ data.tar.gz: a430367cf8071233ff603b81ba35f0f48fd29a98
5
+ SHA512:
6
+ metadata.gz: 74cbbf4ad91e2d8db6bfd8f60230db03df5b975ce3ebf532b523a8635b599d161f614c14ef4df23ba58e62e4baedb4daec1a8a7764c0abc59c82664d70eb0082
7
+ data.tar.gz: 856a1c350414f00011688e0be0b4e08890a90b2a7f53a7a290400de6052dda4e1b672be36f469b31b3d1c2a8b5759d0f716d84d4766204c20a9226d2e35ef199
@@ -0,0 +1 @@
1
+ require "omniauth/pixelpin"
@@ -0,0 +1,3 @@
1
+ require "omniauth/pixelpin/errors"
2
+ require "omniauth/pixelpin/version"
3
+ require "omniauth/strategies/pixelpin"
@@ -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.1"
4
+ end
5
+ end
@@ -0,0 +1,284 @@
1
+ require 'addressable/uri'
2
+ require 'timeout'
3
+ require 'net/http'
4
+ require 'open-uri'
5
+ require 'omniauth'
6
+ require 'openid_connect'
7
+ require 'json'
8
+
9
+ module OmniAuth
10
+ module Strategies
11
+ class OpenIDConnect
12
+ include OmniAuth::Strategy
13
+
14
+ option :client_options, {
15
+ identifier: nil,
16
+ secret: nil,
17
+ redirect_uri: nil,
18
+ scheme: "https",
19
+ host: "login.pixelpin.io",
20
+ port: 443,
21
+ authorization_endpoint: "https://login.pixelpin.io/connect/authorize",
22
+ token_endpoint: "https://login.pixelpin.io/connect/token",
23
+ userinfo_endpoint: "https://login.pixelpin.io/connect/userinfo",
24
+ jwks_uri: 'https://login.pixelpin.io/.well-known/jwks'
25
+ }
26
+ option :issuer, "https://login.pixelpin.io/"
27
+ option :discovery, true
28
+ option :client_signing_alg
29
+ option :client_jwk_signing_key
30
+ option :client_x509_signing_key
31
+ option :scope, [:openid]
32
+ option :response_type, "code"
33
+ option :state
34
+ option :response_mode
35
+ option :display, nil #, [:page, :popup, :touch, :wap]
36
+ option :prompt, nil #, [:none, :login, :consent, :select_account]
37
+ option :hd, nil
38
+ option :max_age
39
+ option :ui_locales
40
+ option :id_token_hint
41
+ option :login_hint
42
+ option :acr_values
43
+ option :send_nonce, true
44
+ option :send_scope_to_token_endpoint, true
45
+ option :client_auth_method
46
+
47
+ uid { user_info.sub }
48
+
49
+ def formatted_address
50
+ formatted_address = HashWithIndifferentAccess.new(user_info.raw_attributes)
51
+ end
52
+
53
+ def address
54
+ if formatted_address["address"].nil?
55
+ address = JSON.parse('{
56
+ "street_address": "",
57
+ "country": "",
58
+ "region": "",
59
+ "locality": "",
60
+ "postal_code": ""
61
+ }')
62
+ else
63
+ address = ActiveSupport::JSON.decode(formatted_address["address"])
64
+ end
65
+ end
66
+
67
+ info do
68
+ {
69
+ name: user_info.name,
70
+ email: user_info.email,
71
+ nickname: user_info.preferred_username,
72
+ first_name: user_info.given_name,
73
+ last_name: user_info.family_name,
74
+ gender: user_info.gender,
75
+ phone: user_info.phone_number,
76
+ birthdate: user_info.birthdate,
77
+ street_address: address["street_address"],
78
+ country: address["country"],
79
+ region: address["region"],
80
+ city: address["locality"],
81
+ zip: address["postal_code"],
82
+ urls: { website: user_info.website }
83
+ }
84
+ end
85
+
86
+ def user_info
87
+ address = JSON.parse(user_info.address)
88
+
89
+ end
90
+
91
+ extra do
92
+ {raw_info: user_info.raw_attributes}
93
+ end
94
+
95
+ credentials do
96
+ {
97
+ id_token: access_token.id_token,
98
+ token: access_token.access_token,
99
+ refresh_token: access_token.refresh_token,
100
+ expires_in: access_token.expires_in,
101
+ scope: access_token.scope
102
+ }
103
+ end
104
+
105
+ def client
106
+ @client ||= ::OpenIDConnect::Client.new(client_options)
107
+ end
108
+
109
+ def config
110
+ cache_options = {
111
+ host:client_options.host,
112
+ port:client_options.port
113
+ }
114
+ @config ||= ::OpenIDConnect::Discovery::Provider::Config.discover!(options.issuer, cache_options = [client_options.host, client_options.port])
115
+ end
116
+
117
+ def request_phase
118
+ options.issuer = issuer if options.issuer.blank?
119
+ discover! if options.discovery
120
+ redirect authorize_uri
121
+ end
122
+
123
+ def callback_phase
124
+ error = request.params['error_reason'] || request.params['error']
125
+ if error
126
+ raise CallbackError.new(request.params['error'], request.params['error_description'] || request.params['error_reason'], request.params['error_uri'])
127
+ elsif request.params['state'].to_s.empty? || request.params['state'] != stored_state
128
+ return Rack::Response.new(['401 Unauthorized'], 401).finish
129
+ elsif !request.params["code"]
130
+ return fail!(:missing_code, OmniAuth::OpenIDConnect::MissingCodeError.new(request.params["error"]))
131
+ else
132
+ options.issuer = issuer if options.issuer.blank?
133
+ discover! if options.discovery
134
+ client.redirect_uri = client_options.redirect_uri
135
+ client.authorization_code = authorization_code
136
+ access_token
137
+ super
138
+ end
139
+ rescue CallbackError => e
140
+ fail!(:invalid_credentials, e)
141
+ rescue ::Timeout::Error, ::Errno::ETIMEDOUT => e
142
+ fail!(:timeout, e)
143
+ rescue ::SocketError => e
144
+ fail!(:failed_to_connect, e)
145
+ end
146
+
147
+
148
+ def authorization_code
149
+ request.params["code"]
150
+ end
151
+
152
+ def authorize_uri
153
+ client.redirect_uri = client_options.redirect_uri
154
+ opts = {
155
+ response_type: options.response_type,
156
+ scope: options.scope,
157
+ state: new_state,
158
+ nonce: (new_nonce if options.send_nonce),
159
+ hd: options.hd,
160
+ }
161
+ client.authorization_uri(opts.reject{|k,v| v.nil?})
162
+ end
163
+
164
+ def public_key
165
+ if options.discovery
166
+ config.jwks
167
+ else
168
+ key_or_secret
169
+ end
170
+ end
171
+
172
+ private
173
+
174
+ def issuer
175
+ resource = "#{client_options.scheme}://#{client_options.host}" + ((client_options.port) ? ":#{client_options.port.to_s}" : '')
176
+ ::OpenIDConnect::Discovery::Provider.discover!(resource).issuer
177
+ end
178
+
179
+ def discover!
180
+ client_options.authorization_endpoint = config.authorization_endpoint
181
+ client_options.token_endpoint = config.token_endpoint
182
+ client_options.userinfo_endpoint = config.userinfo_endpoint
183
+ client_options.jwks_uri = config.jwks_uri
184
+ end
185
+
186
+ def user_info
187
+ @user_info ||= access_token.userinfo!
188
+ end
189
+
190
+ def access_token
191
+ @access_token ||= lambda {
192
+ _access_token = client.access_token!(
193
+ scope: (options.scope if options.send_scope_to_token_endpoint),
194
+ client_auth_method: options.client_auth_method
195
+ )
196
+ _id_token = decode_id_token _access_token.id_token
197
+ _id_token.verify!(
198
+ issuer: options.issuer,
199
+ client_id: client_options.identifier,
200
+ nonce: stored_nonce
201
+ )
202
+ _access_token
203
+ }.call()
204
+ end
205
+
206
+ def decode_id_token(id_token)
207
+ ::OpenIDConnect::ResponseObject::IdToken.decode(id_token, public_key)
208
+ end
209
+
210
+
211
+ def client_options
212
+ options.client_options
213
+ end
214
+
215
+ def new_state
216
+ state = options.state.call if options.state.respond_to? :call
217
+ session['omniauth.state'] = state || SecureRandom.hex(16)
218
+ end
219
+
220
+ def stored_state
221
+ session.delete('omniauth.state')
222
+ end
223
+
224
+ def new_nonce
225
+ session['omniauth.nonce'] = SecureRandom.hex(16)
226
+ end
227
+
228
+ def stored_nonce
229
+ session.delete('omniauth.nonce')
230
+ end
231
+
232
+ def session
233
+ @env.nil? ? {} : super
234
+ end
235
+
236
+ def key_or_secret
237
+ case options.client_signing_alg
238
+ when :HS256, :HS384, :HS512
239
+ return client_options.secret
240
+ when :RS256, :RS384, :RS512
241
+ if options.client_jwk_signing_key
242
+ return parse_jwk_key(options.client_jwk_signing_key)
243
+ elsif options.client_x509_signing_key
244
+ return parse_x509_key(options.client_x509_signing_key)
245
+ end
246
+ else
247
+ end
248
+ end
249
+
250
+ def parse_x509_key(key)
251
+ OpenSSL::X509::Certificate.new(key).public_key
252
+ end
253
+
254
+ def parse_jwk_key(key)
255
+ json = JSON.parse(key)
256
+ if json.has_key?('keys')
257
+ JSON::JWK::Set.new json['keys']
258
+ else
259
+ JSON::JWK.new json
260
+ end
261
+ end
262
+
263
+ def decode(str)
264
+ UrlSafeBase64.decode64(str).unpack('B*').first.to_i(2).to_s
265
+ end
266
+
267
+ class CallbackError < StandardError
268
+ attr_accessor :error, :error_reason, :error_uri
269
+
270
+ def initialize(error, error_reason=nil, error_uri=nil)
271
+ self.error = error
272
+ self.error_reason = error_reason
273
+ self.error_uri = error_uri
274
+ end
275
+
276
+ def message
277
+ [error, error_reason, error_uri].compact.join(' | ')
278
+ end
279
+ end
280
+ end
281
+ end
282
+ end
283
+
284
+ OmniAuth.config.add_camelization 'pixelpin', 'OpenIDConnect'
metadata ADDED
@@ -0,0 +1,251 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: omniauth-pixelpin
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.1.1
5
+ platform: ruby
6
+ authors:
7
+ - Callum Brankin
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2017-06-02 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.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.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.0'
34
+ - - ">="
35
+ - !ruby/object:Gem::Version
36
+ version: 1.0.3
37
+ type: :runtime
38
+ prerelease: false
39
+ version_requirements: !ruby/object:Gem::Requirement
40
+ requirements:
41
+ - - "~>"
42
+ - !ruby/object:Gem::Version
43
+ version: '1.0'
44
+ - - ">="
45
+ - !ruby/object:Gem::Version
46
+ version: 1.0.3
47
+ - !ruby/object:Gem::Dependency
48
+ name: addressable
49
+ requirement: !ruby/object:Gem::Requirement
50
+ requirements:
51
+ - - "~>"
52
+ - !ruby/object:Gem::Version
53
+ version: '2.3'
54
+ type: :runtime
55
+ prerelease: false
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ requirements:
58
+ - - "~>"
59
+ - !ruby/object:Gem::Version
60
+ version: '2.3'
61
+ - !ruby/object:Gem::Dependency
62
+ name: bundler
63
+ requirement: !ruby/object:Gem::Requirement
64
+ requirements:
65
+ - - "~>"
66
+ - !ruby/object:Gem::Version
67
+ version: '1.5'
68
+ type: :development
69
+ prerelease: false
70
+ version_requirements: !ruby/object:Gem::Requirement
71
+ requirements:
72
+ - - "~>"
73
+ - !ruby/object:Gem::Version
74
+ version: '1.5'
75
+ - !ruby/object:Gem::Dependency
76
+ name: minitest
77
+ requirement: !ruby/object:Gem::Requirement
78
+ requirements:
79
+ - - ">="
80
+ - !ruby/object:Gem::Version
81
+ version: '0'
82
+ type: :development
83
+ prerelease: false
84
+ version_requirements: !ruby/object:Gem::Requirement
85
+ requirements:
86
+ - - ">="
87
+ - !ruby/object:Gem::Version
88
+ version: '0'
89
+ - !ruby/object:Gem::Dependency
90
+ name: mocha
91
+ requirement: !ruby/object:Gem::Requirement
92
+ requirements:
93
+ - - ">="
94
+ - !ruby/object:Gem::Version
95
+ version: '0'
96
+ type: :development
97
+ prerelease: false
98
+ version_requirements: !ruby/object:Gem::Requirement
99
+ requirements:
100
+ - - ">="
101
+ - !ruby/object:Gem::Version
102
+ version: '0'
103
+ - !ruby/object:Gem::Dependency
104
+ name: guard
105
+ requirement: !ruby/object:Gem::Requirement
106
+ requirements:
107
+ - - ">="
108
+ - !ruby/object:Gem::Version
109
+ version: '0'
110
+ type: :development
111
+ prerelease: false
112
+ version_requirements: !ruby/object:Gem::Requirement
113
+ requirements:
114
+ - - ">="
115
+ - !ruby/object:Gem::Version
116
+ version: '0'
117
+ - !ruby/object:Gem::Dependency
118
+ name: guard-minitest
119
+ requirement: !ruby/object:Gem::Requirement
120
+ requirements:
121
+ - - ">="
122
+ - !ruby/object:Gem::Version
123
+ version: '0'
124
+ type: :development
125
+ prerelease: false
126
+ version_requirements: !ruby/object:Gem::Requirement
127
+ requirements:
128
+ - - ">="
129
+ - !ruby/object:Gem::Version
130
+ version: '0'
131
+ - !ruby/object:Gem::Dependency
132
+ name: guard-bundler
133
+ requirement: !ruby/object:Gem::Requirement
134
+ requirements:
135
+ - - ">="
136
+ - !ruby/object:Gem::Version
137
+ version: '0'
138
+ type: :development
139
+ prerelease: false
140
+ version_requirements: !ruby/object:Gem::Requirement
141
+ requirements:
142
+ - - ">="
143
+ - !ruby/object:Gem::Version
144
+ version: '0'
145
+ - !ruby/object:Gem::Dependency
146
+ name: rake
147
+ requirement: !ruby/object:Gem::Requirement
148
+ requirements:
149
+ - - ">="
150
+ - !ruby/object:Gem::Version
151
+ version: '0'
152
+ type: :development
153
+ prerelease: false
154
+ version_requirements: !ruby/object:Gem::Requirement
155
+ requirements:
156
+ - - ">="
157
+ - !ruby/object:Gem::Version
158
+ version: '0'
159
+ - !ruby/object:Gem::Dependency
160
+ name: simplecov
161
+ requirement: !ruby/object:Gem::Requirement
162
+ requirements:
163
+ - - ">="
164
+ - !ruby/object:Gem::Version
165
+ version: '0'
166
+ type: :development
167
+ prerelease: false
168
+ version_requirements: !ruby/object:Gem::Requirement
169
+ requirements:
170
+ - - ">="
171
+ - !ruby/object:Gem::Version
172
+ version: '0'
173
+ - !ruby/object:Gem::Dependency
174
+ name: pry
175
+ requirement: !ruby/object:Gem::Requirement
176
+ requirements:
177
+ - - ">="
178
+ - !ruby/object:Gem::Version
179
+ version: '0'
180
+ type: :development
181
+ prerelease: false
182
+ version_requirements: !ruby/object:Gem::Requirement
183
+ requirements:
184
+ - - ">="
185
+ - !ruby/object:Gem::Version
186
+ version: '0'
187
+ - !ruby/object:Gem::Dependency
188
+ name: coveralls
189
+ requirement: !ruby/object:Gem::Requirement
190
+ requirements:
191
+ - - ">="
192
+ - !ruby/object:Gem::Version
193
+ version: '0'
194
+ type: :development
195
+ prerelease: false
196
+ version_requirements: !ruby/object:Gem::Requirement
197
+ requirements:
198
+ - - ">="
199
+ - !ruby/object:Gem::Version
200
+ version: '0'
201
+ - !ruby/object:Gem::Dependency
202
+ name: faker
203
+ requirement: !ruby/object:Gem::Requirement
204
+ requirements:
205
+ - - ">="
206
+ - !ruby/object:Gem::Version
207
+ version: '0'
208
+ type: :development
209
+ prerelease: false
210
+ version_requirements: !ruby/object:Gem::Requirement
211
+ requirements:
212
+ - - ">="
213
+ - !ruby/object:Gem::Version
214
+ version: '0'
215
+ description: PixelPin OpenID Connect Strategy for OmniAuth
216
+ email:
217
+ - callum@pixelpin.co.uk
218
+ executables: []
219
+ extensions: []
220
+ extra_rdoc_files: []
221
+ files:
222
+ - lib/omniauth-pixelpin.rb
223
+ - lib/omniauth/pixelpin.rb
224
+ - lib/omniauth/pixelpin/errors.rb
225
+ - lib/omniauth/pixelpin/version.rb
226
+ - lib/omniauth/strategies/pixelpin.rb
227
+ homepage: https://github.com/PixelPinPlugins/omniauth-pixelpin
228
+ licenses:
229
+ - MIT
230
+ metadata: {}
231
+ post_install_message:
232
+ rdoc_options: []
233
+ require_paths:
234
+ - lib
235
+ required_ruby_version: !ruby/object:Gem::Requirement
236
+ requirements:
237
+ - - ">="
238
+ - !ruby/object:Gem::Version
239
+ version: '0'
240
+ required_rubygems_version: !ruby/object:Gem::Requirement
241
+ requirements:
242
+ - - ">="
243
+ - !ruby/object:Gem::Version
244
+ version: '0'
245
+ requirements: []
246
+ rubyforge_project:
247
+ rubygems_version: 2.5.2
248
+ signing_key:
249
+ specification_version: 4
250
+ summary: PixelPin OpenID Connect Strategy for OmniAuth
251
+ test_files: []