OpenAuth2 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,28 @@
1
+ module OpenAuth2
2
+ module Provider
3
+ module Google
4
+ Options = {
5
+ :authorize_url => 'https://accounts.google.com',
6
+ :code_url => 'https://accounts.google.com',
7
+ :authorize_path => '/o/oauth2/auth',
8
+ :redirect_uri => 'http://localhost:9393/google/callback',
9
+ :token_path => '/o/oauth2/token',
10
+ :endpoint => 'https://www.googleapis.com'
11
+ }
12
+
13
+ def self.parse(config, body)
14
+ json = JSON.parse(body)
15
+
16
+ config.access_token = json['access_token']
17
+ config.token_arrived_at = Time.now
18
+ config.token_expires_at = Time.now+3600
19
+
20
+ # google sends refresh_token when getting access_token, but not
21
+ # when refreshing
22
+ unless config.refresh_token
23
+ config.refresh_token = json['refresh_token']
24
+ end
25
+ end
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,150 @@
1
+ module OpenAuth2
2
+
3
+ # Used to get Access/Refresh tokens from OAuth server.
4
+ class Token
5
+ extend DelegateToConfig
6
+ include Connection
7
+
8
+ # Use it to set @config. Unlike Client, no error is raised since
9
+ # this is not part of public api. This will be called from
10
+ # Client#token internally only.
11
+ #
12
+ # Accepts:
13
+ # config: OpenAuth2::Config object
14
+ #
15
+ # Returns: self.
16
+ #
17
+ def initialize(config)
18
+ @config = config
19
+ @faraday_url = authorize_url
20
+
21
+ self
22
+ end
23
+
24
+ # Packages the info from config & passed in arguments into an url
25
+ # that user has to visit to authorize this app.
26
+ #
27
+ # Examples:
28
+ # token.build_code_url
29
+ # #=> 'http://...'
30
+ #
31
+ # # or
32
+ # token.build_code_url(:scope => 'publish_stream')
33
+ #
34
+ # Accepts:
35
+ # params: (optional) Hash of additional config to be bundled into
36
+ # the url.
37
+ #
38
+ # Returns: String (url).
39
+ #
40
+ def build_code_url(params={})
41
+ url = URI::HTTPS.build(:host => host,
42
+ :path => authorize_path,
43
+ :query => encoded_body(params))
44
+
45
+ url.to_s
46
+ end
47
+
48
+ # Make request to OAuth server for access token & ask @config to
49
+ # parse it. @config delegates that to the appropriate provider.
50
+ #
51
+ # We ask @config since the format of response differs between
52
+ # OAuth servers widely.
53
+ #
54
+ # Accepts:
55
+ # params: (optional) Hash of additional config to be sent with
56
+ # request.
57
+ #
58
+ # Returns: ?.
59
+ #
60
+ def get(params={})
61
+ body = get_body_hash(params)
62
+ raw_request = post(body)
63
+
64
+ parse(raw_request)
65
+ end
66
+
67
+ # Make request to OAuth server to refresh the access token &
68
+ # ask @config to parse it.
69
+ #
70
+ # Accepts:
71
+ # params: (optional) Hash of additional config to be sent with
72
+ # request.
73
+ #
74
+ # Returns: ?.
75
+ #
76
+ def refresh(params={})
77
+ body = refresh_body_hash(params)
78
+ raw_request = post(body)
79
+
80
+ parse(raw_request)
81
+ end
82
+
83
+ def token_expired?
84
+ token_expires_at > Time.now
85
+ rescue
86
+ nil
87
+ end
88
+
89
+ private
90
+
91
+ # We use URI#parse to get rid of those pesky extra /.
92
+ def host
93
+ URI.parse(code_url).host
94
+ end
95
+
96
+ # Make travel safe.
97
+ def encoded_body(params)
98
+ URI.encode_www_form(url_body_hash(params))
99
+ end
100
+
101
+ # Combine default options & user arguments.
102
+ def url_body_hash(params)
103
+
104
+ # user can define scope as String or Array
105
+ joined_scope = scope.join(',') if scope.respond_to?(:join)
106
+
107
+ {
108
+ :response_type => response_type,
109
+ :client_id => client_id,
110
+ :redirect_uri => redirect_uri,
111
+ :scope => joined_scope
112
+ }.merge(params)
113
+ end
114
+
115
+ # TODO: learn about merge vs merge!
116
+ def get_body_hash(params)
117
+ {
118
+ :client_id => client_id,
119
+ :client_secret => client_secret,
120
+ :code => code,
121
+ :grant_type => access_token_grant_name,
122
+ :redirect_uri => redirect_uri
123
+ }.merge(params)
124
+ end
125
+
126
+ def refresh_body_hash(params)
127
+ {
128
+ :client_id => client_id,
129
+ :client_secret => client_secret,
130
+ :grant_type => refresh_token_grant_name,
131
+ refresh_token_name => refresh_token
132
+ }.merge(params)
133
+ end
134
+
135
+ # Makes the actual request. connection is the Faraday object.
136
+ def post(body)
137
+ connection.post do |conn|
138
+ conn.headers["Content-Type"] = "application/x-www-form-urlencoded"
139
+ conn.headers["Accept"] = "application/json"
140
+ conn.url(token_path)
141
+ conn.body = body
142
+ end
143
+ end
144
+
145
+ def parse(response)
146
+ @config.parse(response.body)
147
+ response
148
+ end
149
+ end
150
+ end
@@ -0,0 +1,3 @@
1
+ module OpenAuth2
2
+ VERSION = '0.0.1'
3
+ end
@@ -0,0 +1,74 @@
1
+ # -*- encoding: utf-8 -*-
2
+ require './lib/open_auth2/version'
3
+
4
+ Gem::Specification.new do |s|
5
+ s.name = "OpenAuth2"
6
+ s.version = OpenAuth2::VERSION
7
+ s.authors = ["Senthil A"]
8
+ s.email = ["senthil196@gmail.com"]
9
+ s.homepage = "https://github.com/senthilnambi/OpenAuth2"
10
+ s.description = %q{OpenAuth2 is a thin OAuth2 wrapper written on top of Faraday in Ruby.}
11
+ s.summary = %q{OpenAuth2 is a thin OAuth2 wrapper written on top of Faraday in Ruby. The goal is a simple, well documented, easy to use interface for all your OAuth2 needs.}
12
+
13
+ s.rubyforge_project = "OpenAuth2"
14
+
15
+ s.files = `git ls-files`.split("\n")
16
+ s.test_files = `git ls-files -- spec/*`.split("\n")
17
+ s.executables = `git ls-files -- bin/*`.split("\n").map do |f|
18
+ File.basename(f)
19
+ end
20
+
21
+ s.require_paths = ["lib"]
22
+
23
+ s.add_dependency 'faraday', '~> 0.7'
24
+ s.add_dependency 'activesupport', '~> 3.2'
25
+
26
+ s.add_development_dependency 'rake', '~> 0.9'
27
+ s.add_development_dependency 'rspec', '~> 2.8'
28
+ s.add_development_dependency 'vcr', '~> 1.11'
29
+ s.add_development_dependency 'fakeweb', '~> 1.3'
30
+ s.add_development_dependency 'timecop', '~> 0.3'
31
+
32
+ # = MANIFEST =
33
+ s.files = %w[
34
+ Gemfile
35
+ License
36
+ Rakefile
37
+ Readme.markdown
38
+ Spec.markdown
39
+ examples/fb.rb
40
+ examples/google.rb
41
+ lib/open_auth2.rb
42
+ lib/open_auth2/client.rb
43
+ lib/open_auth2/config.rb
44
+ lib/open_auth2/connection.rb
45
+ lib/open_auth2/delegate_to_config.rb
46
+ lib/open_auth2/provider.rb
47
+ lib/open_auth2/provider/base.rb
48
+ lib/open_auth2/provider/default.rb
49
+ lib/open_auth2/provider/facebook.rb
50
+ lib/open_auth2/provider/google.rb
51
+ lib/open_auth2/token.rb
52
+ lib/open_auth2/version.rb
53
+ open_auth2.gemspec
54
+ spec/client_spec.rb
55
+ spec/config_spec.rb
56
+ spec/facebook/client_spec.rb
57
+ spec/facebook/token_spec.rb
58
+ spec/fixtures/creds.rb
59
+ spec/fixtures/vcr/fb/access_token.yml
60
+ spec/fixtures/vcr/fb/cocacola.yml
61
+ spec/fixtures/vcr/fb/me.yml
62
+ spec/fixtures/vcr/fb/post.yml
63
+ spec/fixtures/vcr/fb/refresh_token.yml
64
+ spec/fixtures/vcr/goog/access_token.yml
65
+ spec/fixtures/vcr/goog/list.yml
66
+ spec/fixtures/vcr/goog/post.yml
67
+ spec/fixtures/vcr/goog/refresh_token.yml
68
+ spec/google/client_spec.rb
69
+ spec/google/token_spec.rb
70
+ spec/spec_helper.rb
71
+ spec/token_spec.rb
72
+ ]
73
+ # = MANIFEST =
74
+ end
@@ -0,0 +1,110 @@
1
+ require 'open_auth2'
2
+ require 'spec_helper'
3
+
4
+ describe OpenAuth2::Client do
5
+ let(:config) do
6
+ OpenAuth2::Config.new do |c|
7
+ c.provider = :facebook
8
+ c.access_token = :access_token
9
+ end
10
+ end
11
+
12
+ context '#initialize' do
13
+ it 'accepts config as argument' do
14
+ subject = described_class.new(config)
15
+ subject.config.should == config
16
+ end
17
+
18
+ it 'accepts config via block' do
19
+ subject = described_class.new do |c|
20
+ c.config = config
21
+ end
22
+ end
23
+
24
+ it 'raises NoConfigObject' do
25
+ expect do
26
+ subject = described_class.new
27
+ end.to raise_error(OpenAuth2::NoConfigObject)
28
+ end
29
+
30
+ it 'raises UnknownConfigObject' do
31
+ expect do
32
+ subject = described_class.new('string')
33
+ end.to raise_error(OpenAuth2::UnknownConfigObject)
34
+ end
35
+
36
+ it 'sets @faraday_url' do
37
+ subject.faraday_url.should == 'https://graph.facebook.com'
38
+ end
39
+ end
40
+
41
+ context '#configure' do
42
+ it 'accepts a block to set/overwrite config' do
43
+ subject.configure do |c|
44
+ c.access_token = :access_token
45
+ c.refresh_token = :refresh_token
46
+ end
47
+
48
+ subject.access_token.should == :access_token
49
+ subject.refresh_token.should == :refresh_token
50
+ end
51
+
52
+ it 'raises NoConfigObject' do
53
+ expect do
54
+ subject = described_class.new(config)
55
+ subject.configure {|c| c.config = nil }
56
+ end.to raise_error(OpenAuth2::NoConfigObject)
57
+ end
58
+
59
+ it 'raises UnknownConfigObject' do
60
+ expect do
61
+ subject = described_class.new(config)
62
+ subject.configure {|c| c.config = 'string' }
63
+ end.to raise_error(OpenAuth2::UnknownConfigObject)
64
+ end
65
+ end
66
+
67
+ context '#token' do
68
+ it 'returns OpenAuth2::Token object' do
69
+ subject.token.should be_an(OpenAuth2::Token)
70
+ end
71
+ end
72
+
73
+ context '#build_code_url' do
74
+ it 'delegates to OpenAuth2::Token' do
75
+ OpenAuth2::Token.any_instance.should_receive(:build_code_url)
76
+ subject.build_code_url
77
+ end
78
+ end
79
+
80
+ subject { described_class.new(config) }
81
+
82
+ context OpenAuth2::DelegateToConfig do
83
+ it 'delegates Options getter methods' do
84
+ subject.authorize_url.should == 'https://graph.facebook.com'
85
+ end
86
+
87
+ it 'delegates Options setter methods' do
88
+ url = 'http://facebook.com'
89
+ subject.authorize_url = url
90
+
91
+ subject.authorize_url.should == url
92
+ end
93
+
94
+ it 'overwritten Options stays that way' do
95
+ config.access_token.should == :access_token
96
+ end
97
+ end
98
+
99
+ context OpenAuth2::Connection do
100
+ it 'returns Faraday::Connection object' do
101
+ subject.connection.should be_a(Faraday::Connection)
102
+ end
103
+
104
+ it 'yields Faraday::Connection object' do
105
+ subject.connection do |f|
106
+ f.response :logger
107
+ end
108
+ end
109
+ end
110
+ end
@@ -0,0 +1,119 @@
1
+ require 'open_auth2'
2
+ require 'spec_helper'
3
+
4
+ describe OpenAuth2::Config do
5
+ subject { described_class.new }
6
+
7
+ it 'overwrites default values' do
8
+ overwrite_response_type
9
+ subject.response_type.should == :overwritten
10
+ end
11
+
12
+ context '#initialize' do
13
+ subject do
14
+ described_class.new do |c|
15
+ c.client_id = :set_in_new
16
+ end
17
+ end
18
+
19
+ it 'sets default as provider' do
20
+ subject.provider.should == :default
21
+ end
22
+
23
+ it 'accepts a block to set config' do
24
+ subject.client_id.should == :set_in_new
25
+ end
26
+ end
27
+
28
+ context '#configure' do
29
+ it 'accepts a block to set/overwrite config' do
30
+ subject.configure do |c|
31
+ c.client_id = :set_in_configure
32
+ end
33
+
34
+ subject.client_id.should == :set_in_configure
35
+ end
36
+ end
37
+
38
+ context '#provider=' do
39
+ before do
40
+ subject.provider = :facebook
41
+ end
42
+
43
+ it 'sets provider' do
44
+ subject.provider.should == :facebook
45
+ end
46
+
47
+ it 'sets provider_string' do
48
+ subject.provider_string.should == 'facebook'
49
+ end
50
+
51
+ let(:facebook_const) do
52
+ OpenAuth2::Provider::Facebook
53
+ end
54
+
55
+ it 'sets provider_const' do
56
+ subject.provider_const.should == facebook_const
57
+ end
58
+
59
+ it 'copies over options from provider' do
60
+ subject.authorize_url.should == 'https://graph.facebook.com'
61
+ end
62
+
63
+ it 'keeps non-overlapping default options' do
64
+ subject.response_type.should == 'code'
65
+ end
66
+
67
+ it 'overwrites overlapping default options' do
68
+ subject.refresh_token_name.should == 'fb_exchange_token'
69
+ end
70
+
71
+ it 'raises UnknownProvider if arg is not in list of providers' do
72
+ expect do
73
+ subject.provider = :unknown
74
+ end.to raise_error(OpenAuth2::UnknownProvider)
75
+ end
76
+
77
+ it 'provides list of known providers with UnknownProvider' do
78
+ # mimicking beh. of users including their own provider
79
+ module OpenAuth2::Provider module UserDefined end end
80
+
81
+ providers = [:Default, :Facebook, :Google, :UserDefined]
82
+ error_message = "Known Providers: #{providers}"
83
+
84
+ expect do
85
+ subject.provider = :unknown
86
+ end.to raise_error(OpenAuth2::UnknownProvider, error_message)
87
+ end
88
+ end
89
+
90
+ let(:overwrite_response_type) do
91
+ subject.configure do |c|
92
+ c.response_type = :overwritten
93
+ end
94
+ end
95
+
96
+ context '#reset_provider' do
97
+ it 'resets locally set values' do
98
+ overwrite_response_type
99
+ subject.reset_provider
100
+
101
+ subject.response_type.should == 'code'
102
+ end
103
+
104
+ let(:set_to_fb_and_reset) do
105
+ subject.provider = :facebook
106
+ subject.reset_provider
107
+ end
108
+
109
+ it 'resets provider to default' do
110
+ set_to_fb_and_reset
111
+ subject.provider.should == :default
112
+ end
113
+
114
+ it 'resets all config to default values' do
115
+ set_to_fb_and_reset
116
+ subject.authorize_url.should == nil
117
+ end
118
+ end
119
+ end