OpenAuth2 0.0.1
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/Gemfile +4 -0
- data/License +9 -0
- data/Rakefile +126 -0
- data/Readme.markdown +224 -0
- data/Spec.markdown +0 -0
- data/examples/fb.rb +9 -0
- data/examples/google.rb +53 -0
- data/lib/open_auth2.rb +33 -0
- data/lib/open_auth2/client.rb +182 -0
- data/lib/open_auth2/config.rb +102 -0
- data/lib/open_auth2/connection.rb +38 -0
- data/lib/open_auth2/delegate_to_config.rb +25 -0
- data/lib/open_auth2/provider.rb +21 -0
- data/lib/open_auth2/provider/base.rb +31 -0
- data/lib/open_auth2/provider/default.rb +18 -0
- data/lib/open_auth2/provider/facebook.rb +23 -0
- data/lib/open_auth2/provider/google.rb +28 -0
- data/lib/open_auth2/token.rb +150 -0
- data/lib/open_auth2/version.rb +3 -0
- data/open_auth2.gemspec +74 -0
- data/spec/client_spec.rb +110 -0
- data/spec/config_spec.rb +119 -0
- data/spec/facebook/client_spec.rb +82 -0
- data/spec/facebook/token_spec.rb +92 -0
- data/spec/fixtures/creds.rb +18 -0
- data/spec/fixtures/vcr/fb/access_token.yml +36 -0
- data/spec/fixtures/vcr/fb/cocacola.yml +68 -0
- data/spec/fixtures/vcr/fb/me.yml +36 -0
- data/spec/fixtures/vcr/fb/post.yml +34 -0
- data/spec/fixtures/vcr/fb/refresh_token.yml +36 -0
- data/spec/fixtures/vcr/goog/access_token.yml +38 -0
- data/spec/fixtures/vcr/goog/list.yml +50 -0
- data/spec/fixtures/vcr/goog/post.yml +44 -0
- data/spec/fixtures/vcr/goog/refresh_token.yml +37 -0
- data/spec/google/client_spec.rb +59 -0
- data/spec/google/token_spec.rb +87 -0
- data/spec/spec_helper.rb +13 -0
- data/spec/token_spec.rb +23 -0
- metadata +179 -0
@@ -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
|
data/open_auth2.gemspec
ADDED
@@ -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
|
data/spec/client_spec.rb
ADDED
@@ -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
|
data/spec/config_spec.rb
ADDED
@@ -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
|