oauth2-client 1.0.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/.gitignore +18 -0
- data/.travis.yml +6 -0
- data/Gemfile +17 -0
- data/Gemfile.lock +37 -0
- data/LICENSE +20 -0
- data/README.md +152 -0
- data/Rakefile +11 -0
- data/TODO +10 -0
- data/examples/google_client.rb +159 -0
- data/lib/oauth2.rb +7 -0
- data/lib/oauth2/client.rb +63 -0
- data/lib/oauth2/connection.rb +188 -0
- data/lib/oauth2/error.rb +3 -0
- data/lib/oauth2/grant.rb +7 -0
- data/lib/oauth2/grant/authorization_code.rb +71 -0
- data/lib/oauth2/grant/base.rb +41 -0
- data/lib/oauth2/grant/client_credentials.rb +27 -0
- data/lib/oauth2/grant/device.rb +37 -0
- data/lib/oauth2/grant/implicit.rb +46 -0
- data/lib/oauth2/grant/password.rb +28 -0
- data/lib/oauth2/grant/refresh_token.rb +26 -0
- data/lib/oauth2/helper.rb +46 -0
- data/lib/oauth2/version.rb +11 -0
- data/oauth2-client.gemspec +13 -0
- data/spec/.DS_Store +0 -0
- data/spec/examples/google_client_spec.rb +223 -0
- data/spec/mocks/oauth_client.yml +60 -0
- data/spec/oauth2/client_spec.rb +157 -0
- data/spec/oauth2/connection_spec.rb +273 -0
- data/spec/oauth2/grant/authorization_code_spec.rb +89 -0
- data/spec/oauth2/grant/base_spec.rb +57 -0
- data/spec/oauth2/grant/client_credentials_spec.rb +28 -0
- data/spec/oauth2/grant/device_spec.rb +35 -0
- data/spec/oauth2/grant/implicit_spec.rb +36 -0
- data/spec/oauth2/grant/password_spec.rb +28 -0
- data/spec/oauth2/grant/refresh_token_spec.rb +27 -0
- data/spec/spec_helper.rb +15 -0
- metadata +83 -0
@@ -0,0 +1,28 @@
|
|
1
|
+
module OAuth2
|
2
|
+
module Grant
|
3
|
+
class Password < Base
|
4
|
+
|
5
|
+
def grant_type
|
6
|
+
'password'
|
7
|
+
end
|
8
|
+
|
9
|
+
# Retrieve an access token given the specified client.
|
10
|
+
#
|
11
|
+
# @param username
|
12
|
+
# @param password
|
13
|
+
# @param [Hash] params additional params
|
14
|
+
# @param [Hash] opts options
|
15
|
+
def get_token(username, password, opts={})
|
16
|
+
opts[:params] ||= {}
|
17
|
+
opts[:params].merge!({
|
18
|
+
:grant_type => grant_type,
|
19
|
+
:username => username,
|
20
|
+
:password => password
|
21
|
+
})
|
22
|
+
opts[:authenticate] ||= :headers
|
23
|
+
method = opts.delete(:method) || :post
|
24
|
+
make_request(method, @token_path, opts)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
module OAuth2
|
2
|
+
module Grant
|
3
|
+
class RefreshToken < Base
|
4
|
+
|
5
|
+
def grant_type
|
6
|
+
'refresh_token'
|
7
|
+
end
|
8
|
+
|
9
|
+
# Retrieve an access token for a given refresh token
|
10
|
+
#
|
11
|
+
# @param [String] refresh_token refresh token
|
12
|
+
# @param [Hash] params additional params
|
13
|
+
# @param [Hash] opts options
|
14
|
+
def get_token(refresh_token, opts={})
|
15
|
+
params = opts[:params] || {}
|
16
|
+
opts[:params] = params.merge!({
|
17
|
+
:grant_type => grant_type,
|
18
|
+
:refresh_token => refresh_token
|
19
|
+
})
|
20
|
+
opts[:authenticate] ||= :headers
|
21
|
+
method = opts.delete(:method) || :post
|
22
|
+
make_request(method, @token_path, opts)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
require 'openssl'
|
2
|
+
require 'base64'
|
3
|
+
require 'addressable/uri'
|
4
|
+
module OAuth2
|
5
|
+
module UrlHelper
|
6
|
+
# convenience method to build response URI
|
7
|
+
def build_url(uri, opts={})
|
8
|
+
path = opts[:path] || ''
|
9
|
+
query = opts[:params] || {}
|
10
|
+
fragment = opts[:fragment] || {}
|
11
|
+
url = Addressable::URI.parse uri
|
12
|
+
url.path = path
|
13
|
+
url.query_values = query unless query.empty?
|
14
|
+
url.fragment = Addressable::URI.form_encode(fragment) unless fragment.empty?
|
15
|
+
url.to_s
|
16
|
+
end
|
17
|
+
|
18
|
+
# generates a random key of up to +size+ bytes. The value returned is Base64 encoded with non-word
|
19
|
+
# characters removed.
|
20
|
+
def generate_urlsafe_key(size=48)
|
21
|
+
seed = Time.now.to_i
|
22
|
+
size = size - seed.to_s.length
|
23
|
+
Base64.encode64("#{ OpenSSL::Random.random_bytes(size) }#{ seed }").gsub(/\W/, '')
|
24
|
+
end
|
25
|
+
alias_method :generate_nonce, :generate_urlsafe_key
|
26
|
+
|
27
|
+
def generate_timestamp #:nodoc:
|
28
|
+
Time.now.to_i.to_s
|
29
|
+
end
|
30
|
+
|
31
|
+
def http_basic_encode(username, password)
|
32
|
+
encoded_data = ["#{username}:#{password}"].pack("m0")
|
33
|
+
"Basic #{encoded_data}"
|
34
|
+
end
|
35
|
+
module_function :http_basic_encode
|
36
|
+
|
37
|
+
# converts a hash to a URI query string
|
38
|
+
# @params [Hash] params URI parameters
|
39
|
+
def to_query(params)
|
40
|
+
unless params.is_a?(Hash)
|
41
|
+
raise "Expected Hash but got #{params.class.name}"
|
42
|
+
end
|
43
|
+
Addressable::URI.form_encode(params)
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
@@ -0,0 +1,11 @@
|
|
1
|
+
module OAuth2
|
2
|
+
class Version
|
3
|
+
MAJOR = 1 unless defined? OAuth2::Version::MAJOR
|
4
|
+
MINOR = 0 unless defined? OAuth2::Version::MINOR
|
5
|
+
PATCH = 0 unless defined? OAuth2::Version::PATCH
|
6
|
+
|
7
|
+
def self.to_s
|
8
|
+
[MAJOR, MINOR, PATCH].compact.join('.')
|
9
|
+
end
|
10
|
+
end
|
11
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
Gem::Specification.new do |s|
|
2
|
+
s.name = 'oauth2-client'
|
3
|
+
s.version = '1.0.0'
|
4
|
+
s.date = %q{2013-01-22}
|
5
|
+
s.summary = "OAuth2 Ruby Client"
|
6
|
+
s.description = "Create quick and dirty OAuth2 clients for many services. Google OAuth2 client included"
|
7
|
+
s.authors = ["Kevin Mutyaba"]
|
8
|
+
s.email = %q{tiabasnk@gmail.com}
|
9
|
+
s.homepage = ''
|
10
|
+
s.rubygems_version = %q{1.0.0}
|
11
|
+
s.files = `git ls-files`.split("\n")
|
12
|
+
s.require_paths = ['lib']
|
13
|
+
end
|
data/spec/.DS_Store
ADDED
Binary file
|
@@ -0,0 +1,223 @@
|
|
1
|
+
require File.expand_path('../../spec_helper', __FILE__)
|
2
|
+
require 'google_client'
|
3
|
+
|
4
|
+
describe GoogleClient do
|
5
|
+
|
6
|
+
subject do
|
7
|
+
|
8
|
+
GoogleClient.new('https://accounts.google.com', '827502413694.apps.googleusercontent.com', 'a2nQpcUm2Dgq1chWdAvbXGTk',{
|
9
|
+
:token_path => '/o/oauth2/token',
|
10
|
+
:authorize_path => '/o/oauth2/auth',
|
11
|
+
:device_path => '/o/oauth2/device/code',
|
12
|
+
:connection_options => {
|
13
|
+
:headers => {
|
14
|
+
"User-Agent" => "GoOAuth2 0.1",
|
15
|
+
"Accept" => "application/json"
|
16
|
+
}
|
17
|
+
}
|
18
|
+
})
|
19
|
+
end
|
20
|
+
#
|
21
|
+
# https://developers.google.com/accounts/docs/OAuth2WebServer#formingtheurl
|
22
|
+
describe "#webserver_authorization_url" do
|
23
|
+
context "with scope as string" do
|
24
|
+
it "returns the authorization url" do
|
25
|
+
params = {
|
26
|
+
"approval_prompt" => "force",
|
27
|
+
"client_id" => "827502413694.apps.googleusercontent.com",
|
28
|
+
"redirect_uri" => "http://localhost",
|
29
|
+
"response_type" =>"code",
|
30
|
+
"scope" => "https://www.googleapis.com/auth/userinfo.email https://www.googleapis.com/auth/userinfo.profile",
|
31
|
+
"state" => "/profile",
|
32
|
+
"access_type" => "offline"
|
33
|
+
}
|
34
|
+
|
35
|
+
auth_url = subject.webserver_authorization_url(
|
36
|
+
:scope => 'https://www.googleapis.com/auth/userinfo.email https://www.googleapis.com/auth/userinfo.profile',
|
37
|
+
:state => '/profile',
|
38
|
+
:redirect_uri => 'http://localhost',
|
39
|
+
:approval_prompt => 'force',
|
40
|
+
:access_type => 'offline'
|
41
|
+
)
|
42
|
+
|
43
|
+
parsed_url = Addressable::URI.parse(auth_url)
|
44
|
+
expect(parsed_url.path).to eq '/o/oauth2/auth'
|
45
|
+
expect(parsed_url.query_values).to eq params
|
46
|
+
expect(parsed_url.scheme).to eq 'https'
|
47
|
+
expect(parsed_url.host).to eq 'accounts.google.com'
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
context "with scope as array" do
|
52
|
+
it "returns the authorization url" do
|
53
|
+
params = {
|
54
|
+
"approval_prompt"=>"force",
|
55
|
+
"client_id"=>"827502413694.apps.googleusercontent.com",
|
56
|
+
"redirect_uri"=>"http://localhost",
|
57
|
+
"response_type"=>"code",
|
58
|
+
"scope"=>"https://www.googleapis.com/auth/userinfo.email https://www.googleapis.com/auth/userinfo.profile",
|
59
|
+
"state"=>"/profile"
|
60
|
+
}
|
61
|
+
|
62
|
+
auth_url = subject.webserver_authorization_url(
|
63
|
+
:scope => [
|
64
|
+
'https://www.googleapis.com/auth/userinfo.email',
|
65
|
+
'https://www.googleapis.com/auth/userinfo.profile'
|
66
|
+
],
|
67
|
+
:state => '/profile',
|
68
|
+
:redirect_uri => 'http://localhost',
|
69
|
+
:approval_prompt => 'force'
|
70
|
+
)
|
71
|
+
|
72
|
+
parsed_url = Addressable::URI.parse(auth_url)
|
73
|
+
expect(parsed_url.path).to eq '/o/oauth2/auth'
|
74
|
+
expect(parsed_url.query_values).to eq params
|
75
|
+
expect(parsed_url.scheme).to eq 'https'
|
76
|
+
expect(parsed_url.host).to eq 'accounts.google.com'
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
context "scope neither array or string" do
|
81
|
+
it "raises and error" do
|
82
|
+
expect do
|
83
|
+
subject.webserver_authorization_url(
|
84
|
+
:scope => {},
|
85
|
+
:redirect_uri => 'https://oauth2-login-demo.appspot.com/code')
|
86
|
+
end.to raise_error
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
describe "#exchange_auth_code_for_token" do
|
92
|
+
it "makes a request to google oauth2 server" do
|
93
|
+
|
94
|
+
fake_response = double(
|
95
|
+
:code => '200',
|
96
|
+
:body => ''
|
97
|
+
)
|
98
|
+
|
99
|
+
Net::HTTP.any_instance.should_receive(:post).with(
|
100
|
+
"/o/oauth2/token",
|
101
|
+
"redirect_uri=https%3A%2F%2Flocalhost&code=4%2FdbB0-UD1cvrQg2EuEFtRtHwPEmvR.IrScsjgB5M4VuJJVnL49Cc8QdUjRdAI",
|
102
|
+
{
|
103
|
+
"Accept"=>"application/json",
|
104
|
+
"User-Agent"=>"GoOAuth2 0.1",
|
105
|
+
"Authorization"=>"Basic ODI3NTAyNDEzNjk0LmFwcHMuZ29vZ2xldXNlcmNvbnRlbnQuY29tOmEyblFwY1VtMkRncTFjaFdkQXZiWEdUaw==",
|
106
|
+
"Content-Type"=>"application/x-www-form-urlencoded"
|
107
|
+
}
|
108
|
+
).and_return(fake_response)
|
109
|
+
|
110
|
+
subject.exchange_auth_code_for_token(
|
111
|
+
:params => {
|
112
|
+
:code => '4/dbB0-UD1cvrQg2EuEFtRtHwPEmvR.IrScsjgB5M4VuJJVnL49Cc8QdUjRdAI',
|
113
|
+
:redirect_uri => 'https://localhost'
|
114
|
+
}
|
115
|
+
)
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
119
|
+
describe "#client_authorization_url" do
|
120
|
+
it "returns url string for obtaining authorization" do
|
121
|
+
params = {
|
122
|
+
"approval_prompt" => "force",
|
123
|
+
"client_id" => "827502413694.apps.googleusercontent.com",
|
124
|
+
"redirect_uri" => "https://oauth2-login-demo.appspot.com/token",
|
125
|
+
"response_type" => "token",
|
126
|
+
"scope" => "https://www.googleapis.com/auth/userinfo.email",
|
127
|
+
"state" => "/profile"
|
128
|
+
}
|
129
|
+
|
130
|
+
auth_url = subject.clientside_authorization_url(
|
131
|
+
:scope => 'https://www.googleapis.com/auth/userinfo.email',
|
132
|
+
:state => '/profile',
|
133
|
+
:redirect_uri => 'https://oauth2-login-demo.appspot.com/token',
|
134
|
+
:approval_prompt => 'force'
|
135
|
+
)
|
136
|
+
|
137
|
+
parsed_url = Addressable::URI.parse(auth_url)
|
138
|
+
expect(parsed_url.path).to eq '/o/oauth2/auth'
|
139
|
+
expect(parsed_url.query_values).to eq params
|
140
|
+
expect(parsed_url.scheme).to eq 'https'
|
141
|
+
expect(parsed_url.host).to eq 'accounts.google.com'
|
142
|
+
end
|
143
|
+
end
|
144
|
+
|
145
|
+
describe "#refresh_token" do
|
146
|
+
it "makes a request to google to obtain new token" do
|
147
|
+
fake_response = double(
|
148
|
+
:code => '200',
|
149
|
+
:body => ''
|
150
|
+
)
|
151
|
+
|
152
|
+
Net::HTTP.any_instance.should_receive(:post).with(
|
153
|
+
"/o/oauth2/token",
|
154
|
+
"state=%2Fprofile&grant_type=refresh_token&refresh_token=2YotnFZFEjr1zCsicMWpAA",
|
155
|
+
{
|
156
|
+
"Accept" => "application/json",
|
157
|
+
"User-Agent" => "GoOAuth2 0.1",
|
158
|
+
"Authorization" => "Basic ODI3NTAyNDEzNjk0LmFwcHMuZ29vZ2xldXNlcmNvbnRlbnQuY29tOmEyblFwY1VtMkRncTFjaFdkQXZiWEdUaw==",
|
159
|
+
"Content-Type" => "application/x-www-form-urlencoded"
|
160
|
+
}
|
161
|
+
).and_return(fake_response)
|
162
|
+
|
163
|
+
subject.refresh_access_token(
|
164
|
+
:params => {
|
165
|
+
:state => '/profile',
|
166
|
+
:refresh_token => '2YotnFZFEjr1zCsicMWpAA'
|
167
|
+
}
|
168
|
+
)
|
169
|
+
end
|
170
|
+
end
|
171
|
+
|
172
|
+
describe "#get_device_code" do
|
173
|
+
it "makes a request to google to obtain a device code" do
|
174
|
+
fake_response = double(
|
175
|
+
:code => '200',
|
176
|
+
:body => ''
|
177
|
+
)
|
178
|
+
|
179
|
+
Net::HTTP.any_instance.should_receive(:post).with(
|
180
|
+
"/o/oauth2/device/code",
|
181
|
+
"scope=https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fuserinfo.email+https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fuserinfo.profile&client_id=827502413694.apps.googleusercontent.com",
|
182
|
+
{
|
183
|
+
"Accept"=>"application/json",
|
184
|
+
"User-Agent"=>"GoOAuth2 0.1",
|
185
|
+
"Content-Type"=>"application/x-www-form-urlencoded"
|
186
|
+
}
|
187
|
+
).and_return(fake_response)
|
188
|
+
|
189
|
+
subject.get_device_code(
|
190
|
+
:params => {
|
191
|
+
:scope => 'https://www.googleapis.com/auth/userinfo.email https://www.googleapis.com/auth/userinfo.profile'
|
192
|
+
}
|
193
|
+
)
|
194
|
+
end
|
195
|
+
end
|
196
|
+
|
197
|
+
describe "#exchange_device_code_for_token" do
|
198
|
+
it "makes request to google to obtain an access token" do
|
199
|
+
fake_response = double(
|
200
|
+
:code => '200',
|
201
|
+
:body => ''
|
202
|
+
)
|
203
|
+
|
204
|
+
Net::HTTP.any_instance.should_receive(:post).with(
|
205
|
+
"/o/oauth2/token",
|
206
|
+
"state=%2Fprofile&code=G3Y6jU3a&grant_type=http%3A%2F%2Foauth.net%2Fgrant_type%2Fdevice%2F1.0",
|
207
|
+
{
|
208
|
+
"Accept"=>"application/json",
|
209
|
+
"User-Agent" => "GoOAuth2 0.1",
|
210
|
+
"Authorization"=>"Basic ODI3NTAyNDEzNjk0LmFwcHMuZ29vZ2xldXNlcmNvbnRlbnQuY29tOmEyblFwY1VtMkRncTFjaFdkQXZiWEdUaw==",
|
211
|
+
"Content-Type"=>"application/x-www-form-urlencoded"
|
212
|
+
}
|
213
|
+
).and_return(fake_response)
|
214
|
+
|
215
|
+
subject.exchange_device_code_for_token(
|
216
|
+
:params => {
|
217
|
+
:state => '/profile',
|
218
|
+
:code => 'G3Y6jU3a'
|
219
|
+
}
|
220
|
+
)
|
221
|
+
end
|
222
|
+
end
|
223
|
+
end
|
@@ -0,0 +1,60 @@
|
|
1
|
+
test:
|
2
|
+
google:
|
3
|
+
client_id: '827502413694.apps.googleusercontent.com'
|
4
|
+
client_secret: 'a2nQpcUm2Dgq1chWdAvbXGTk'
|
5
|
+
host: accounts.google.com
|
6
|
+
port: 443
|
7
|
+
token_path: /o/oauth2/token
|
8
|
+
authorize_path: /o/oauth2/auth
|
9
|
+
device_path: /o/oauth2/device/code
|
10
|
+
http_client: #OAuth2Client::Connection
|
11
|
+
max_redirects: 5
|
12
|
+
ssl:
|
13
|
+
|
14
|
+
yammer:
|
15
|
+
client_id: 'PRbTcg9qjgKsp4jjpm1pw'
|
16
|
+
client_secret: 'Xn7kp7Ly0TCY4GtZWkmSsqGEPg10DmMADyjWkf2U'
|
17
|
+
host: www.yammer.com
|
18
|
+
port: 443
|
19
|
+
token_path: /oauth2/access_token
|
20
|
+
authorize_path: /dialog/oauth/
|
21
|
+
device_path:
|
22
|
+
http_client: #OAuth2Client::Connection
|
23
|
+
max_redirects: 5
|
24
|
+
ssl: #
|
25
|
+
|
26
|
+
microsoft:
|
27
|
+
client_id: 'PRbTcg9qjgKsp4jjpm1pw'
|
28
|
+
client_secret: 'Xn7kp7Ly0TCY4GtZWkmSsqGEPg10DmMADyjWkf2U'
|
29
|
+
host: login.live.com
|
30
|
+
port: 443
|
31
|
+
token_path: /oauth20_token.srf
|
32
|
+
authorize_path: /oauth20_authorize.srf
|
33
|
+
device_path:
|
34
|
+
http_client: #OAuth2Client::Connection
|
35
|
+
max_redirects: 5
|
36
|
+
ssl: #
|
37
|
+
|
38
|
+
github:
|
39
|
+
client_id: '2945e6425da3d5d17ffc'
|
40
|
+
client_secret: '0a8f686f2835a70a79dbcece2ec63bc5079f40a8'
|
41
|
+
host: github.com
|
42
|
+
port: 443
|
43
|
+
token_path: /login/oauth/access_token
|
44
|
+
authorize_path: /login/oauth/authorize
|
45
|
+
device_path:
|
46
|
+
http_client: #OAuth2Client::Connection
|
47
|
+
max_redirects: 5
|
48
|
+
ssl: #
|
49
|
+
|
50
|
+
foursquare:
|
51
|
+
client_id: '2945e6425da3d5d17ffc'
|
52
|
+
client_secret: '0a8f686f2835a70a79dbcece2ec63bc5079f40a8'
|
53
|
+
host: foursquare.com
|
54
|
+
port: 443
|
55
|
+
token_path: /oauth2/access_token
|
56
|
+
authorize_path: /oauth2/authenticate
|
57
|
+
device_path:
|
58
|
+
http_client: #OAuth2Client::Connection
|
59
|
+
max_redirects: 5
|
60
|
+
ssl: #
|
@@ -0,0 +1,157 @@
|
|
1
|
+
require File.expand_path('../../spec_helper', __FILE__)
|
2
|
+
require 'ostruct'
|
3
|
+
|
4
|
+
describe OAuth2::Client do
|
5
|
+
|
6
|
+
before :all do
|
7
|
+
@client_id= 's6BhdRkqt3'
|
8
|
+
@client_secret = '4hJZY88TCBB9q8IpkeualA2lZsUhOSclkkSKw3RXuE'
|
9
|
+
@host = 'example.com'
|
10
|
+
@client = OAuth2::Client.new(@host, @client_id, @client_secret)
|
11
|
+
end
|
12
|
+
|
13
|
+
subject { @client }
|
14
|
+
|
15
|
+
context "with default options" do
|
16
|
+
describe "#token_path" do
|
17
|
+
it "returns " do
|
18
|
+
expect(subject.token_path).to eq '/oauth2/token'
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
describe "#authorize_path" do
|
23
|
+
it "returns " do
|
24
|
+
expect(subject.authorize_path).to eq '/oauth2/authorize'
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
describe "#device_path" do
|
29
|
+
it "returns " do
|
30
|
+
expect(subject.device_path).to eq '/oauth2/device/code'
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
context "with custom options" do
|
36
|
+
subject do
|
37
|
+
OAuth2::Client.new(@host, @client_id, @client_secret, {
|
38
|
+
:token_path => '/o/v2/token',
|
39
|
+
:authorize_path => '/o/v2/authorize',
|
40
|
+
:device_path => '/o/v2/device/code'
|
41
|
+
})
|
42
|
+
end
|
43
|
+
|
44
|
+
describe "#token_path" do
|
45
|
+
it "returns token path" do
|
46
|
+
expect(subject.token_path).to eq '/o/v2/token'
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
describe "#authorize_path" do
|
51
|
+
it "returns authorize path" do
|
52
|
+
expect(subject.authorize_path).to eq '/o/v2/authorize'
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
describe "#device_path" do
|
57
|
+
it "returns device path" do
|
58
|
+
expect(subject.device_path).to eq '/o/v2/device/code'
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
describe "host" do
|
64
|
+
it "returns host" do
|
65
|
+
expect(subject.host).to eq 'example.com'
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
describe "host=" do
|
70
|
+
before do
|
71
|
+
subject.host = 'elpmaxe.com'
|
72
|
+
end
|
73
|
+
|
74
|
+
it "set the connection to nil" do
|
75
|
+
expect(subject.instance_variable_get(:'@connection')).to eq nil
|
76
|
+
end
|
77
|
+
|
78
|
+
it "sets new host on client" do
|
79
|
+
expect(subject.host).to eq 'elpmaxe.com'
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
describe "#connection_options" do
|
84
|
+
context "with default connection options" do
|
85
|
+
it "returns empty hash" do
|
86
|
+
expect(subject.connection_options).to eq ({})
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
context "with custom connection options" do
|
91
|
+
it "returns default options" do
|
92
|
+
subject.connection_options = { :max_redirects => 10, :use_ssl => true }
|
93
|
+
expect(subject.connection_options).to eq ({:max_redirects => 10, :use_ssl => true})
|
94
|
+
end
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
describe "#implicit" do
|
99
|
+
it "returns implicit grant object" do
|
100
|
+
expect(@client.implicit).to be_instance_of(OAuth2::Grant::Implicit)
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
describe "#authorization_code" do
|
105
|
+
it "returns authorization code grant" do
|
106
|
+
expect(@client.authorization_code).to be_instance_of(OAuth2::Grant::AuthorizationCode)
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
describe "#refresh_token" do
|
111
|
+
it "returns refresh token grant" do
|
112
|
+
expect(@client.refresh_token).to be_instance_of(OAuth2::Grant::RefreshToken)
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
116
|
+
describe "#client_credentials" do
|
117
|
+
it "returns client credentials grant" do
|
118
|
+
expect(@client.client_credentials).to be_instance_of(OAuth2::Grant::ClientCredentials)
|
119
|
+
end
|
120
|
+
end
|
121
|
+
|
122
|
+
describe "#password" do
|
123
|
+
it "returns password grant" do
|
124
|
+
expect(@client.password).to be_instance_of(OAuth2::Grant::Password)
|
125
|
+
end
|
126
|
+
end
|
127
|
+
|
128
|
+
describe "" do
|
129
|
+
it "returns device code grant" do
|
130
|
+
expect(@client.device_code).to be_instance_of(OAuth2::Grant::DeviceCode)
|
131
|
+
end
|
132
|
+
end
|
133
|
+
|
134
|
+
|
135
|
+
describe "#implicit" do
|
136
|
+
it "returns implicit grant object" do
|
137
|
+
expect(subject.implicit).to be_instance_of(OAuth2::Grant::Implicit)
|
138
|
+
end
|
139
|
+
end
|
140
|
+
|
141
|
+
describe "#connection" do
|
142
|
+
context "with default connection options" do
|
143
|
+
it "returns HttpConnection" do
|
144
|
+
expect(subject.send(:connection)).to be_instance_of(OAuth2::HttpConnection)
|
145
|
+
end
|
146
|
+
end
|
147
|
+
|
148
|
+
context "with custom connection options" do
|
149
|
+
it "returns custom connection" do
|
150
|
+
# custom_http = Struct.new('CustomHttpClient')
|
151
|
+
# conn_options = { :connection_client => custom_http }
|
152
|
+
# oauth_client = OAuth2::Client.new('example.com', @client_id, @client_secret, conn_options)
|
153
|
+
# expect(oauth_client.send(:connection)).to be_instance_of custom_http
|
154
|
+
end
|
155
|
+
end
|
156
|
+
end
|
157
|
+
end
|