aptible-auth 0.11.3 → 0.11.5
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/aptible/auth/token.rb +66 -18
- data/lib/aptible/auth/version.rb +1 -1
- data/spec/aptible/auth/token_spec.rb +41 -5
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: f84b4c267178de22880242466b3cf1094be20fb6
|
4
|
+
data.tar.gz: f77b05461a7db6598902a9bdfbb8140691e493b9
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 8a373677f9e0aadfae4220f181ceb31eea72ad3b756960bdf56b2e6039ee99156470101b4f256dca089345d13dbabdc0cc9e9e0c052d8074adbbdc4be83572d5
|
7
|
+
data.tar.gz: 2a187d5ad9ded64e5d2a0689c43bf49f429230eff390425af7136507172edab58ef129b4bb3a679e96ebad851838c3fc6138b6fbecf2383418769dbd2175cc33
|
data/lib/aptible/auth/token.rb
CHANGED
@@ -3,44 +3,70 @@ require 'oauth2'
|
|
3
3
|
module Aptible
|
4
4
|
module Auth
|
5
5
|
class Token < Resource
|
6
|
-
|
6
|
+
# Unlike other resources, tokens aren't created in a REST fashion.
|
7
|
+
# Instead, they're created via OAuth grants. This means we need to
|
8
|
+
# override the way HyperResource / aptible-resource normally do things
|
9
|
+
# and plug in an OAuth library.
|
10
|
+
#
|
11
|
+
# To do so, we take control of the creation arguments and feed them into
|
12
|
+
# the OAuth2 library (in Token.create!), and then feed the response back
|
13
|
+
# to HyperResource (in Token#apply_oauth_response).
|
14
|
+
belongs_to :user
|
15
|
+
belongs_to :actor
|
16
|
+
|
17
|
+
field :access_token
|
18
|
+
field :refresh_token
|
19
|
+
field :expires_at
|
7
20
|
|
8
21
|
def self.create(options)
|
22
|
+
# For backwards compatibility: we used to throw in .create (which isn't
|
23
|
+
# consistent with other resources), and we probably need to continue
|
24
|
+
# doing this. We also need to continue throwing a OAuth2::Error.
|
9
25
|
token = new
|
10
26
|
token.process_options(options)
|
11
27
|
token
|
12
28
|
end
|
13
29
|
|
30
|
+
def self.create!(options)
|
31
|
+
Token.create(options)
|
32
|
+
rescue OAuth2::Error => e
|
33
|
+
# Rethrow OAuth2::Error as HyperResource::ResponseError for
|
34
|
+
# aptible-resource to handle
|
35
|
+
raise HyperResource::ResponseError.new(e.code, response: e.response,
|
36
|
+
cause: e)
|
37
|
+
end
|
38
|
+
|
14
39
|
def authenticate_user(email, password, options = {})
|
15
40
|
options[:scope] ||= 'manage'
|
16
|
-
|
17
|
-
|
41
|
+
oauth_token = oauth.password.get_token(email, password, options)
|
42
|
+
apply_oauth_response(oauth_token)
|
18
43
|
end
|
19
44
|
|
20
45
|
def authenticate_client(id, secret, subject, options = {})
|
21
46
|
options[:scope] ||= 'manage'
|
22
|
-
|
47
|
+
oauth_token = oauth.assertion.get_token({
|
23
48
|
iss: id,
|
24
49
|
sub: subject
|
25
50
|
}.merge(signing_params_from_secret(secret).merge(options)))
|
26
|
-
|
51
|
+
apply_oauth_response(oauth_token)
|
27
52
|
end
|
28
53
|
|
29
54
|
def authenticate_impersonate(subject_token, subject_token_type, options)
|
30
55
|
# TODO: This duplicates aptible-resource, is it worth extracting?
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
56
|
+
actor_token = \
|
57
|
+
case actor_token = options.delete(:token)
|
58
|
+
when Aptible::Resource::Base then actor_token.access_token
|
59
|
+
when Fridge::AccessToken then actor_token.to_s
|
60
|
+
when String then actor_token
|
61
|
+
else bearer_token
|
62
|
+
end
|
37
63
|
|
38
64
|
# TODO: Do we want to check whether the token is non-nil at this stage?
|
39
65
|
options[:scope] ||= 'manage'
|
40
|
-
|
41
|
-
|
66
|
+
oauth_token = oauth.token_exchange.get_token(
|
67
|
+
actor_token, 'urn:ietf:params:oauth:token-type:jwt',
|
42
68
|
subject_token, subject_token_type, options)
|
43
|
-
|
69
|
+
apply_oauth_response(oauth_token)
|
44
70
|
end
|
45
71
|
|
46
72
|
def oauth
|
@@ -68,12 +94,34 @@ module Aptible
|
|
68
94
|
end
|
69
95
|
end
|
70
96
|
|
97
|
+
def token
|
98
|
+
# If the user set an arbitrary token, then we'll return that one,
|
99
|
+
# otherwise we'll fall back to the Token itself, which makes it
|
100
|
+
# possible to create a token and immediately access it #user or #actor
|
101
|
+
# methods.
|
102
|
+
# NOTE: Setting the token after the fact probably doesn't work anyway,
|
103
|
+
# since the Authorization header won't be updated.
|
104
|
+
@token || access_token
|
105
|
+
end
|
106
|
+
|
107
|
+
def expires_at
|
108
|
+
# The Auth API returns the expiry as a timestamp (i.e. an Integer), but
|
109
|
+
# our API client knows only to handle times as strings. This overrides
|
110
|
+
# the field method for expires_at to return a Time despite the
|
111
|
+
# underlying API field being an Integer.
|
112
|
+
Time.at(attributes[:expires_at])
|
113
|
+
end
|
114
|
+
|
71
115
|
private
|
72
116
|
|
73
|
-
def
|
74
|
-
|
75
|
-
|
76
|
-
|
117
|
+
def apply_oauth_response(oauth_token)
|
118
|
+
# apply() + loaded is what HyperResource normally does after
|
119
|
+
# deserializing a response back from the API. On top of that, we need
|
120
|
+
# to set the Authorization header so that the token can be used to make
|
121
|
+
# further API requests (e.g. accessing token#user or token#actor).
|
122
|
+
adapter.apply(oauth_token.to_hash, self)
|
123
|
+
self.loaded = true
|
124
|
+
headers['Authorization'] = "Bearer #{bearer_token}"
|
77
125
|
self
|
78
126
|
end
|
79
127
|
|
data/lib/aptible/auth/version.rb
CHANGED
@@ -5,9 +5,16 @@ describe Aptible::Auth::Token do
|
|
5
5
|
let(:response) { double OAuth2::AccessToken }
|
6
6
|
|
7
7
|
before { subject.stub(:oauth) { oauth } }
|
8
|
-
|
9
|
-
before
|
10
|
-
|
8
|
+
let(:expires_at) { Time.now - Random.rand(1000) }
|
9
|
+
before do
|
10
|
+
response.stub(:to_hash) do
|
11
|
+
{
|
12
|
+
access_token: 'access_token',
|
13
|
+
refresh_token: nil,
|
14
|
+
expires_at: expires_at.to_i
|
15
|
+
}
|
16
|
+
end
|
17
|
+
end
|
11
18
|
|
12
19
|
describe '.create' do
|
13
20
|
it 'should call #authenticate_user if passed :email and :password' do
|
@@ -60,10 +67,20 @@ describe Aptible::Auth::Token do
|
|
60
67
|
end
|
61
68
|
|
62
69
|
it 'should set the access_token' do
|
63
|
-
oauth.stub_chain(:password, :get_token, :token) { 'access_token' }
|
64
70
|
subject.authenticate_user(*args)
|
65
71
|
expect(subject.access_token).to eq 'access_token'
|
66
72
|
end
|
73
|
+
|
74
|
+
it 'should set the Authorization header' do
|
75
|
+
subject.authenticate_user(*args)
|
76
|
+
expect(subject.headers['Authorization']).to eq 'Bearer access_token'
|
77
|
+
end
|
78
|
+
|
79
|
+
it 'should set the expires_at property' do
|
80
|
+
subject.authenticate_user(*args)
|
81
|
+
expect(subject.expires_at).to be_a Time
|
82
|
+
expect(subject.expires_at.to_i).to eq expires_at.to_i
|
83
|
+
end
|
67
84
|
end
|
68
85
|
|
69
86
|
describe '#authenticate_client' do
|
@@ -96,10 +113,29 @@ describe Aptible::Auth::Token do
|
|
96
113
|
end
|
97
114
|
|
98
115
|
it 'should set the access_token' do
|
99
|
-
oauth.stub_chain(:assertion, :get_token, :token) { 'access_token' }
|
100
116
|
subject.authenticate_client(*args)
|
101
117
|
expect(subject.access_token).to eq 'access_token'
|
102
118
|
end
|
119
|
+
|
120
|
+
it 'should set the Authorization header' do
|
121
|
+
subject.authenticate_client(*args)
|
122
|
+
expect(subject.headers['Authorization']).to eq 'Bearer access_token'
|
123
|
+
end
|
124
|
+
end
|
125
|
+
|
126
|
+
describe '#authenticate_impersonate' do
|
127
|
+
let(:args) { ['foo@bar.com', 'aptible:user:email', {}] }
|
128
|
+
before { oauth.stub_chain(:token_exchange, :get_token) { response } }
|
129
|
+
|
130
|
+
it 'should set the access_token' do
|
131
|
+
subject.authenticate_impersonate(*args)
|
132
|
+
expect(subject.access_token).to eq 'access_token'
|
133
|
+
end
|
134
|
+
|
135
|
+
it 'should set the Authorization header' do
|
136
|
+
subject.authenticate_impersonate(*args)
|
137
|
+
expect(subject.headers['Authorization']).to eq 'Bearer access_token'
|
138
|
+
end
|
103
139
|
end
|
104
140
|
|
105
141
|
describe '#signing_params_from_secret' do
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: aptible-auth
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.11.
|
4
|
+
version: 0.11.5
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Frank Macreery
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2016-
|
11
|
+
date: 2016-06-03 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: aptible-billing
|