panjiva-oauth2 0.4.1 → 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,15 +1,15 @@
1
1
  ---
2
2
  !binary "U0hBMQ==":
3
3
  metadata.gz: !binary |-
4
- ZTRiNmRhZTJhZjVlNTY5ZDU1MDQzZjEyNDg1NzRhM2QyYWJlOTIxMw==
4
+ NTU4NTVhZjFkNzVjMTUwZjZjOGJhNTkyYTc3MzMwMDE1NjQ5NmIxMA==
5
5
  data.tar.gz: !binary |-
6
- NTI0MjQ4MzBkYTlmM2ExZTZjZDg5ODgzMDZiYjZhMjUyZWM4M2RmMw==
6
+ NzQxNzJkNTI2ZjM1OWE3Y2RjMTgwOWQzZDY3MjhkNWNhMGQ2MDZkYg==
7
7
  SHA512:
8
8
  metadata.gz: !binary |-
9
- MTJkYTgzNjM2MTQ3YzVkYTk0YTNhNDFmZDQwZjNlNmE2NjBmM2I4Y2RhMWI1
10
- Njk0NjA1N2ViZjI0NzA3Njc2NDkwMTY0OThmM2ZkMjFjNTQzZjY5NmZlNTEw
11
- Y2NkNTdmYTEyOWFjMzJkMGRjNGRjMGI2NWM2YWRjZTAyYTBmMjI=
9
+ YzA0ZDhhZjU5YmMzNzg4ZjFmNTFhNGY1NDc1NWE0YTFjM2YzMjFhYzg5YmQ3
10
+ MDI0OWQ0MzU0NjgxZDU2OTQzOTEzMmNmOGQ2YTBhZGFlYjQzYWE1MmVkMTU1
11
+ MjYwY2ZkZjM4NGU2MDExOWY0MDlmYTU3OTJmYWViZmIzNDBmZTc=
12
12
  data.tar.gz: !binary |-
13
- OTFiNzYwMDY4ZWQxZWEwMzBmYmM4YThiOTM0ZTA5OTk3ZGY2OTBmYmYyOGEy
14
- MTYyYTkyZWE3YjA5ZGY2OWJmOGMyYTY1ZTJmMmQ4OTlmMmU0ZGZjYzMzZTc2
15
- NDkyYTVhMWVkMjAxMmI4M2M5NTZlMGJjZDU4MWJhYjRhZjVhYWM=
13
+ YjgwZjk4ZTgwMWEwZDg1NWU1OWQyZTVhMGFiMzQ0MzUyNTczZmYzZTk4MjRl
14
+ MmE0NDIzMzc2Y2QzMTkwOWNmNWYwMjhlM2ZkZWMxNDY0NjMwNDllNDBkZDY2
15
+ NmUxZWRmNGU1NTk2MzY4MjY0MGNiNjNjYTc2MWQzMjc3YjRiMzg=
@@ -0,0 +1 @@
1
+ require 'autotest/bundler'
data/.gitignore CHANGED
@@ -32,4 +32,7 @@ Gemfile.lock
32
32
  coverage.data
33
33
 
34
34
  ## PROJECT::SPECIFIC
35
- .svn
35
+ .svn
36
+
37
+ ## Rubinius
38
+ *.rbc
@@ -1,7 +1,5 @@
1
1
  rvm:
2
2
  - 1.8.7
3
- - 1.9.1
4
3
  - 1.9.2
5
- - jruby
6
- - rbx
7
4
  - ree
5
+ - ruby-head
data/Gemfile CHANGED
@@ -1,3 +1,3 @@
1
- source "http://rubygems.org"
1
+ source 'http://rubygems.org'
2
2
 
3
3
  gemspec
data/README.md CHANGED
@@ -1,4 +1,4 @@
1
- OAuth2 Fork (version 0.4.1 - OUT OF DATE)
1
+ OAuth2 Fork (version 0.5.0 - OUT OF DATE)
2
2
  =========================================
3
3
 
4
4
  changelog: relaxed 0.8 > version dependency for faraday
@@ -15,7 +15,7 @@ Installation
15
15
 
16
16
  Continuous Integration
17
17
  ----------------------
