prx_auth-rails 4.2.1 → 5.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/.github/workflows/check-project-std.yml +1 -1
- data/app/controllers/prx_auth/rails/sessions_controller.rb +30 -16
- 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/initializers/assets.rb +3 -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/prx_auth-rails.gemspec +1 -1
- data/test/dummy/app/controllers/application_controller.rb +0 -2
- data/test/dummy/config/initializers/assets.rb +1 -1
- 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 +55 -10
- data/test/prx_auth/rails/sessions_helper_test.rb +71 -0
- data/test/prx_auth/rails_test.rb +2 -2
- metadata +10 -8
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: bf94b7a4117fd51ed8b81e97822613f25ef10d9cd634b2d5d976809c2e50c281
|
4
|
+
data.tar.gz: 4830822f96f9526bdf828b611ed1d4920a4919f27feed31ac259b51c32777516
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 8cdfcac52bffd86c335598f97fe76d93acceba591d4b709493374f7776eaf2eb7c10c1f4c57de17e0dbb6c40246fbb84c085972bd2d1e9800aacf73b1da0017a
|
7
|
+
data.tar.gz: e28b6dc7e0255a764ca7eb9469b7f28d8727f9804fd6a750e9905c2fe11799935665d6b67bee441c8bb2081bb3c5f4f58e642336e634d55f74d9974ff4d0fd61
|
@@ -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"
|
13
|
-
|
10
|
+
WILDCARD_SESSION_KEY = "prx.auth.wildcard"
|
11
|
+
DEFAULT_SCOPES = "openid"
|
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
|
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", except:
|
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/prx_auth-rails.gemspec
CHANGED
@@ -26,7 +26,7 @@ Gem::Specification.new do |spec|
|
|
26
26
|
spec.add_development_dependency "guard"
|
27
27
|
spec.add_development_dependency "guard-minitest"
|
28
28
|
spec.add_development_dependency "m", "~> 1.5"
|
29
|
-
spec.add_development_dependency "rails", "~>
|
29
|
+
spec.add_development_dependency "rails", "~> 8.0.1"
|
30
30
|
spec.add_development_dependency "pry"
|
31
31
|
spec.add_development_dependency "sqlite3"
|
32
32
|
spec.add_development_dependency "webmock"
|
@@ -1,7 +1,7 @@
|
|
1
1
|
# Be sure to restart your server when you modify this file.
|
2
2
|
|
3
3
|
# Version of your assets, change this if you want to expire all your assets.
|
4
|
-
Rails.application.config.assets.version = "1.0"
|
4
|
+
# Rails.application.config.assets.version = "1.0"
|
5
5
|
|
6
6
|
# Add additional assets to the asset load path.
|
7
7
|
# Rails.application.config.assets.paths << Emoji.images_path
|
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+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
|
@@ -58,7 +76,7 @@ module PrxAuth::Rails
|
|
58
76
|
|
59
77
|
assert session[@nonce_session_key].nil?
|
60
78
|
assert response.code == "302"
|
61
|
-
assert response.
|
79
|
+
assert response.headers["Location"].match?(/after-sign-in-path/)
|
62
80
|
end
|
63
81
|
end
|
64
82
|
end
|
@@ -85,14 +103,14 @@ module PrxAuth::Rails
|
|
85
103
|
session[@nonce_session_key] = "nonce-does-not-match"
|
86
104
|
post :create, params: @token_params, format: :json
|
87
105
|
assert response.code == "302"
|
88
|
-
assert response.
|
106
|
+
assert response.headers["Location"].match(/auth_error\?error=verification_failed/)
|
89
107
|
end
|
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
|
@@ -109,15 +127,42 @@ module PrxAuth::Rails
|
|
109
127
|
post :create, params: @token_params, format: :json
|
110
128
|
|
111
129
|
assert response.code == "302"
|
112
|
-
assert response.
|
130
|
+
assert response.headers["Location"].match?(/error=verification_failed/)
|
113
131
|
end
|
114
132
|
end
|
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
|
data/test/prx_auth/rails_test.rb
CHANGED
@@ -12,7 +12,7 @@ describe PrxAuth::Rails do
|
|
12
12
|
end
|
13
13
|
|
14
14
|
it "installs and configures prx_auth middleware" do
|
15
|
-
mw =
|
15
|
+
mw = Minitest::Mock.new
|
16
16
|
mw.expect :insert_after, nil do |c1, c2, cert_location:, issuer:|
|
17
17
|
assert_equal Rack::Head, c1
|
18
18
|
assert_equal Rack::PrxAuth, c2
|
@@ -20,7 +20,7 @@ describe PrxAuth::Rails do
|
|
20
20
|
assert_equal "id.prx.test", issuer
|
21
21
|
end
|
22
22
|
|
23
|
-
app =
|
23
|
+
app = Minitest::Mock.new
|
24
24
|
app.expect :middleware, mw
|
25
25
|
|
26
26
|
subject.install_middleware!(app)
|
metadata
CHANGED
@@ -1,14 +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.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Chris Rhoden
|
8
|
-
autorequire:
|
9
8
|
bindir: bin
|
10
9
|
cert_chain: []
|
11
|
-
date:
|
10
|
+
date: 2025-04-07 00:00:00.000000000 Z
|
12
11
|
dependencies:
|
13
12
|
- !ruby/object:Gem::Dependency
|
14
13
|
name: actionpack
|
@@ -114,14 +113,14 @@ dependencies:
|
|
114
113
|
requirements:
|
115
114
|
- - "~>"
|
116
115
|
- !ruby/object:Gem::Version
|
117
|
-
version:
|
116
|
+
version: 8.0.1
|
118
117
|
type: :development
|
119
118
|
prerelease: false
|
120
119
|
version_requirements: !ruby/object:Gem::Requirement
|
121
120
|
requirements:
|
122
121
|
- - "~>"
|
123
122
|
- !ruby/object:Gem::Version
|
124
|
-
version:
|
123
|
+
version: 8.0.1
|
125
124
|
- !ruby/object:Gem::Dependency
|
126
125
|
name: pry
|
127
126
|
requirement: !ruby/object:Gem::Requirement
|
@@ -208,6 +207,8 @@ files:
|
|
208
207
|
- README.md
|
209
208
|
- Rakefile
|
210
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
|
211
212
|
- app/views/prx_auth/rails/sessions/auth_error.html.erb
|
212
213
|
- app/views/prx_auth/rails/sessions/show.html.erb
|
213
214
|
- config/initializers/assets.rb
|
@@ -216,6 +217,8 @@ files:
|
|
216
217
|
- lib/prx_auth/rails/configuration.rb
|
217
218
|
- lib/prx_auth/rails/engine.rb
|
218
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
|
219
222
|
- lib/prx_auth/rails/railtie.rb
|
220
223
|
- lib/prx_auth/rails/token.rb
|
221
224
|
- lib/prx_auth/rails/version.rb
|
@@ -280,6 +283,7 @@ files:
|
|
280
283
|
- test/prx_auth/rails/configuration_test.rb
|
281
284
|
- test/prx_auth/rails/ext/controller_test.rb
|
282
285
|
- test/prx_auth/rails/sessions_controller_test.rb
|
286
|
+
- test/prx_auth/rails/sessions_helper_test.rb
|
283
287
|
- test/prx_auth/rails/token_test.rb
|
284
288
|
- test/prx_auth/rails_test.rb
|
285
289
|
- test/test_helper.rb
|
@@ -287,7 +291,6 @@ homepage: https://github.com/PRX/prx_auth-rails
|
|
287
291
|
licenses:
|
288
292
|
- MIT
|
289
293
|
metadata: {}
|
290
|
-
post_install_message:
|
291
294
|
rdoc_options: []
|
292
295
|
require_paths:
|
293
296
|
- lib
|
@@ -302,8 +305,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
302
305
|
- !ruby/object:Gem::Version
|
303
306
|
version: '0'
|
304
307
|
requirements: []
|
305
|
-
rubygems_version: 3.
|
306
|
-
signing_key:
|
308
|
+
rubygems_version: 3.6.2
|
307
309
|
specification_version: 4
|
308
310
|
summary: Rails integration for next generation PRX Authorization system.
|
309
311
|
test_files: []
|