Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Newer
Older
100755 343 lines (304 sloc) 15.271 kB
76c4b80 @arsduo Separated API into its own file, and reorganized the require statements.
authored
1 # OpenSSL and Base64 are required to support signed_request
2 require 'openssl'
3 require 'base64'
4
a045e6f @arsduo Split OAuth into its own file.
authored
5 module Koala
6 module Facebook
7 class OAuth
8 attr_reader :app_id, :app_secret, :oauth_callback_url
c4e0a84 @arsduo Merge branch 'fb_exchange_token' of https://github.com/etiennebarrie/…
authored
9
63cfd87 @arsduo Added more YARD documentation in OAuth.
authored
10 # Creates a new OAuth client.
11 #
12 # @param app_id [String, Integer] a Facebook application ID
13 # @param app_secret a Facebook application secret
14 # @param oauth_callback_url the URL in your app to which users authenticating with OAuth will be sent
a045e6f @arsduo Split OAuth into its own file.
authored
15 def initialize(app_id, app_secret, oauth_callback_url = nil)
5a7c7fa @arsduo Additional documentation
authored
16 @app_id = app_id
a045e6f @arsduo Split OAuth into its own file.
authored
17 @app_secret = app_secret
18 @oauth_callback_url = oauth_callback_url
19 end
c4e0a84 @arsduo Merge branch 'fb_exchange_token' of https://github.com/etiennebarrie/…
authored
20
63cfd87 @arsduo Added more YARD documentation in OAuth.
authored
21 # Parses the cookie set Facebook's JavaScript SDK.
22 #
d2a095d @arsduo Add note to OAuth method
authored
23 # @note this method can only be called once per session, as the OAuth code
24 # Facebook supplies can only be redeemed once. Your application
25 # must handle cross-request storage of this information; you can no
26 # longer call this method multiple times. (This works out, as the
27 # method has to make a call to FB's servers anyway, which you don't
28 # want on every call.)
63cfd87 @arsduo Added more YARD documentation in OAuth.
authored
29 #
c4e0a84 @arsduo Merge branch 'fb_exchange_token' of https://github.com/etiennebarrie/…
authored
30 # @param cookie_hash a set of cookies that includes the Facebook cookie.
63cfd87 @arsduo Added more YARD documentation in OAuth.
authored
31 # You can pass Rack/Rails/Sinatra's cookie hash directly to this method.
32 #
33 # @return the authenticated user's information as a hash, or nil.
2c3e982 @arsduo Avoid unnecessary call to Facebook for get_user_from_cookies
authored
34 def get_user_info_from_cookies(cookie_hash)
ac29641 @arsduo Added support for parsing Facebook's new signed_request cookie format.
authored
35 if signed_cookie = cookie_hash["fbsr_#{@app_id}"]
36 parse_signed_cookie(signed_cookie)
37 elsif unsigned_cookie = cookie_hash["fbs_#{@app_id}"]
38 parse_unsigned_cookie(unsigned_cookie)
a045e6f @arsduo Split OAuth into its own file.
authored
39 end
40 end
2c3e982 @arsduo Avoid unnecessary call to Facebook for get_user_from_cookies
authored
41 alias_method :get_user_info_from_cookie, :get_user_info_from_cookies
a045e6f @arsduo Split OAuth into its own file.
authored
42
43 # URLs
c4e0a84 @arsduo Merge branch 'fb_exchange_token' of https://github.com/etiennebarrie/…
authored
44
63cfd87 @arsduo Added more YARD documentation in OAuth.
authored
45 # Builds an OAuth URL, where users will be prompted to log in and for any desired permissions.
c4e0a84 @arsduo Merge branch 'fb_exchange_token' of https://github.com/etiennebarrie/…
authored
46 # When the users log in, you receive a callback with their
63cfd87 @arsduo Added more YARD documentation in OAuth.
authored
47 # See http://developers.facebook.com/docs/authentication/.
48 #
49 # @see #url_for_access_token
50 #
c4e0a84 @arsduo Merge branch 'fb_exchange_token' of https://github.com/etiennebarrie/…
authored
51 # @note The server-side authentication and dialog methods should only be used
5a7c7fa @arsduo Additional documentation
authored
52 # if your application can't use the Facebook Javascript SDK,
63cfd87 @arsduo Added more YARD documentation in OAuth.
authored
53 # which provides a much better user experience.
54 # See http://developers.facebook.com/docs/reference/javascript/.
55 #
56 # @param options any query values to add to the URL, as well as any special/required values listed below.
57 # @option options permissions an array or comma-separated string of desired permissions
61bc6b8 @arsduo Add CSRF note to url_for_oauth_code
authored
58 # @option options state a unique string to serve as a CSRF (cross-site request
59 # forgery) token -- highly recommended for security. See
60 # https://developers.facebook.com/docs/howtos/login/server-side-login/
c4e0a84 @arsduo Merge branch 'fb_exchange_token' of https://github.com/etiennebarrie/…
authored
61 #
63cfd87 @arsduo Added more YARD documentation in OAuth.
authored
62 # @raise ArgumentError if no OAuth callback was specified in OAuth#new or in options as :redirect_uri
63 #
64 # @return an OAuth URL you can send your users to
a045e6f @arsduo Split OAuth into its own file.
authored
65 def url_for_oauth_code(options = {})
66 # for permissions, see http://developers.facebook.com/docs/authentication/permissions
279ae5a @arsduo Added url_for_dialog and refactored url generators
authored
67 if permissions = options.delete(:permissions)
68 options[:scope] = permissions.is_a?(Array) ? permissions.join(",") : permissions
69 end
70 url_options = {:client_id => @app_id}.merge(options)
c4e0a84 @arsduo Merge branch 'fb_exchange_token' of https://github.com/etiennebarrie/…
authored
71
a045e6f @arsduo Split OAuth into its own file.
authored
72 # Creates the URL for oauth authorization for a given callback and optional set of permissions
18f4d96 @arsduo Support API versions in OAuth URLs
authored
73 build_url(:dialog_host, "/dialog/oauth", true, url_options)
a045e6f @arsduo Split OAuth into its own file.
authored
74 end
75
63cfd87 @arsduo Added more YARD documentation in OAuth.
authored
76 # Once you receive an OAuth code, you need to redeem it from Facebook using an appropriate URL.
77 # (This is done by your server behind the scenes.)
78 # See http://developers.facebook.com/docs/authentication/.
c4e0a84 @arsduo Merge branch 'fb_exchange_token' of https://github.com/etiennebarrie/…
authored
79 #
63cfd87 @arsduo Added more YARD documentation in OAuth.
authored
80 # @see #url_for_oauth_code
c4e0a84 @arsduo Merge branch 'fb_exchange_token' of https://github.com/etiennebarrie/…
authored
81 #
63cfd87 @arsduo Added more YARD documentation in OAuth.
authored
82 # @note (see #url_for_oauth_code)
83 #
bed3e27 @arsduo Additional documentation.
authored
84 # @param code an OAuth code received from Facebook
63cfd87 @arsduo Added more YARD documentation in OAuth.
authored
85 # @param options any additional query parameters to add to the URL
86 #
87 # @raise (see #url_for_oauth_code)
88 #
89 # @return an URL your server can query for the user's access token
a045e6f @arsduo Split OAuth into its own file.
authored
90 def url_for_access_token(code, options = {})
91 # Creates the URL for the token corresponding to a given code generated by Facebook
279ae5a @arsduo Added url_for_dialog and refactored url generators
authored
92 url_options = {
c4e0a84 @arsduo Merge branch 'fb_exchange_token' of https://github.com/etiennebarrie/…
authored
93 :client_id => @app_id,
279ae5a @arsduo Added url_for_dialog and refactored url generators
authored
94 :code => code,
95 :client_secret => @app_secret
96 }.merge(options)
18f4d96 @arsduo Support API versions in OAuth URLs
authored
97 build_url(:graph_server, "/oauth/access_token", true, url_options)
a045e6f @arsduo Split OAuth into its own file.
authored
98 end
99
63cfd87 @arsduo Added more YARD documentation in OAuth.
authored
100 # Builds a URL for a given dialog (feed, friends, OAuth, pay, send, etc.)
101 # See http://developers.facebook.com/docs/reference/dialogs/.
c4e0a84 @arsduo Merge branch 'fb_exchange_token' of https://github.com/etiennebarrie/…
authored
102 #
63cfd87 @arsduo Added more YARD documentation in OAuth.
authored
103 # @note (see #url_for_oauth_code)
104 #
105 # @param dialog_type the kind of Facebook dialog you want to show
106 # @param options any additional query parameters to add to the URL
107 #
108 # @return an URL your server can query for the user's access token
279ae5a @arsduo Added url_for_dialog and refactored url generators
authored
109 def url_for_dialog(dialog_type, options = {})
110 # some endpoints require app_id, some client_id, supply both doesn't seem to hurt
c4e0a84 @arsduo Merge branch 'fb_exchange_token' of https://github.com/etiennebarrie/…
authored
111 url_options = {:app_id => @app_id, :client_id => @app_id}.merge(options)
18f4d96 @arsduo Support API versions in OAuth URLs
authored
112 build_url(:dialog_host, "/dialog/#{dialog_type}", true, url_options)
279ae5a @arsduo Added url_for_dialog and refactored url generators
authored
113 end
c4e0a84 @arsduo Merge branch 'fb_exchange_token' of https://github.com/etiennebarrie/…
authored
114
ed62f39 @binarygeek added ability for oauth object to generate a client code using a long…
binarygeek authored
115 # Generates a 'client code' from a server side long-lived access token. With the generated
116 # code, it can be sent to a client application which can then use it to get a long-lived
117 # access token from Facebook. After which the clients can use that access token to make
118 # requests to Facebook without having to use the server token, yet the server access token
119 # remains valid.
120 # See https://developers.facebook.com/docs/facebook-login/access-tokens/#long-via-code
121 #
122 # @param access_token a user's long lived (server) access token
123 #
124 # @raise Koala::Facebook::ServerError if Facebook returns a server error (status >= 500)
125 # @raise Koala::Facebook::OAuthTokenRequestError if Facebook returns an error response (status >= 400)
126 # @raise Koala::Facebook::BadFacebookResponse if Facebook returns a blank response
127 # @raise Koala::KoalaError if response does not contain 'code' hash key
128 #
129 # @return a string of the generated 'code'
130 def generate_client_code(access_token)
8c680f0 @binarygeek changed to make backwards compatible
binarygeek authored
131 response = fetch_token_string({:redirect_uri => @oauth_callback_url, :access_token => access_token}, false, 'client_code')
ed62f39 @binarygeek added ability for oauth object to generate a client code using a long…
binarygeek authored
132
133 # Facebook returns an empty body in certain error conditions
134 if response == ''
135 raise BadFacebookResponse.new(200, '', 'generate_client_code received an error: empty response body')
136 else
137 result = MultiJson.load(response)
138 end
139
140 result.has_key?('code') ? result['code'] : raise(Koala::KoalaError.new("Facebook returned a valid response without the expected 'code' in the body (response = #{response})"))
141 end
142
279ae5a @arsduo Added url_for_dialog and refactored url generators
authored
143 # access tokens
c4e0a84 @arsduo Merge branch 'fb_exchange_token' of https://github.com/etiennebarrie/…
authored
144
bed3e27 @arsduo Additional documentation.
authored
145 # Fetches an access token, token expiration, and other info from Facebook.
146 # Useful when you've received an OAuth code using the server-side authentication process.
147 # @see url_for_oauth_code
5a7c7fa @arsduo Additional documentation
authored
148 #
149 # @note (see #url_for_oauth_code)
c4e0a84 @arsduo Merge branch 'fb_exchange_token' of https://github.com/etiennebarrie/…
authored
150 #
bed3e27 @arsduo Additional documentation.
authored
151 # @param code (see #url_for_access_token)
152 # @param options any additional parameters to send to Facebook when redeeming the token
c4e0a84 @arsduo Merge branch 'fb_exchange_token' of https://github.com/etiennebarrie/…
authored
153 #
c7a741f @archfear Updated error handling logic.
archfear authored
154 # @raise Koala::Facebook::OAuthTokenRequestError if Facebook returns an error response
c4e0a84 @arsduo Merge branch 'fb_exchange_token' of https://github.com/etiennebarrie/…
authored
155 #
156 # @return a hash of the access token info returned by Facebook (token, expiration, etc.)
47c26ff @arsduo Split OAuth into its own file.
authored
157 def get_access_token_info(code, options = {})
a045e6f @arsduo Split OAuth into its own file.
authored
158 # convenience method to get a parsed token from Facebook for a given code
159 # should this require an OAuth callback URL?
ac29641 @arsduo Added support for parsing Facebook's new signed_request cookie format.
authored
160 get_token_from_server({:code => code, :redirect_uri => options[:redirect_uri] || @oauth_callback_url}, false, options)
a045e6f @arsduo Split OAuth into its own file.
authored
161 end
162
bed3e27 @arsduo Additional documentation.
authored
163 # Fetches the access token (ignoring expiration and other info) from Facebook.
164 # Useful when you've received an OAuth code using the server-side authentication process.
165 # @see get_access_token_info
c4e0a84 @arsduo Merge branch 'fb_exchange_token' of https://github.com/etiennebarrie/…
authored
166 #
5a7c7fa @arsduo Additional documentation
authored
167 # @note (see #url_for_oauth_code)
c4e0a84 @arsduo Merge branch 'fb_exchange_token' of https://github.com/etiennebarrie/…
authored
168 #
bed3e27 @arsduo Additional documentation.
authored
169 # @param (see #get_access_token_info)
170 #
171 # @raise (see #get_access_token_info)
172 #
5a7c7fa @arsduo Additional documentation
authored
173 # @return the access token
47c26ff @arsduo Split OAuth into its own file.
authored
174 def get_access_token(code, options = {})
a045e6f @arsduo Split OAuth into its own file.
authored
175 # upstream methods will throw errors if needed
47c26ff @arsduo Split OAuth into its own file.
authored
176 if info = get_access_token_info(code, options)
a045e6f @arsduo Split OAuth into its own file.
authored
177 string = info["access_token"]
178 end
179 end
180
5a7c7fa @arsduo Additional documentation
authored
181 # Fetches the application's access token, along with any other information provided by Facebook.
182 # See http://developers.facebook.com/docs/authentication/ (search for App Login).
c4e0a84 @arsduo Merge branch 'fb_exchange_token' of https://github.com/etiennebarrie/…
authored
183 #
5a7c7fa @arsduo Additional documentation
authored
184 # @param options any additional parameters to send to Facebook when redeeming the token
185 #
186 # @return the application access token and other information (expiration, etc.)
47c26ff @arsduo Split OAuth into its own file.
authored
187 def get_app_access_token_info(options = {})
a045e6f @arsduo Split OAuth into its own file.
authored
188 # convenience method to get a the application's sessionless access token
ff5f704 @miv :grant_type instead of :type and client_credentials instead of client…
miv authored
189 get_token_from_server({:grant_type => 'client_credentials'}, true, options)
a045e6f @arsduo Split OAuth into its own file.
authored
190 end
191
5a7c7fa @arsduo Additional documentation
authored
192 # Fetches the application's access token (ignoring expiration and other info).
193 # @see get_app_access_token_info
c4e0a84 @arsduo Merge branch 'fb_exchange_token' of https://github.com/etiennebarrie/…
authored
194 #
5a7c7fa @arsduo Additional documentation
authored
195 # @param (see #get_app_access_token_info)
196 #
197 # @return the application access token
47c26ff @arsduo Split OAuth into its own file.
authored
198 def get_app_access_token(options = {})
199 if info = get_app_access_token_info(options)
a045e6f @arsduo Split OAuth into its own file.
authored
200 string = info["access_token"]
201 end
202 end
203
2446509 @etiennebarrie Add support for access token exchange
etiennebarrie authored
204 # Fetches an access_token with extended expiration time, along with any other information provided by Facebook.
205 # See https://developers.facebook.com/docs/offline-access-deprecation/#extend_token (search for fb_exchange_token).
206 #
207 # @param access_token the access token to exchange
208 # @param options any additional parameters to send to Facebook when exchanging tokens.
209 #
210 # @return the access token with extended expiration time and other information (expiration, etc.)
1c404f3 @etiennebarrie Rename get_exchange_access_token[_info]
etiennebarrie authored
211 def exchange_access_token_info(access_token, options = {})
2446509 @etiennebarrie Add support for access token exchange
etiennebarrie authored
212 get_token_from_server({
213 :grant_type => 'fb_exchange_token',
214 :fb_exchange_token => access_token
215 }, true, options)
216 end
217
218 # Fetches an access token with extended expiration time (ignoring expiration and other info).
c4e0a84 @arsduo Merge branch 'fb_exchange_token' of https://github.com/etiennebarrie/…
authored
219
1c404f3 @etiennebarrie Rename get_exchange_access_token[_info]
etiennebarrie authored
220 # @see exchange_access_token_info
2446509 @etiennebarrie Add support for access token exchange
etiennebarrie authored
221 #
1c404f3 @etiennebarrie Rename get_exchange_access_token[_info]
etiennebarrie authored
222 # @param (see #exchange_access_token_info)
2446509 @etiennebarrie Add support for access token exchange
etiennebarrie authored
223 #
224 # @return A new access token or the existing one, set to expire in 60 days.
1c404f3 @etiennebarrie Rename get_exchange_access_token[_info]
etiennebarrie authored
225 def exchange_access_token(access_token, options = {})
226 if info = exchange_access_token_info(access_token, options)
2446509 @etiennebarrie Add support for access token exchange
etiennebarrie authored
227 info["access_token"]
228 end
229 end
230
5a7c7fa @arsduo Additional documentation
authored
231 # Parses a signed request string provided by Facebook to canvas apps or in a secure cookie.
232 #
233 # @param input the signed request from Facebook
c4e0a84 @arsduo Merge branch 'fb_exchange_token' of https://github.com/etiennebarrie/…
authored
234 #
c7a741f @archfear Updated error handling logic.
archfear authored
235 # @raise OAuthSignatureError if the signature is incomplete, invalid, or using an unsupported algorithm
c4e0a84 @arsduo Merge branch 'fb_exchange_token' of https://github.com/etiennebarrie/…
authored
236 #
237 # @return a hash of the validated request information
a045e6f @arsduo Split OAuth into its own file.
authored
238 def parse_signed_request(input)
239 encoded_sig, encoded_envelope = input.split('.', 2)
c7a741f @archfear Updated error handling logic.
archfear authored
240 raise OAuthSignatureError, 'Invalid (incomplete) signature data' unless encoded_sig && encoded_envelope
a68919e @arsduo OAuth.parse_signed_request now raises a proper error if the request s…
authored
241
a045e6f @arsduo Split OAuth into its own file.
authored
242 signature = base64_url_decode(encoded_sig).unpack("H*").first
dcad081 @eckz Updated MultiJson to 1.3
eckz authored
243 envelope = MultiJson.load(base64_url_decode(encoded_envelope))
a045e6f @arsduo Split OAuth into its own file.
authored
244
c7a741f @archfear Updated error handling logic.
archfear authored
245 raise OAuthSignatureError, "Unsupported algorithm #{envelope['algorithm']}" if envelope['algorithm'] != 'HMAC-SHA256'
a045e6f @arsduo Split OAuth into its own file.
authored
246
247 # now see if the signature is valid (digest, key, data)
e968e0b Removed the string transformation from encoded_envelope during the di…
Will Sulzer authored
248 hmac = OpenSSL::HMAC.hexdigest(OpenSSL::Digest::SHA256.new, @app_secret, encoded_envelope)
c7a741f @archfear Updated error handling logic.
archfear authored
249 raise OAuthSignatureError, 'Invalid signature' if (signature != hmac)
a045e6f @arsduo Split OAuth into its own file.
authored
250
a68919e @arsduo OAuth.parse_signed_request now raises a proper error if the request s…
authored
251 envelope
a045e6f @arsduo Split OAuth into its own file.
authored
252 end
253
254 protected
255
47c26ff @arsduo Split OAuth into its own file.
authored
256 def get_token_from_server(args, post = false, options = {})
a045e6f @arsduo Split OAuth into its own file.
authored
257 # fetch the result from Facebook's servers
c7a741f @archfear Updated error handling logic.
archfear authored
258 response = fetch_token_string(args, post, "access_token", options)
259 parse_access_token(response)
a045e6f @arsduo Split OAuth into its own file.
authored
260 end
261
262 def parse_access_token(response_text)
4e84664 @arsduo Support Facebook's new JSON-based access token response
authored
263 MultiJson.load(response_text)
13ccca1 @bunshin MultiJson::ParseError renamed as LoadError for backward compatibility
bunshin authored
264 rescue MultiJson::LoadError
f553fcd @ridiculous Try to parse access_token response.body as JSON
ridiculous authored
265 response_text.split("&").inject({}) do |hash, bit|
a045e6f @arsduo Split OAuth into its own file.
authored
266 key, value = bit.split("=")
267 hash.merge!(key => value)
268 end
269 end
c4e0a84 @arsduo Merge branch 'fb_exchange_token' of https://github.com/etiennebarrie/…
authored
270
ac29641 @arsduo Added support for parsing Facebook's new signed_request cookie format.
authored
271 def parse_unsigned_cookie(fb_cookie)
272 # remove the opening/closing quote
273 fb_cookie = fb_cookie.gsub(/\"/, "")
274
275 # since we no longer get individual cookies, we have to separate out the components ourselves
276 components = {}
277 fb_cookie.split("&").map {|param| param = param.split("="); components[param[0]] = param[1]}
278
279 # generate the signature and make sure it matches what we expect
280 auth_string = components.keys.sort.collect {|a| a == "sig" ? nil : "#{a}=#{components[a]}"}.reject {|a| a.nil?}.join("")
281 sig = Digest::MD5.hexdigest(auth_string + @app_secret)
282 sig == components["sig"] && (components["expires"] == "0" || Time.now.to_i < components["expires"].to_i) ? components : nil
283 end
c4e0a84 @arsduo Merge branch 'fb_exchange_token' of https://github.com/etiennebarrie/…
authored
284
ac29641 @arsduo Added support for parsing Facebook's new signed_request cookie format.
authored
285 def parse_signed_cookie(fb_cookie)
286 components = parse_signed_request(fb_cookie)
d5c6549 @arsduo Remove unnecessary parentheses.
authored
287 if code = components["code"]
2c3e982 @arsduo Avoid unnecessary call to Facebook for get_user_from_cookies
authored
288 begin
289 token_info = get_access_token_info(code, :redirect_uri => '')
c7a741f @archfear Updated error handling logic.
archfear authored
290 rescue Koala::Facebook::OAuthTokenRequestError => err
291 if err.fb_error_type == 'OAuthException' && err.fb_error_message =~ /Code was invalid or expired/
292 return nil
293 else
294 raise
295 end
2c3e982 @arsduo Avoid unnecessary call to Facebook for get_user_from_cookies
authored
296 end
297
298 components.merge(token_info) if token_info
ac29641 @arsduo Added support for parsing Facebook's new signed_request cookie format.
authored
299 else
9483fa5 @arsduo Log a warning if the signed cookie is missing the code
authored
300 Koala::Utils.logger.warn("Signed cookie didn't contain Facebook OAuth code! Components: #{components}")
ac29641 @arsduo Added support for parsing Facebook's new signed_request cookie format.
authored
301 nil
302 end
303 end
a045e6f @arsduo Split OAuth into its own file.
authored
304
47c26ff @arsduo Split OAuth into its own file.
authored
305 def fetch_token_string(args, post = false, endpoint = "access_token", options = {})
c7a741f @archfear Updated error handling logic.
archfear authored
306 response = Koala.make_request("/oauth/#{endpoint}", {
a045e6f @arsduo Split OAuth into its own file.
authored
307 :client_id => @app_id,
308 :client_secret => @app_secret
c7a741f @archfear Updated error handling logic.
archfear authored
309 }.merge!(args), post ? "post" : "get", {:use_ssl => true}.merge!(options))
310
311 raise ServerError.new(response.status, response.body) if response.status >= 500
312 raise OAuthTokenRequestError.new(response.status, response.body) if response.status >= 400
313
314 response.body
a045e6f @arsduo Split OAuth into its own file.
authored
315 end
316
317 # base 64
318 # directly from https://github.com/facebook/crypto-request-examples/raw/master/sample.rb
319 def base64_url_decode(str)
320 str += '=' * (4 - str.length.modulo(4))
321 Base64.decode64(str.tr('-_', '+/'))
322 end
c4e0a84 @arsduo Merge branch 'fb_exchange_token' of https://github.com/etiennebarrie/…
authored
323
18f4d96 @arsduo Support API versions in OAuth URLs
authored
324 def server_url(type)
325 url = "https://#{Koala.config.send(type)}"
326 if version = Koala.config.api_version
327 "#{url}/#{version}"
328 else
329 url
330 end
331 end
332
333 def build_url(type, path, require_redirect_uri = false, url_options = {})
c4e0a84 @arsduo Merge branch 'fb_exchange_token' of https://github.com/etiennebarrie/…
authored
334 if require_redirect_uri && !(url_options[:redirect_uri] ||= url_options.delete(:callback) || @oauth_callback_url)
1d88ad6 @jayeff Fix build_url error message
jayeff authored
335 raise ArgumentError, "build_url must get a callback either from the OAuth object or in the parameters!"
279ae5a @arsduo Added url_for_dialog and refactored url generators
authored
336 end
18f4d96 @arsduo Support API versions in OAuth URLs
authored
337 params = Koala::HTTPService.encode_params(url_options)
338 "#{server_url(type)}#{path}?#{params}"
279ae5a @arsduo Added url_for_dialog and refactored url generators
authored
339 end
a045e6f @arsduo Split OAuth into its own file.
authored
340 end
341 end
8c58d02 @marcgg Removed all trailing whitespaces
marcgg authored
342 end
Something went wrong with that request. Please try again.