oauth2 0.2.0 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore CHANGED
@@ -32,3 +32,4 @@ Gemfile.lock
32
32
  coverage.data
33
33
 
34
34
  ## PROJECT::SPECIFIC
35
+ .svn
@@ -0,0 +1,7 @@
1
+ rvm:
2
+ - 1.8.7
3
+ - 1.9.1
4
+ - 1.9.2
5
+ - jruby
6
+ - rbx
7
+ - ree
@@ -1,22 +1,22 @@
1
- == 0.0.10 (June 19)
2
-
1
+ 0.0.10 - June 19, 2010
2
+ ----------------------
3
3
  * Handle ActiveSupport JSON case where incompatible string does not raise an error. (via Flameeyes)
4
4
  * Depend on latest version of MultiJSON.
5
5
 
6
- == 0.0.9 (June 18)
7
-
6
+ 0.0.9 - June 18, 2010
7
+ ---------------------
8
8
  * Support a JSON token response with swappable JSON parser via MultiJSON.
9
9
  * Add support for "expires_in" parameter and relevant methods on AccessToken.
10
10
 
11
- == 0.0.8 (April 27)
12
-
11
+ 0.0.8 - April 27, 2010
12
+ ----------------------
13
13
  * Change get_request_token to use POST to conform to OAuth 2.0 spec. (via jeremy)
14
14
 
15
- == 0.0.7 (April 27)
16
-
15
+ 0.0.7 - April 27, 2010
16
+ ----------------------
17
17
  * Updating Faraday dependency for improved SSL support (via technoweenie)
18
18
 
19
- == 0.0.6 (April 25)
20
-
19
+ 0.0.6 - April 25, 2010
20
+ ----------------------
21
21
  * Added ResponseString so as not to throw away response information when making requests.
22
- * Deprecated #access_token on WebServer strategy in favor of #get_access_token
22
+ * Deprecated #access_token on WebServer strategy in favor of #get_access_token
@@ -1,4 +1,4 @@
1
- Copyright (c) 2009 Intridea, Inc. and Michael Bleigh
1
+ Copyright (c) 2011 Intridea, Inc. and Michael Bleigh
2
2
 
3
3
  Permission is hereby granted, free of charge, to any person obtaining
