aptible-auth 0.0.1 → 0.1.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.
- checksums.yaml +4 -4
- data/README.md +42 -5
- data/aptible-auth.gemspec +4 -1
- data/lib/aptible/auth.rb +12 -1
- data/lib/aptible/auth/client.rb +21 -6
- data/lib/aptible/auth/token.rb +50 -0
- data/lib/aptible/auth/version.rb +1 -1
- data/spec/aptible/auth/client_spec.rb +5 -1
- data/spec/aptible/auth/token_spec.rb +84 -0
- data/spec/aptible/auth_spec.rb +16 -0
- metadata +51 -7
- data/lib/aptible/auth/strategy/pubkey.rb +0 -25
- data/spec/aptible/auth/strategy/pubkey_spec.rb +0 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 101f4e5eba0e9ddacf579ed8758ebbbdfba30d84
|
4
|
+
data.tar.gz: b2daa6d3703e05bfcba62c36d7469890430a7463
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 535418028b5197789fb200a8608133df28e5f2c6622d7a9d614c259409850139231209988a633a592fc6ef45e6808ecd8012ba1bea42223220b55e99df4280c8
|
7
|
+
data.tar.gz: c784ba5e1f430fd0ee88de2dc06a13214d7b0f4aab0c5ef57055fcd447dc4c56a69e02312f1293ff17612b179894c6b53ad8e734bd4a5c099d1a31fc9eae6c42
|
data/README.md
CHANGED
@@ -4,21 +4,58 @@
|
|
4
4
|
[](https://travis-ci.org/aptible/aptible-auth-ruby)
|
5
5
|
[](https://gemnasium.com/aptible/aptible-auth-ruby)
|
6
6
|
|
7
|
-
Ruby client for [auth.aptible.com](https://auth.aptible.com/).
|
8
|
-
|
9
|
-
However, due to the complexity of OAuth 2.0 and the fact that it is a fragmented and evolving standard, we provide this gem as a standard Ruby client library. All of our internal services use it, and so it can be expected to work.
|
7
|
+
Ruby client for [auth.aptible.com](https://auth.aptible.com/). Aptible's authorization server is built on top of [OAuth 2.0](http://tools.ietf.org/html/rfc6749) and [HAL+JSON](http://tools.ietf.org/html/draft-kelly-json-hal-06), and so this client is just a thin layer on top of the [oauth2](https://github.com/intridea/oauth2) and [HyperResource](https://github.com/gamache/hyperresource) gems.
|
10
8
|
|
11
9
|
## Installation
|
12
10
|
|
13
|
-
Add the following
|
11
|
+
Add the following lines to your application's Gemfile.
|
14
12
|
|
15
13
|
gem 'aptible-auth'
|
14
|
+
gem 'oauth2', github: 'fancyremarker/oauth2', branch: 'aptible'
|
15
|
+
|
16
|
+
The forked version of the OAuth2 gem is necessary until [intridea/oauth2#165](https://github.com/intridea/oauth2/pull/165) and [intridea/oauth2#166](https://github.com/intridea/oauth2/pull/166) are merged.
|
16
17
|
|
17
18
|
And then run `bundle install`.
|
18
19
|
|
19
20
|
## Usage
|
20
21
|
|
21
|
-
|
22
|
+
First, get a token:
|
23
|
+
|
24
|
+
```ruby
|
25
|
+
token = Aptible::Auth::Token.new(email: 'user0@example.com', password: 'password')
|
26
|
+
```
|
27
|
+
|
28
|
+
Then, initialize a client:
|
29
|
+
```ruby
|
30
|
+
auth = Aptible::Auth::Client.new(token: token)
|
31
|
+
```
|
32
|
+
|
33
|
+
From here, you can interact with the Authorization API however you wish:
|
34
|
+
|
35
|
+
```ruby
|
36
|
+
auth.get
|
37
|
+
auth.clients.count
|
38
|
+
# => 4
|
39
|
+
auth.clients.first.name
|
40
|
+
# => "Client 0"
|
41
|
+
client = auth.clients.create(name: 'Dogeclient')
|
42
|
+
client.href
|
43
|
+
# => "http://localhost:4000/clients/60765b69-ffd8-4762-b9d2-96354ddb16f9"
|
44
|
+
```
|
45
|
+
|
46
|
+
## Configuration
|
47
|
+
|
48
|
+
| Parameter | Description | Default |
|
49
|
+
| --------- | ----------- | --------------- |
|
50
|
+
| `root_url` | Root URL of the authorization server | `https://auth.aptible.com` |
|
51
|
+
|
52
|
+
To point the client at a different authorization server (e.g., during development), add the following to your application's initializers:
|
53
|
+
|
54
|
+
```ruby
|
55
|
+
Aptible::Auth.configure do |config|
|
56
|
+
config.root_url = 'http://some.other.url'
|
57
|
+
end
|
58
|
+
```
|
22
59
|
|
23
60
|
## Contributing
|
24
61
|
|
data/aptible-auth.gemspec
CHANGED
@@ -19,10 +19,13 @@ Gem::Specification.new do |spec|
|
|
19
19
|
spec.test_files = spec.files.grep(/^spec\//)
|
20
20
|
spec.require_paths = ['lib']
|
21
21
|
|
22
|
+
spec.add_dependency 'gem_config'
|
22
23
|
spec.add_dependency 'oauth2'
|
24
|
+
spec.add_dependency 'hyperresource'
|
23
25
|
|
24
26
|
spec.add_development_dependency 'bundler', '~> 1.3'
|
25
27
|
spec.add_development_dependency 'aptible-tasks', '>= 0.2.0'
|
26
28
|
spec.add_development_dependency 'rake'
|
27
|
-
spec.
|
29
|
+
spec.add_development_dependency 'rspec', '~> 2.0'
|
30
|
+
spec.add_development_dependency 'pry'
|
28
31
|
end
|
data/lib/aptible/auth.rb
CHANGED
@@ -1,8 +1,19 @@
|
|
1
1
|
require 'aptible/auth/version'
|
2
|
+
require 'aptible/auth/token'
|
2
3
|
require 'aptible/auth/client'
|
3
4
|
|
5
|
+
require 'gem_config'
|
6
|
+
|
4
7
|
module Aptible
|
5
8
|
module Auth
|
6
|
-
|
9
|
+
include GemConfig::Base
|
10
|
+
|
11
|
+
with_configuration do
|
12
|
+
has :root_url, classes: [String], default: 'https://auth.aptible.com'
|
13
|
+
end
|
14
|
+
|
15
|
+
def self.public_key
|
16
|
+
Client.new.get.public_key
|
17
|
+
end
|
7
18
|
end
|
8
19
|
end
|
data/lib/aptible/auth/client.rb
CHANGED
@@ -1,12 +1,27 @@
|
|
1
|
-
require '
|
2
|
-
require 'aptible/auth/strategy/pubkey'
|
1
|
+
require 'hyperresource'
|
3
2
|
|
4
3
|
module Aptible
|
5
4
|
module Auth
|
6
|
-
class Client <
|
7
|
-
|
8
|
-
|
9
|
-
|
5
|
+
class Client < HyperResource
|
6
|
+
attr_accessor :token, :config
|
7
|
+
|
8
|
+
def initialize(options = {})
|
9
|
+
unless options.is_a?(Hash)
|
10
|
+
fail ArgumentError, 'Call Aptible::Auth::Client.new with a Hash'
|
11
|
+
end
|
12
|
+
@token = options[:token]
|
13
|
+
|
14
|
+
options[:root] ||= config.root_url
|
15
|
+
options[:headers] ||= { 'Content-Type' => 'application/json' }
|
16
|
+
options[:headers].merge!(
|
17
|
+
'Authorization' => "Bearer #{options[:token].access_token}"
|
18
|
+
) if options[:token]
|
19
|
+
|
20
|
+
super(options)
|
21
|
+
end
|
22
|
+
|
23
|
+
def config
|
24
|
+
@config ||= Aptible::Auth.configuration
|
10
25
|
end
|
11
26
|
end
|
12
27
|
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
require 'oauth2'
|
2
|
+
|
3
|
+
module Aptible
|
4
|
+
module Auth
|
5
|
+
class Token
|
6
|
+
attr_accessor :client, :access_token, :refresh_token, :expires_at
|
7
|
+
|
8
|
+
def initialize(options = {})
|
9
|
+
oauth_params = {
|
10
|
+
site: Aptible::Auth.configuration.root_url,
|
11
|
+
token_url: '/tokens'
|
12
|
+
}
|
13
|
+
@client = OAuth2::Client.new(nil, nil, oauth_params)
|
14
|
+
|
15
|
+
process_options(options)
|
16
|
+
end
|
17
|
+
|
18
|
+
def authenticate_user(email, password, options = {})
|
19
|
+
options[:scope] ||= 'manage'
|
20
|
+
response = client.password.get_token(email, password, options)
|
21
|
+
parse_oauth_response(response)
|
22
|
+
end
|
23
|
+
|
24
|
+
def authenticate_client(id, secret, user, options = {})
|
25
|
+
options[:scope] ||= 'manage'
|
26
|
+
response = client.assertion.get_token(id, secret, user, options)
|
27
|
+
parse_oauth_response(response)
|
28
|
+
end
|
29
|
+
|
30
|
+
private
|
31
|
+
|
32
|
+
def process_options(options)
|
33
|
+
if (email = options.delete(:email)) &&
|
34
|
+
(password = options.delete(:password))
|
35
|
+
authenticate_user(email, password, options)
|
36
|
+
elsif (client_id = options.delete(:client_id)) &&
|
37
|
+
(client_secret = options.delete(:client_secret)) &&
|
38
|
+
(user = options.delete(:user))
|
39
|
+
authenticate_client(client_id, client_secret, user, options)
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
def parse_oauth_response(response)
|
44
|
+
@access_token = response.token
|
45
|
+
@refresh_token = response.refresh_token
|
46
|
+
@expires_at = Time.at(response.expires_at)
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
data/lib/aptible/auth/version.rb
CHANGED
@@ -0,0 +1,84 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Aptible::Auth::Token do
|
4
|
+
let(:client) { double OAuth2::Client }
|
5
|
+
let(:response) { double OAuth2::AccessToken }
|
6
|
+
|
7
|
+
before { response.stub(:token) }
|
8
|
+
before { response.stub(:refresh_token) }
|
9
|
+
before { response.stub(:expires_at) { Time.now.to_i } }
|
10
|
+
|
11
|
+
describe '#initialize' do
|
12
|
+
it 'should call #authenticate_user if passed :email and :password' do
|
13
|
+
Aptible::Auth::Token.any_instance.should_receive(
|
14
|
+
:authenticate_user
|
15
|
+
).with 'user@example.com', 'foobar', {}
|
16
|
+
described_class.new(email: 'user@example.com', password: 'foobar')
|
17
|
+
end
|
18
|
+
|
19
|
+
it 'should #authenticate_client if passed a client ID and secret' do
|
20
|
+
Aptible::Auth::Token.any_instance.should_receive(
|
21
|
+
:authenticate_client
|
22
|
+
).with 'id', 'secret', 'user@example.com', {}
|
23
|
+
described_class.new(
|
24
|
+
client_id: 'id',
|
25
|
+
client_secret: 'secret',
|
26
|
+
user: 'user@example.com'
|
27
|
+
)
|
28
|
+
end
|
29
|
+
|
30
|
+
it 'should not raise error if given no arguments' do
|
31
|
+
expect { described_class.new }.not_to raise_error
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
describe '#authenticate_user' do
|
36
|
+
let(:args) { %w(user@example.com foobar) }
|
37
|
+
|
38
|
+
before { subject.stub(:client) { client } }
|
39
|
+
before { client.stub_chain(:password, :get_token) { response } }
|
40
|
+
|
41
|
+
it 'should use the password strategy' do
|
42
|
+
params = { scope: 'manage' }
|
43
|
+
expect(client.password).to receive(:get_token).with(*(args + [params]))
|
44
|
+
subject.authenticate_user(*args)
|
45
|
+
end
|
46
|
+
|
47
|
+
it 'should allow the token scope to be specified' do
|
48
|
+
args << { scope: 'read' }
|
49
|
+
expect(client.password).to receive(:get_token).with(*args)
|
50
|
+
subject.authenticate_user(*args)
|
51
|
+
end
|
52
|
+
|
53
|
+
it 'should set the access_token' do
|
54
|
+
client.stub_chain(:password, :get_token, :token) { 'access_token' }
|
55
|
+
subject.authenticate_user(*args)
|
56
|
+
expect(subject.access_token).to eq 'access_token'
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
describe '#authenticate_client' do
|
61
|
+
let(:args) { %w(id secret user@example.com) }
|
62
|
+
|
63
|
+
before { subject.stub(:client) { client } }
|
64
|
+
before { client.stub_chain(:assertion, :get_token) { response } }
|
65
|
+
|
66
|
+
it 'should use the assertion strategy' do
|
67
|
+
params = { scope: 'manage' }
|
68
|
+
expect(client.assertion).to receive(:get_token).with(*(args + [params]))
|
69
|
+
subject.authenticate_client(*args)
|
70
|
+
end
|
71
|
+
|
72
|
+
it 'should allow the token scope to be specified' do
|
73
|
+
args << { scope: 'read' }
|
74
|
+
expect(client.assertion).to receive(:get_token).with(*args)
|
75
|
+
subject.authenticate_client(*args)
|
76
|
+
end
|
77
|
+
|
78
|
+
it 'should set the access_token' do
|
79
|
+
client.stub_chain(:assertion, :get_token, :token) { 'access_token' }
|
80
|
+
subject.authenticate_client(*args)
|
81
|
+
expect(subject.access_token).to eq 'access_token'
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Aptible::Auth do
|
4
|
+
it 'should have a configurable root_url' do
|
5
|
+
config = described_class.configuration
|
6
|
+
expect(config).to be_a GemConfig::Configuration
|
7
|
+
expect(config.root_url).to eq 'https://auth.aptible.com'
|
8
|
+
end
|
9
|
+
|
10
|
+
it 'should expose the server public key' do
|
11
|
+
get = double 'get'
|
12
|
+
Aptible::Auth::Client.any_instance.stub(:get) { get }
|
13
|
+
expect(get).to receive :public_key
|
14
|
+
described_class.public_key
|
15
|
+
end
|
16
|
+
end
|
metadata
CHANGED
@@ -1,15 +1,29 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: aptible-auth
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0
|
4
|
+
version: 0.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Frank Macreery
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-
|
11
|
+
date: 2014-02-09 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: gem_config
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - '>='
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - '>='
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0'
|
13
27
|
- !ruby/object:Gem::Dependency
|
14
28
|
name: oauth2
|
15
29
|
requirement: !ruby/object:Gem::Requirement
|
@@ -24,6 +38,20 @@ dependencies:
|
|
24
38
|
- - '>='
|
25
39
|
- !ruby/object:Gem::Version
|
26
40
|
version: '0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: hyperresource
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - '>='
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
48
|
+
type: :runtime
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - '>='
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
27
55
|
- !ruby/object:Gem::Dependency
|
28
56
|
name: bundler
|
29
57
|
requirement: !ruby/object:Gem::Requirement
|
@@ -73,13 +101,27 @@ dependencies:
|
|
73
101
|
- - ~>
|
74
102
|
- !ruby/object:Gem::Version
|
75
103
|
version: '2.0'
|
76
|
-
type: :
|
104
|
+
type: :development
|
77
105
|
prerelease: false
|
78
106
|
version_requirements: !ruby/object:Gem::Requirement
|
79
107
|
requirements:
|
80
108
|
- - ~>
|
81
109
|
- !ruby/object:Gem::Version
|
82
110
|
version: '2.0'
|
111
|
+
- !ruby/object:Gem::Dependency
|
112
|
+
name: pry
|
113
|
+
requirement: !ruby/object:Gem::Requirement
|
114
|
+
requirements:
|
115
|
+
- - '>='
|
116
|
+
- !ruby/object:Gem::Version
|
117
|
+
version: '0'
|
118
|
+
type: :development
|
119
|
+
prerelease: false
|
120
|
+
version_requirements: !ruby/object:Gem::Requirement
|
121
|
+
requirements:
|
122
|
+
- - '>='
|
123
|
+
- !ruby/object:Gem::Version
|
124
|
+
version: '0'
|
83
125
|
description: Ruby client for auth.aptible.com
|
84
126
|
email:
|
85
127
|
- frank@macreery.com
|
@@ -97,10 +139,11 @@ files:
|
|
97
139
|
- aptible-auth.gemspec
|
98
140
|
- lib/aptible/auth.rb
|
99
141
|
- lib/aptible/auth/client.rb
|
100
|
-
- lib/aptible/auth/
|
142
|
+
- lib/aptible/auth/token.rb
|
101
143
|
- lib/aptible/auth/version.rb
|
102
144
|
- spec/aptible/auth/client_spec.rb
|
103
|
-
- spec/aptible/auth/
|
145
|
+
- spec/aptible/auth/token_spec.rb
|
146
|
+
- spec/aptible/auth_spec.rb
|
104
147
|
- spec/spec_helper.rb
|
105
148
|
homepage: https://github.com/aptible/aptible-auth
|
106
149
|
licenses:
|
@@ -122,11 +165,12 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
122
165
|
version: '0'
|
123
166
|
requirements: []
|
124
167
|
rubyforge_project:
|
125
|
-
rubygems_version: 2.
|
168
|
+
rubygems_version: 2.2.1
|
126
169
|
signing_key:
|
127
170
|
specification_version: 4
|
128
171
|
summary: Ruby client for auth.aptible.com
|
129
172
|
test_files:
|
130
173
|
- spec/aptible/auth/client_spec.rb
|
131
|
-
- spec/aptible/auth/
|
174
|
+
- spec/aptible/auth/token_spec.rb
|
175
|
+
- spec/aptible/auth_spec.rb
|
132
176
|
- spec/spec_helper.rb
|
@@ -1,25 +0,0 @@
|
|
1
|
-
require 'oauth2'
|
2
|
-
|
3
|
-
module Aptible
|
4
|
-
module Auth
|
5
|
-
module Strategy
|
6
|
-
# The Pubkey Strategy (Aptible-custom)
|
7
|
-
class Pubkey < OAuth2::Strategy::Base
|
8
|
-
# TODO: Implement
|
9
|
-
#
|
10
|
-
# @raise [NotImplementedError]
|
11
|
-
def get_token(fingerprint, params = {}, opts = {})
|
12
|
-
# rubocop:disable UselessAssignment
|
13
|
-
params = {
|
14
|
-
'grant_type' => 'pubkey',
|
15
|
-
'fingerprint' => fingerprint,
|
16
|
-
'password' => password
|
17
|
-
}.merge(client_params).merge(params)
|
18
|
-
# rubocop:enable UselessAssignment
|
19
|
-
|
20
|
-
fail NotImplementedError, 'Strategy not yet implemented'
|
21
|
-
end
|
22
|
-
end
|
23
|
-
end
|
24
|
-
end
|
25
|
-
end
|