prx_auth-rails 1.4.1 → 2.0.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|