require 'faraday'
module OAuth2
class Client
attr_accessor :id, :secret, :site, :connection, :options, :raise_errors, :token_method
attr_writer :json
# Instantiate a new OAuth 2.0 client using the
# client ID and client secret registered to your
# application.
#
# Options:
#
# :site :: Specify a base URL for your OAuth 2.0 client.
# :authorize_path :: Specify the path to the authorization endpoint.
# :authorize_url :: Specify a full URL of the authorization endpoint.
# :access_token_path :: Specify the path to the access token endpoint.
# :access_token_method :: Specify the method to use for token endpoints, can be :get or :post
# (note: for Facebook this should be :get and for Google this should be :post)
# :access_token_url :: Specify the full URL of the access token endpoint.
# :parse_json :: If true, application/json responses will be automatically parsed.
# :ssl :: Specify SSL options for the connection.
# :adapter :: The name of the Faraday::Adapter::* class to use, e.g. :net_http. To pass arguments
# to the adapter pass an array here, e.g. [:action_dispatch, my_test_session]
# :raise_errors :: Default true. When false it will then return the error status and response instead of raising an exception.
def initialize(client_id, client_secret, opts={})
self.options = opts.dup
self.token_method = self.options.delete(:access_token_method) || :post
adapter = self.options.delete(:adapter)
ssl_opts = self.options.delete(:ssl) || {}
connection_opts = ssl_opts ? {:ssl => ssl_opts} : {}
self.id = client_id
self.secret = client_secret
self.site = self.options.delete(:site) if self.options[:site]
self.connection = Faraday::Connection.new(site, connection_opts)
self.json = self.options.delete(:parse_json)
self.raise_errors = !(self.options.delete(:raise_errors) == false)
if adapter && adapter != :test
connection.build do |b|
b.adapter(*[adapter].flatten)
end
end
end
def authorize_url(params=nil)
path = options[:authorize_url] || options[:authorize_path] || "/oauth/authorize"
connection.build_url(path, params).to_s
end
def access_token_url(params=nil)
path = options[:access_token_url] || options[:access_token_path] || "/oauth/access_token"
connection.build_url(path, params).to_s
end
# Makes a request relative to the specified site root.
def request(verb, url, params={}, headers={})
if (verb == :get) || (verb == :delete)
resp = connection.run_request(verb, url, nil, headers) do |req|
req.params.update(params)
end
else
resp = connection.run_request(verb, url, params, headers)
end
if raise_errors
case resp.status
when 200...299
return response_for(resp)
when 302
return request(verb, resp.headers['location'], params, headers)
when 401
e = OAuth2::AccessDenied.new("Received HTTP 401 during request.")
e.response = resp
raise e
when 409
e = OAuth2::Conflict.new("Received HTTP 409 during request.")
e.response = resp
raise e
else
e = OAuth2::HTTPError.new("Received HTTP #{resp.status} during request.")
e.response = resp
raise e
end
else
response_for resp
end
end
def json?; !!@json end
def web_server; OAuth2::Strategy::WebServer.new(self) end
def password; OAuth2::Strategy::Password.new(self) end
private
def response_for(resp)
if json?
return ResponseObject.from(resp)
else
return ResponseString.new(resp)
end
end
end
end