18
- [![Build Status](http://travis-ci.org/intridea/oauth2.png)](http://travis-ci.org/intridea/oauth2)
18
+ [![Build Status](https://secure.travis-ci.org/intridea/oauth2.png)](http://travis-ci.org/intridea/oauth2)
19
19
 
20
20
  Resources
21
21
  ---------
@@ -23,67 +23,48 @@ Resources
23
23
  * Report Issues on GitHub (https://github.com/intridea/oauth2/issues)
24
24
  * Read More at the Wiki (https://wiki.github.com/intridea/oauth2)
25
25
 
26
- Web Server Example (Sinatra)
27
- ----------------------------
28
- Below is a fully functional example of a Sinatra application that would authenticate to Facebook utilizing the OAuth 2.0 web server flow.
26
+ Generic Client Example
27
+ ----------------------
29
28
 
30
- require 'rubygems'
31
- require 'sinatra'
32
29
  require 'oauth2'
33
- require 'json'
34
-
35
- def client
36
- OAuth2::Client.new('app_id', 'app_secret', :site => 'https://graph.facebook.com')
37
- end
38
-
39
- get '/auth/facebook' do
40
- redirect client.web_server.authorize_url(
41
- :redirect_uri => redirect_uri,
42
- :scope => 'email,offline_access'
43
- )
44
- end
45
-
46
- get '/auth/facebook/callback' do
47
- access_token = client.web_server.get_access_token(params[:code], :redirect_uri => redirect_uri)
48
- user = JSON.parse(access_token.get('/me'))
49
- user.inspect
50
- end
51
-
52
- def redirect_uri
53
- uri = URI.parse(request.url)
54
- uri.path = '/auth/facebook/callback'
55
- uri.query = nil
56
- uri.to_s
57
- end
58
-
59
- That's all there is to it! You can use the access token like you would with the
60
- OAuth gem, calling HTTP verbs on it etc. You can view more examples on the [OAuth2
61
- Wiki](http://wiki.github.com/intridea/oauth2/examples).
62
-
63
- JSON Parsing
64
- ------------
65
- Because JSON has become the standard format of the OAuth 2.0 specification,
66
- the <tt>oauth2</tt> gem contains a mode that will perform automatic parsing
67
- of JSON response bodies, returning a hash instead of a string. To enable this
68
- mode, simply add the <tt>:parse_json</tt> option to your client initialization:
30
+ client = OAuth2::Client.new('client_id', 'client_secret', :site => 'https://example.org')
31
+
32
+ client.auth_code.authorize_url(:redirect_uri => 'http://localhost:8080/oauth2/callback')
33
+ # => "https://example.org/oauth/authorization?response_type=code&client_id=client_id&redirect_uri=http://localhost:8080/oauth2/callback"
34
+
35
+ token = client.auth_code.get_token('authorization_code_value', :redirect_uri => 'http://localhost:8080/oauth2/callback')
36
+ response = token.get('/api/resource', :params => { 'query_foo' => 'bar' })
37
+ response.class.name
38
+ # => OAuth2::Response
39
+
40
+ OAuth2::Response
41
+ ----------------
42
+ The AccessToken methods #get, #post, #put and #delete and the generic #request will return an instance of the #OAuth2::Response class.
43
+ This instance contains a #parsed method that will parse the response body and return a Hash if the Content-Type is application/x-www-form-urlencoded or if the body is a JSON object. It will return an Array if the body is a JSON array. Otherwise, it will return the original body string.
44
+
45
+ The original response body, headers, and status can be accessed via their respective methods.
46
+
47
+ OAuth2::AccessToken
48
+ -------------------
49
+ If you have an existing Access Token for a user, you can initialize an instance using various class methods including the standard new, from_hash (if you have a hash of the values), or from_kvform (if you have an application/x-www-form-urlencoded encoded string of the values).
50
+
51
+ OAuth2::Error
52
+ -------------
53
+ On 400+ status code responses, an OAuth2::Error will be raised. If it is a standard OAuth2 error response, the body will be parsed and #code and #description will contain the values provided from the error and error_description parameters. The #response property of OAuth2::Error will always contain the OAuth2::Response instance.
54
+
55
+ If you do not want an error to be raised, you may use :raise_errors => false option on initialization of the client. In this case the OAuth2::Response instance will be returned as usual and on 400+ status code responses, the Response instance will contain the OAuth2::Error instance.
56
+
57
+ Authorization Grants
58
+ --------------------
59
+ Currently the Authorization Code and Resource Owner Password Credentials authentication grant types have helper strategy classes that simplify client use. They are available via the #auth_code and #password methods respectively.
69
60
 
70
- client = OAuth2::Client.new(
71
- 'app_id',
72
- 'app_secret',
73
- :site => 'https://example.com',
74
- :parse_json => true,
75
- )
76
-
77
- # Obtain an access token using the client
78
- token.get('/some/url.json') #=> {"some" => "hash"}
61
+ auth_url = client.auth_code.authorization_url(:redirect_uri => 'http://localhost:8080/oauth/callback')
62
+ token = client.auth_code.get_token('code_value', :redirect_uri => 'http://localhost:8080/oauth/callback')
79
63
 
80
- Testing
81
- -------
82
- To use the OAuth2 client for testing error conditions do:
64
+ token = client.password.get_token('username', 'password')
83
65
 
84
- my_client.raise_errors = false
66
+ You can always use the #request method on the OAuth2::Client instance to make requests for tokens for any Authentication grant type.
85
67
 
86
- It will then return the error status and response instead of raising an exception.
87
68
 
88
69
  Note on Patches/Pull Requests
89
70
  -----------------------------
@@ -94,7 +75,31 @@ Note on Patches/Pull Requests
94
75
  5. Add specs for your feature or bug fix.
95
76
  6. Run <tt>bundle exec rake spec</tt>. If your changes are not 100% covered, go back to step 5.
96
77
  7. Commit and push your changes.
97
- 8. Submit a pull request. Please do not include changes to the [gemspec](https://github.com/intridea/oauth2/blob/master/oauth2.gemspec), [version](https://github.com/intridea/oauth2/blob/master/lib/oauth2/version.rb), or [changelog](https://github.com/intridea/oauth2/blob/master/CHANGELOG.md) file. (If you want to create your own version for some reason, please do so in a separate commit.)
78
+ 8. Submit a pull request. Please do not include changes to the [gemspec](https://github.com/intridea/oauth2/blob/master/oauth2.gemspec), [version](https://github.com/intridea/oauth2/blob/master/lib/oauth2/version.rb), or [changelog](https://github.com/intridea/oauth2/wiki/Changelg) . (If you want to create your own version for some reason, please do so in a separate commit.)
79
+
80
+ Supported Rubies
81
+ ----------------
82
+ This library aims to support and is [tested
83
+ against](http://travis-ci.org/intridea/oauth2) the following Ruby
84
+ implementations:
85
+
86
+ * Ruby 1.8.7
87
+ * Ruby 1.9.2
88
+ * Ruby Enterprise Edition 1.8.7
89
+
90
+ If something doesn't work on one of these interpreters, it should be considered
91
+ a bug.
92
+
93
+ This library may inadvertently work (or seem to work) on other Ruby
94
+ implementations, however support will only be provided for the versions listed
95
+ above.
96
+
97
+ If you would like this library to support another Ruby version, you may
98
+ volunteer to be a maintainer. Being a maintainer entails making sure all tests
99
+ run and pass on that implementation. When something breaks on your
100
+ implementation, you will be personally responsible for providing patches in a
101
+ timely fashion. If critical issues for a particular implementation exist at the
102
+ time of a major release, support for that Ruby version may be dropped.
98
103
 
99
104
  Copyright
100
105
  ---------
data/Rakefile CHANGED
@@ -1,3 +1,5 @@
1
+ #!/usr/bin/env rake
2
+
1
3
  require 'bundler'
2
4
  Bundler::GemHelper.install_tasks
3
5
 
@@ -7,7 +9,7 @@ RSpec::Core::RakeTask.new(:spec)
7
9
  task :default => :spec
8
10
  task :test => :spec
9
11
 
10
- require 'rake/rdoctask'
12
+ require 'rdoc/task'
11
13
  Rake::RDocTask.new do |rdoc|
12
14
  rdoc.rdoc_dir = 'rdoc'
13
15
  rdoc.title = "oauth2 #{OAuth2::VERSION}"
@@ -1,13 +1,7 @@
1
- module OAuth2
2
- class ErrorWithResponse < StandardError; attr_accessor :response end
3
- class AccessDenied < ErrorWithResponse; end
4
- class Conflict < ErrorWithResponse; end
5
- class HTTPError < ErrorWithResponse; end
6
- end
7
-
1
+ require 'oauth2/error'
8
2
  require 'oauth2/client'
9
3
  require 'oauth2/strategy/base'
10
- require 'oauth2/strategy/web_server'
4
+ require 'oauth2/strategy/auth_code'
11
5
  require 'oauth2/strategy/password'
12
6
  require 'oauth2/access_token'
13
- require 'oauth2/response_object'
7
+ require 'oauth2/response'
@@ -1,53 +1,151 @@
1
1
  module OAuth2
2
2
  class AccessToken
3
3
  attr_reader :client, :token, :refresh_token, :expires_in, :expires_at, :params
4
- attr_accessor :token_param
4
+ attr_accessor :options
5
5
 
6
- def initialize(client, token, refresh_token=nil, expires_in=nil, params={})
6
+ class << self
7
+ # Initializes an AccessToken from a Hash
8
+ #
9
+ # @param [Client] the OAuth2::Client instance
10
+ # @param [Hash] a hash of AccessToken property values
11
+ # @return [AccessToken] the initalized AccessToken
12
+ def from_hash(client, hash)
13
+ self.new(client, hash.delete('access_token') || hash.delete(:access_token), hash)
14
+ end
15
+
16
+ # Initializes an AccessToken from a key/value application/x-www-form-urlencoded string
17
+ #
18
+ # @param [Client] client the OAuth2::Client instance
19
+ # @param [String] kvform the application/x-www-form-urlencoded string
20
+ # @return [AccessToken] the initalized AccessToken
21
+ def from_kvform(client, kvform)
22
+ from_hash(client, Rack::Utils.parse_query(kvform))
23
+ end
24
+ end
25
+
26
+ # Initalize an AccessToken
27
+ #
28
+ # @param [Client] client the OAuth2::Client instance
29
+ # @param [String] token the Access Token value
30
+ # @param [Hash] opts the options to create the Access Token with
31
+ # @option opts [String] :refresh_token (nil) the refresh_token value
32
+ # @option opts [FixNum, String] :expires_in (nil) the number of seconds in which the AccessToken will expire
33
+ # @option opts [FixNum, String] :expires_at (nil) the epoch time in seconds in which AccessToken will expire
34
+ # @option opts [Symbol] :mode (:header) the transmission mode of the Access Token parameter value
35
+ # one of :header, :body or :query
36
+ # @option opts [String] :header_format ('Bearer %s') the string format to use for the Authorization header
37
+ # @option opts [String] :param_name ('bearer_token') the parameter name to use for transmission of the
38
+ # Access Token value in :body or :query transmission mode
39
+ def initialize(client, token, opts={})
7
40
  @client = client
8
41
  @token = token.to_s
9
- @refresh_token = refresh_token.to_s
10
- @expires_in = (expires_in.nil? || expires_in == '') ? nil : expires_in.to_i
11
- @expires_at = Time.now + @expires_in if @expires_in
12
- @params = params
13
- @token_param = 'oauth_token'
42
+ [:refresh_token, :expires_in, :expires_at].each do |arg|
43
+ instance_variable_set("@#{arg}", opts.delete(arg) || opts.delete(arg.to_s))
44
+ end
45
+ @expires_in ||= opts.delete('expires')
46
+ @expires_in &&= @expires_in.to_i
47
+ @expires_at ||= Time.now.to_i + @expires_in if @expires_in
48
+ @options = {:mode => opts.delete(:mode) || :header,
49
+ :header_format => opts.delete(:header_format) || 'Bearer %s',
50
+ :param_name => opts.delete(:param_name) || 'bearer_token'}
51
+ @params = opts
14
52
  end
15
53
 
54
+ # Indexer to additional params present in token response
55
+ #
56
+ # @param [String] key entry key to Hash
16
57
  def [](key)
17
58
  @params[key]
18
59
  end
19
60
 
20
- # True if the token in question has an expiration time.
61
+ # Whether or not the token expires
62
+ #
63
+ # @return [Boolean]
21
64
  def expires?
22
- !!@expires_in
65
+ !!@expires_at
23
66
  end
24
67
 
68
+ # Whether or not the token is expired
69
+ #
70
+ # @return [Boolean]
25
71
  def expired?
26
- expires? && expires_at < Time.now
72
+ expires? && (expires_at < Time.now.to_i)
27
73
  end
28
74
 
29
- def request(verb, path, params={}, headers={})
30
- if params.instance_of?(Hash)
31
- params = params.merge token_param => @token
32
- end
33
- headers = headers.merge 'Authorization' => "OAuth #{@token}"
34
- @client.request(verb, path, params, headers)
75
+ # Refreshes the current Access Token
76
+ #
77
+ # @return [AccessToken] a new AccessToken
78
+ # @note options should be carried over to the new AccessToken
79
+ def refresh!(params={})
80
+ raise "A refresh_token is not available" unless refresh_token
81
+ params.merge!(:client_id => @client.id,
82
+ :client_secret => @client.secret,
83
+ :grant_type => 'refresh_token',
84
+ :refresh_token => refresh_token)
85
+ new_token = @client.get_token(params)
86
+ new_token.options = options
87
+ new_token
88
+ end
89
+
90
+ # Make a request with the Access Token
91
+ #
92
+ # @param [Symbol] verb the HTTP request method
93
+ # @param [String] path the HTTP URL path of the request
94
+ # @param [Hash] opts the options to make the request with
95
+ # @see Client#request
96
+ def request(verb, path, opts={}, &block)
97
+ set_token(opts)
98
+ @client.request(verb, path, opts, &block)
35
99
  end
36
100
 
37
- def get(path, params={}, headers={})
38
- request(:get, path, params, headers)
101
+ # Make a GET request with the Access Token
102
+ #
103
+ # @see AccessToken#request
104
+ def get(path, opts={}, &block)
105
+ request(:get, path, opts, &block)
39
106
  end
40
107
 
41
- def post(path, params={}, headers={})
42
- request(:post, path, params, headers)
108
+ # Make a POST request with the Access Token
109
+ #
110
+ # @see AccessToken#request
111
+ def post(path, opts={}, &block)
112
+ request(:post, path, opts, &block)
43
113
  end
44
114
 
45
- def put(path, params={}, headers={})
46
- request(:put, path, params, headers)
115
+ # Make a PUT request with the Access Token
116
+ #
117
+ # @see AccessToken#request
118
+ def put(path, opts={}, &block)
119
+ request(:put, path, opts, &block)
47
120
  end
48
121
 
49
- def delete(path, params={}, headers={})
50
- request(:delete, path, params, headers)
122
+ # Make a DELETE request with the Access Token
123
+ #
124
+ # @see AccessToken#request
125
+ def delete(path, opts={}, &block)
126
+ request(:delete, path, opts, &block)
127
+ end
128
+
129
+ private
130
+ def set_token(opts)
131
+ case options[:mode]
132
+ when :header
133
+ opts[:headers] ||= {}
134
+ opts[:headers]['Authorization'] = options[:header_format] % token
135
+ when :query
136
+ opts[:params] ||= {}
137
+ opts[:params][options[:param_name]] = token
138
+ when :body
139
+ opts[:body] ||= {}
140
+ if opts[:body].is_a?(Hash)
141
+ opts[:body][options[:param_name]] = token
142
+ else
143
+ opts[:body] << "&#{options[:param_name]}=#{token}"
144
+ end
145
+ # @todo support for multi-part (file uploads)
146
+ else
147
+ raise "invalid :mode option of #{options[:mode]}"
148
+ end
51
149
  end
52
150
  end
53
151
  end
@@ -1,105 +1,146 @@
1
1
  require 'faraday'
2
2
 
3
3
  module OAuth2
4
+ # The OAuth2::Client class
4
5
  class Client
5
- attr_accessor :id, :secret, :site, :connection, :options, :raise_errors, :token_method
6
- attr_writer :json
6
+ attr_reader :id, :secret
7
+ attr_accessor :site, :connection, :options
7
8
 
8
9
  # Instantiate a new OAuth 2.0 client using the
9
- # client ID and client secret registered to your
10
+ # Client ID and Client Secret registered to your
10
11
  # application.
11
12
  #
12
- # Options:
13
+ # @param [String] client_id the client_id value
14
+ # @param [String] client_secret the client_secret value
15
+ # @param [Hash] opts the options to create the client with
16
+ # @option opts [String] :site the OAuth2 provider site host
17
+ # @option opts [String] :authorize_url ('/oauth/authorize') absolute or relative URL path to the Authorization endpoint
18
+ # @option opts [String] :token_url ('/oauth/token') absolute or relative URL path to the Token endpoint
19
+ # @option opts [Symbol] :token_method (:post) HTTP method to use to request token (:get or :post)
20
+ # @option opts [Hash] :connection_opts ({}) Hash of connection options to pass to initialize Faraday with
21
+ # @option opts [FixNum] :max_redirects (5) maximum number of redirects to follow
22
+ # @option opts [Boolean] :raise_errors (true) whether or not to raise an OAuth2::Error
23
+ # on responses with 400+ status codes
24
+ # @yield [builder] The Faraday connection builder
25
+ def initialize(client_id, client_secret, opts={}, &block)
26
+ @id = client_id
27
+ @secret = client_secret
28
+ @site = opts.delete(:site)
29
+ ssl = opts.delete(:ssl)
30
+ @options = {:authorize_url => '/oauth/authorize',
31
+ :token_url => '/oauth/token',
32
+ :token_method => :post,
33
+ :connection_opts => {},
34
+ :connection_build => block,
35
+ :max_redirects => 5,
36
+ :raise_errors => true}.merge(opts)
37
+ @options[:connection_opts][:ssl] = ssl if ssl
38
+ end
39
+
40
+ # Set the site host
13
41
  #
14
- # <tt>:site</tt> :: Specify a base URL for your OAuth 2.0 client.
15
- # <tt>:authorize_path</tt> :: Specify the path to the authorization endpoint.
16
- # <tt>:authorize_url</tt> :: Specify a full URL of the authorization endpoint.
17
- # <tt>:access_token_path</tt> :: Specify the path to the access token endpoint.
18
- # <tt>:access_token_method</tt> :: Specify the method to use for token endpoints, can be :get or :post
19
- # (note: for Facebook this should be :get and for Google this should be :post)
20
- # <tt>:access_token_url</tt> :: Specify the full URL of the access token endpoint.
21
- # <tt>:parse_json</tt> :: If true, <tt>application/json</tt> responses will be automatically parsed.
22
- # <tt>:ssl</tt> :: Specify SSL options for the connection.
23
- # <tt>:adapter</tt> :: The name of the Faraday::Adapter::* class to use, e.g. :net_http. To pass arguments
24
- # to the adapter pass an array here, e.g. [:action_dispatch, my_test_session]
25
- # <tt>:raise_errors</tt> :: Default true. When false it will then return the error status and response instead of raising an exception.
26
- def initialize(client_id, client_secret, opts={})
27
- self.options = opts.dup
28
- self.token_method = self.options.delete(:access_token_method) || :post
29
- adapter = self.options.delete(:adapter)
30
- ssl_opts = self.options.delete(:ssl) || {}
31
- connection_opts = ssl_opts ? {:ssl => ssl_opts} : {}
32
- self.id = client_id
33
- self.secret = client_secret
34
- self.site = self.options.delete(:site) if self.options[:site]
35
- self.connection = Faraday::Connection.new(site, connection_opts)
36
- self.json = self.options.delete(:parse_json)
37
- self.raise_errors = !(self.options.delete(:raise_errors) == false)
42
+ # @param [String] the OAuth2 provider site host
43
+ def site=(value)
44
+ @connection = nil
45
+ @site = value
46
+ end
38
47
 
39
- if adapter && adapter != :test
40
- connection.build do |b|
41
- b.adapter(*[adapter].flatten)
42
- end
48
+ # The Faraday connection object
49
+ def connection
50
+ @connection ||= begin
51
+ conn = Faraday.new(site, options[:connection_opts])
52
+ conn.build do |b|
53
+ options[:connection_build].call(b)
54
+ end if options[:connection_build]
55
+ conn
43
56
  end
44
57
  end
45
58
 
59
+ # The authorize endpoint URL of the OAuth2 provider
60
+ #
61
+ # @param [Hash] params additional query parameters
46
62
  def authorize_url(params=nil)
47
- path = options[:authorize_url] || options[:authorize_path] || "/oauth/authorize"
48
- connection.build_url(path, params).to_s
63
+ connection.build_url(options[:authorize_url], params).to_s
49
64
  end
50
65
 
51
- def access_token_url(params=nil)
52
- path = options[:access_token_url] || options[:access_token_path] || "/oauth/access_token"
53
- connection.build_url(path, params).to_s
66
+ # The token endpoint URL of the OAuth2 provider
67
+ #
68
+ # @param [Hash] params additional query parameters
69
+ def token_url(params=nil)
70
+ connection.build_url(options[:token_url], params).to_s
54
71
  end
55
72
 
56
73
  # Makes a request relative to the specified site root.
57
- def request(verb, url, params={}, headers={})
58
- if (verb == :get) || (verb == :delete)
59
- resp = connection.run_request(verb, url, nil, headers) do |req|
60
- req.params.update(params)
61
- end
62
- else
63
- resp = connection.run_request(verb, url, params, headers)
74
+ #
75
+ # @param [Symbol] verb one of :get, :post, :put, :delete
76
+ # @param [String] url URL path of request
77
+ # @param [Hash] opts the options to make the request with
78
+ # @option opts [Hash] :params additional query parameters for the URL of the request
79
+ # @option opts [Hash, String] :body the body of the request
80
+ # @option opts [Hash] :headers http request headers
81
+ # @option opts [Boolean] :raise_errors whether or not to raise an OAuth2::Error on 400+ status
82
+ # code response for this request. Will default to client option
83
+ # @option opts [Symbol] :parse @see Response::initialize
84
+ # @yield [req] The Faraday request
85
+ def request(verb, url, opts={})
86
+ url = self.connection.build_url(url, opts[:params]).to_s
87
+
88
+ response = connection.run_request(verb, url, opts[:body], opts[:headers]) do |req|
89
+ yield(req) if block_given?
64
90
  end
91
+ response = Response.new(response, :parse => opts[:parse])
65
92
 
66
- if raise_errors
67
- case resp.status
68
- when 200...299
69
- return response_for(resp)
70
- when 302
71
- return request(verb, resp.headers['location'], params, headers)
72
- when 401
73
- e = OAuth2::AccessDenied.new("Received HTTP 401 during request.")
74
- e.response = resp
75
- raise e
76
- when 409
77
- e = OAuth2::Conflict.new("Received HTTP 409 during request.")
78
- e.response = resp
79
- raise e
80
- else
81
- e = OAuth2::HTTPError.new("Received HTTP #{resp.status} during request.")
82
- e.response = resp
83
- raise e
93
+ case response.status
94
+ when 200..299
95
+ response
96
+ when 300..399
97
+ opts[:redirect_count] ||= 0
98
+ opts[:redirect_count] += 1
99
+ return response if opts[:redirect_count] > options[:max_redirects]
100
+ if response.status == 303
101
+ verb = :get
102
+ opts.delete(:body)
84
103
  end
104
+ request(verb, response.headers['location'], opts)
105
+ when 400..599
106
+ e = Error.new(response)
107
+ raise e if opts[:raise_errors] || options[:raise_errors]
108
+ response.error = e
109
+ response
85
110
  else
86
- response_for resp
111
+ raise Error.new(response), "Unhandled status code value of #{response.status}"
87
112
  end
88
113
  end
89
114
 
90
- def json?; !!@json end
91
-
92
- def web_server; OAuth2::Strategy::WebServer.new(self) end
93
- def password; OAuth2::Strategy::Password.new(self) end
94
-
95
- private
96
-
97
- def response_for(resp)
98
- if json?
99
- return ResponseObject.from(resp)
115
+ # Initializes an AccessToken by making a request to the token endpoint
116
+ #
117
+ # @param [Hash] params a Hash of params for the token endpoint
118
+ # @return [AccessToken] the initalized AccessToken
119
+ def get_token(params)
120
+ opts = {:raise_errors => true, :parse => params.delete(:parse)}
121
+ if options[:token_method] == :post
122
+ opts[:body] = params
123
+ opts[:headers] = {'Content-Type' => 'application/x-www-form-urlencoded'}
100
124
  else
101
- return ResponseString.new(resp)
125
+ opts[:params] = params
102
126
  end
127
+ response = request(options[:token_method], token_url, opts)
128
+ raise Error.new(response) unless response.parsed.is_a?(Hash) && response.parsed['access_token']
129
+ AccessToken.from_hash(self, response.parsed)
130
+ end
131
+
132
+ # The Authorization Code strategy
133
+ #
134
+ # @see http://tools.ietf.org/html/draft-ietf-oauth-v2-15#section-4.1
135
+ def auth_code
136
+ @auth_code ||= OAuth2::Strategy::AuthCode.new(self)
137
+ end
138
+
139
+ # The Resource Owner Password Credentials strategy
140
+ #
141
+ # @see http://tools.ietf.org/html/draft-ietf-oauth-v2-15#section-4.3
142
+ def password
143
+ @password ||= OAuth2::Strategy::Password.new(self)
103
144
  end
104
145
  end
105
146
  end