oauth2 0.5.2 → 0.6.0

Sign up to get free protection for your applications and to get access to all the features.
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: