prx_auth-rails 4.3.0 → 5.0.1
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/.github/workflows/check-project-std.yml +1 -1
- data/app/controllers/prx_auth/rails/sessions_controller.rb +29 -15
- data/app/helpers/prx_auth/rails/sessions_helper.rb +27 -0
- data/app/views/prx_auth/rails/sessions/access_error.html.erb +20 -0
- data/app/views/prx_auth/rails/sessions/auth_error.html.erb +19 -7
- data/app/views/prx_auth/rails/sessions/show.html.erb +1 -1
- data/config/routes.rb +6 -3
- data/lib/prx_auth/rails/engine.rb +1 -0
- data/lib/prx_auth/rails/ext/controller/account_info.rb +51 -0
- data/lib/prx_auth/rails/ext/controller/user_info.rb +62 -0
- data/lib/prx_auth/rails/ext/controller.rb +25 -83
- data/lib/prx_auth/rails/version.rb +1 -1
- data/test/dummy/app/controllers/application_controller.rb +0 -2
- data/test/dummy/config/routes.rb +0 -1
- data/test/prx_auth/rails/ext/controller_test.rb +18 -5
- data/test/prx_auth/rails/sessions_controller_test.rb +52 -7
- data/test/prx_auth/rails/sessions_helper_test.rb +71 -0
- metadata +7 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 78518e6f1ac8806d8b51a50834bfe59208bb778ff277e1685572268b30a41647
|
4
|
+
data.tar.gz: a855a3b4967db5f7bdfbca77d555d4d06e6cc482fd3caa85e6285b280ac441c4
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 9d6d5ce5d77f09e51092482773890e9b27826e2dab76d4912cccb123ec361c1f4acee0a2076c553deb94cc7981ea89e8a7546ea4e561aa18621986c638102802
|
7
|
+
data.tar.gz: 59c1622e39c4ba7ad666bc8948ca68f495b87083a4f240068666688579ca6945187ad9d099297b872bf9d9e41d4f2d89c82691088c81ed4668e9e2f4e9de510e
|
@@ -2,34 +2,31 @@
|
|
2
2
|
|
3
3
|
module PrxAuth::Rails
|
4
4
|
class SessionsController < ApplicationController
|
5
|
-
|
6
|
-
|
7
|
-
skip_before_action :authenticate!, raise: false
|
5
|
+
skip_before_action :set_after_sign_in_path, :authenticate!, raise: false
|
8
6
|
|
9
7
|
before_action :set_nonce!, only: [:new, :show]
|
10
|
-
before_action :set_after_sign_in_path
|
11
8
|
|
12
9
|
ID_NONCE_SESSION_KEY = "id_prx_openid_nonce"
|
10
|
+
WILDCARD_SESSION_KEY = "prx.auth.wildcard"
|
13
11
|
DEFAULT_SCOPES = "openid apps"
|
14
12
|
|
15
13
|
def new
|
16
14
|
config = PrxAuth::Rails.configuration
|
17
15
|
|
18
|
-
scope =
|
19
|
-
if config.prx_scope.present?
|
20
|
-
"#{DEFAULT_SCOPES} #{config.prx_scope}"
|
21
|
-
else
|
22
|
-
DEFAULT_SCOPES
|
23
|
-
end
|
24
|
-
|
25
16
|
id_auth_params = {
|
26
17
|
client_id: config.prx_client_id,
|
27
18
|
nonce: fetch_nonce,
|
28
19
|
response_type: "id_token token",
|
29
|
-
scope:
|
20
|
+
scope: "#{DEFAULT_SCOPES} #{config.prx_scope}".strip,
|
30
21
|
prompt: "necessary"
|
31
22
|
}
|
32
23
|
|
24
|
+
if session[WILDCARD_SESSION_KEY]
|
25
|
+
id_auth_params[:account] = "*"
|
26
|
+
# TODO: what if they need more than _just_ read-private?
|
27
|
+
id_auth_params[:scope] = "#{DEFAULT_SCOPES} read-private" if session[WILDCARD_SESSION_KEY] == "readonly"
|
28
|
+
end
|
29
|
+
|
33
30
|
url = "//" + config.id_host + "/authorize?" + id_auth_params.to_query
|
34
31
|
|
35
32
|
redirect_to url, allow_other_host: true
|
@@ -38,9 +35,7 @@ module PrxAuth::Rails
|
|
38
35
|
def show
|
39
36
|
end
|
40
37
|
|
41
|
-
def
|
42
|
-
sign_out_user
|
43
|
-
redirect_to after_sign_out_path, allow_other_host: true
|
38
|
+
def access_error
|
44
39
|
end
|
45
40
|
|
46
41
|
def auth_error
|
@@ -55,10 +50,29 @@ module PrxAuth::Rails
|
|
55
50
|
sign_in_user(access_token)
|
56
51
|
redirect_to after_sign_in_path_for(current_user)
|
57
52
|
else
|
53
|
+
session.delete(WILDCARD_SESSION_KEY)
|
58
54
|
redirect_to auth_error_sessions_path(error: params[:error] || "unknown_error")
|
59
55
|
end
|
60
56
|
end
|
61
57
|
|
58
|
+
def destroy
|
59
|
+
sign_out_user
|
60
|
+
redirect_to after_sign_out_path, allow_other_host: true
|
61
|
+
end
|
62
|
+
|
63
|
+
def logout
|
64
|
+
sign_out_user
|
65
|
+
redirect_to "//#{id_host}/session/sign_out", allow_other_host: true
|
66
|
+
end
|
67
|
+
|
68
|
+
def refresh
|
69
|
+
wildcard = params[:wildcard] if current_user_admin?
|
70
|
+
sign_out_user
|
71
|
+
session[WILDCARD_SESSION_KEY] = wildcard
|
72
|
+
|
73
|
+
redirect_to new_sessions_path
|
74
|
+
end
|
75
|
+
|
62
76
|
private
|
63
77
|
|
64
78
|
def after_sign_in_path_for(_)
|
@@ -0,0 +1,27 @@
|
|
1
|
+
module PrxAuth::Rails
|
2
|
+
module SessionsHelper
|
3
|
+
def current_user_app?(name)
|
4
|
+
current_user && current_user_app(name).present?
|
5
|
+
end
|
6
|
+
|
7
|
+
def current_user_app(name)
|
8
|
+
current_user_apps.find { |key, url| key.downcase.include?(name) }&.last
|
9
|
+
end
|
10
|
+
|
11
|
+
def current_user_id_profile
|
12
|
+
"https://#{PrxAuth::Rails.configuration.id_host}/profile"
|
13
|
+
end
|
14
|
+
|
15
|
+
def current_user_id_accounts
|
16
|
+
"https://#{PrxAuth::Rails.configuration.id_host}/accounts"
|
17
|
+
end
|
18
|
+
|
19
|
+
def current_user_image?
|
20
|
+
current_user && current_user_image.present?
|
21
|
+
end
|
22
|
+
|
23
|
+
def current_user_image
|
24
|
+
current_user_info["image_href"]
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
<div class="row">
|
2
|
+
|
3
|
+
<div class="col-lg-3"></div>
|
4
|
+
|
5
|
+
<div class="col-lg-6 my-5">
|
6
|
+
<div class="card">
|
7
|
+
<div class="card-body my-2">
|
8
|
+
<h1 class="card-title text-center">Not Authorized</h1>
|
9
|
+
<p class="card-text text-center">
|
10
|
+
<%= link_to "Your accounts", current_user_id_accounts %> are not authorized to use this PRX application.
|
11
|
+
<br/>
|
12
|
+
If you believe this to be in error, please <a href="https://help.prx.org/hc/en-us">contact PRX support.</a>
|
13
|
+
</p>
|
14
|
+
</div>
|
15
|
+
</div>
|
16
|
+
</div>
|
17
|
+
|
18
|
+
<div class="col-lg-3"></div>
|
19
|
+
|
20
|
+
</div>
|
@@ -1,8 +1,20 @@
|
|
1
|
-
<div class=
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
1
|
+
<div class="row">
|
2
|
+
|
3
|
+
<div class="col-lg-3"></div>
|
4
|
+
|
5
|
+
<div class="col-lg-6 my-5">
|
6
|
+
<div class="card">
|
7
|
+
<div class="card-body my-2">
|
8
|
+
<h1 class="card-title text-center"><%= @auth_error_message&.titleize || "Unknown" %> Error</h1>
|
9
|
+
<p class="card-text text-center">
|
10
|
+
Something went terribly wrong - please <%= link_to "try logging in again", new_sessions_path %>.
|
11
|
+
<br/>
|
12
|
+
If the problem persists, <a href="https://help.prx.org/hc/en-us">contact PRX support.</a>
|
13
|
+
</p>
|
14
|
+
</div>
|
15
|
+
</div>
|
16
|
+
</div>
|
17
|
+
|
18
|
+
<div class="col-lg-3"></div>
|
19
|
+
|
8
20
|
</div>
|
@@ -1,5 +1,5 @@
|
|
1
1
|
<div style="display:none;">
|
2
|
-
<%= form_for(:sessions, :
|
2
|
+
<%= form_for(:sessions, url: sessions_path) do |f| %>
|
3
3
|
<%= hidden_field_tag :access_token, '', id: 'access-token-field' %>
|
4
4
|
<%= hidden_field_tag :id_token, '', id: 'id-token-field' %>
|
5
5
|
<%= hidden_field_tag :error, '', id: 'error-field' %>
|
data/config/routes.rb
CHANGED
@@ -1,7 +1,10 @@
|
|
1
|
-
|
2
|
-
scope module: "prx_auth/rails" do
|
3
|
-
resource "sessions",
|
1
|
+
Rails.application.routes.draw do
|
2
|
+
scope module: "prx_auth/rails", path: "auth" do
|
3
|
+
resource "sessions", except: %w[edit update] do
|
4
|
+
get "access_error", to: "sessions#access_error"
|
4
5
|
get "auth_error", to: "sessions#auth_error"
|
6
|
+
get "logout", to: "sessions#logout"
|
7
|
+
get "refresh", to: "sessions#refresh"
|
5
8
|
end
|
6
9
|
end
|
7
10
|
end
|
@@ -4,6 +4,7 @@ module PrxAuth
|
|
4
4
|
config.to_prepare do
|
5
5
|
::ApplicationController.helper_method [
|
6
6
|
:current_user, :prx_jwt,
|
7
|
+
:current_user_access?, :current_user_admin?, :current_user_wildcard?,
|
7
8
|
:current_user_info, :current_user_name, :current_user_apps,
|
8
9
|
:account_name_for, :account_for, :accounts_for
|
9
10
|
]
|
@@ -0,0 +1,51 @@
|
|
1
|
+
require "open-uri"
|
2
|
+
|
3
|
+
module PrxAuth
|
4
|
+
module Rails
|
5
|
+
module AccountInfo
|
6
|
+
PRX_ACCOUNT_MAPPING_SESSION_KEY = "prx.auth.account.mapping".freeze
|
7
|
+
|
8
|
+
def account_name_for(account_id)
|
9
|
+
account_for(account_id).try(:[], "name")
|
10
|
+
end
|
11
|
+
|
12
|
+
def account_for(account_id)
|
13
|
+
lookup_accounts([account_id]).first
|
14
|
+
end
|
15
|
+
|
16
|
+
def accounts_for(account_ids)
|
17
|
+
lookup_accounts(account_ids)
|
18
|
+
end
|
19
|
+
|
20
|
+
private
|
21
|
+
|
22
|
+
def lookup_accounts(ids)
|
23
|
+
return fetch_accounts(ids) unless defined?(session)
|
24
|
+
|
25
|
+
session[PRX_ACCOUNT_MAPPING_SESSION_KEY] ||= {}
|
26
|
+
|
27
|
+
# fetch any accounts we don't have yet
|
28
|
+
missing = ids - session[PRX_ACCOUNT_MAPPING_SESSION_KEY].keys
|
29
|
+
if missing.present?
|
30
|
+
fetch_accounts(missing).each do |account|
|
31
|
+
minimal = account.slice("name", "type")
|
32
|
+
session[PRX_ACCOUNT_MAPPING_SESSION_KEY][account["id"]] = minimal
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
ids.map { |id| session[PRX_ACCOUNT_MAPPING_SESSION_KEY][id] }
|
37
|
+
end
|
38
|
+
|
39
|
+
def fetch_accounts(ids)
|
40
|
+
ids_param = ids.map(&:to_s).join(",")
|
41
|
+
path = "/api/v1/accounts?account_ids=#{ids_param}"
|
42
|
+
url = "https://#{PrxAuth::Rails.configuration.id_host}#{path}"
|
43
|
+
|
44
|
+
options = {}
|
45
|
+
options[:ssl_verify_mode] = OpenSSL::SSL::VERIFY_NONE if ::Rails.env.development?
|
46
|
+
resp = JSON.parse(URI.open(url, options).read) # standard:disable Security/Open
|
47
|
+
resp.try(:[], "_embedded").try(:[], "prx:items") || []
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
@@ -0,0 +1,62 @@
|
|
1
|
+
require "open-uri"
|
2
|
+
|
3
|
+
module PrxAuth
|
4
|
+
module Rails
|
5
|
+
module UserInfo
|
6
|
+
PRX_USER_INFO_SESSION_KEY = "prx.auth.info".freeze
|
7
|
+
PRX_ADMIN_SCOPE = "prxadmin".freeze
|
8
|
+
|
9
|
+
def current_user
|
10
|
+
prx_auth_token
|
11
|
+
end
|
12
|
+
|
13
|
+
def current_user_access?(scope = :read_private)
|
14
|
+
current_user&.globally_authorized?(scope) || current_user&.authorized_account_ids(scope)&.any?
|
15
|
+
end
|
16
|
+
|
17
|
+
def current_user_info
|
18
|
+
session[PRX_USER_INFO_SESSION_KEY] ||= begin
|
19
|
+
info = fetch_userinfo
|
20
|
+
info.slice("name", "preferred_username", "email", "image_href", "apps")
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def current_user_name
|
25
|
+
current_user_info["name"] || current_user_info["preferred_username"] || current_user_info["email"]
|
26
|
+
end
|
27
|
+
|
28
|
+
def current_user_apps
|
29
|
+
apps = (current_user_info.try(:[], "apps") || []).map do |name, url|
|
30
|
+
label = name.sub(/^https?:\/\//, "").sub(/\..+/, "").capitalize
|
31
|
+
["PRX #{label}", url]
|
32
|
+
end
|
33
|
+
|
34
|
+
# only return entire list in development
|
35
|
+
if ::Rails.env.production? || ::Rails.env.staging?
|
36
|
+
apps.to_h.select { |k, v| v.match?(/\.(org|tech)/) }
|
37
|
+
else
|
38
|
+
apps.to_h
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
def current_user_admin?
|
43
|
+
current_user&.scopes&.include?(PRX_ADMIN_SCOPE)
|
44
|
+
end
|
45
|
+
|
46
|
+
def current_user_wildcard?
|
47
|
+
current_user&.globally_authorized?(:read_private)
|
48
|
+
end
|
49
|
+
|
50
|
+
private
|
51
|
+
|
52
|
+
def fetch_userinfo
|
53
|
+
path = "/userinfo?scope=apps+email+profile"
|
54
|
+
url = "https://#{PrxAuth::Rails.configuration.id_host}#{path}"
|
55
|
+
options = {}
|
56
|
+
options[:ssl_verify_mode] = OpenSSL::SSL::VERIFY_NONE if ::Rails.env.development?
|
57
|
+
options["Authorization"] = "Bearer #{prx_jwt}"
|
58
|
+
JSON.parse(URI.open(url, options).read) # standard:disable Security/Open
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
@@ -1,19 +1,26 @@
|
|
1
|
+
require "active_support/concern"
|
1
2
|
require "prx_auth/rails/token"
|
2
|
-
require "
|
3
|
+
require "prx_auth/rails/ext/controller/account_info"
|
4
|
+
require "prx_auth/rails/ext/controller/user_info"
|
3
5
|
|
4
6
|
module PrxAuth
|
5
7
|
module Rails
|
6
8
|
module Controller
|
9
|
+
extend ActiveSupport::Concern
|
10
|
+
include PrxAuth::Rails::AccountInfo
|
11
|
+
include PrxAuth::Rails::UserInfo
|
12
|
+
|
7
13
|
class SessionTokenExpiredError < RuntimeError; end
|
8
14
|
|
9
15
|
PRX_AUTH_ENV_KEY = "prx.auth".freeze
|
10
16
|
PRX_JWT_SESSION_KEY = "prx.auth.jwt".freeze
|
11
|
-
|
12
|
-
PRX_JWT_REFRESH_TTL = 300
|
13
|
-
PRX_ACCOUNT_MAPPING_SESSION_KEY = "prx.auth.account.mapping".freeze
|
14
|
-
PRX_USER_INFO_SESSION_KEY = "prx.auth.info".freeze
|
17
|
+
PRX_JWT_REFRESH_TTL = 60
|
15
18
|
PRX_REFRESH_BACK_KEY = "prx.auth.back".freeze
|
16
19
|
|
20
|
+
included do
|
21
|
+
before_action :set_after_sign_in_path, :authenticate!
|
22
|
+
end
|
23
|
+
|
17
24
|
def prx_auth_token
|
18
25
|
env_token || session_token
|
19
26
|
rescue SessionTokenExpiredError
|
@@ -24,8 +31,6 @@ module PrxAuth
|
|
24
31
|
end
|
25
32
|
|
26
33
|
def set_after_sign_in_path
|
27
|
-
return if instance_of?(PrxAuth::Rails::SessionsController)
|
28
|
-
|
29
34
|
session[PRX_REFRESH_BACK_KEY] = request.fullpath
|
30
35
|
end
|
31
36
|
|
@@ -38,41 +43,23 @@ module PrxAuth
|
|
38
43
|
end
|
39
44
|
|
40
45
|
def authenticate!
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
request.get? && jwt_ttl < PRX_JWT_REFRESH_TTL
|
48
|
-
end
|
49
|
-
|
50
|
-
def current_user
|
51
|
-
prx_auth_token
|
52
|
-
end
|
53
|
-
|
54
|
-
def current_user_info
|
55
|
-
session[PRX_USER_INFO_SESSION_KEY] ||= begin
|
56
|
-
info = fetch_userinfo
|
57
|
-
info.slice("name", "preferred_username", "email", "image_href", "apps")
|
46
|
+
if !current_user
|
47
|
+
redirect_to new_sessions_path
|
48
|
+
elsif !current_user_access?
|
49
|
+
redirect_to access_error_sessions_path
|
50
|
+
else
|
51
|
+
true
|
58
52
|
end
|
59
53
|
end
|
60
54
|
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
label = name.sub(/^https?:\/\//, "").sub(/\..+/, "").capitalize
|
68
|
-
["PRX #{label}", url]
|
69
|
-
end
|
70
|
-
|
71
|
-
# only return entire list in development
|
72
|
-
if ::Rails.env.production? || ::Rails.env.staging?
|
73
|
-
apps.to_h.select { |k, v| v.match?(/\.(org|tech)/) }
|
55
|
+
# trigger refresh on a non-turbo GET request, if possible
|
56
|
+
def prx_auth_needs_refresh?(jwt_ttl)
|
57
|
+
if jwt_ttl < 0
|
58
|
+
true
|
59
|
+
elsif jwt_ttl < PRX_JWT_REFRESH_TTL
|
60
|
+
request.get? && !request.headers["Turbo-Frame"]
|
74
61
|
else
|
75
|
-
|
62
|
+
false
|
76
63
|
end
|
77
64
|
end
|
78
65
|
|
@@ -89,53 +76,8 @@ module PrxAuth
|
|
89
76
|
reset_session
|
90
77
|
end
|
91
78
|
|
92
|
-
def account_name_for(account_id)
|
93
|
-
account_for(account_id).try(:[], "name")
|
94
|
-
end
|
95
|
-
|
96
|
-
def account_for(account_id)
|
97
|
-
lookup_accounts([account_id]).first
|
98
|
-
end
|
99
|
-
|
100
|
-
def accounts_for(account_ids)
|
101
|
-
lookup_accounts(account_ids)
|
102
|
-
end
|
103
|
-
|
104
79
|
private
|
105
80
|
|
106
|
-
def lookup_accounts(ids)
|
107
|
-
session[PRX_ACCOUNT_MAPPING_SESSION_KEY] ||= {}
|
108
|
-
|
109
|
-
# fetch any accounts we don't have yet
|
110
|
-
missing = ids - session[PRX_ACCOUNT_MAPPING_SESSION_KEY].keys
|
111
|
-
if missing.present?
|
112
|
-
fetch_accounts(missing).each do |account|
|
113
|
-
minimal = account.slice("name", "type")
|
114
|
-
session[PRX_ACCOUNT_MAPPING_SESSION_KEY][account["id"]] = minimal
|
115
|
-
end
|
116
|
-
end
|
117
|
-
|
118
|
-
ids.map { |id| session[PRX_ACCOUNT_MAPPING_SESSION_KEY][id] }
|
119
|
-
end
|
120
|
-
|
121
|
-
def fetch_accounts(ids)
|
122
|
-
ids_param = ids.map(&:to_s).join(",")
|
123
|
-
resp = fetch("/api/v1/accounts?account_ids=#{ids_param}")
|
124
|
-
resp.try(:[], "_embedded").try(:[], "prx:items") || []
|
125
|
-
end
|
126
|
-
|
127
|
-
def fetch_userinfo
|
128
|
-
fetch("/userinfo?scope=apps+email+profile", prx_jwt)
|
129
|
-
end
|
130
|
-
|
131
|
-
def fetch(path, token = nil)
|
132
|
-
url = "https://#{PrxAuth::Rails.configuration.id_host}#{path}"
|
133
|
-
options = {}
|
134
|
-
options[:ssl_verify_mode] = OpenSSL::SSL::VERIFY_NONE if ::Rails.env.development?
|
135
|
-
options["Authorization"] = "Bearer #{token}" if token
|
136
|
-
JSON.parse(URI.open(url, options).read) # standard:disable Security/Open
|
137
|
-
end
|
138
|
-
|
139
81
|
# token from data set by prx_auth rack middleware
|
140
82
|
def env_token
|
141
83
|
@env_token_data ||= if request.env[PRX_AUTH_ENV_KEY]
|
data/test/dummy/config/routes.rb
CHANGED
@@ -7,16 +7,19 @@ module PrxAuth::Rails::Ext
|
|
7
7
|
@jwt_session_key = ApplicationController::PRX_JWT_SESSION_KEY
|
8
8
|
@user_info_key = ApplicationController::PRX_USER_INFO_SESSION_KEY
|
9
9
|
@account_mapping_key = ApplicationController::PRX_ACCOUNT_MAPPING_SESSION_KEY
|
10
|
-
@
|
10
|
+
@stub_aur = {"1234" => "test_app:read-private"}
|
11
|
+
@stub_claims = {"iat" => Time.now.to_i, "exp" => Time.now.to_i + 3600, "aur" => @stub_aur}
|
11
12
|
end
|
12
13
|
|
13
14
|
# stub auth and init controller+session by getting a page
|
14
15
|
def with_stubbed_auth(jwt)
|
15
16
|
session[@jwt_session_key] = "some-jwt"
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
17
|
+
JSON::JWT.stub(:decode, @stub_claims) do
|
18
|
+
@controller.stub(:prx_auth_needs_refresh?, false) do
|
19
|
+
get :index
|
20
|
+
assert_equal response.code, "200"
|
21
|
+
yield
|
22
|
+
end
|
20
23
|
end
|
21
24
|
end
|
22
25
|
|
@@ -26,6 +29,16 @@ module PrxAuth::Rails::Ext
|
|
26
29
|
assert response.headers["Location"].ends_with?("/sessions/new")
|
27
30
|
end
|
28
31
|
|
32
|
+
test "redirects unless you have read-private in this namespace" do
|
33
|
+
session[@jwt_session_key] = "some-jwt"
|
34
|
+
@stub_claims["aur"]["1234"] = "other_app:read-private"
|
35
|
+
JSON::JWT.stub(:decode, @stub_claims) do
|
36
|
+
get :index
|
37
|
+
assert_equal response.code, "302"
|
38
|
+
assert_includes response.location, "auth/sessions/access_error"
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
29
42
|
test "uses a valid session token" do
|
30
43
|
session[@jwt_session_key] = "some-jwt"
|
31
44
|
JSON::JWT.stub(:decode, @stub_claims) do
|
@@ -3,9 +3,10 @@ require "test_helper"
|
|
3
3
|
module PrxAuth::Rails
|
4
4
|
class SessionsControllerTest < ActionController::TestCase
|
5
5
|
setup do
|
6
|
-
@
|
6
|
+
@jwt_key = SessionsController::PRX_JWT_SESSION_KEY
|
7
7
|
@nonce_session_key = SessionsController::ID_NONCE_SESSION_KEY
|
8
8
|
@refresh_back_key = SessionsController::PRX_REFRESH_BACK_KEY
|
9
|
+
@wildcard_key = SessionsController::WILDCARD_SESSION_KEY
|
9
10
|
@token_params = {id_token: "idtok", access_token: "accesstok"}
|
10
11
|
@stub_claims = {"nonce" => "123", "sub" => "1"}
|
11
12
|
@stub_token = PrxAuth::Rails::Token.new(Rack::PrxAuth::TokenData.new)
|
@@ -31,13 +32,30 @@ module PrxAuth::Rails
|
|
31
32
|
assert nonce1 == nonce2
|
32
33
|
end
|
33
34
|
|
35
|
+
test "new includes scopes and accounts" do
|
36
|
+
get :new
|
37
|
+
assert response.code == "302"
|
38
|
+
assert_includes response.location, "scope=openid"
|
39
|
+
|
40
|
+
PrxAuth::Rails.configuration.prx_scope = "feeder:*"
|
41
|
+
get :new
|
42
|
+
assert response.code == "302"
|
43
|
+
assert_includes response.location, "scope=openid+apps+feeder%3A%2A"
|
44
|
+
|
45
|
+
session[@wildcard_key] = "true"
|
46
|
+
get :new
|
47
|
+
assert response.code == "302"
|
48
|
+
assert_includes response.location, "scope=openid"
|
49
|
+
assert_includes response.location, "account=%2A"
|
50
|
+
end
|
51
|
+
|
34
52
|
test "create should validate a token and set the session variable" do
|
35
|
-
session[
|
53
|
+
session[@jwt_key] = nil
|
36
54
|
@controller.stub(:validate_token, @stub_claims) do
|
37
55
|
@controller.stub(:session_token, @stub_token) do
|
38
56
|
session[@nonce_session_key] = "123"
|
39
57
|
post :create, params: @token_params, format: :json
|
40
|
-
assert session[
|
58
|
+
assert session[@jwt_key] == "accesstok"
|
41
59
|
end
|
42
60
|
end
|
43
61
|
end
|
@@ -90,9 +108,9 @@ module PrxAuth::Rails
|
|
90
108
|
end
|
91
109
|
|
92
110
|
test "auth_error should return a formatted error message to the user" do
|
93
|
-
get :auth_error, params: {error: "
|
111
|
+
get :auth_error, params: {error: "bad_things"}
|
94
112
|
assert response.code == "200"
|
95
|
-
assert response.body.match?(/
|
113
|
+
assert response.body.match?(/Bad Things Error/)
|
96
114
|
end
|
97
115
|
|
98
116
|
test "auth_error should expect the error param" do
|
@@ -115,9 +133,36 @@ module PrxAuth::Rails
|
|
115
133
|
end
|
116
134
|
|
117
135
|
test "should clear the user token on sign out" do
|
118
|
-
session[
|
136
|
+
session[@jwt_key] = "some-token"
|
119
137
|
post :destroy
|
120
|
-
assert session[
|
138
|
+
assert session[@jwt_key].nil?
|
139
|
+
end
|
140
|
+
|
141
|
+
test "should clear the user token and send to ID on logout" do
|
142
|
+
session[@jwt_key] = "some-token"
|
143
|
+
get :logout
|
144
|
+
assert session[@jwt_key].nil?
|
145
|
+
assert response.code == "302"
|
146
|
+
assert_equal "//id.prx.test/session/sign_out", response.location
|
147
|
+
end
|
148
|
+
|
149
|
+
test "refreshes auth" do
|
150
|
+
session[@jwt_key] = "some-token"
|
151
|
+
get :refresh
|
152
|
+
assert session[@jwt_key].nil?
|
153
|
+
assert response.code == "302"
|
154
|
+
assert_includes response.location, new_sessions_path
|
155
|
+
end
|
156
|
+
|
157
|
+
test "refreshes wildcard auth for admins" do
|
158
|
+
@controller.stub(:current_user_admin?, true) do
|
159
|
+
session[@jwt_key] = "some-token"
|
160
|
+
get :refresh, params: {wildcard: true}
|
161
|
+
assert session[@jwt_key].nil?
|
162
|
+
assert session[@wildcard_key] = "true"
|
163
|
+
assert response.code == "302"
|
164
|
+
assert_includes response.location, new_sessions_path
|
165
|
+
end
|
121
166
|
end
|
122
167
|
end
|
123
168
|
end
|
@@ -0,0 +1,71 @@
|
|
1
|
+
require "test_helper"
|
2
|
+
|
3
|
+
class TestHelper
|
4
|
+
attr_accessor :current_user, :current_user_apps, :current_user_info
|
5
|
+
include PrxAuth::Rails::SessionsHelper
|
6
|
+
end
|
7
|
+
|
8
|
+
describe PrxAuth::Rails::SessionsHelper do
|
9
|
+
let(:helper) { TestHelper.new }
|
10
|
+
|
11
|
+
describe "#current_user_app?" do
|
12
|
+
it "makes sure there is a current user" do
|
13
|
+
helper.current_user = nil
|
14
|
+
refute helper.current_user_app?("foo")
|
15
|
+
refute helper.current_user_app?("bar")
|
16
|
+
end
|
17
|
+
|
18
|
+
it "determines if you have an app or not" do
|
19
|
+
helper.current_user = {}
|
20
|
+
helper.current_user_apps = {
|
21
|
+
"app for BAR" => "https://bar.prx.org",
|
22
|
+
"and then BAZ" => "https://baz.staging.prx.tech"
|
23
|
+
}
|
24
|
+
|
25
|
+
refute helper.current_user_app?("foo")
|
26
|
+
assert helper.current_user_app?("bar")
|
27
|
+
assert helper.current_user_app?("baz")
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
describe "#current_user_app" do
|
32
|
+
it "returns app urls" do
|
33
|
+
helper.current_user = {}
|
34
|
+
helper.current_user_apps = {
|
35
|
+
"dev domain" => "https://foo.prx.dev",
|
36
|
+
"real Bar domain" => "https://bar.prx.org",
|
37
|
+
"staging Baz domain" => "https://baz.staging.prx.tech"
|
38
|
+
}
|
39
|
+
|
40
|
+
assert_nil helper.current_user_app("foo")
|
41
|
+
assert_equal "https://bar.prx.org", helper.current_user_app("bar")
|
42
|
+
assert_equal "https://baz.staging.prx.tech", helper.current_user_app("baz")
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
describe "#current_user_id_profile" do
|
47
|
+
it "returns the ID host" do
|
48
|
+
assert_includes helper.current_user_id_profile, PrxAuth::Rails.configuration.id_host
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
describe "#current_user_image?" do
|
53
|
+
it "checks if the user has an image" do
|
54
|
+
refute helper.current_user_image?
|
55
|
+
|
56
|
+
helper.current_user = {}
|
57
|
+
helper.current_user_info = {"image_href" => ""}
|
58
|
+
refute helper.current_user_image?
|
59
|
+
|
60
|
+
helper.current_user_info = {"image_href" => "http://some.where/img"}
|
61
|
+
assert helper.current_user_image?
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
describe "#current_user_image" do
|
66
|
+
it "returns the user image url" do
|
67
|
+
helper.current_user_info = {"image_href" => "http://some.where/img"}
|
68
|
+
assert_equal "http://some.where/img", helper.current_user_image
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: prx_auth-rails
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 5.0.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Chris Rhoden
|
8
8
|
bindir: bin
|
9
9
|
cert_chain: []
|
10
|
-
date: 2025-
|
10
|
+
date: 2025-04-08 00:00:00.000000000 Z
|
11
11
|
dependencies:
|
12
12
|
- !ruby/object:Gem::Dependency
|
13
13
|
name: actionpack
|
@@ -207,6 +207,8 @@ files:
|
|
207
207
|
- README.md
|
208
208
|
- Rakefile
|
209
209
|
- app/controllers/prx_auth/rails/sessions_controller.rb
|
210
|
+
- app/helpers/prx_auth/rails/sessions_helper.rb
|
211
|
+
- app/views/prx_auth/rails/sessions/access_error.html.erb
|
210
212
|
- app/views/prx_auth/rails/sessions/auth_error.html.erb
|
211
213
|
- app/views/prx_auth/rails/sessions/show.html.erb
|
212
214
|
- config/initializers/assets.rb
|
@@ -215,6 +217,8 @@ files:
|
|
215
217
|
- lib/prx_auth/rails/configuration.rb
|
216
218
|
- lib/prx_auth/rails/engine.rb
|
217
219
|
- lib/prx_auth/rails/ext/controller.rb
|
220
|
+
- lib/prx_auth/rails/ext/controller/account_info.rb
|
221
|
+
- lib/prx_auth/rails/ext/controller/user_info.rb
|
218
222
|
- lib/prx_auth/rails/railtie.rb
|
219
223
|
- lib/prx_auth/rails/token.rb
|
220
224
|
- lib/prx_auth/rails/version.rb
|
@@ -279,6 +283,7 @@ files:
|
|
279
283
|
- test/prx_auth/rails/configuration_test.rb
|
280
284
|
- test/prx_auth/rails/ext/controller_test.rb
|
281
285
|
- test/prx_auth/rails/sessions_controller_test.rb
|
286
|
+
- test/prx_auth/rails/sessions_helper_test.rb
|
282
287
|
- test/prx_auth/rails/token_test.rb
|
283
288
|
- test/prx_auth/rails_test.rb
|
284
289
|
- test/test_helper.rb
|