omniauth-test 0.0.8 → 0.0.9

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.
@@ -1,45 +1,206 @@
1
- require 'omniauth/oauth'
2
- require 'multi_json'
3
-
1
+ require 'omniauth/strategies/oauth2'
2
+ require 'base64'
3
+ require 'openssl'
4
+ require 'rack/utils'
5
+ require 'uri'
6
+
4
7
  module OmniAuth
5
- module Strategies
6
- class Test < OAuth2
7
-
8
- def initialize(app, api_key = nil, secret_key = nil, options = {}, &block)
9
- client_options = {
10
- :site => 'http://auth.cibplus.com',
11
- :authorize_url => "http://localhost:3000/auth/test/callback",
12
- :access_token_url => "http://auth.cibplus.com/oauth/token"
13
- }
14
- super(app, :test, api_key, secret_key, client_options, &block)
15
- end
16
-
17
- protected
18
-
19
- def user_data
20
- #@data ||= MultiJson.decode(@access_token.get("/auth/my_strategy/user.json"))
21
- end
22
-
23
- def request_phase
24
- options[:scope] ||= "read"
25
- super
26
- end
27
-
28
- def user_hash
29
- user_data
30
- end
31
-
32
- def auth_hash
33
- OmniAuth::Utils.deep_merge(super, {
34
- 'uid' => user_data["uid"],
35
- 'user_info' => user_data['user_info'],
36
- 'extra' => {
37
- 'admin' => user_data['extra']['admin'],
38
- 'first_name' => user_data['extra']['first_name'],
39
- 'last_name' => user_data['extra']['last_name'],
40
- }
41
- })
42
- end
8
+ module Strategies
9
+ class Test < OmniAuth::Strategies::OAuth2
10
+ class NoAuthorizationCodeError < StandardError; end
11
+ class UnknownSignatureAlgorithmError < NotImplementedError; end
12
+
13
+ DEFAULT_SCOPE = 'email'
14
+
15
+ option :client_options, {
16
+ :site => 'https://auth.cibplus.com',
17
+ :authorize_url => "https://www.facebook.com/dialog/oauth",
18
+ :token_url => '/oauth/token'
19
+ }
20
+
21
+ option :token_params, {
22
+ :parse => :query
23
+ }
24
+
25
+ option :access_token_options, {
26
+ :header_format => 'OAuth %s',
27
+ :param_name => 'access_token'
28
+ }
29
+
30
+ option :authorize_options, [:scope, :display, :auth_type]
31
+
32
+ uid { raw_info['id'] }
33
+
34
+ info do
35
+ prune!({
36
+ 'nickname' => raw_info['username'],
37
+ 'email' => raw_info['email'],
38
+ 'name' => raw_info['name'],
39
+ 'first_name' => raw_info['first_name'],
40
+ 'last_name' => raw_info['last_name'],
41
+ 'image' => image_url(uid, options),
42
+ 'description' => raw_info['bio'],
43
+ 'urls' => {
44
+ 'Facebook' => raw_info['link'],
45
+ 'Website' => raw_info['website']
46
+ },
47
+ 'location' => (raw_info['location'] || {})['name'],
48
+ 'verified' => raw_info['verified']
49
+ })
50
+ end
51
+
52
+ extra do
53
+ hash = {}
54
+ hash['raw_info'] = raw_info unless skip_info?
55
+ prune! hash
56
+ end
57
+
58
+ def raw_info
59
+ @raw_info ||= access_token.get('/me', info_options).parsed || {}
60
+ end
61
+
62
+ def info_options
63
+ params = {:appsecret_proof => appsecret_proof}
64
+ params.merge!({:fields => options[:info_fields]}) if options[:info_fields]
65
+ params.merge!({:locale => options[:locale]}) if options[:locale]
66
+
67
+ { :params => params }
68
+ end
69
+
70
+ def callback_phase
71
+ with_authorization_code! do
72
+ super
73
+ end
74
+ rescue NoAuthorizationCodeError => e
75
+ fail!(:no_authorization_code, e)
76
+ rescue UnknownSignatureAlgorithmError => e
77
+ fail!(:unknown_signature_algoruthm, e)
78
+ end
79
+
80
+ # NOTE If we're using code from the signed request then FB sets the redirect_uri to '' during the authorize
81
+ # phase and it must match during the access_token phase:
82
+ # https://github.com/facebook/facebook-php-sdk/blob/master/src/base_facebook.php#L477
83
+ def callback_url
84
+ if @authorization_code_from_signed_request_in_cookie
85
+ ''
86
+ else
87
+ options[:callback_url] || super
88
+ end
89
+ end
90
+
91
+ def access_token_options
92
+ options.access_token_options.inject({}) { |h,(k,v)| h[k.to_sym] = v; h }
93
+ end
94
+
95
+ # You can pass +display+, +scope+, or +auth_type+ params to the auth request, if you need to set them dynamically.
96
+ # You can also set these options in the OmniAuth config :authorize_params option.
97
+ #
98
+ # For example: /auth/facebook?display=popup
99
+ def authorize_params
100
+ super.tap do |params|
101
+ %w[display scope auth_type].each do |v|
102
+ if request.params[v]
103
+ params[v.to_sym] = request.params[v]
104
+ end
105
+ end
106
+
107
+ params[:scope] ||= DEFAULT_SCOPE
108
+ end
109
+ end
110
+
111
+ protected
112
+
113
+ def build_access_token
114
+ super.tap do |token|
115
+ token.options.merge!(access_token_options)
116
+ end
117
+ end
118
+
119
+ private
120
+
121
+ def signed_request_from_cookie
122
+ @signed_request_from_cookie ||= raw_signed_request_from_cookie && parse_signed_request(raw_signed_request_from_cookie)
123
+ end
124
+
125
+ def raw_signed_request_from_cookie
126
+ request.cookies["fbsr_#{client.id}"]
127
+ end
128
+
129
+ # Picks the authorization code in order, from:
130
+ #
131
+ # 1. The request 'code' param (manual callback from standard server-side flow)
132
+ # 2. A signed request from cookie (passed from the client during the client-side flow)
133
+ def with_authorization_code!
134
+ if request.params.key?('code')
135
+ yield
136
+ elsif code_from_signed_request = signed_request_from_cookie && signed_request_from_cookie['code']
137
+ request.params['code'] = code_from_signed_request
138
+ @authorization_code_from_signed_request_in_cookie = true
139
+ # NOTE The code from the signed fbsr_XXX cookie is set by the FB JS SDK will confirm that the identity of the
140
+ # user contained in the signed request matches the user loading the app.
141
+ original_provider_ignores_state = options.provider_ignores_state
142
+ options.provider_ignores_state = true
143
+ begin
144
+ yield
145
+ ensure
146
+ request.params.delete('code')
147
+ @authorization_code_from_signed_request_in_cookie = false
148
+ options.provider_ignores_state = original_provider_ignores_state
149
+ end
150
+ else
151
+ raise NoAuthorizationCodeError, 'must pass either a `code` (via URL or by an `fbsr_XXX` signed request cookie)'
152
+ end
153
+ end
154
+
155
+ def prune!(hash)
156
+ hash.delete_if do |_, value|
157
+ prune!(value) if value.is_a?(Hash)
158
+ value.nil? || (value.respond_to?(:empty?) && value.empty?)
159
+ end
160
+ end
161
+
162
+ def parse_signed_request(value)
163
+ signature, encoded_payload = value.split('.')
164
+ return if signature.nil?
165
+
166
+ decoded_hex_signature = base64_decode_url(signature)
167
+ decoded_payload = MultiJson.decode(base64_decode_url(encoded_payload))
168
+
169
+ unless decoded_payload['algorithm'] == 'HMAC-SHA256'
170
+ raise UnknownSignatureAlgorithmError, "unknown algorithm: #{decoded_payload['algorithm']}"
171
+ end
172
+
173
+ if valid_signature?(client.secret, decoded_hex_signature, encoded_payload)
174
+ decoded_payload
175
+ end
176
+ end
177
+
178
+ def valid_signature?(secret, signature, payload, algorithm = OpenSSL::Digest::SHA256.new)
179
+ OpenSSL::HMAC.digest(algorithm, secret, payload) == signature
180
+ end
181
+
182
+ def base64_decode_url(value)
183
+ value += '=' * (4 - value.size.modulo(4))
184
+ Base64.decode64(value.tr('-_', '+/'))
185
+ end
186
+
187
+ def image_url(uid, options)
188
+ uri_class = options[:secure_image_url] ? URI::HTTPS : URI::HTTP
189
+ url = uri_class.build({:host => 'graph.facebook.com', :path => "/#{uid}/picture"})
190
+
191
+ query = if options[:image_size].is_a?(String)
192
+ { :type => options[:image_size] }
193
+ elsif options[:image_size].is_a?(Hash)
194
+ options[:image_size]
195
+ end
196
+ url.query = Rack::Utils.build_query(query) if query
197
+
198
+ url.to_s
199
+ end
200
+
201
+ def appsecret_proof
202
+ @appsecret_proof ||= OpenSSL::HMAC.hexdigest(OpenSSL::Digest::SHA256.new, client.secret, access_token.token)
203
+ end
204
+ end
43
205
  end
44
- end
45
- end
206
+ end
@@ -1,3 +1,3 @@
1
1
  module OmniauthTest
2
- VERSION = "0.0.8"
2
+ VERSION = "0.0.9"
3
3
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: omniauth-test
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.8
4
+ version: 0.0.9
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors: