oauth2 0.5.2 → 0.6.0

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/.rspec CHANGED
@@ -1,3 +1,2 @@
1
1
  --color
2
- --format=nested
3
- --backtrace
2
+ --order random
@@ -1,7 +1,9 @@
1
+ language: ruby
1
2
  rvm:
2
3
  - 1.8.7
3
4
  - 1.9.2
4
5
  - 1.9.3
5
- - jruby
6
- - rbx
7
- - ree
6
+ - jruby-18mode
7
+ - jruby-19mode
8
+ - rbx-18mode
9
+ - rbx-19mode
data/README.md CHANGED
@@ -26,7 +26,7 @@ the entire specification over time.
26
26
  client.auth_code.authorize_url(:redirect_uri => 'http://localhost:8080/oauth2/callback')
27
27
  # => "https://example.org/oauth/authorization?response_type=code&client_id=client_id&redirect_uri=http://localhost:8080/oauth2/callback"
28
28
 
29
- token = client.auth_code.get_token('authorization_code_value', :redirect_uri => 'http://localhost:8080/oauth2/callback')
29
+ token = client.auth_code.get_token('authorization_code_value', :redirect_uri => 'http://localhost:8080/oauth2/callback', :headers => {'Authorization' => 'Basic some_password'})
30
30
  response = token.get('/api/resource', :params => { 'query_foo' => 'bar' })
31
31
  response.class.name
32
32
  # => OAuth2::Response
@@ -51,8 +51,7 @@ application/x-www-form-urlencoded encoded string of the values).
51
51
 
52
52
  ## <a name="error"></a>OAuth2::Error
53
53
  On 400+ status code responses, an OAuth2::Error will be raised. If it is a
54
- standard OAuth2 error response, the body will be parsed and #code and
55
- #description will contain the values provided from the error and
54
+ standard OAuth2 error response, the body will be parsed and #code and #description will contain the values provided from the error and
56
55
  error_description parameters. The #response property of OAuth2::Error will
57
56
  always contain the OAuth2::Response instance.
58
57
 
@@ -62,15 +61,22 @@ instance will be returned as usual and on 400+ status code responses, the
62
61
  Response instance will contain the OAuth2::Error instance.
63
62
 
64
63
  ## <a name="authorization_grants"></a>Authorization Grants
65
- Currently the Authorization Code and Resource Owner Password Credentials
64
+ Currently the Authorization Code, Resource Owner Password Credentials, and Client Credentials
66
65
  authentication grant types have helper strategy classes that simplify client
67
- use. They are available via the #auth_code and #password methods respectively.
66
+ use. They are available via the #auth_code, #password, and #client_credentials methods respectively.
68
67
 
69
68
  auth_url = client.auth_code.authorize_url(:redirect_uri => 'http://localhost:8080/oauth/callback')
70
69
  token = client.auth_code.get_token('code_value', :redirect_uri => 'http://localhost:8080/oauth/callback')
71
70
 
72
71
  token = client.password.get_token('username', 'password')
73
72
 
73
+ token = client.client_credentials.get_token
74
+
75
+ If you want to specify additional headers to be sent out with the
76
+ request, add a 'headers' hash under 'params':
77
+
78
+ token = client.auth_code.get_token('code_value', :redirect_uri => 'http://localhost:8080/oauth/callback', :headers => {'Some' => 'Header'})
79
+
74
80
  You can always use the #request method on the OAuth2::Client instance to make
75
81
  requests for tokens for any Authentication grant type.
76
82
 
@@ -100,11 +106,9 @@ implementations:
100
106
  * Ruby 1.9.3
101
107
  * [JRuby][]
102
108
  * [Rubinius][]
103
- * [Ruby Enterprise Edition][ree]
104
109
 
105
110
  [jruby]: http://www.jruby.org/
106
111
  [rubinius]: http://rubini.us/
107
- [ree]: http://www.rubyenterpriseedition.com/
108
112
 
109
113
  If something doesn't work on one of these interpreters, it should be considered
110
114
  a bug.
@@ -3,5 +3,6 @@ require 'oauth2/client'
3
3
  require 'oauth2/strategy/base'
