g5_authenticatable_api 0.2.0 → 0.3.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/.ruby-version +1 -0
- data/CHANGELOG.md +6 -0
- data/Gemfile +2 -2
- data/README.md +1 -1
- data/circle.yml +1 -1
- data/lib/g5_authenticatable_api/helpers/grape.rb +2 -2
- data/lib/g5_authenticatable_api/helpers/rails.rb +2 -2
- data/lib/g5_authenticatable_api/token_validator.rb +12 -7
- data/lib/g5_authenticatable_api/version.rb +1 -1
- data/spec/lib/g5_authenticatable_api/token_validator_spec.rb +25 -1
- data/spec/support/shared_examples/token_authenticatable_api.rb +0 -57
- data/spec/support/shared_examples/token_validation.rb +56 -0
- data/spec/support/shared_examples/warden_authenticatable_api.rb +4 -7
- metadata +6 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 1aa117f0b0c46d048619a8b7bffe14b1030b0e67
|
4
|
+
data.tar.gz: bbb88bf02f07f19c095ef2ab23d68df33783a205
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 4788c4eb67bc7139ffeb7664d68dd6816ed735bcca9fcd7b38f4a20153c9e1cf3b93cfd6c523e191658d4b331b0d2bd64d0b591c571be2d3cd6693f7e470368e
|
7
|
+
data.tar.gz: fb3fd459a31acc154515473e5c0e11734a9929f35c4051f3cf94d18138a4da6c89e03eb9a9b3fb9e4a194540d22ee605d60b872ec022b75400fededeb315ca26
|
data/.ruby-version
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
2.1.2
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,9 @@
|
|
1
|
+
## v0.3.0 (2014-12-23)
|
2
|
+
|
3
|
+
* When there is already an authenticated session, validate the current
|
4
|
+
user's access token against the auth server on every API request
|
5
|
+
([#5](https://github.com/G5/g5_authenticatable_api/pull/5))
|
6
|
+
|
1
7
|
## v0.2.0 (2014-03-12)
|
2
8
|
|
3
9
|
* First open source release to [RubyGems](https://rubygems.org)
|
data/Gemfile
CHANGED
@@ -6,7 +6,7 @@ source 'https://rubygems.org'
|
|
6
6
|
gemspec
|
7
7
|
|
8
8
|
# Gems used by the dummy application
|
9
|
-
gem 'rails', '
|
9
|
+
gem 'rails', '4.1.4'
|
10
10
|
gem 'jquery-rails'
|
11
11
|
gem 'pg'
|
12
12
|
gem 'grape'
|
@@ -24,7 +24,7 @@ group :test do
|
|
24
24
|
gem 'simplecov', require: false
|
25
25
|
gem 'codeclimate-test-reporter', require: false
|
26
26
|
gem 'webmock'
|
27
|
-
gem 'shoulda-matchers'
|
27
|
+
gem 'shoulda-matchers', '~> 2.6'
|
28
28
|
gem 'rspec-http', require: false
|
29
29
|
end
|
30
30
|
|
data/README.md
CHANGED
data/circle.yml
CHANGED
@@ -4,7 +4,7 @@ module G5AuthenticatableApi
|
|
4
4
|
module Helpers
|
5
5
|
module Grape
|
6
6
|
def authenticate_user!
|
7
|
-
raise_auth_error if !
|
7
|
+
raise_auth_error if !token_validator.valid?
|
8
8
|
end
|
9
9
|
|
10
10
|
def warden
|
@@ -14,7 +14,7 @@ module G5AuthenticatableApi
|
|
14
14
|
private
|
15
15
|
def token_validator
|
16
16
|
request = Rack::Request.new(env)
|
17
|
-
@token_validator ||= TokenValidator.new(request.params, headers)
|
17
|
+
@token_validator ||= TokenValidator.new(request.params, headers, warden)
|
18
18
|
end
|
19
19
|
|
20
20
|
def raise_auth_error
|
@@ -4,7 +4,7 @@ module G5AuthenticatableApi
|
|
4
4
|
module Helpers
|
5
5
|
module Rails
|
6
6
|
def authenticate_api_user!
|
7
|
-
raise_auth_error if !
|
7
|
+
raise_auth_error if !token_validator.valid?
|
8
8
|
end
|
9
9
|
|
10
10
|
def warden
|
@@ -13,7 +13,7 @@ module G5AuthenticatableApi
|
|
13
13
|
|
14
14
|
private
|
15
15
|
def token_validator
|
16
|
-
@token_validator ||= TokenValidator.new(request.params, request.headers)
|
16
|
+
@token_validator ||= TokenValidator.new(request.params, request.headers, warden)
|
17
17
|
end
|
18
18
|
|
19
19
|
def raise_auth_error
|
@@ -2,9 +2,10 @@ module G5AuthenticatableApi
|
|
2
2
|
class TokenValidator
|
3
3
|
attr_reader :error
|
4
4
|
|
5
|
-
def initialize(params={},headers={})
|
5
|
+
def initialize(params={},headers={},warden=nil)
|
6
6
|
@params = params || {}
|
7
7
|
@headers = headers || {}
|
8
|
+
@warden = warden
|
8
9
|
end
|
9
10
|
|
10
11
|
def validate!
|
@@ -25,12 +26,9 @@ module G5AuthenticatableApi
|
|
25
26
|
end
|
26
27
|
|
27
28
|
def access_token
|
28
|
-
@access_token ||=
|
29
|
-
|
30
|
-
|
31
|
-
else
|
32
|
-
@params['access_token']
|
33
|
-
end
|
29
|
+
@access_token ||= (extract_token_from_header ||
|
30
|
+
@params['access_token'] ||
|
31
|
+
@warden.try(:user).try(:g5_access_token))
|
34
32
|
end
|
35
33
|
|
36
34
|
def auth_response_header
|
@@ -61,5 +59,12 @@ module G5AuthenticatableApi
|
|
61
59
|
error_description = error.description if error.respond_to?(:description)
|
62
60
|
error_description
|
63
61
|
end
|
62
|
+
|
63
|
+
def extract_token_from_header
|
64
|
+
if @headers['Authorization']
|
65
|
+
parts = @headers['Authorization'].match(/Bearer (?<access_token>\S+)/)
|
66
|
+
parts['access_token']
|
67
|
+
end
|
68
|
+
end
|
64
69
|
end
|
65
70
|
end
|
@@ -3,11 +3,12 @@ require 'spec_helper'
|
|
3
3
|
describe G5AuthenticatableApi::TokenValidator do
|
4
4
|
subject { validator }
|
5
5
|
|
6
|
-
let(:validator) { described_class.new(params, headers) }
|
6
|
+
let(:validator) { described_class.new(params, headers, warden) }
|
7
7
|
|
8
8
|
let(:headers) {}
|
9
9
|
let(:params) { {'access_token' => token_value} }
|
10
10
|
let(:token_value) { 'abc123' }
|
11
|
+
let(:warden) {}
|
11
12
|
|
12
13
|
describe '#access_token' do
|
13
14
|
subject(:access_token) { validator.access_token }
|
@@ -29,6 +30,29 @@ describe G5AuthenticatableApi::TokenValidator do
|
|
29
30
|
expect(access_token).to eq(token_value)
|
30
31
|
end
|
31
32
|
end
|
33
|
+
|
34
|
+
context 'with warden user' do
|
35
|
+
let(:warden) { double(:warden, user: user) }
|
36
|
+
let(:user) { FactoryGirl.build_stubbed(:user) }
|
37
|
+
|
38
|
+
context 'without token on request' do
|
39
|
+
let(:params) {}
|
40
|
+
let(:headers) {}
|
41
|
+
|
42
|
+
it 'should extract the token value from the session user' do
|
43
|
+
expect(access_token).to eq(user.g5_access_token)
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
context 'with auth param' do
|
48
|
+
let(:params) { {'access_token' => token_value} }
|
49
|
+
let(:headers) {}
|
50
|
+
|
51
|
+
it 'should give precedence to the token on the request' do
|
52
|
+
expect(access_token).to eq(token_value)
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
32
56
|
end
|
33
57
|
|
34
58
|
describe '#validate!' do
|
@@ -1,60 +1,3 @@
|
|
1
|
-
shared_examples_for 'token validation' do
|
2
|
-
context 'when token is valid' do
|
3
|
-
include_context 'valid access token'
|
4
|
-
|
5
|
-
before { subject }
|
6
|
-
|
7
|
-
it 'should be successful' do
|
8
|
-
expect(response).to be_success
|
9
|
-
end
|
10
|
-
|
11
|
-
it 'should validate the access token against the auth server' do
|
12
|
-
expect(a_request(:get, 'auth.g5search.com/oauth/token/info').
|
13
|
-
with(headers: {'Authorization' => "Bearer #{token_value}"})).to have_been_made
|
14
|
-
end
|
15
|
-
end
|
16
|
-
|
17
|
-
context 'when token is invalid' do
|
18
|
-
include_context 'invalid access token'
|
19
|
-
|
20
|
-
before { subject }
|
21
|
-
|
22
|
-
it 'should be unauthorized' do
|
23
|
-
expect(response).to be_http_unauthorized
|
24
|
-
end
|
25
|
-
|
26
|
-
it 'should return an authenticate header' do
|
27
|
-
expect(response.headers).to have_key('WWW-Authenticate')
|
28
|
-
end
|
29
|
-
|
30
|
-
it 'should return the authentication error' do
|
31
|
-
expect(response.headers['WWW-Authenticate']).to match("error=\"#{error_code}\"")
|
32
|
-
end
|
33
|
-
|
34
|
-
it 'should return the authentication error description' do
|
35
|
-
expect(response.headers['WWW-Authenticate']).to match("error_description=\"#{error_description}\"")
|
36
|
-
end
|
37
|
-
end
|
38
|
-
|
39
|
-
context 'when some other oauth error occurs' do
|
40
|
-
include_context 'OAuth2 error'
|
41
|
-
|
42
|
-
before { subject }
|
43
|
-
|
44
|
-
it 'should be unauthorized' do
|
45
|
-
expect(response).to be_http_unauthorized
|
46
|
-
end
|
47
|
-
|
48
|
-
it 'should return an authenticate header' do
|
49
|
-
expect(response.headers).to have_key('WWW-Authenticate')
|
50
|
-
end
|
51
|
-
|
52
|
-
it 'should return the default authentication error code' do
|
53
|
-
expect(response.headers['WWW-Authenticate']).to match('error="invalid_request"')
|
54
|
-
end
|
55
|
-
end
|
56
|
-
end
|
57
|
-
|
58
1
|
shared_examples_for 'a token authenticatable api' do
|
59
2
|
let(:token_value) { 'abc123' }
|
60
3
|
|
@@ -0,0 +1,56 @@
|
|
1
|
+
shared_examples_for 'token validation' do
|
2
|
+
context 'when token is valid' do
|
3
|
+
include_context 'valid access token'
|
4
|
+
|
5
|
+
before { subject }
|
6
|
+
|
7
|
+
it 'should be successful' do
|
8
|
+
expect(response).to be_success
|
9
|
+
end
|
10
|
+
|
11
|
+
it 'should validate the access token against the auth server' do
|
12
|
+
expect(a_request(:get, 'auth.g5search.com/oauth/token/info').
|
13
|
+
with(headers: {'Authorization' => "Bearer #{token_value}"})).to have_been_made
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
context 'when token is invalid' do
|
18
|
+
include_context 'invalid access token'
|
19
|
+
|
20
|
+
before { subject }
|
21
|
+
|
22
|
+
it 'should be unauthorized' do
|
23
|
+
expect(response).to be_http_unauthorized
|
24
|
+
end
|
25
|
+
|
26
|
+
it 'should return an authenticate header' do
|
27
|
+
expect(response.headers).to have_key('WWW-Authenticate')
|
28
|
+
end
|
29
|
+
|
30
|
+
it 'should return the authentication error' do
|
31
|
+
expect(response.headers['WWW-Authenticate']).to match("error=\"#{error_code}\"")
|
32
|
+
end
|
33
|
+
|
34
|
+
it 'should return the authentication error description' do
|
35
|
+
expect(response.headers['WWW-Authenticate']).to match("error_description=\"#{error_description}\"")
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
context 'when some other oauth error occurs' do
|
40
|
+
include_context 'OAuth2 error'
|
41
|
+
|
42
|
+
before { subject }
|
43
|
+
|
44
|
+
it 'should be unauthorized' do
|
45
|
+
expect(response).to be_http_unauthorized
|
46
|
+
end
|
47
|
+
|
48
|
+
it 'should return an authenticate header' do
|
49
|
+
expect(response.headers).to have_key('WWW-Authenticate')
|
50
|
+
end
|
51
|
+
|
52
|
+
it 'should return the default authentication error code' do
|
53
|
+
expect(response.headers['WWW-Authenticate']).to match('error="invalid_request"')
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
@@ -3,15 +3,12 @@ require 'spec_helper'
|
|
3
3
|
shared_examples_for 'a warden authenticatable api' do
|
4
4
|
context 'when user is authenticated' do
|
5
5
|
let(:user) { create(:user) }
|
6
|
+
let(:token_value) { user.g5_access_token }
|
6
7
|
|
7
|
-
before
|
8
|
-
|
9
|
-
subject
|
10
|
-
end
|
8
|
+
before { login_as(user, scope: :user) }
|
9
|
+
after { logout }
|
11
10
|
|
12
|
-
|
13
|
-
expect(response).to be_success
|
14
|
-
end
|
11
|
+
include_examples 'token validation'
|
15
12
|
end
|
16
13
|
|
17
14
|
context 'when user is not authenticated' do
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: g5_authenticatable_api
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.3.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Maeve Revels
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-
|
11
|
+
date: 2014-12-23 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rack
|
@@ -47,6 +47,7 @@ extra_rdoc_files: []
|
|
47
47
|
files:
|
48
48
|
- ".gitignore"
|
49
49
|
- ".rspec"
|
50
|
+
- ".ruby-version"
|
50
51
|
- CHANGELOG.md
|
51
52
|
- Gemfile
|
52
53
|
- LICENSE.txt
|
@@ -126,6 +127,7 @@ files:
|
|
126
127
|
- spec/support/shared_contexts/invalid_access_token.rb
|
127
128
|
- spec/support/shared_contexts/valid_access_token.rb
|
128
129
|
- spec/support/shared_examples/token_authenticatable_api.rb
|
130
|
+
- spec/support/shared_examples/token_validation.rb
|
129
131
|
- spec/support/shared_examples/warden_authenticatable_api.rb
|
130
132
|
- spec/support/warden.rb
|
131
133
|
homepage: https://github.com/G5/g5_authenticatable_api
|
@@ -148,7 +150,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
148
150
|
version: '0'
|
149
151
|
requirements: []
|
150
152
|
rubyforge_project:
|
151
|
-
rubygems_version: 2.2.
|
153
|
+
rubygems_version: 2.2.2
|
152
154
|
signing_key:
|
153
155
|
specification_version: 4
|
154
156
|
summary: Helpers for securing APIs with G5
|
@@ -219,5 +221,6 @@ test_files:
|
|
219
221
|
- spec/support/shared_contexts/invalid_access_token.rb
|
220
222
|
- spec/support/shared_contexts/valid_access_token.rb
|
221
223
|
- spec/support/shared_examples/token_authenticatable_api.rb
|
224
|
+
- spec/support/shared_examples/token_validation.rb
|
222
225
|
- spec/support/shared_examples/warden_authenticatable_api.rb
|
223
226
|
- spec/support/warden.rb
|