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.
- data/lib/omniauth/strategies/test.rb +204 -43
- data/lib/omniauth/test/version.rb +1 -1
- metadata +1 -1
@@ -1,45 +1,206 @@
|
|
1
|
-
require 'omniauth/
|
2
|
-
require '
|
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
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
:
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
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
|
-
|
45
|
-
end
|
206
|
+
end
|