4
4
  require 'oauth2/strategy/auth_code'
5
5
  require 'oauth2/strategy/password'
6
+ require 'oauth2/strategy/client_credentials'
6
7
  require 'oauth2/access_token'
7
8
  require 'oauth2/response'
@@ -91,9 +91,7 @@ module OAuth2
91
91
  response = Response.new(response, :parse => opts[:parse])
92
92
 
93
93
  case response.status
94
- when 200..299
95
- response
96
- when 300..399
94
+ when 301, 302, 303, 307
97
95
  opts[:redirect_count] ||= 0
98
96
  opts[:redirect_count] += 1
99
97
  return response if opts[:redirect_count] > options[:max_redirects]
@@ -102,6 +100,9 @@ module OAuth2
102
100
  opts.delete(:body)
103
101
  end
104
102
  request(verb, response.headers['location'], opts)
103
+ when 200..299, 300..399
104
+ # on non-redirecting 3xx statuses, just return the response
105
+ response
105
106
  when 400..599
106
107
  e = Error.new(response)
107
108
  raise e if opts[:raise_errors] || options[:raise_errors]
@@ -120,8 +121,10 @@ module OAuth2
120
121
  def get_token(params, access_token_opts={})
121
122
  opts = {:raise_errors => options[:raise_errors], :parse => params.delete(:parse)}
122
123
  if options[:token_method] == :post
124
+ headers = params.delete(:headers)
123
125
  opts[:body] = params
124
126
  opts[:headers] = {'Content-Type' => 'application/x-www-form-urlencoded'}
127
+ opts[:headers].merge!(headers) if headers
125
128
  else
126
129
  opts[:params] = params
127
130
  end
@@ -143,5 +146,12 @@ module OAuth2
143
146
  def password
144
147
  @password ||= OAuth2::Strategy::Password.new(self)
145
148
  end
149
+
150
+ # The Client Credentials strategy
151
+ #
152
+ # @see http://tools.ietf.org/html/draft-ietf-oauth-v2-15#section-4.4
153
+ def client_credentials
154
+ @client_credentials ||= OAuth2::Strategy::ClientCredentials.new(self)
155
+ end
146
156
  end
147
157
  end
@@ -7,11 +7,18 @@ module OAuth2
7
7
  def initialize(response)
8
8
  response.error = self
9
9
  @response = response
10
+
11
+ message = []
12
+
10
13
  if response.parsed.is_a?(Hash)
11
14
  @code = response.parsed['error']
12
15
  @description = response.parsed['error_description']
16
+ message << "#{@code}: #{@description}"
13
17
  end
14
- end
15
18
 
19
+ message << response.body
20
+
21
+ super(message.join("\n"))
22
+ end
16
23
  end
17
24
  end
@@ -0,0 +1,28 @@
1
+ require 'httpauth'
2
+
3
+ module OAuth2
4
+ module Strategy
5
+ # The Client Credentials Strategy
6
+ #
7
+ # @see http://tools.ietf.org/html/draft-ietf-oauth-v2-15#section-4.4
8
+ class ClientCredentials < Base
9
+ # Not used for this strategy
10
+ #
11
+ # @raise [NotImplementedError]
12
+ def authorize_url
13
+ raise NotImplementedError, "The authorization endpoint is not used in this strategy"
14
+ end
15
+
16
+ # Retrieve an access token given the specified client.
17
+ #
18
+ # @param [Hash] params additional params
19
+ # @param [Hash] opts options
20
+ def get_token(params={}, opts={})
21
+ request_body = opts.delete('auth_scheme') == 'request_body'
22
+ params.merge!('grant_type' => 'client_credentials')
23
+ params.merge!(request_body ? client_params : {:headers => {'Authorization' => HTTPAuth::Basic.pack_authorization(client_params['client_id'], client_params['client_secret'])}})
24
+ @client.get_token(params, opts.merge('refresh_token' => nil))
25
+ end
26
+ end
27
+ end
28
+ end
@@ -1,3 +1,3 @@
1
1
  module OAuth2
