prx_auth-rails 1.4.1 → 2.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.
- checksums.yaml +4 -4
- data/app/controllers/prx_auth/rails/sessions_controller.rb +48 -42
- data/config/initializers/assets.rb +1 -0
- data/lib/prx_auth/rails/engine.rb +5 -1
- data/lib/prx_auth/rails/ext/controller.rb +100 -37
- data/lib/prx_auth/rails/version.rb +1 -1
- data/prx_auth-rails.gemspec +5 -7
- data/test/dummy/app/controllers/application_controller.rb +2 -0
- data/test/dummy/app/views/application/index.html.erb +1 -0
- data/test/dummy/config/routes.rb +2 -0
- data/test/prx_auth/rails/ext/controller_test.rb +165 -0
- data/test/prx_auth/rails/sessions_controller_test.rb +33 -10
- data/test/test_helper.rb +1 -0
- metadata +40 -9
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 76cccc8605691493ace58a976780a69b37bb138d63874eec2a4b1158a316c237
|
4
|
+
data.tar.gz: 121c8ac1bfe90d10d4424030c8472f5f443d5a26a62cf4e4480dae5de356c408
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 1f6e5d4ca1a8590e1f313791d91f08179eff18217671fbc532f5a6a6dcf365f81519e71192dd80257b35af148b53b8b46933c6fd9d3ce47d678329d91919f38c
|
7
|
+
data.tar.gz: 4292c219ad997eea92c2ae81e66db3223e8e4d3cd7f63d521ca0ee59e008e409ba6cf228e97aa5f24765da30dc3defa8e47a9349491d1d5c5885cfb7ca7fad45
|
@@ -4,13 +4,11 @@ module PrxAuth::Rails
|
|
4
4
|
|
5
5
|
skip_before_action :authenticate!
|
6
6
|
|
7
|
-
before_action :set_nonce!, only: :show
|
7
|
+
before_action :set_nonce!, only: [:new, :show]
|
8
8
|
|
9
9
|
ID_NONCE_SESSION_KEY = 'id_prx_openid_nonce'.freeze
|
10
10
|
|
11
11
|
def new
|
12
|
-
set_nonce! unless fetch_nonce.present?
|
13
|
-
|
14
12
|
config = PrxAuth::Rails.configuration
|
15
13
|
|
16
14
|
id_auth_params = {
|
@@ -27,81 +25,89 @@ module PrxAuth::Rails
|
|
27
25
|
def show
|
28
26
|
end
|
29
27
|
|
28
|
+
def destroy
|
29
|
+
sign_out_user
|
30
|
+
redirect_to after_sign_out_path
|
31
|
+
end
|
32
|
+
|
30
33
|
def auth_error
|
31
34
|
@auth_error_message = params.require(:error)
|
32
35
|
end
|
33
36
|
|
34
37
|
def create
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
lookup_and_register_accounts_names
|
44
|
-
after_sign_in_path_for(current_user)
|
45
|
-
else
|
46
|
-
auth_error_sessions_path(error: 'verification_failed')
|
47
|
-
end
|
48
|
-
reset_nonce!
|
49
|
-
|
50
|
-
redirect_to result_path
|
38
|
+
if valid_nonce? && users_match?
|
39
|
+
clear_nonce!
|
40
|
+
sign_in_user(access_token)
|
41
|
+
redirect_to after_sign_in_path_for(current_user)
|
42
|
+
else
|
43
|
+
clear_nonce!
|
44
|
+
redirect_to auth_error_sessions_path(error: 'verification_failed')
|
45
|
+
end
|
51
46
|
end
|
52
47
|
|
53
48
|
private
|
54
49
|
|
55
50
|
def after_sign_in_path_for(_)
|
51
|
+
back_path = after_sign_in_user_redirect
|
52
|
+
if back_path.present?
|
53
|
+
back_path
|
54
|
+
elsif defined?(super)
|
55
|
+
super
|
56
|
+
else
|
57
|
+
'/'
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
def after_sign_out_path
|
56
62
|
return super if defined?(super)
|
57
63
|
|
58
|
-
"/"
|
64
|
+
"https://#{id_host}/session/sign_out"
|
65
|
+
end
|
66
|
+
|
67
|
+
def id_token
|
68
|
+
params.require('id_token')
|
69
|
+
end
|
70
|
+
|
71
|
+
def access_token
|
72
|
+
params.require('access_token')
|
59
73
|
end
|
60
74
|
|
61
75
|
def id_claims
|
62
|
-
|
63
|
-
validate_token(id_token)
|
76
|
+
@id_claims ||= validate_token(id_token)
|
64
77
|
end
|
65
78
|
|
66
79
|
def access_claims
|
67
|
-
|
68
|
-
validate_token(access_token)
|
80
|
+
@access_claims ||= validate_token(access_token)
|
69
81
|
end
|
70
82
|
|
71
|
-
def
|
72
|
-
session
|
83
|
+
def clear_nonce!
|
84
|
+
session.delete(ID_NONCE_SESSION_KEY)
|
73
85
|
end
|
74
86
|
|
75
87
|
def set_nonce!
|
76
|
-
|
77
|
-
return n if n.present?
|
78
|
-
|
79
|
-
session[ID_NONCE_SESSION_KEY] = SecureRandom.hex
|
88
|
+
session[ID_NONCE_SESSION_KEY] ||= SecureRandom.hex
|
80
89
|
end
|
81
90
|
|
82
91
|
def fetch_nonce
|
83
92
|
session[ID_NONCE_SESSION_KEY]
|
84
93
|
end
|
85
94
|
|
86
|
-
def valid_nonce?
|
87
|
-
|
88
|
-
|
89
|
-
fetch_nonce == nonce
|
95
|
+
def valid_nonce?
|
96
|
+
id_claims['nonce'].present? && id_claims['nonce'] == fetch_nonce
|
90
97
|
end
|
91
98
|
|
92
|
-
def users_match?
|
93
|
-
|
94
|
-
|
95
|
-
claims1['sub'] == claims2['sub']
|
99
|
+
def users_match?
|
100
|
+
id_claims['sub'].present? && id_claims['sub'] == access_claims['sub']
|
96
101
|
end
|
97
102
|
|
98
103
|
def validate_token(token)
|
99
|
-
id_host = PrxAuth::Rails.configuration.id_host
|
100
104
|
prx_auth_cert = Rack::PrxAuth::Certificate.new("https://#{id_host}/api/v1/certs")
|
101
105
|
auth_validator = Rack::PrxAuth::AuthValidator.new(token, prx_auth_cert, id_host)
|
102
|
-
auth_validator.
|
103
|
-
|
104
|
-
|
106
|
+
auth_validator.claims.with_indifferent_access
|
107
|
+
end
|
108
|
+
|
109
|
+
def id_host
|
110
|
+
PrxAuth::Rails.configuration.id_host
|
105
111
|
end
|
106
112
|
end
|
107
113
|
end
|
@@ -0,0 +1 @@
|
|
1
|
+
Rails.application.config.assets.precompile << %w(prx_auth-rails_manifest.js)
|
@@ -2,7 +2,11 @@ module PrxAuth
|
|
2
2
|
module Rails
|
3
3
|
class Engine < ::Rails::Engine
|
4
4
|
config.to_prepare do
|
5
|
-
::ApplicationController.helper_method [
|
5
|
+
::ApplicationController.helper_method [
|
6
|
+
:current_user, :prx_jwt,
|
7
|
+
:current_user_info, :current_user_name, :current_user_apps,
|
8
|
+
:account_name_for, :account_for, :accounts_for,
|
9
|
+
]
|
6
10
|
end
|
7
11
|
end
|
8
12
|
end
|
@@ -4,14 +4,27 @@ require 'open-uri'
|
|
4
4
|
module PrxAuth
|
5
5
|
module Rails
|
6
6
|
module Controller
|
7
|
+
class SessionTokenExpiredError < RuntimeError; end
|
7
8
|
|
8
|
-
|
9
|
+
PRX_AUTH_ENV_KEY = 'prx.auth'.freeze
|
10
|
+
PRX_JWT_SESSION_KEY = 'prx.auth.jwt'.freeze
|
11
|
+
PRX_JWT_REFRESH_TTL = 300.freeze
|
12
|
+
PRX_ACCOUNT_MAPPING_SESSION_KEY = 'prx.auth.account.mapping'.freeze
|
13
|
+
PRX_USER_INFO_SESSION_KEY = 'prx.auth.info'.freeze
|
14
|
+
PRX_REFRESH_BACK_KEY = 'prx.auth.back'.freeze
|
9
15
|
|
10
16
|
def prx_auth_token
|
11
|
-
|
12
|
-
|
17
|
+
env_token || session_token
|
18
|
+
rescue SessionTokenExpiredError
|
19
|
+
session.delete(PRX_JWT_SESSION_KEY)
|
20
|
+
session.delete(PRX_ACCOUNT_MAPPING_SESSION_KEY)
|
21
|
+
session.delete(PRX_USER_INFO_SESSION_KEY)
|
22
|
+
session[PRX_REFRESH_BACK_KEY] = request.fullpath
|
23
|
+
redirect_to PrxAuth::Rails::Engine.routes.url_helpers.new_sessions_path
|
24
|
+
end
|
13
25
|
|
14
|
-
|
26
|
+
def prx_jwt
|
27
|
+
session[PRX_JWT_SESSION_KEY]
|
15
28
|
end
|
16
29
|
|
17
30
|
def prx_authenticated?
|
@@ -24,66 +37,116 @@ module PrxAuth
|
|
24
37
|
redirect_to PrxAuth::Rails::Engine.routes.url_helpers.new_sessions_path
|
25
38
|
end
|
26
39
|
|
40
|
+
def prx_auth_needs_refresh?(jwt_ttl)
|
41
|
+
request.get? && jwt_ttl < PRX_JWT_REFRESH_TTL
|
42
|
+
end
|
43
|
+
|
27
44
|
def current_user
|
28
|
-
|
45
|
+
prx_auth_token
|
46
|
+
end
|
29
47
|
|
30
|
-
|
48
|
+
def current_user_info
|
49
|
+
session[PRX_USER_INFO_SESSION_KEY] ||= fetch_userinfo
|
31
50
|
end
|
32
51
|
|
33
|
-
def
|
34
|
-
|
35
|
-
lookup_account_names_mapping
|
52
|
+
def current_user_name
|
53
|
+
current_user_info['name'] || current_user_info['preferred_username'] || current_user_info['email']
|
36
54
|
end
|
37
55
|
|
38
|
-
def
|
39
|
-
|
56
|
+
def current_user_apps
|
57
|
+
apps = (current_user_info.try(:[], 'apps') || []).map do |name, url|
|
58
|
+
label = name.sub(/^https?:\/\//, '').sub(/\..+/, '').capitalize
|
59
|
+
["PRX #{label}", url]
|
60
|
+
end
|
40
61
|
|
41
|
-
|
62
|
+
# only return entire list in development
|
63
|
+
if ::Rails.env.production? || ::Rails.env.staging?
|
64
|
+
apps.to_h.select { |k, v| v.match?(/\.(org|tech)/) }
|
65
|
+
else
|
66
|
+
apps.to_h
|
67
|
+
end
|
68
|
+
end
|
42
69
|
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
session[PRX_ACCOUNT_NAME_MAPPING_KEY][id] = lookup_account_name_for(id)
|
48
|
-
end
|
70
|
+
def sign_in_user(token)
|
71
|
+
session[PRX_JWT_SESSION_KEY] = token
|
72
|
+
accounts_for(current_user.resources)
|
73
|
+
end
|
49
74
|
|
50
|
-
|
75
|
+
def after_sign_in_user_redirect
|
76
|
+
session.delete(PRX_REFRESH_BACK_KEY)
|
77
|
+
end
|
51
78
|
|
52
|
-
|
79
|
+
def sign_out_user
|
80
|
+
reset_session
|
53
81
|
end
|
54
82
|
|
55
|
-
def
|
56
|
-
|
83
|
+
def account_name_for(account_id)
|
84
|
+
account_for(account_id).try(:[], :name)
|
85
|
+
end
|
86
|
+
|
87
|
+
def account_for(account_id)
|
88
|
+
lookup_accounts([account_id]).first
|
89
|
+
end
|
90
|
+
|
91
|
+
def accounts_for(account_ids)
|
92
|
+
lookup_accounts(account_ids)
|
57
93
|
end
|
58
94
|
|
59
95
|
private
|
60
96
|
|
61
|
-
def
|
62
|
-
|
97
|
+
def lookup_accounts(ids)
|
98
|
+
session[PRX_ACCOUNT_MAPPING_SESSION_KEY] ||= {}
|
99
|
+
|
100
|
+
# fetch any accounts we don't have yet
|
101
|
+
missing = ids - session[PRX_ACCOUNT_MAPPING_SESSION_KEY].keys
|
102
|
+
if missing.present?
|
103
|
+
fetch_accounts(missing).each do |account|
|
104
|
+
session[PRX_ACCOUNT_MAPPING_SESSION_KEY][account['id']] = account.with_indifferent_access
|
105
|
+
end
|
106
|
+
end
|
63
107
|
|
64
|
-
|
65
|
-
res[id]
|
108
|
+
ids.map { |id| session[PRX_ACCOUNT_MAPPING_SESSION_KEY][id] }
|
66
109
|
end
|
67
110
|
|
68
|
-
def
|
69
|
-
id_host = PrxAuth::Rails.configuration.id_host
|
111
|
+
def fetch_accounts(ids)
|
70
112
|
ids_param = ids.map(&:to_s).join(',')
|
113
|
+
fetch("/api/v1/accounts?account_ids=#{ids_param}")['accounts']
|
114
|
+
end
|
71
115
|
|
116
|
+
def fetch_userinfo
|
117
|
+
fetch("/userinfo?scope=apps+email+profile", prx_jwt)
|
118
|
+
end
|
119
|
+
|
120
|
+
def fetch(path, token = nil)
|
121
|
+
url = "https://#{PrxAuth::Rails.configuration.id_host}#{path}"
|
72
122
|
options = {}
|
73
123
|
options[:ssl_verify_mode] = OpenSSL::SSL::VERIFY_NONE if ::Rails.env.development?
|
124
|
+
options['Authorization'] = "Bearer #{token}" if token
|
125
|
+
JSON.parse(URI.open(url, options).read)
|
126
|
+
end
|
74
127
|
|
75
|
-
|
128
|
+
# token from data set by prx_auth rack middleware
|
129
|
+
def env_token
|
130
|
+
@env_token_data ||= if request.env[PRX_AUTH_ENV_KEY]
|
131
|
+
token_data = request.env[PRX_AUTH_ENV_KEY]
|
132
|
+
PrxAuth::Rails::Token.new(token_data)
|
133
|
+
end
|
134
|
+
end
|
76
135
|
|
77
|
-
|
136
|
+
# token from jwt stored in session
|
137
|
+
def session_token
|
138
|
+
@session_prx_auth_token ||= if prx_jwt
|
139
|
+
# NOTE: we already validated this jwt - so just decode it
|
140
|
+
validator = Rack::PrxAuth::AuthValidator.new(prx_jwt)
|
78
141
|
|
79
|
-
|
80
|
-
|
142
|
+
# does this jwt need to be refreshed?
|
143
|
+
if prx_auth_needs_refresh?(validator.time_to_live)
|
144
|
+
raise SessionTokenExpiredError.new
|
145
|
+
end
|
81
146
|
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
else
|
86
|
-
@_prx_auth_token
|
147
|
+
# create new data/token from access claims
|
148
|
+
token_data = Rack::PrxAuth::TokenData.new(validator.claims)
|
149
|
+
PrxAuth::Rails::Token.new(token_data)
|
87
150
|
end
|
88
151
|
end
|
89
152
|
end
|
data/prx_auth-rails.gemspec
CHANGED
@@ -8,10 +8,8 @@ Gem::Specification.new do |spec|
|
|
8
8
|
spec.version = PrxAuth::Rails::VERSION
|
9
9
|
spec.authors = ["Chris Rhoden"]
|
10
10
|
spec.email = ["carhoden@gmail.com"]
|
11
|
-
spec.description =
|
12
|
-
|
13
|
-
spec.summary = %q{Rails integration for next generation PRX Authorization system.
|
14
|
-
}
|
11
|
+
spec.description = "Rails integration for next generation PRX Authorization system."
|
12
|
+
spec.summary = "Rails integration for next generation PRX Authorization system."
|
15
13
|
spec.homepage = "https://github.com/PRX/prx_auth-rails"
|
16
14
|
spec.license = "MIT"
|
17
15
|
|
@@ -29,11 +27,11 @@ Gem::Specification.new do |spec|
|
|
29
27
|
spec.add_development_dependency 'coveralls', '~> 0'
|
30
28
|
spec.add_development_dependency 'guard'
|
31
29
|
spec.add_development_dependency 'guard-minitest'
|
30
|
+
spec.add_development_dependency 'm', '~> 1.5'
|
32
31
|
spec.add_development_dependency "rails", "~> 6.1.0"
|
33
32
|
spec.add_development_dependency 'pry'
|
34
33
|
spec.add_development_dependency 'sqlite3'
|
34
|
+
spec.add_development_dependency 'webmock'
|
35
35
|
|
36
|
-
|
37
|
-
|
38
|
-
spec.add_runtime_dependency 'prx_auth', "~> 1.2"
|
36
|
+
spec.add_runtime_dependency 'prx_auth', ">= 1.7.0"
|
39
37
|
end
|
@@ -0,0 +1 @@
|
|
1
|
+
the controller index!
|
data/test/dummy/config/routes.rb
CHANGED
@@ -0,0 +1,165 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
module PrxAuth::Rails::Ext
|
4
|
+
class ControllerTest < ActionController::TestCase
|
5
|
+
|
6
|
+
setup do
|
7
|
+
@controller = ApplicationController.new
|
8
|
+
@jwt_session_key = ApplicationController::PRX_JWT_SESSION_KEY
|
9
|
+
@user_info_key = ApplicationController::PRX_USER_INFO_SESSION_KEY
|
10
|
+
@account_mapping_key = ApplicationController::PRX_ACCOUNT_MAPPING_SESSION_KEY
|
11
|
+
@stub_claims = {'iat' => Time.now.to_i, 'exp' => Time.now.to_i + 3600}
|
12
|
+
end
|
13
|
+
|
14
|
+
# stub auth and init controller+session by getting a page
|
15
|
+
def with_stubbed_auth(jwt)
|
16
|
+
session[@jwt_session_key] = 'some-jwt'
|
17
|
+
@controller.stub(:prx_auth_needs_refresh?, false) do
|
18
|
+
get :index
|
19
|
+
assert_equal response.code, '200'
|
20
|
+
yield
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
test 'redirects unless you are authenticated' do
|
25
|
+
get :index
|
26
|
+
assert_equal response.code, '302'
|
27
|
+
assert response.headers['Location'].ends_with?('/sessions/new')
|
28
|
+
end
|
29
|
+
|
30
|
+
test 'uses a valid session token' do
|
31
|
+
session[@jwt_session_key] = 'some-jwt'
|
32
|
+
JSON::JWT.stub(:decode, @stub_claims) do
|
33
|
+
get :index
|
34
|
+
assert_equal response.code, '200'
|
35
|
+
assert response.body.include?('the controller index!')
|
36
|
+
assert @controller.current_user.is_a?(PrxAuth::Rails::Token)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
test 'redirects if your token is nearing expiration' do
|
41
|
+
session[@jwt_session_key] = 'some-jwt'
|
42
|
+
@stub_claims['exp'] = Time.now.to_i + 10
|
43
|
+
JSON::JWT.stub(:decode, @stub_claims) do
|
44
|
+
get :index
|
45
|
+
assert_equal response.code, '302'
|
46
|
+
assert response.headers['Location'].ends_with?('/sessions/new')
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
test 'does not redirect if your token has expired on a non-GET request' do
|
51
|
+
session[@jwt_session_key] = 'some-jwt'
|
52
|
+
@stub_claims['exp'] = Time.now.to_i + 10
|
53
|
+
JSON::JWT.stub(:decode, @stub_claims) do
|
54
|
+
put :index
|
55
|
+
assert_equal response.code, '200'
|
56
|
+
assert response.body.include?('the controller index!')
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
test 'fetches current user info' do
|
61
|
+
with_stubbed_auth('some-jwt') do
|
62
|
+
body = {
|
63
|
+
'name' => 'Some Username',
|
64
|
+
'apps' => {'publish.prx.test' => 'https://publish.prx.test'},
|
65
|
+
'other' => 'stuff'
|
66
|
+
}
|
67
|
+
|
68
|
+
id_host = PrxAuth::Rails.configuration.id_host
|
69
|
+
stub_request(:get, "https://#{id_host}/userinfo?scope=apps%20email%20profile").
|
70
|
+
with(headers: {'Authorization' => 'Bearer some-jwt'}).
|
71
|
+
to_return(status: 200, body: JSON.generate(body))
|
72
|
+
|
73
|
+
assert session[@user_info_key] == nil
|
74
|
+
assert_equal @controller.current_user_info, body
|
75
|
+
refute session[@user_info_key] == nil
|
76
|
+
assert_equal @controller.current_user_name, 'Some Username'
|
77
|
+
assert_equal @controller.current_user_apps, {'PRX Publish' => 'https://publish.prx.test'}
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
test 'has user name fallbacks' do
|
82
|
+
with_stubbed_auth('some-jwt') do
|
83
|
+
session[@user_info_key] = {'name' => 'one', 'preferred_username' => 'two', 'email' => 'three'}
|
84
|
+
assert_equal @controller.current_user_name, 'one'
|
85
|
+
|
86
|
+
session[@user_info_key] = {'preferred_username' => 'two', 'email' => 'three'}
|
87
|
+
assert_equal @controller.current_user_name, 'two'
|
88
|
+
|
89
|
+
session[@user_info_key] = {'email' => 'three'}
|
90
|
+
assert_equal @controller.current_user_name, 'three'
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
test 'filters apps displayed in production' do
|
95
|
+
with_stubbed_auth('some-jwt') do
|
96
|
+
Rails.env.stub(:production?, true) do
|
97
|
+
session[@user_info_key] = {
|
98
|
+
'apps' => {
|
99
|
+
'localhost stuff' => 'http://localhost:4000/path1',
|
100
|
+
'publish.prx.test' => 'https://publish.prx.test/path2',
|
101
|
+
'metrics.prx.tech' => 'https://metrics.prx.tech/path3',
|
102
|
+
'augury.prx.org' => 'https://augury.prx.org/path4',
|
103
|
+
}
|
104
|
+
}
|
105
|
+
|
106
|
+
assert_equal @controller.current_user_apps, {
|
107
|
+
'PRX Metrics' => 'https://metrics.prx.tech/path3',
|
108
|
+
'PRX Augury' => 'https://augury.prx.org/path4',
|
109
|
+
}
|
110
|
+
end
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
test 'fetches accounts' do
|
115
|
+
with_stubbed_auth('some-jwt') do
|
116
|
+
one = {'id' => 1, 'type' => 'IndividualAccount', 'name' => 'One'}
|
117
|
+
three = {'id' => 3, 'type' => 'GroupAccount', 'name' => 'Three'}
|
118
|
+
body = {'accounts' => [one, three]}
|
119
|
+
|
120
|
+
id_host = PrxAuth::Rails.configuration.id_host
|
121
|
+
stub_request(:get, "https://#{id_host}/api/v1/accounts?account_ids=1,2,3").
|
122
|
+
to_return(status: 200, body: JSON.generate(body))
|
123
|
+
|
124
|
+
assert_nil session[@account_mapping_key]
|
125
|
+
assert_equal @controller.accounts_for([1, 2, 3]), [one, nil, three]
|
126
|
+
refute_nil session[@account_mapping_key]
|
127
|
+
assert_equal @controller.account_for(1), one
|
128
|
+
assert_equal @controller.account_for(3), three
|
129
|
+
assert_equal @controller.account_name_for(1), 'One'
|
130
|
+
assert_equal @controller.account_name_for(3), 'Three'
|
131
|
+
end
|
132
|
+
end
|
133
|
+
|
134
|
+
test 'handles unknown account ids' do
|
135
|
+
with_stubbed_auth('some-jwt') do
|
136
|
+
id_host = PrxAuth::Rails.configuration.id_host
|
137
|
+
stub_request(:get, "https://#{id_host}/api/v1/accounts?account_ids=2").
|
138
|
+
to_return(status: 200, body: JSON.generate({accounts: []})).
|
139
|
+
times(3)
|
140
|
+
|
141
|
+
assert_equal @controller.accounts_for([2]), [nil]
|
142
|
+
assert_nil @controller.account_for(2)
|
143
|
+
assert_nil @controller.account_name_for(2)
|
144
|
+
end
|
145
|
+
end
|
146
|
+
|
147
|
+
test 'only fetches only missing accounts' do
|
148
|
+
with_stubbed_auth('some-jwt') do
|
149
|
+
one = {'name' => 'One'}
|
150
|
+
two = {'id' => 2, 'type' => 'StationAccount', 'name' => 'Two'}
|
151
|
+
three = {'name' => 'Three'}
|
152
|
+
session[@account_mapping_key] = {1 => one, 3 => three}
|
153
|
+
body = {'accounts' => [two]}
|
154
|
+
|
155
|
+
id_host = PrxAuth::Rails.configuration.id_host
|
156
|
+
stub_request(:get, "https://#{id_host}/api/v1/accounts?account_ids=2").
|
157
|
+
to_return(status: 200, body: JSON.generate(body))
|
158
|
+
|
159
|
+
assert_equal @controller.accounts_for([1, 2, 3]), [one, two, three]
|
160
|
+
assert_equal @controller.account_for(2), two
|
161
|
+
assert_equal @controller.account_name_for(2), 'Two'
|
162
|
+
end
|
163
|
+
end
|
164
|
+
end
|
165
|
+
end
|
@@ -6,8 +6,10 @@ module PrxAuth::Rails
|
|
6
6
|
setup do
|
7
7
|
@routes = PrxAuth::Rails::Engine.routes
|
8
8
|
@nonce_session_key = SessionsController::ID_NONCE_SESSION_KEY
|
9
|
-
@
|
9
|
+
@refresh_back_key = SessionsController::PRX_REFRESH_BACK_KEY
|
10
|
+
@token_params = {id_token: 'idtok', access_token: 'accesstok'}
|
10
11
|
@stub_claims = {'nonce' => '123', 'sub' => '1'}
|
12
|
+
@stub_token = PrxAuth::Rails::Token.new(Rack::PrxAuth::TokenData.new())
|
11
13
|
end
|
12
14
|
|
13
15
|
test "new creates nonce" do
|
@@ -31,11 +33,12 @@ module PrxAuth::Rails
|
|
31
33
|
end
|
32
34
|
|
33
35
|
test 'create should validate a token and set the session variable' do
|
36
|
+
session[SessionsController::PRX_JWT_SESSION_KEY] = nil
|
34
37
|
@controller.stub(:validate_token, @stub_claims) do
|
35
|
-
@controller.stub(:
|
38
|
+
@controller.stub(:session_token, @stub_token) do
|
36
39
|
session[@nonce_session_key] = '123'
|
37
40
|
post :create, params: @token_params, format: :json
|
38
|
-
assert session[
|
41
|
+
assert session[SessionsController::PRX_JWT_SESSION_KEY] == 'accesstok'
|
39
42
|
end
|
40
43
|
end
|
41
44
|
end
|
@@ -50,7 +53,7 @@ module PrxAuth::Rails
|
|
50
53
|
|
51
54
|
test 'create should reset the nonce after consumed' do
|
52
55
|
@controller.stub(:validate_token, @stub_claims) do
|
53
|
-
@controller.stub(:
|
56
|
+
@controller.stub(:session_token, @stub_token) do
|
54
57
|
session[@nonce_session_key] = '123'
|
55
58
|
post :create, params: @token_params, format: :json
|
56
59
|
|
@@ -61,7 +64,21 @@ module PrxAuth::Rails
|
|
61
64
|
end
|
62
65
|
end
|
63
66
|
|
64
|
-
test '
|
67
|
+
test 'redirects to a back-path after refresh' do
|
68
|
+
@controller.stub(:validate_token, @stub_claims) do
|
69
|
+
@controller.stub(:session_token, @stub_token) do
|
70
|
+
session[@nonce_session_key] = '123'
|
71
|
+
session[@refresh_back_key] = '/lets/go/here?okay'
|
72
|
+
post :create, params: @token_params, format: :json
|
73
|
+
|
74
|
+
assert session[@refresh_back_key] == nil
|
75
|
+
assert response.code == '302'
|
76
|
+
assert response.headers['Location'].ends_with?('/lets/go/here?okay')
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
test 'should respond with redirect to the auth error page / code if the nonce does not match' do
|
65
82
|
@controller.stub(:validate_token, @stub_claims) do
|
66
83
|
session[@nonce_session_key] = 'nonce-does-not-match'
|
67
84
|
post :create, params: @token_params, format: :json
|
@@ -86,13 +103,19 @@ module PrxAuth::Rails
|
|
86
103
|
@controller.stub(:id_claims, @stub_claims) do
|
87
104
|
@controller.stub(:access_claims, @stub_claims.merge('sub' => '444')) do
|
88
105
|
|
89
|
-
|
90
|
-
|
106
|
+
session[@nonce_session_key] = '123'
|
107
|
+
post :create, params: @token_params, format: :json
|
91
108
|
|
92
|
-
|
93
|
-
|
94
|
-
|
109
|
+
assert response.code == '302'
|
110
|
+
assert response.body.match?(/error=verification_failed/)
|
111
|
+
end
|
95
112
|
end
|
96
113
|
end
|
114
|
+
|
115
|
+
test 'should clear the user token on sign out' do
|
116
|
+
session[SessionsController::PRX_JWT_SESSION_KEY] = 'some-token'
|
117
|
+
post :destroy
|
118
|
+
assert session[SessionsController::PRX_JWT_SESSION_KEY] == nil
|
119
|
+
end
|
97
120
|
end
|
98
121
|
end
|
data/test/test_helper.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: prx_auth-rails
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 2.0.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Chris Rhoden
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2021-
|
11
|
+
date: 2021-05-13 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: actionpack
|
@@ -94,6 +94,20 @@ dependencies:
|
|
94
94
|
- - ">="
|
95
95
|
- !ruby/object:Gem::Version
|
96
96
|
version: '0'
|
97
|
+
- !ruby/object:Gem::Dependency
|
98
|
+
name: m
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - "~>"
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: '1.5'
|
104
|
+
type: :development
|
105
|
+
prerelease: false
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
107
|
+
requirements:
|
108
|
+
- - "~>"
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: '1.5'
|
97
111
|
- !ruby/object:Gem::Dependency
|
98
112
|
name: rails
|
99
113
|
requirement: !ruby/object:Gem::Requirement
|
@@ -136,23 +150,35 @@ dependencies:
|
|
136
150
|
- - ">="
|
137
151
|
- !ruby/object:Gem::Version
|
138
152
|
version: '0'
|
153
|
+
- !ruby/object:Gem::Dependency
|
154
|
+
name: webmock
|
155
|
+
requirement: !ruby/object:Gem::Requirement
|
156
|
+
requirements:
|
157
|
+
- - ">="
|
158
|
+
- !ruby/object:Gem::Version
|
159
|
+
version: '0'
|
160
|
+
type: :development
|
161
|
+
prerelease: false
|
162
|
+
version_requirements: !ruby/object:Gem::Requirement
|
163
|
+
requirements:
|
164
|
+
- - ">="
|
165
|
+
- !ruby/object:Gem::Version
|
166
|
+
version: '0'
|
139
167
|
- !ruby/object:Gem::Dependency
|
140
168
|
name: prx_auth
|
141
169
|
requirement: !ruby/object:Gem::Requirement
|
142
170
|
requirements:
|
143
|
-
- - "
|
171
|
+
- - ">="
|
144
172
|
- !ruby/object:Gem::Version
|
145
|
-
version:
|
173
|
+
version: 1.7.0
|
146
174
|
type: :runtime
|
147
175
|
prerelease: false
|
148
176
|
version_requirements: !ruby/object:Gem::Requirement
|
149
177
|
requirements:
|
150
|
-
- - "
|
178
|
+
- - ">="
|
151
179
|
- !ruby/object:Gem::Version
|
152
|
-
version:
|
153
|
-
description:
|
154
|
-
|
155
|
-
'
|
180
|
+
version: 1.7.0
|
181
|
+
description: Rails integration for next generation PRX Authorization system.
|
156
182
|
email:
|
157
183
|
- carhoden@gmail.com
|
158
184
|
executables: []
|
@@ -168,6 +194,7 @@ files:
|
|
168
194
|
- app/controllers/prx_auth/rails/sessions_controller.rb
|
169
195
|
- app/views/prx_auth/rails/sessions/auth_error.html.erb
|
170
196
|
- app/views/prx_auth/rails/sessions/show.html.erb
|
197
|
+
- config/initializers/assets.rb
|
171
198
|
- config/routes.rb
|
172
199
|
- lib/prx_auth/rails.rb
|
173
200
|
- lib/prx_auth/rails/configuration.rb
|
@@ -191,6 +218,7 @@ files:
|
|
191
218
|
- test/dummy/app/mailers/application_mailer.rb
|
192
219
|
- test/dummy/app/models/application_record.rb
|
193
220
|
- test/dummy/app/models/concerns/.keep
|
221
|
+
- test/dummy/app/views/application/index.html.erb
|
194
222
|
- test/dummy/app/views/layouts/application.html.erb
|
195
223
|
- test/dummy/app/views/layouts/mailer.html.erb
|
196
224
|
- test/dummy/app/views/layouts/mailer.text.erb
|
@@ -234,6 +262,7 @@ files:
|
|
234
262
|
- test/dummy/storage/.keep
|
235
263
|
- test/log/development.log
|
236
264
|
- test/prx_auth/rails/configuration_test.rb
|
265
|
+
- test/prx_auth/rails/ext/controller_test.rb
|
237
266
|
- test/prx_auth/rails/sessions_controller_test.rb
|
238
267
|
- test/prx_auth/rails/token_test.rb
|
239
268
|
- test/test_helper.rb
|
@@ -275,6 +304,7 @@ test_files:
|
|
275
304
|
- test/dummy/app/mailers/application_mailer.rb
|
276
305
|
- test/dummy/app/models/application_record.rb
|
277
306
|
- test/dummy/app/models/concerns/.keep
|
307
|
+
- test/dummy/app/views/application/index.html.erb
|
278
308
|
- test/dummy/app/views/layouts/application.html.erb
|
279
309
|
- test/dummy/app/views/layouts/mailer.html.erb
|
280
310
|
- test/dummy/app/views/layouts/mailer.text.erb
|
@@ -318,6 +348,7 @@ test_files:
|
|
318
348
|
- test/dummy/storage/.keep
|
319
349
|
- test/log/development.log
|
320
350
|
- test/prx_auth/rails/configuration_test.rb
|
351
|
+
- test/prx_auth/rails/ext/controller_test.rb
|
321
352
|
- test/prx_auth/rails/sessions_controller_test.rb
|
322
353
|
- test/prx_auth/rails/token_test.rb
|
323
354
|
- test/test_helper.rb
|