devise_g5_authenticatable 0.1.3 → 0.2.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/CHANGELOG.md +5 -0
- data/README.md +25 -2
- data/lib/devise_g5_authenticatable.rb +8 -0
- data/lib/devise_g5_authenticatable/hooks/g5_authenticatable.rb +16 -0
- data/lib/devise_g5_authenticatable/models/g5_authenticatable.rb +1 -0
- data/lib/devise_g5_authenticatable/version.rb +1 -1
- data/spec/features/token_validation_spec.rb +82 -0
- data/spec/support/devise.rb +1 -0
- data/spec/support/user_feature_methods.rb +4 -1
- data/spec/tasks/export_users_spec.rb +15 -5
- metadata +5 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 7b68a3deae4616dbf188a936d77e442d39dd761d
|
4
|
+
data.tar.gz: d615bdc6cbce1fec5ba81cdcd2a3bf5454beda29
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: c3f7e0ca76d585d91942ea3f98b285e153ed6d49e2cb26369112507d28f7e7c562b742408f224c02525c44c519e6c07399bba6b51bbf251380da5831d1729c47
|
7
|
+
data.tar.gz: 43b89ca19bc3938df96be0861492767277cc1d96f2ecff341b9e2571e9a0277f8d129c1635fbbb9f0f3c116af1a436837c6a4c58aa2bac4378eb5561e51901ab
|
data/CHANGELOG.md
CHANGED
data/README.md
CHANGED
@@ -10,7 +10,7 @@ G5 users.
|
|
10
10
|
|
11
11
|
## Current Version
|
12
12
|
|
13
|
-
0.
|
13
|
+
0.2.0
|
14
14
|
|
15
15
|
## Requirements
|
16
16
|
|
@@ -66,7 +66,7 @@ environment variables for your client application:
|
|
66
66
|
|
67
67
|
### Configuration
|
68
68
|
|
69
|
-
In `config/initializers/devise.rb`, add the following:
|
69
|
+
In `config/initializers/devise.rb`, add the following to enable authentication:
|
70
70
|
|
71
71
|
```ruby
|
72
72
|
Devise.setup do |config|
|
@@ -182,6 +182,29 @@ will need to insert the following in your `config/initializers/devise.rb`:
|
|
182
182
|
require 'devise_g5_authenticatable/models/protected_attributes'
|
183
183
|
```
|
184
184
|
|
185
|
+
### Token validation
|
186
|
+
|
187
|
+
After a user authenticates, their access token will be stored on the G5
|
188
|
+
Authenticatable model. By default, this token will not be validated against
|
189
|
+
the auth server again until the local session is destroyed, either because
|
190
|
+
it times out, or because the user explicitly logs out of the local application.
|
191
|
+
|
192
|
+
In order to implement single sign-out, you can enable strict token validation.
|
193
|
+
This will validate the token against the auth server on every request, and
|
194
|
+
automatically destroy the local session if the token is no longer valid.
|
195
|
+
|
196
|
+
In your `config/initializers/devise.rb':
|
197
|
+
|
198
|
+
```ruby
|
199
|
+
Devise.setup do |config|
|
200
|
+
# ...
|
201
|
+
config.g5_strict_token_validation = true
|
202
|
+
end
|
203
|
+
```
|
204
|
+
|
205
|
+
Note that strict token validation incurs a non-trivial amount of performance
|
206
|
+
overhead, which is why it is disabled by default.
|
207
|
+
|
185
208
|
## Examples
|
186
209
|
|
187
210
|
Currently, the best source of example code is in the [test Rails
|
@@ -9,6 +9,14 @@ require 'devise_g5_authenticatable/controllers/url_helpers'
|
|
9
9
|
|
10
10
|
require 'devise_g5_authenticatable/engine'
|
11
11
|
|
12
|
+
module Devise
|
13
|
+
# Should devise_g5_authenticatable validate the user's access token
|
14
|
+
# against the auth server for every request? Default is false
|
15
|
+
@@g5_strict_token_validation = false
|
16
|
+
|
17
|
+
mattr_accessor :g5_strict_token_validation
|
18
|
+
end
|
19
|
+
|
12
20
|
Devise.add_module(:g5_authenticatable,
|
13
21
|
strategy: false,
|
14
22
|
route: {session: [nil, :new, :destroy]},
|
@@ -0,0 +1,16 @@
|
|
1
|
+
Warden::Manager.after_set_user only: :fetch do |record, warden, options|
|
2
|
+
if Devise.g5_strict_token_validation
|
3
|
+
scope = options[:scope]
|
4
|
+
|
5
|
+
auth_client = G5AuthenticationClient::Client.new(allow_password_credentials: 'false',
|
6
|
+
access_token: record.g5_access_token)
|
7
|
+
begin
|
8
|
+
auth_client.token_info
|
9
|
+
rescue StandardError => error
|
10
|
+
proxy = Devise::Hooks::Proxy.new(warden)
|
11
|
+
proxy.sign_out(record)
|
12
|
+
record.revoke_g5_credentials!
|
13
|
+
throw :warden, scope: scope
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,82 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe 'Token validation per request' do
|
4
|
+
let(:user) { create(:user) }
|
5
|
+
let(:protected_path) { edit_user_registration_path }
|
6
|
+
let(:token_info_url) { 'http://auth.g5search.com/oauth/token/info' }
|
7
|
+
|
8
|
+
before do
|
9
|
+
stub_request(:get, token_info_url).
|
10
|
+
with(headers: {'Authorization'=>"Bearer #{user.g5_access_token}"}).
|
11
|
+
to_return(status: 200, body: '', headers: {})
|
12
|
+
end
|
13
|
+
|
14
|
+
before do
|
15
|
+
visit_path_and_login_with(protected_path, user)
|
16
|
+
|
17
|
+
# Now that we're logged in, any subsequent attempts to
|
18
|
+
# authenticate with the auth server will trigger an omniauth
|
19
|
+
# failure, which is a condition we can test for
|
20
|
+
stub_g5_invalid_credentials
|
21
|
+
end
|
22
|
+
|
23
|
+
context 'when token validation is disabled' do
|
24
|
+
before do
|
25
|
+
Devise.g5_strict_token_validation = false
|
26
|
+
visit protected_path
|
27
|
+
end
|
28
|
+
|
29
|
+
it 'should not valid the token against the auth server' do
|
30
|
+
expect(a_request(:get, token_info_url)).to_not have_been_made
|
31
|
+
end
|
32
|
+
|
33
|
+
it 'should allow the user to access the protected page' do
|
34
|
+
expect(current_path).to eq(protected_path)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
context 'when token validation is enabled' do
|
39
|
+
before { Devise.g5_strict_token_validation = true }
|
40
|
+
|
41
|
+
context 'when the access_token is valid' do
|
42
|
+
before { visit protected_path }
|
43
|
+
|
44
|
+
it 'should validate the token against the auth server' do
|
45
|
+
expect(a_request(:get, token_info_url).
|
46
|
+
with(headers: {'Authorization' => "Bearer #{user.g5_access_token}"})).to have_been_made
|
47
|
+
end
|
48
|
+
|
49
|
+
it 'should allow the user to access the protected page' do
|
50
|
+
expect(current_path).to eq(protected_path)
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
context 'when the access_token has been invalidated' do
|
55
|
+
before do
|
56
|
+
stub_request(:get, token_info_url).
|
57
|
+
with(headers: {'Authorization'=>"Bearer #{user.g5_access_token}"}).
|
58
|
+
to_return(status: 401,
|
59
|
+
headers: {'Content-Type' => 'application/json; charset=utf-8',
|
60
|
+
'Cache-Control' => 'no-cache'},
|
61
|
+
body: {'error' => 'invalid_token',
|
62
|
+
'error_description' => 'The access token expired'}.to_json)
|
63
|
+
visit protected_path
|
64
|
+
end
|
65
|
+
|
66
|
+
it 'should force the user to re-authenticate' do
|
67
|
+
expect(page).to have_content('Invalid credentials')
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
context 'when there is some other error from the auth server' do
|
72
|
+
before do
|
73
|
+
stub_request(:get, token_info_url).to_raise(StandardError)
|
74
|
+
visit protected_path
|
75
|
+
end
|
76
|
+
|
77
|
+
it 'should force the user to re-authenticate' do
|
78
|
+
expect(page).to have_content('Invalid credentials')
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
data/spec/support/devise.rb
CHANGED
@@ -19,7 +19,10 @@ module UserFeatureMethods
|
|
19
19
|
end
|
20
20
|
|
21
21
|
RSpec.configure do |config|
|
22
|
-
config.before(:each)
|
22
|
+
config.before(:each) do
|
23
|
+
OmniAuth.config.test_mode = true
|
24
|
+
OmniAuth.config.mock_auth[:g5] = nil
|
25
|
+
end
|
23
26
|
config.after(:each) { OmniAuth.config.test_mode = false }
|
24
27
|
|
25
28
|
config.include UserFeatureMethods, type: :feature
|
@@ -6,20 +6,30 @@ describe 'g5:export_users' do
|
|
6
6
|
let(:user_exporter) { double(:user_exporter, export: nil) }
|
7
7
|
before { allow(G5::UserExporter).to receive(:new).and_return(user_exporter) }
|
8
8
|
|
9
|
-
|
9
|
+
let!(:old_client_id) { ENV['G5_AUTH_CLIENT_ID'] }
|
10
10
|
let(:default_client_id) { 'default_client_id' }
|
11
|
+
before { ENV['G5_AUTH_CLIENT_ID'] = default_client_id }
|
12
|
+
after { ENV['G5_AUTH_CLIENT_ID'] = old_client_id }
|
11
13
|
|
12
|
-
|
14
|
+
let!(:old_client_secret) { ENV['G5_AUTH_CLIENT_SECRET'] }
|
13
15
|
let(:default_client_secret) { 'default_client_secret' }
|
16
|
+
before { ENV['G5_AUTH_CLIENT_SECRET'] = default_client_secret }
|
17
|
+
after { ENV['G5_AUTH_CLIENT_SECRET'] = old_client_secret }
|
14
18
|
|
15
|
-
|
19
|
+
let!(:old_redirect_uri) { ENV['G5_AUTH_REDIRECT_URI'] }
|
16
20
|
let(:default_redirect_uri) { 'http://test.host/default' }
|
21
|
+
before { ENV['G5_AUTH_REDIRECT_URI'] = default_redirect_uri }
|
22
|
+
after { ENV['G5_AUTH_REDIRECT_URI'] = old_redirect_uri }
|
17
23
|
|
18
|
-
|
24
|
+
let!(:old_endpoint) { ENV['G5_AUTH_ENDPOINT'] }
|
19
25
|
let(:default_endpoint) { 'https://my.g5auth.host' }
|
26
|
+
before { ENV['G5_AUTH_ENDPOINT'] = default_endpoint }
|
27
|
+
after { ENV['G5_AUTH_ENDPOINT'] = old_endpoint }
|
20
28
|
|
21
|
-
|
29
|
+
let!(:old_auth_code) { ENV['G5_AUTH_AUTHORIZATION_CODE'] }
|
22
30
|
let(:default_auth_code) { 'default_auth_code' }
|
31
|
+
before { ENV['G5_AUTH_AUTHORIZATION_CODE'] = default_auth_code }
|
32
|
+
after { ENV['G5_AUTH_AUTHORIZATION_CODE'] = old_auth_code }
|
23
33
|
|
24
34
|
def expect_init_user_exporter_with(option_name, expected_value)
|
25
35
|
expect(G5::UserExporter).to receive(:new) do |args|
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: devise_g5_authenticatable
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.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:
|
11
|
+
date: 2015-01-09 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: devise
|
@@ -82,6 +82,7 @@ files:
|
|
82
82
|
- lib/devise_g5_authenticatable/g5/auth_user_creator.rb
|
83
83
|
- lib/devise_g5_authenticatable/g5/auth_user_updater.rb
|
84
84
|
- lib/devise_g5_authenticatable/g5/user_exporter.rb
|
85
|
+
- lib/devise_g5_authenticatable/hooks/g5_authenticatable.rb
|
85
86
|
- lib/devise_g5_authenticatable/models/g5_authenticatable.rb
|
86
87
|
- lib/devise_g5_authenticatable/models/protected_attributes.rb
|
87
88
|
- lib/devise_g5_authenticatable/omniauth.rb
|
@@ -160,6 +161,7 @@ files:
|
|
160
161
|
- spec/features/registration_spec.rb
|
161
162
|
- spec/features/sign_in_spec.rb
|
162
163
|
- spec/features/sign_out_spec.rb
|
164
|
+
- spec/features/token_validation_spec.rb
|
163
165
|
- spec/g5/auth_password_validator_spec.rb
|
164
166
|
- spec/g5/auth_user_creator_spec.rb
|
165
167
|
- spec/g5/auth_user_updater_spec.rb
|
@@ -273,6 +275,7 @@ test_files:
|
|
273
275
|
- spec/features/registration_spec.rb
|
274
276
|
- spec/features/sign_in_spec.rb
|
275
277
|
- spec/features/sign_out_spec.rb
|
278
|
+
- spec/features/token_validation_spec.rb
|
276
279
|
- spec/g5/auth_password_validator_spec.rb
|
277
280
|
- spec/g5/auth_user_creator_spec.rb
|
278
281
|
- spec/g5/auth_user_updater_spec.rb
|