2
- VERSION = "0.5.2"
2
+ VERSION = "0.6.0"
3
3
  end
@@ -4,12 +4,12 @@ require File.expand_path('../lib/oauth2/version', __FILE__)
4
4
  Gem::Specification.new do |gem|
5
5
  gem.add_dependency 'faraday', '~> 0.7'
6
6
  gem.add_dependency 'multi_json', '~> 1.0'
7
+ gem.add_dependency 'httpauth', '~> 0.1'
7
8
  gem.add_development_dependency 'multi_xml'
8
9
  gem.add_development_dependency 'rake'
9
10
  gem.add_development_dependency 'rdoc'
10
11
  gem.add_development_dependency 'rspec'
11
12
  gem.add_development_dependency 'simplecov'
12
- gem.add_development_dependency 'yard'
13
13
  gem.authors = ["Michael Bleigh", "Erik Michaels-Ober"]
14
14
  gem.description = %q{A Ruby wrapper for the OAuth 2.0 protocol built with a similar style to the original OAuth gem.}
15
15
  gem.email = ['michael@intridea.com', 'sferik@gmail.com']
@@ -1,5 +1,7 @@
1
- require 'simplecov'
2
- SimpleCov.start
1
+ unless ENV['CI']
2
+ require 'simplecov'
3
+ SimpleCov.start
4
+ end
3
5
  require 'oauth2'
4
6
  require 'rspec'
5
7
  require 'rspec/autorun'
@@ -14,7 +14,7 @@ describe OAuth2::Client do
14
14
  stub.get('/conflict') {|env| [409, {'Content-Type' => 'text/plain'}, 'not authorized']}
15
15
  stub.get('/redirect') {|env| [302, {'Content-Type' => 'text/plain', 'location' => '/success' }, '']}
16
16
  stub.post('/redirect') {|env| [303, {'Content-Type' => 'text/plain', 'location' => '/reflect' }, '']}
17
- stub.get('/error') {|env| [500, {}, '']}
17
+ stub.get('/error') {|env| [500, {'Content-Type' => 'text/plain'}, 'unknown error']}
18
18
  stub.get('/empty_get') {|env| [204, {}, nil]}
19
19
  end
20
20
  end
@@ -148,6 +148,8 @@ describe OAuth2::Client do
148
148
  rescue Exception => e
149
149
  e.code.should == error_value
150
150
  e.description.should == error_description_value