4
4
  a copy of this software and associated documentation files (the
@@ -0,0 +1,95 @@
1
+ OAuth2
2
+ ======
3
+ A Ruby wrapper for the OAuth 2.0 specification. This is a work in progress, being built first to solve the pragmatic process of connecting to existing OAuth 2.0 endpoints (a.k.a. Facebook) with the goal of building it up to meet the entire specification over time.
4
+
5
+ Installation
6
+ ------------
7
+ gem install oauth2
8
+
9
+ Continuous Integration
10
+ ----------------------
11
+ [![Build Status](http://travis-ci.org/intridea/oauth2.png)](http://travis-ci.org/intridea/oauth2)
12
+
13
+ Resources
14
+ ---------
15
+ * View Source on GitHub (https://github.com/intridea/oauth2)
16
+ * Report Issues on GitHub (https://github.com/intridea/oauth2/issues)
17
+ * Read More at the Wiki (https://wiki.github.com/intridea/oauth2)
18
+
19
+ Web Server Example (Sinatra)
20
+ ----------------------------
21
+ Below is a fully functional example of a Sinatra application that would authenticate to Facebook utilizing the OAuth 2.0 web server flow.
22
+
23
+ require 'rubygems'
24
+ require 'sinatra'
25
+ require 'oauth2'
26
+ require 'json'
27
+
28
+ def client
29
+ OAuth2::Client.new('app_id', 'app_secret', :site => 'https://graph.facebook.com')
30
+ end
31
+
32
+ get '/auth/facebook' do
33
+ redirect client.web_server.authorize_url(
34
+ :redirect_uri => redirect_uri,
35
+ :scope => 'email,offline_access'
36
+ )
37
+ end
38
+
39
+ get '/auth/facebook/callback' do
40
+ access_token = client.web_server.get_access_token(params[:code], :redirect_uri => redirect_uri)
41
+ user = JSON.parse(access_token.get('/me'))
42
+ user.inspect
43
+ end
44
+
45
+ def redirect_uri
46
+ uri = URI.parse(request.url)
47
+ uri.path = '/auth/facebook/callback'
48
+ uri.query = nil
49
+ uri.to_s
50
+ end
51
+
52
+ That's all there is to it! You can use the access token like you would with the
53
+ OAuth gem, calling HTTP verbs on it etc. You can view more examples on the [OAuth2
54
+ Wiki](http://wiki.github.com/intridea/oauth2/examples).
55
+
56
+ JSON Parsing
57
+ ------------
58
+ Because JSON has become the standard format of the OAuth 2.0 specification,
59
+ the <tt>oauth2</tt> gem contains a mode that will perform automatic parsing
60
+ of JSON response bodies, returning a hash instead of a string. To enable this
61
+ mode, simply add the <tt>:parse_json</tt> option to your client initialization:
62
+
63
+ client = OAuth2::Client.new(
64
+ 'app_id',
65
+ 'app_secret',
66
+ :site => 'https://example.com',
67
+ :parse_json => true,
68
+ )
69
+
70
+ # Obtain an access token using the client
71
+ token.get('/some/url.json') #=> {"some" => "hash"}
72
+
73
+ Testing
74
+ -------
75
+ To use the OAuth2 client for testing error conditions do:
76
+
77
+ my_client.raise_errors = false
78
+
79
+ It will then return the error status and response instead of raising an exception.
80
+
81
+ Note on Patches/Pull Requests
82
+ -----------------------------
83
+ 1. Fork the project.
84
+ 2. Create a topic branch.
85
+ 3. Implement your feature or bug fix.
86
+ 4. Add documentation for your feature or bug fix.
87
+ 5. Add specs for your feature or bug fix.
88
+ 6. Run <tt>bundle exec rake spec</tt>. If your changes are not 100% covered, go back to step 5.
89
+ 7. Commit and push your changes.
90
+ 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.)
91
+
92
+ Copyright
93
+ ---------
94
+ Copyright (c) 2011 Intridea, Inc. and Michael Bleigh.
95
+ See [LICENSE](https://github.com/intridea/oauth2/blob/master/LICENSE.md) for details.
@@ -7,5 +7,6 @@ end
7
7
  require 'oauth2/client'
8
8
  require 'oauth2/strategy/base'
9
9
  require 'oauth2/strategy/web_server'
10
+ require 'oauth2/strategy/password'
10
11
  require 'oauth2/access_token'
11
12
  require 'oauth2/response_object'
@@ -1,9 +1,9 @@
1
1
  module OAuth2
2
2
  class AccessToken
3
- attr_reader :client, :token, :refresh_token, :expires_in, :expires_at
3
+ attr_reader :client, :token, :refresh_token, :expires_in, :expires_at, :params
4
4
  attr_accessor :token_param
5
5
 
6
- def initialize(client, token, refresh_token = nil, expires_in = nil, params = {})
6
+ def initialize(client, token, refresh_token=nil, expires_in=nil, params={})
7
7
  @client = client
8
8
  @token = token.to_s
9
9
  @refresh_token = refresh_token.to_s
@@ -26,25 +26,25 @@ module OAuth2
26
26
  expires? && expires_at < Time.now
27
27
  end
28
28
 
29
- def request(verb, path, params = {}, headers = {})
29
+ def request(verb, path, params={}, headers={})
30
30
  params = params.merge token_param => @token
31
31
  headers = headers.merge 'Authorization' => "OAuth #{@token}"
32
32
  @client.request(verb, path, params, headers)
33
33
  end
34
34
 
35
- def get(path, params = {}, headers = {})
35
+ def get(path, params={}, headers={})
36
36
  request(:get, path, params, headers)
37
37
  end
38
38
 
39
- def post(path, params = {}, headers = {})
39
+ def post(path, params={}, headers={})
40
40
  request(:post, path, params, headers)
41
41
  end
42
42
 
43
- def put(path, params = {}, headers = {})
43
+ def put(path, params={}, headers={})
44
44
  request(:put, path, params, headers)
45
45
  end
46
46
 
47
- def delete(path, params = {}, headers = {})
47
+ def delete(path, params={}, headers={})
48
48
  request(:delete, path, params, headers)
49
49
  end
50
50
  end
@@ -2,7 +2,7 @@ require 'faraday'
2
2
 
3
3
  module OAuth2
4
4
  class Client
5
- attr_accessor :id, :secret, :site, :connection, :options
5
+ attr_accessor :id, :secret, :site, :connection, :options, :raise_errors
6
6
  attr_writer :json
7
7
 
8
8
  # Instantiate a new OAuth 2.0 client using the
@@ -17,32 +17,41 @@ module OAuth2
17
17
  # <tt>:access_token_path</tt> :: Specify the path to the access token endpoint.
18
18
  # <tt>:access_token_url</tt> :: Specify the full URL of the access token endpoint.
19
19
  # <tt>:parse_json</tt> :: If true, <tt>application/json</tt> responses will be automatically parsed.
20
- def initialize(client_id, client_secret, opts = {})
21
- adapter = opts.delete(:adapter)
22
- self.id = client_id
23
- self.secret = client_secret
24
- self.site = opts.delete(:site) if opts[:site]
25
- self.options = opts
26
- self.connection = Faraday::Connection.new(site)
27
- self.json = opts.delete(:parse_json)
20
+ # <tt>:ssl</tt> :: Specify SSL options for the connection.
21
+ # <tt>:adapter</tt> :: The name of the Faraday::Adapter::* class to use, e.g. :net_http. To pass arguments
22
+ # to the adapter pass an array here, e.g. [:action_dispatch, my_test_session]
23
+ # <tt>:raise_errors</tt> :: Default true. When false it will then return the error status and response instead of raising an exception.
24
+ def initialize(client_id, client_secret, opts={})
25
+ self.options = opts.dup
26
+ adapter = self.options.delete(:adapter)
27
+ ssl_opts = self.options.delete(:ssl) || {}
28
+ connection_opts = ssl_opts ? {:ssl => ssl_opts} : {}
29
+ self.id = client_id
30
+ self.secret = client_secret
31
+ self.site = self.options.delete(:site) if self.options[:site]
32
+ self.connection = Faraday::Connection.new(site, connection_opts)
33
+ self.json = self.options.delete(:parse_json)
34
+ self.raise_errors = !(self.options.delete(:raise_errors) == false)
28
35
 
29
36
  if adapter && adapter != :test
30
- connection.build { |b| b.adapter(adapter) }
37
+ connection.build do |b|
38
+ b.adapter(*[adapter].flatten)
39
+ end
31
40
  end
32
41
  end
33
42
 
34
- def authorize_url(params = nil)
43
+ def authorize_url(params=nil)
35
44
  path = options[:authorize_url] || options[:authorize_path] || "/oauth/authorize"
36
45
  connection.build_url(path, params).to_s
37
46
  end
38
47
 
39
- def access_token_url(params = nil)
48
+ def access_token_url(params=nil)
40
49
  path = options[:access_token_url] || options[:access_token_path] || "/oauth/access_token"
41
50
  connection.build_url(path, params).to_s
42
51
  end
43
52
 
44
53
  # Makes a request relative to the specified site root.
45
- def request(verb, url, params = {}, headers = {})
54
+ def request(verb, url, params={}, headers={})
46
55
  if verb == :get
47
56
  resp = connection.run_request(verb, url, nil, headers) do |req|
48
57
  req.params.update(params)
@@ -51,26 +60,37 @@ module OAuth2
51
60
  resp = connection.run_request(verb, url, params, headers)
52
61
  end
53
62
 
54
- case resp.status
55
- when 200..299
56
- if json?
57
- return ResponseObject.from(resp)
63
+ if raise_errors
64
+ case resp.status
65
+ when 200...299
66
+ return response_for(resp)
67
+ when 401
68
+ e = OAuth2::AccessDenied.new("Received HTTP 401 during request.")
69
+ e.response = resp
70
+ raise e
58
71
  else
59
- return ResponseString.new(resp)
60
- end
61
- when 401
62
- e = OAuth2::AccessDenied.new("Received HTTP 401 during request.")
63
- e.response = resp
64
- raise e
65
- else
66
- e = OAuth2::HTTPError.new("Received HTTP #{resp.status} during request.")
67
- e.response = resp
68
- raise e
72
+ e = OAuth2::HTTPError.new("Received HTTP #{resp.status} during request.")
73
+ e.response = resp
74
+ raise e
75
+ end
76
+ else
77
+ response_for resp
69
78
  end
70
79
  end
71
80
 
72
81
  def json?; !!@json end
73
82
 
74
83
  def web_server; OAuth2::Strategy::WebServer.new(self) end
84
+ def password; OAuth2::Strategy::Password.new(self) end
85
+
86
+ private
87
+
88
+ def response_for(resp)
89
+ if json?
90
+ return ResponseObject.from(resp)
91
+ else
92
+ return ResponseString.new(resp)
93
+ end
94
+ end
75
95
  end
76
96
  end
@@ -5,20 +5,20 @@ module OAuth2
5
5
  @client = client
6
6
  end
7
7
 
8
- def authorize_url(options = {}) #:nodoc:
8
+ def authorize_url(options={}) #:nodoc:
9
9
  @client.authorize_url(authorize_params(options))
10
10
  end
11
11
 
12
- def authorize_params(options = {}) #:nodoc:
12
+ def authorize_params(options={}) #:nodoc:
13
13
  options = options.inject({}){|h, (k, v)| h[k.to_s] = v; h}
14
14
  {'client_id' => @client.id}.merge(options)
15
15
  end
16
16
 
17
- def access_token_url(options = {})
17
+ def access_token_url(options={})
18
18
  @client.access_token_url(access_token_params(options))
19
19
  end
20
20
 
21
- def access_token_params(options = {})
21
+ def access_token_params(options={})
22
22
  {
23
23
  'client_id' => @client.id,
24
24
  'client_secret' => @client.secret
@@ -0,0 +1,38 @@
1
+ require 'multi_json'
2
+
3
+ module OAuth2
4
+ module Strategy
5
+ class Password < Base
6
+ def authorize_url
7
+ raise NotImplementedError, "The authorization endpoint is not used in this strategy"
8
+ end
9
+ # Retrieve an access token given the specified validation code.
10
+ # Note that you must also provide a <tt>:redirect_uri</tt> option
11
+ # in order to successfully verify your request for most OAuth 2.0
12
+ # endpoints.
13
+ def get_access_token(username, password, options={})
14
+ response = @client.request(:post, @client.access_token_url, access_token_params(username, password, options))
15
+
16
+ params = MultiJson.decode(response) rescue nil
17
+ # the ActiveSupport JSON parser won't cause an exception when
18
+ # given a formencoded string, so make sure that it was
19
+ # actually parsed in an Hash. This covers even the case where
20
+ # it caused an exception since it'll still be nil.
21
+ params = Rack::Utils.parse_query(response) unless params.is_a? Hash
22
+
23
+ access = params.delete('access_token')
24
+ refresh = params.delete('refresh_token')
25
+ expires_in = params.delete('expires_in')
26
+ OAuth2::AccessToken.new(@client, access, refresh, expires_in, params)
27
+ end
28
+
29
+ def access_token_params(username, password, options={}) #:nodoc:
30
+ super(options).merge({
31
+ 'grant_type' => 'password',
32
+ 'username' => username,
33
+ 'password' => password
34
+ })
35
+ end
36
+ end
37
+ end
38
+ end
@@ -3,7 +3,7 @@ require 'multi_json'
3
3
  module OAuth2
4
4
  module Strategy
5
5
  class WebServer < Base
6
- def authorize_params(options = {}) #:nodoc:
6
+ def authorize_params(options={}) #:nodoc:
7
7
  super(options).merge('response_type' => 'code')
8
8
  end
9
9
 
@@ -11,36 +11,31 @@ module OAuth2
11
11
  # Note that you must also provide a <tt>:redirect_uri</tt> option
12
12
  # in order to successfully verify your request for most OAuth 2.0
13
13
  # endpoints.
14
- def get_access_token(code, options = {})
15
- response = @client.request(:post, @client.access_token_url, access_token_params(code, options))
14
+ def get_access_token(code, options={})
15
+ response = @client.request(:get, @client.access_token_url, access_token_params(code, options))
16
16
 
17
17
  if response.is_a? Hash
18
- params=response
18
+ params = response
19
19
  else
20
- params = MultiJson.decode(response) rescue nil
20
+ params = MultiJson.decode(response) rescue nil
21
21
  # the ActiveSupport JSON parser won't cause an exception when
22
22
  # given a formencoded string, so make sure that it was
23
23
  # actually parsed in an Hash. This covers even the case where
24
24
  # it caused an exception since it'll still be nil.
25
- params = Rack::Utils.parse_query(response) unless params.is_a? Hash
25
+ params = Rack::Utils.parse_query(response) unless params.is_a? Hash
26
26
  end
27
27
 
28
- access = params['access_token']
29
- refresh = params['refresh_token']
30
- expires_in = params['expires_in'] || params['expires'] # params['expires'] is only for facebook
28
+ access = params.delete('access_token')
29
+ refresh = params.delete('refresh_token')
30
+ # params['expires'] is only for Facebook
31
+ expires_in = params.delete('expires_in') || params.delete('expires')
31
32
  OAuth2::AccessToken.new(@client, access, refresh, expires_in, params)
32
33
  end
33
34
 
34
- # <b>DEPRECATED:</b> Use #get_access_token instead.
35
- def access_token(*args)
36
- warn '[DEPRECATED] OAuth2::Strategy::WebServer#access_token is deprecated, use #get_access_token instead. Will be removed in 0.1.0'
37
- get_access_token(*args)
38
- end
39
-
40
- def access_token_params(code, options = {}) #:nodoc:
35
+ def access_token_params(code, options={}) #:nodoc:
41
36
  super(options).merge({
42
37
  'grant_type' => 'authorization_code',
43
- 'code' => code
38
+ 'code' => code,
44
39
  })
45
40
  end
46
41
  end
@@ -1,3 +1,3 @@
1
1
  module OAuth2
2
- VERSION = "0.2.0"
2
+ VERSION = "0.3.0"
3
3
  end
@@ -9,8 +9,6 @@ Gem::Specification.new do |s|
9
9
  s.description = %q{A Ruby wrapper for the OAuth 2.0 protocol built with a similar style to the original OAuth gem.}
10
10
  s.summary = %q{A Ruby wrapper for the OAuth 2.0 protocol.}
11
11
  s.email = "michael@intridea.com"
12
- s.extra_rdoc_files = ["LICENSE", "README.rdoc"]
13
- s.rdoc_options = ["--charset=UTF-8"]
14
12
  s.homepage = "http://github.com/intridea/oauth2"
15
13
  s.require_paths = ["lib"]
16
14
  s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
@@ -5,18 +5,18 @@ describe OAuth2::AccessToken do
5
5
  cli = OAuth2::Client.new('abc', 'def', :site => 'https://api.example.com')
6
6
  cli.connection.build do |b|
7
7
  b.adapter :test do |stub|
8
- stub.get('/client?oauth_token=monkey') { |env| [200, {}, 'get'] }
9
- stub.post('/client') { |env| [200, {}, 'oauth_token=' << env[:body]['oauth_token']] }
10
- stub.put('/client') { |env| [200, {}, 'oauth_token=' << env[:body]['oauth_token']] }
11
- stub.delete('/client') { |env| [200, {}, 'oauth_token=' << env[:body]['oauth_token']] }
8
+ stub.get('/client?oauth_token=monkey') {|env| [200, {}, 'get']}
9
+ stub.post('/client') {|env| [200, {}, 'oauth_token=' << env[:body]['oauth_token']]}
10
+ stub.put('/client') {|env| [200, {}, 'oauth_token=' << env[:body]['oauth_token']]}
11
+ stub.delete('/client') {|env| [200, {}, 'oauth_token=' << env[:body]['oauth_token']]}
12
12
  end
13
13
  end
14
14
  cli
15
15
  end
16
16
 
17
- let(:token) { 'monkey' }
17
+ let(:token) {'monkey'}
18
18
 
19
- subject { OAuth2::AccessToken.new(client, token) }
19
+ subject {OAuth2::AccessToken.new(client, token)}
20
20
 
21
21
  describe '#initialize' do
22
22
  it 'should assign client and token' do
@@ -24,6 +24,12 @@ describe OAuth2::AccessToken do
24
24
  subject.token.should == token
25
25
  end
26
26
 
27
+ it 'should assign extra params' do
28
+ target = OAuth2::AccessToken.new(client, token, nil, nil, {'foo' => 'bar'})
29
+ target.params.should include('foo')
30
+ target.params['foo'].should == 'bar'
31
+ end
32
+
27
33
  it "makes GET requests with access token" do
28
34
  subject.send(:get, 'client').should == 'get'
29
35
  end
@@ -51,7 +57,7 @@ describe OAuth2::AccessToken do
51
57
  Time.stub!(:now).and_return(@now)
52
58
  end
53
59
 
54
- subject{ OAuth2::AccessToken.new(client, token, 'abaca', 600)}
60
+ subject{OAuth2::AccessToken.new(client, token, 'abaca', 600)}
55
61
 
56
62
  it 'should be a time representation of #expires_in' do
57
63
  subject.expires_at.should == (@now + 600)
@@ -5,10 +5,10 @@ describe OAuth2::Client do
5
5
  cli = OAuth2::Client.new('abc', 'def', :site => 'https://api.example.com')
6
6
  cli.connection.build do |b|
7
7
  b.adapter :test do |stub|
8
- stub.get('/success') { |env| [200, {'Content-Type' => 'text/awesome'}, 'yay'] }
9
- stub.get('/unauthorized') { |env| [401, {}, ''] }
10
- stub.get('/error') { |env| [500, {}, ''] }
11
- stub.get('/json') { |env| [200, {'Content-Type' => 'application/json; charset=utf8'}, '{"abc":"def"}']}
8
+ stub.get('/success') {|env| [200, {'Content-Type' => 'text/awesome'}, 'yay']}
9
+ stub.get('/unauthorized') {|env| [401, {'Content-Type' => 'text/plain'}, 'not authorized']}
10
+ stub.get('/error') {|env| [500, {}, '']}
11
+ stub.get('/json') {|env| [200, {'Content-Type' => 'application/json; charset=utf8'}, '{"abc":"def"}']}
12
12
  end
13
13
  end
14
14
  cli
@@ -27,6 +27,33 @@ describe OAuth2::Client do
27
27
  it 'should assign Faraday::Connection#host' do
28
28
  subject.connection.host.should == 'api.example.com'
29
29
  end
30
+
31
+ it 'should leave Faraday::Connection#ssl unset' do
32
+ subject.connection.ssl.should == {}
33
+ end
34
+
35
+ it "should be able to pass parameters to the adapter, e.g. Faraday::Adapter::ActionDispatch" do
36
+ connection = stub('connection')
37
+ Faraday::Connection.stub(:new => connection)
38
+ session = stub('session', :to_ary => nil)
39
+ builder = stub('builder')
40
+ connection.stub(:build).and_yield(builder)
41
+
42
+ builder.should_receive(:adapter).with(:action_dispatch, session)
43
+
44
+ OAuth2::Client.new('abc', 'def', :adapter => [:action_dispatch, session])
45
+ end
46
+
47
+ it "defaults raise_errors to true" do
48
+ subject.raise_errors.should be_true
49
+ end
50
+
51
+ it "allows true/false for raise_errors option" do
52
+ client = OAuth2::Client.new('abc', 'def', :site => 'https://api.example.com', :raise_errors => false)
53
+ client.raise_errors.should be_false
54
+ client = OAuth2::Client.new('abc', 'def', :site => 'https://api.example.com', :raise_errors => true)
55
+ client.raise_errors.should be_true
56
+ end
30
57
  end
31
58
 
32
59
  %w(authorize access_token).each do |path_type|
@@ -55,12 +82,21 @@ describe OAuth2::Client do
55
82
  response.headers.should == {'Content-Type' => 'text/awesome'}
56
83
  end
57
84
 
85
+ it "returns ResponseString on error if raise_errors is false" do
86
+ subject.raise_errors = false
87
+ response = subject.request(:get, '/unauthorized', {}, {})
88
+
89
+ response.should == 'not authorized'
90
+ response.status.should == 401
91
+ response.headers.should == {'Content-Type' => 'text/plain'}
92
+ end
93
+
58
94
  it "raises OAuth2::AccessDenied on 401 response" do
59
- lambda { subject.request(:get, '/unauthorized', {}, {}) }.should raise_error(OAuth2::AccessDenied)
95
+ lambda {subject.request(:get, '/unauthorized', {}, {})}.should raise_error(OAuth2::AccessDenied)
60
96
  end
61
97
 
62
98
  it "raises OAuth2::HTTPError on error response" do
63
- lambda { subject.request(:get, '/error', {}, {}) }.should raise_error(OAuth2::HTTPError)
99
+ lambda {subject.request(:get, '/error', {}, {})}.should raise_error(OAuth2::HTTPError)
64
100
  end
65
101
  end
66
102
 
@@ -95,4 +131,18 @@ describe OAuth2::Client do
95
131
  subject.json = false
96
132
  end
97
133
  end
134
+
135
+ context 'with SSL options' do
136
+ subject do
137
+ cli = OAuth2::Client.new('abc', 'def', :site => 'https://api.example.com', :ssl => {:ca_file => 'foo.pem'})
138
+ cli.connection.build do |b|
139
+ b.adapter :test
140
+ end
141
+ cli
142
+ end
143
+
144
+ it 'should pass the SSL options along to Faraday::Connection#ssl' do
145
+ subject.connection.ssl.should == {:ca_file => 'foo.pem'}
146
+ end
147
+ end
98
148
  end
@@ -2,6 +2,6 @@ require 'spec_helper'
2
2
 
3
3
  describe OAuth2::Strategy::Base do
4
4
  it 'should initialize with a Client' do
5
- lambda{ OAuth2::Strategy::Base.new(OAuth2::Client.new('abc', 'def')) }.should_not raise_error
5
+ lambda{OAuth2::Strategy::Base.new(OAuth2::Client.new('abc', 'def'))}.should_not raise_error
6
6
  end
7
7
  end
@@ -0,0 +1,57 @@
1
+ require 'spec_helper'
2
+
3
+ describe OAuth2::Strategy::Password do
4
+ let(:client) do
5
+ cli = OAuth2::Client.new('abc', 'def', :site => 'http://api.example.com')
6
+ cli.connection.build do |b|
7
+ b.adapter :test do |stub|
8
+ stub.post('/oauth/access_token') do |env|
9
+ case @mode
10
+ when "formencoded"
11
+ [200, {}, 'expires_in=600&access_token=salmon&refresh_token=trout']
12
+ when "json"
13
+ [200, {}, '{"expires_in":600,"access_token":"salmon","refresh_token":"trout"}']
14
+ end
15
+ end
16
+ end
17
+ end
18
+ cli
19
+ end
20
+ subject {client.password}
21
+
22
+ describe "#authorize_url" do
23
+ it "should raise NotImplementedError" do
24
+ lambda {subject.authorize_url}.should raise_error(NotImplementedError)
25
+ end
26
+ end
27
+
28
+ %w(json formencoded).each do |mode|
29
+ describe "#get_access_token (#{mode})" do
30
+ before do
31
+ @mode = mode
32
+ @access = subject.get_access_token('username', 'password')
33
+ end
34
+
35
+ it 'returns AccessToken with same Client' do
36
+ @access.client.should == client
37
+ end
38
+
39
+ it 'returns AccessToken with #token' do
40
+ @access.token.should == 'salmon'
41
+ end
42
+
43
+ it 'returns AccessToken with #refresh_token' do
44
+ @access.refresh_token.should == 'trout'
45
+ end
46
+
47
+ it 'returns AccessToken with #expires_in' do
48
+ @access.expires_in.should == 600
49
+ end
50
+
51
+ it 'returns AccessToken with #expires_at' do
52
+ @access.expires_at.should be_kind_of(Time)
53
+ end
54
+ end
55
+ end
56
+
57
+ end
@@ -5,21 +5,21 @@ describe OAuth2::Strategy::WebServer do
5
5
  cli = OAuth2::Client.new('abc', 'def', :site => 'http://api.example.com')
6
6
  cli.connection.build do |b|
7
7
  b.adapter :test do |stub|
8
- stub.post('/oauth/access_token') do |env|
8
+ stub.get('/oauth/access_token?client_id=abc&client_secret=def&code=sushi&grant_type=authorization_code') do |env|
9
9
  case @mode
10
- when "formencoded"
11
- [200, {}, 'expires_in=600&access_token=salmon&refresh_token=trout&extra_param=steve']
12
- when "json"
13
- [200, {}, '{"expires_in":600,"access_token":"salmon","refresh_token":"trout","extra_param":"steve"}']
14
- when "from_facebook"
15
- [200, {}, 'expires=600&access_token=salmon&refresh_token=trout&extra_param=steve']
10
+ when "formencoded"
11
+ [200, {}, 'expires_in=600&access_token=salmon&refresh_token=trout&extra_param=steve']
12
+ when "json"
13
+ [200, {}, '{"expires_in":600,"access_token":"salmon","refresh_token":"trout","extra_param":"steve"}']
14
+ when "from_facebook"
15
+ [200, {}, 'expires=600&access_token=salmon&refresh_token=trout&extra_param=steve']
16
16
  end
17
17
  end
18
18
  end
19
19
  end
20
20
  cli
21
21
  end
22
- subject { client.web_server }
22
+ subject{client.web_server}
23
23
 
24
24
  describe '#authorize_url' do
25
25
  it 'should include the client_id' do
metadata CHANGED
@@ -2,7 +2,7 @@
2
2
  name: oauth2
3
3
  version: !ruby/object:Gem::Version
4
4
  prerelease:
5
- version: 0.2.0
5
+ version: 0.3.0
6
6
  platform: ruby
7
7
  authors:
8
8
  - Michael Bleigh
@@ -10,8 +10,7 @@ autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
12
 
13
- date: 2011-04-01 00:00:00 -07:00
14
- default_executable:
13
+ date: 2011-04-08 00:00:00 Z
15
14
  dependencies:
16
15
  - !ruby/object:Gem::Dependency
17
16
  name: faraday
@@ -96,39 +95,40 @@ executables: []
96
95
 
97
96
  extensions: []
98
97
 
99
- extra_rdoc_files:
100
- - LICENSE
101
- - README.rdoc
98
+ extra_rdoc_files: []
99
+
102
100
  files:
103
101
  - .document
104
102
  - .gemtest
105
103
  - .gitignore
106
104
  - .rspec
107
- - CHANGELOG.rdoc
105
+ - .travis.yml
106
+ - CHANGELOG.md
108
107
  - Gemfile
109
- - LICENSE
110
- - README.rdoc
108
+ - LICENSE.md
109
+ - README.md
111
110
  - Rakefile
112
111
  - lib/oauth2.rb
113
112
  - lib/oauth2/access_token.rb
114
113
  - lib/oauth2/client.rb
115
114
  - lib/oauth2/response_object.rb
116
115
  - lib/oauth2/strategy/base.rb
116
+ - lib/oauth2/strategy/password.rb
117
117
  - lib/oauth2/strategy/web_server.rb
118
118
  - lib/oauth2/version.rb
119
119
  - oauth2.gemspec
120
120
  - spec/oauth2/access_token_spec.rb
121
121
  - spec/oauth2/client_spec.rb
122
122
  - spec/oauth2/strategy/base_spec.rb
123
+ - spec/oauth2/strategy/password_spec.rb
123
124
  - spec/oauth2/strategy/web_server_spec.rb
124
125
  - spec/spec_helper.rb
125
- has_rdoc: true
126
126
  homepage: http://github.com/intridea/oauth2
127
127
  licenses: []
128
128
 
129
129
  post_install_message:
130
- rdoc_options:
131
- - --charset=UTF-8
130
+ rdoc_options: []
131
+
132
132
  require_paths:
133
133
  - lib
134
134
  required_ruby_version: !ruby/object:Gem::Requirement
@@ -146,7 +146,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
146
146
  requirements: []
147
147
 
148
148
  rubyforge_project:
149
- rubygems_version: 1.6.2
149
+ rubygems_version: 1.7.2
150
150
  signing_key:
151
151
  specification_version: 3
152
152
  summary: A Ruby wrapper for the OAuth 2.0 protocol.
@@ -154,5 +154,7 @@ test_files:
154
154
  - spec/oauth2/access_token_spec.rb
155
155
  - spec/oauth2/client_spec.rb
156
156
  - spec/oauth2/strategy/base_spec.rb
157
+ - spec/oauth2/strategy/password_spec.rb
157
158
  - spec/oauth2/strategy/web_server_spec.rb
158
159
  - spec/spec_helper.rb
160
+ has_rdoc:
@@ -1,80 +0,0 @@
1
- = OAuth2
2
-
3
- A Ruby wrapper for the OAuth 2.0 specification. This is a work in progress, being built first to solve the pragmatic process of connecting to existing OAuth 2.0 endpoints (a.k.a. Facebook) with the goal of building it up to meet the entire specification over time.
4
-
5
- == Installation
6
-
7
- gem install oauth2
8
-
9
- == Resources
10
-
11
- * View Source on GitHub (http://github.com/intridea/oauth2)
12
- * Report Issues on GitHub (http://github.com/intridea/oauth2/issues)
13
- * Read More at the Wiki (http://wiki.github.com/intridea/oauth2/)
14
-
15
- == Web Server Example (Sinatra)
16
-
17
- Below is a fully functional example of a Sinatra application that would authenticate to Facebook utilizing the OAuth 2.0 web server flow.
18
-
19
- require 'rubygems'
20
- require 'sinatra'
21
- require 'oauth2'
22
- require 'json'
23
-
24
- def client
25
- OAuth2::Client.new('app_id', 'app_secret', :site => 'https://graph.facebook.com')
26
- end
27
-
28
- get '/auth/facebook' do
29
- redirect client.web_server.authorize_url(
30
- :redirect_uri => redirect_uri,
31
- :scope => 'email,offline_access'
32
- )
33
- end
34
-
35
- get '/auth/facebook/callback' do
36
- access_token = client.web_server.get_access_token(params[:code], :redirect_uri => redirect_uri)
37
- user = JSON.parse(access_token.get('/me'))
38
-
39
- user.inspect
40
- end
41
-
42
- def redirect_uri
43
- uri = URI.parse(request.url)
44
- uri.path = '/auth/facebook/callback'
45
- uri.query = nil
46
- uri.to_s
47
- end
48
-
49
- That's all there is to it! You can use the access token like you would with the
50
- OAuth gem, calling HTTP verbs on it etc. You can view more examples on the OAuth2
51
- Wiki (http://wiki.github.com/intridea/oauth2/examples)
52
-
53
- == JSON Parsing
54
-
55
- Because JSON has become the standard format of the OAuth 2.0 specification,
56
- the <tt>oauth2</tt> gem contains a mode that will perform automatic parsing
57
- of JSON response bodies, returning a hash instead of a string. To enable this
58
- mode, simply add the <tt>:parse_json</tt> option to your client initialization:
59
-
60
- client = OAuth2::Client.new('app_id', 'app_secret',
61
- :site => 'https://example.com',
62
- :parse_json => true
63
- )
64
-
65
- # Obtain an access token using the client
66
- token.get('/some/url.json') # {"some" => "hash"}
67
-
68
- == Note on Patches/Pull Requests
69
-
70
- * Fork the project.
71
- * Make your feature addition or bug fix.
72
- * Add tests for it. This is important so I don't break it in a
73
- future version unintentionally.
74
- * Commit, do not mess with rakefile, version, or history.
75
- (if you want to have your own version, that is fine but bump version in a commit by itself I can ignore when I pull)
76
- * Send me a pull request. Bonus points for topic branches.
77
-
78
- == Copyright
79
-
80
- Copyright (c) 2010 Intridea, Inc. and Michael Bleigh. See LICENSE for details.