151
+ e.to_s.should match(/#{error_value}/)
152
+ e.to_s.should match(/#{error_description_value}/)
151
153
  end
152
154
  end
153
155
 
@@ -156,6 +158,7 @@ describe OAuth2::Client do
156
158
  subject.request(:get, '/error')
157
159
  rescue Exception => e
158
160
  e.response.should_not be_nil
161
+ e.to_s.should match(/unknown error/)
159
162
  end
160
163
  end
161
164
  end
@@ -0,0 +1,70 @@
1
+ require 'helper'
2
+
3
+ describe OAuth2::Strategy::ClientCredentials do
4
+ let(:kvform_token) { 'expires_in=600&access_token=salmon&refresh_token=trout' }
5
+ let(:json_token) { '{"expires_in":600,"access_token":"salmon","refresh_token":"trout"}' }
6
+
7
+ let(:client) do
8
+ OAuth2::Client.new('abc', 'def', :site => 'http://api.example.com') do |builder|
9
+ builder.adapter :test do |stub|
10
+ stub.post('/oauth/token', {'grant_type' => 'client_credentials'}) do |env|
11
+ client_id, client_secret = HTTPAuth::Basic.unpack_authorization(env[:request_headers]['Authorization'])
12
+ client_id == 'abc' && client_secret == 'def' or raise Faraday::Adapter::Test::Stubs::NotFound.new
13
+ case @mode
14
+ when "formencoded"
15
+ [200, {'Content-Type' => 'application/x-www-form-urlencoded'}, kvform_token]
16
+ when "json"
17
+ [200, {'Content-Type' => 'application/json'}, json_token]
18
+ end
19
+ end
20
+ stub.post('/oauth/token', {'client_id' => 'abc', 'client_secret' => 'def', 'grant_type' => 'client_credentials'}) do |env|
21
+ case @mode
22
+ when "formencoded"
23
+ [200, {'Content-Type' => 'application/x-www-form-urlencoded'}, kvform_token]
24
+ when "json"
25
+ [200, {'Content-Type' => 'application/json'}, json_token]
26
+ end
27
+ end
28
+ end
29
+ end
30
+ end
31
+
32
+ subject {client.client_credentials}
33
+
34
+ describe "#authorize_url" do
35
+ it "should raise NotImplementedError" do
36
+ lambda {subject.authorize_url}.should raise_error(NotImplementedError)
37
+ end
38
+ end
39
+
40
+ %w(json formencoded).each do |mode|
41
+ %w(default basic_auth request_body).each do |auth_scheme|
42
+ describe "#get_token (#{mode}) (#{auth_scheme})" do
43
+ before do
44
+ @mode = mode
45
+ @access = subject.get_token({}, auth_scheme == 'default' ? {} : {'auth_scheme' => auth_scheme})
46
+ end
47
+
48
+ it 'returns AccessToken with same Client' do
49
+ @access.client.should == client
50
+ end
51
+
52
+ it 'returns AccessToken with #token' do
53
+ @access.token.should == 'salmon'
54
+ end
55
+
56
+ it 'returns AccessToken without #refresh_token' do
57
+ @access.refresh_token.should be_nil
58
+ end
59
+
60
+ it 'returns AccessToken with #expires_in' do
61
+ @access.expires_in.should == 600
62
+ end
63
+
64
+ it 'returns AccessToken with #expires_at' do
65
+ @access.expires_at.should_not be_nil
66
+ end
67
+ end
68
+ end
69
+ end
70
+ end
metadata CHANGED
@@ -1,114 +1,150 @@
1
- --- !ruby/object:Gem::Specification
1
+ --- !ruby/object:Gem::Specification
2
2
  name: oauth2
3
- version: !ruby/object:Gem::Version
4
- version: 0.5.2
3
+ version: !ruby/object:Gem::Version
4
+ hash: 7
5
5
  prerelease:
6
+ segments:
7
+ - 0
8
+ - 6
9
+ - 0
10
+ version: 0.6.0
6
11
  platform: ruby
7
- authors:
12
+ authors:
8
13
  - Michael Bleigh
9
14
  - Erik Michaels-Ober
10
15
  autorequire:
11
16
  bindir: bin
12
17
  cert_chain: []
13
- date: 2012-01-04 00:00:00.000000000Z
14
- dependencies:
15
- - !ruby/object:Gem::Dependency
18
+
19
+ date: 2012-04-12 00:00:00 -07:00
20
+ default_executable:
21
+ dependencies:
22
+ - !ruby/object:Gem::Dependency
16
23
  name: faraday
17
- requirement: &70259907739420 !ruby/object:Gem::Requirement
24
+ prerelease: false
25
+ requirement: &id001 !ruby/object:Gem::Requirement
18
26
  none: false
19
- requirements:
27
+ requirements:
20
28
  - - ~>
21
- - !ruby/object:Gem::Version
22
- version: '0.7'
29
+ - !ruby/object:Gem::Version
30
+ hash: 5
31
+ segments:
32
+ - 0
33
+ - 7
34
+ version: "0.7"
23
35
  type: :runtime
24
- prerelease: false
25
- version_requirements: *70259907739420
26
- - !ruby/object:Gem::Dependency
36
+ version_requirements: *id001
37
+ - !ruby/object:Gem::Dependency
27
38
  name: multi_json
28
- requirement: &70259907738920 !ruby/object:Gem::Requirement
39
+ prerelease: false
40
+ requirement: &id002 !ruby/object:Gem::Requirement
29
41
  none: false
30
- requirements:
42
+ requirements:
31
43
  - - ~>
32
- - !ruby/object:Gem::Version
33
- version: '1.0'
44
+ - !ruby/object:Gem::Version
45
+ hash: 15
46
+ segments:
47
+ - 1
48
+ - 0
49
+ version: "1.0"
34
50
  type: :runtime
51
+ version_requirements: *id002
52
+ - !ruby/object:Gem::Dependency
53
+ name: httpauth
35
54
  prerelease: false
36
- version_requirements: *70259907738920
37
- - !ruby/object:Gem::Dependency
38
- name: multi_xml
39
- requirement: &70259907738540 !ruby/object:Gem::Requirement
55
+ requirement: &id003 !ruby/object:Gem::Requirement
40
56
  none: false
41
- requirements:
42
- - - ! '>='
43
- - !ruby/object:Gem::Version
44
- version: '0'
45
- type: :development
57
+ requirements:
58
+ - - ~>
59
+ - !ruby/object:Gem::Version
60
+ hash: 9
61
+ segments:
62
+ - 0
63
+ - 1
64
+ version: "0.1"
65
+ type: :runtime
66
+ version_requirements: *id003
67
+ - !ruby/object:Gem::Dependency
68
+ name: multi_xml
46
69
  prerelease: false
47
- version_requirements: *70259907738540
48
- - !ruby/object:Gem::Dependency
49
- name: rake
50
- requirement: &70259907738080 !ruby/object:Gem::Requirement
70
+ requirement: &id004 !ruby/object:Gem::Requirement
51
71
  none: false
52
- requirements:
53
- - - ! '>='
54
- - !ruby/object:Gem::Version
55
- version: '0'
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ hash: 3
76
+ segments:
77
+ - 0
78
+ version: "0"
56
79
  type: :development
80
+ version_requirements: *id004
81
+ - !ruby/object:Gem::Dependency
82
+ name: rake
57
83
  prerelease: false
58
- version_requirements: *70259907738080
59
- - !ruby/object:Gem::Dependency
60
- name: rdoc
61
- requirement: &70259907737660 !ruby/object:Gem::Requirement
84
+ requirement: &id005 !ruby/object:Gem::Requirement
62
85
  none: false
63
- requirements:
64
- - - ! '>='
65
- - !ruby/object:Gem::Version
66
- version: '0'
86
+ requirements:
87
+ - - ">="
88
+ - !ruby/object:Gem::Version
89
+ hash: 3
90
+ segments:
91
+ - 0
92
+ version: "0"
67
93
  type: :development
94
+ version_requirements: *id005
95
+ - !ruby/object:Gem::Dependency
96
+ name: rdoc
68
97
  prerelease: false
69
- version_requirements: *70259907737660
70
- - !ruby/object:Gem::Dependency
71
- name: rspec
72
- requirement: &70259907737240 !ruby/object:Gem::Requirement
98
+ requirement: &id006 !ruby/object:Gem::Requirement
73
99
  none: false
74
- requirements:
75
- - - ! '>='
76
- - !ruby/object:Gem::Version
77
- version: '0'
100
+ requirements:
101
+ - - ">="
102
+ - !ruby/object:Gem::Version
103
+ hash: 3
104
+ segments:
105
+ - 0
106
+ version: "0"
78
107
  type: :development
108
+ version_requirements: *id006
109
+ - !ruby/object:Gem::Dependency
110
+ name: rspec
79
111
  prerelease: false
80
- version_requirements: *70259907737240
81
- - !ruby/object:Gem::Dependency
82
- name: simplecov
83
- requirement: &70259907767020 !ruby/object:Gem::Requirement
112
+ requirement: &id007 !ruby/object:Gem::Requirement
84
113
  none: false
85
- requirements:
86
- - - ! '>='
87
- - !ruby/object:Gem::Version
88
- version: '0'
114
+ requirements:
115
+ - - ">="
116
+ - !ruby/object:Gem::Version
117
+ hash: 3
118
+ segments:
119
+ - 0
120
+ version: "0"
89
121
  type: :development
122
+ version_requirements: *id007
123
+ - !ruby/object:Gem::Dependency
124
+ name: simplecov
90
125
  prerelease: false
91
- version_requirements: *70259907767020
92
- - !ruby/object:Gem::Dependency
93
- name: yard
94
- requirement: &70259907766600 !ruby/object:Gem::Requirement
126
+ requirement: &id008 !ruby/object:Gem::Requirement
95
127
  none: false
96
- requirements:
97
- - - ! '>='
98
- - !ruby/object:Gem::Version
99
- version: '0'
128
+ requirements:
129
+ - - ">="
130
+ - !ruby/object:Gem::Version
131
+ hash: 3
132
+ segments:
133
+ - 0
134
+ version: "0"
100
135
  type: :development
101
- prerelease: false
102
- version_requirements: *70259907766600
103
- description: A Ruby wrapper for the OAuth 2.0 protocol built with a similar style
104
- to the original OAuth gem.
105
- email:
136
+ version_requirements: *id008
137
+ description: A Ruby wrapper for the OAuth 2.0 protocol built with a similar style to the original OAuth gem.
138
+ email:
106
139
  - michael@intridea.com
107
140
  - sferik@gmail.com
108
141
  executables: []
142
+
109
143
  extensions: []
144
+
110
145
  extra_rdoc_files: []
111
- files:
146
+
147
+ files:
112
148
  - .document
113
149
  - .gemtest
114
150
  - .gitignore
@@ -125,6 +161,7 @@ files:
125
161
  - lib/oauth2/response.rb
126
162
  - lib/oauth2/strategy/auth_code.rb
127
163
  - lib/oauth2/strategy/base.rb
164
+ - lib/oauth2/strategy/client_credentials.rb
128
165
  - lib/oauth2/strategy/password.rb
129
166
  - lib/oauth2/version.rb
130
167
  - oauth2.gemspec
@@ -134,37 +171,50 @@ files:
134
171
  - spec/oauth2/response_spec.rb
135
172
  - spec/oauth2/strategy/auth_code_spec.rb
136
173
  - spec/oauth2/strategy/base_spec.rb
174
+ - spec/oauth2/strategy/client_credentials_spec.rb
137
175
  - spec/oauth2/strategy/password_spec.rb
176
+ has_rdoc: true
138
177
  homepage: http://github.com/intridea/oauth2
139
178
  licenses: []
179
+
140
180
  post_install_message:
141
181
  rdoc_options: []
142
- require_paths:
182
+
183
+ require_paths:
143
184
  - lib
144
- required_ruby_version: !ruby/object:Gem::Requirement
185
+ required_ruby_version: !ruby/object:Gem::Requirement
145
186
  none: false
146
- requirements:
147
- - - ! '>='
148
- - !ruby/object:Gem::Version
149
- version: '0'
150
- required_rubygems_version: !ruby/object:Gem::Requirement
187
+ requirements:
188
+ - - ">="
189
+ - !ruby/object:Gem::Version
190
+ hash: 3
191
+ segments:
192
+ - 0
193
+ version: "0"
194
+ required_rubygems_version: !ruby/object:Gem::Requirement
151
195
  none: false
152
- requirements:
153
- - - ! '>='
154
- - !ruby/object:Gem::Version
196
+ requirements:
197
+ - - ">="
198
+ - !ruby/object:Gem::Version
199
+ hash: 23
200
+ segments:
201
+ - 1
202
+ - 3
203
+ - 6
155
204
  version: 1.3.6
156
205
  requirements: []
206
+
157
207
  rubyforge_project:
158
- rubygems_version: 1.8.13
208
+ rubygems_version: 1.6.2
159
209
  signing_key:
160
210
  specification_version: 3
161
211
  summary: A Ruby wrapper for the OAuth 2.0 protocol.
162
- test_files:
212
+ test_files:
163
213
  - spec/helper.rb
164
214
  - spec/oauth2/access_token_spec.rb
165
215
  - spec/oauth2/client_spec.rb
166
216
  - spec/oauth2/response_spec.rb
167
217
  - spec/oauth2/strategy/auth_code_spec.rb
168
218
  - spec/oauth2/strategy/base_spec.rb
219
+ - spec/oauth2/strategy/client_credentials_spec.rb
169
220
  - spec/oauth2/strategy/password_spec.rb
170
- has_rdoc: