prx_auth-rails 1.3.0 → 1.7.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/app/assets/config/prx_auth-rails_manifest.js +3 -0
- data/app/assets/images/prx_auth-rails/user.svg +5 -0
- data/app/assets/javascripts/prx_auth-rails/user_widget.js.erb +46 -0
- data/app/assets/stylesheets/prx_auth-rails/user_widget.css +69 -0
- data/app/controllers/prx_auth/rails/sessions_controller.rb +16 -3
- data/config/initializers/assets.rb +1 -0
- data/lib/prx_auth/rails/engine.rb +5 -1
- data/lib/prx_auth/rails/ext/controller.rb +54 -2
- data/lib/prx_auth/rails/version.rb +1 -1
- data/test/prx_auth/rails/sessions_controller_test.rb +25 -15
- 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: 9a692b8cc459acfdf888599245ff2db7d7ed92a3c967fbccacdd871aa4e78cd7
|
4
|
+
data.tar.gz: 17439da5ec7e7cc7f85d00083a47aaebb6d6bd495db25fa75581bf0758726d6c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 2a185d858e8a50a33e1f18c85e7dabf5f01a46fbc068dd74d222bb48ab03732ced79c60affd45f7e70efd628cfaaf259e9d4781c390470de86a06dd46158bf0c
|
7
|
+
data.tar.gz: d8f2b9c1c1367c2954575950f1ddc731f329f59d111efcb11282d78651a06cf22c74557f834d51ff6fa3ca7360d1cb06ad4736cd2a41d0ff28c5554913fcc193
|
@@ -0,0 +1,5 @@
|
|
1
|
+
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
2
|
+
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
3
|
+
<svg width="100%" height="100%" viewBox="0 0 51 51" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" xmlns:serif="http://www.serif.com/" style="fill-rule:evenodd;clip-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:1.41421;">
|
4
|
+
<path d="M51,25.5C51,11.44 39.56,0 25.5,0C11.44,0 0,11.44 0,25.5C0,32.927 3.194,39.621 8.277,44.285L8.253,44.306L9.08,45.003C9.134,45.049 9.192,45.086 9.246,45.13C9.685,45.495 10.141,45.841 10.604,46.175C10.755,46.284 10.905,46.392 11.058,46.498C11.553,46.839 12.061,47.163 12.58,47.47C12.693,47.537 12.807,47.602 12.922,47.666C13.49,47.99 14.07,48.295 14.665,48.575C14.708,48.596 14.753,48.614 14.796,48.635C16.734,49.535 18.801,50.196 20.964,50.586C21.02,50.597 21.077,50.607 21.134,50.617C21.806,50.733 22.485,50.826 23.172,50.888C23.255,50.895 23.339,50.9 23.423,50.907C24.107,50.964 24.799,51 25.5,51C26.195,51 26.88,50.964 27.56,50.909C27.647,50.902 27.733,50.897 27.819,50.89C28.501,50.828 29.174,50.738 29.839,50.624C29.896,50.613 29.955,50.603 30.012,50.592C32.142,50.21 34.18,49.564 36.092,48.686C36.163,48.654 36.234,48.623 36.305,48.59C36.877,48.321 37.436,48.031 37.984,47.722C38.12,47.645 38.256,47.567 38.391,47.487C38.89,47.194 39.38,46.887 39.857,46.56C40.029,46.443 40.196,46.32 40.366,46.198C40.773,45.905 41.173,45.602 41.561,45.286C41.648,45.217 41.74,45.156 41.825,45.085L42.673,44.376L42.648,44.355C47.776,39.689 51,32.965 51,25.5ZM1.855,25.5C1.855,12.462 12.462,1.855 25.5,1.855C38.538,1.855 49.145,12.462 49.145,25.5C49.145,32.526 46.062,38.843 41.181,43.177C40.908,42.988 40.634,42.82 40.353,42.679L32.502,38.754C31.797,38.401 31.359,37.693 31.359,36.905L31.359,34.164C31.541,33.939 31.733,33.685 31.932,33.406C32.948,31.971 33.763,30.374 34.357,28.656C35.532,28.097 36.291,26.927 36.291,25.606L36.291,22.319C36.291,21.515 35.996,20.735 35.468,20.122L35.468,15.794C35.516,15.312 35.687,12.597 33.722,10.357C32.013,8.406 29.247,7.418 25.5,7.418C21.753,7.418 18.987,8.406 17.278,10.356C15.313,12.596 15.484,15.313 15.532,15.793L15.532,20.121C15.005,20.734 14.709,21.514 14.709,22.318L14.709,25.605C14.709,26.626 15.167,27.578 15.952,28.221C16.703,31.163 18.249,33.39 18.82,34.145L18.82,36.828C18.82,37.585 18.407,38.281 17.742,38.644L10.41,42.643C10.177,42.77 9.945,42.919 9.713,43.085C4.892,38.753 1.855,32.475 1.855,25.5Z" style="fill:white;fill-rule:nonzero;"/>
|
5
|
+
</svg>
|
@@ -0,0 +1,46 @@
|
|
1
|
+
// https://stackoverflow.com/questions/8578617/inject-a-script-tag-with-remote-src-and-wait-for-it-to-execute
|
2
|
+
function prxInjectScript(src, callback) {
|
3
|
+
const script = document.createElement('script');
|
4
|
+
|
5
|
+
script.type = 'text/javascript';
|
6
|
+
script.async = false;
|
7
|
+
script.src = src;
|
8
|
+
|
9
|
+
script.onload = function () { script.onload = null; callback(); }
|
10
|
+
|
11
|
+
document.getElementsByTagName('head')[0].appendChild(script);
|
12
|
+
}
|
13
|
+
|
14
|
+
document.addEventListener('DOMContentLoaded', function () {
|
15
|
+
|
16
|
+
const widget = document.getElementById('prx-user-widget');
|
17
|
+
const account = document.getElementById('prx-user-widget-menu-account');
|
18
|
+
|
19
|
+
const idHost = 'https://' + widget.getAttribute('data-id-host');;
|
20
|
+
const scriptUrl = idHost + '/widget.js';
|
21
|
+
|
22
|
+
prxInjectScript(scriptUrl, function () {
|
23
|
+
const signIn = new PRXSignIn(idHost);
|
24
|
+
|
25
|
+
signIn.signedIn(function (prx) {
|
26
|
+
|
27
|
+
if (!prx.userinfo) {
|
28
|
+
// Not logged in
|
29
|
+
widget.classList.add('no-user-info');
|
30
|
+
|
31
|
+
const url = idHost + '/session?return_to=' + encodeURIComponent(window.location);
|
32
|
+
|
33
|
+
account.innerHTML = '<a class=sign-in href="' + url + '">Sign in</a>';
|
34
|
+
} else {
|
35
|
+
// Logged in
|
36
|
+
widget.classList.add('user-info');
|
37
|
+
|
38
|
+
const account = document.getElementById('prx-user-widget-menu-account');
|
39
|
+
account.innerText = prx.userinfo.email;
|
40
|
+
|
41
|
+
signIn.listApps('prx-user-widget-menu-apps');
|
42
|
+
}
|
43
|
+
});
|
44
|
+
});
|
45
|
+
});
|
46
|
+
|
@@ -0,0 +1,69 @@
|
|
1
|
+
#prx-user-widget {
|
2
|
+
display: flex;
|
3
|
+
flex-direction: column;
|
4
|
+
height: 100%;
|
5
|
+
justify-content: center;
|
6
|
+
padding: 0 20px;
|
7
|
+
position: absolute;
|
8
|
+
right: 0;
|
9
|
+
transition-property: opacity;
|
10
|
+
transition-duration: 0.2s;
|
11
|
+
}
|
12
|
+
@media (max-width: ) {
|
13
|
+
#prx-user-widget {
|
14
|
+
height: auto;
|
15
|
+
top: 0;
|
16
|
+
}
|
17
|
+
}
|
18
|
+
#prx-user-widget:hover {
|
19
|
+
}
|
20
|
+
#prx-user-widget:hover .user-icon {
|
21
|
+
opacity: 1;
|
22
|
+
}
|
23
|
+
#prx-user-widget:hover #prx-user-widget-menu {
|
24
|
+
display: block;
|
25
|
+
}
|
26
|
+
#prx-user-widget .user-icon {
|
27
|
+
cursor: pointer;
|
28
|
+
height: 2em;
|
29
|
+
opacity: 0.7;
|
30
|
+
width: 2em;
|
31
|
+
}
|
32
|
+
#prx-user-widget #prx-user-widget-menu {
|
33
|
+
background-color: #1a1a1a;
|
34
|
+
display: none;
|
35
|
+
right: 0;
|
36
|
+
padding: 10px 20px;
|
37
|
+
position: absolute;
|
38
|
+
top: 100%;
|
39
|
+
z-index: 999;
|
40
|
+
display: none;
|
41
|
+
}
|
42
|
+
|
43
|
+
#prx-user-widget #prx-user-widget-menu h1 {
|
44
|
+
color: white;
|
45
|
+
font-size: .9em;
|
46
|
+
font-weight: 700;
|
47
|
+
}
|
48
|
+
|
49
|
+
#prx-user-widget #prx-user-widget-menu-apps {
|
50
|
+
padding: 0;
|
51
|
+
}
|
52
|
+
#prx-user-widget #prx-user-widget-menu-apps ul {
|
53
|
+
border-top: 1px solid #ddd;
|
54
|
+
padding: 15px 0 0;
|
55
|
+
}
|
56
|
+
|
57
|
+
#prx-user-widget #prx-user-widget-menu-apps ul li a {
|
58
|
+
display: block;
|
59
|
+
font-weight: normal;
|
60
|
+
opacity: 0.7;
|
61
|
+
padding: 5px 0;
|
62
|
+
text-transform: none;
|
63
|
+
}
|
64
|
+
#prx-user-widget #prx-user-widget-menu-apps ul li a:hover {
|
65
|
+
opacity: 1;
|
66
|
+
}
|
67
|
+
.prx-home #prx-user-widget.loaded:hover {
|
68
|
+
background: transparent;
|
69
|
+
}
|
@@ -1,5 +1,3 @@
|
|
1
|
-
require 'open-uri'
|
2
|
-
|
3
1
|
module PrxAuth::Rails
|
4
2
|
class SessionsController < ApplicationController
|
5
3
|
include PrxAuth::Rails::Engine.routes.url_helpers
|
@@ -29,6 +27,11 @@ module PrxAuth::Rails
|
|
29
27
|
def show
|
30
28
|
end
|
31
29
|
|
30
|
+
def destroy
|
31
|
+
sign_out_user
|
32
|
+
redirect_to after_sign_out_path
|
33
|
+
end
|
34
|
+
|
32
35
|
def auth_error
|
33
36
|
@auth_error_message = params.require(:error)
|
34
37
|
end
|
@@ -42,6 +45,7 @@ module PrxAuth::Rails
|
|
42
45
|
result_path = if valid_nonce?(jwt_id_claims['nonce']) &&
|
43
46
|
users_match?(jwt_id_claims, jwt_access_claims)
|
44
47
|
sign_in_user(jwt_access_claims)
|
48
|
+
lookup_and_register_accounts_names
|
45
49
|
after_sign_in_path_for(current_user)
|
46
50
|
else
|
47
51
|
auth_error_sessions_path(error: 'verification_failed')
|
@@ -59,6 +63,12 @@ module PrxAuth::Rails
|
|
59
63
|
"/"
|
60
64
|
end
|
61
65
|
|
66
|
+
def after_sign_out_path
|
67
|
+
return super if defined?(super)
|
68
|
+
|
69
|
+
"https://#{id_host}/session/sign_out"
|
70
|
+
end
|
71
|
+
|
62
72
|
def id_claims
|
63
73
|
id_token = params.require('id_token')
|
64
74
|
validate_token(id_token)
|
@@ -97,12 +107,15 @@ module PrxAuth::Rails
|
|
97
107
|
end
|
98
108
|
|
99
109
|
def validate_token(token)
|
100
|
-
id_host = PrxAuth::Rails.configuration.id_host
|
101
110
|
prx_auth_cert = Rack::PrxAuth::Certificate.new("https://#{id_host}/api/v1/certs")
|
102
111
|
auth_validator = Rack::PrxAuth::AuthValidator.new(token, prx_auth_cert, id_host)
|
103
112
|
auth_validator.
|
104
113
|
claims.
|
105
114
|
with_indifferent_access
|
106
115
|
end
|
116
|
+
|
117
|
+
def id_host
|
118
|
+
PrxAuth::Rails.configuration.id_host
|
119
|
+
end
|
107
120
|
end
|
108
121
|
end
|
@@ -0,0 +1 @@
|
|
1
|
+
Rails.application.config.assets.precompile << %w(prx_auth-rails_manifest.js)
|
@@ -1,13 +1,18 @@
|
|
1
1
|
require 'prx_auth/rails/token'
|
2
|
+
require 'open-uri'
|
2
3
|
|
3
4
|
module PrxAuth
|
4
5
|
module Rails
|
5
6
|
module Controller
|
7
|
+
|
8
|
+
PRX_ACCOUNT_NAME_MAPPING_KEY = 'prx.account.name.mapping'.freeze
|
9
|
+
PRX_TOKEN_SESSION_KEY = 'prx.auth'.freeze
|
10
|
+
|
6
11
|
def prx_auth_token
|
7
12
|
rack_auth_token = env_prx_auth_token
|
8
13
|
return rack_auth_token if rack_auth_token.present?
|
9
14
|
|
10
|
-
session[
|
15
|
+
session[PRX_TOKEN_SESSION_KEY] && Rack::PrxAuth::TokenData.new(session[PRX_TOKEN_SESSION_KEY])
|
11
16
|
end
|
12
17
|
|
13
18
|
def prx_authenticated?
|
@@ -26,12 +31,59 @@ module PrxAuth
|
|
26
31
|
PrxAuth::Rails::Token.new(prx_auth_token)
|
27
32
|
end
|
28
33
|
|
34
|
+
def lookup_and_register_accounts_names
|
35
|
+
session[PRX_ACCOUNT_NAME_MAPPING_KEY] =
|
36
|
+
lookup_account_names_mapping
|
37
|
+
end
|
38
|
+
|
39
|
+
def account_name_for(id)
|
40
|
+
id = id.to_i
|
41
|
+
|
42
|
+
session[PRX_ACCOUNT_NAME_MAPPING_KEY] ||= {}
|
43
|
+
|
44
|
+
name =
|
45
|
+
if session[PRX_ACCOUNT_NAME_MAPPING_KEY].has_key?(id)
|
46
|
+
session[PRX_ACCOUNT_NAME_MAPPING_KEY][id]
|
47
|
+
else
|
48
|
+
session[PRX_ACCOUNT_NAME_MAPPING_KEY][id] = lookup_account_name_for(id)
|
49
|
+
end
|
50
|
+
|
51
|
+
name = "[#{id}] Unknown Account Name" unless name.present?
|
52
|
+
|
53
|
+
name
|
54
|
+
end
|
55
|
+
|
29
56
|
def sign_in_user(token)
|
30
|
-
session[
|
57
|
+
session[PRX_TOKEN_SESSION_KEY] = token
|
58
|
+
end
|
59
|
+
|
60
|
+
def sign_out_user
|
61
|
+
session.delete(PRX_TOKEN_SESSION_KEY)
|
31
62
|
end
|
32
63
|
|
33
64
|
private
|
34
65
|
|
66
|
+
def lookup_account_name_for(id)
|
67
|
+
id = id.to_i
|
68
|
+
|
69
|
+
res = lookup_account_names_mapping([id])
|
70
|
+
res[id]
|
71
|
+
end
|
72
|
+
|
73
|
+
def lookup_account_names_mapping(ids=current_user.resources)
|
74
|
+
id_host = PrxAuth::Rails.configuration.id_host
|
75
|
+
ids_param = ids.map(&:to_s).join(',')
|
76
|
+
|
77
|
+
options = {}
|
78
|
+
options[:ssl_verify_mode] = OpenSSL::SSL::VERIFY_NONE if ::Rails.env.development?
|
79
|
+
|
80
|
+
accounts = URI.open("https://#{id_host}/api/v1/accounts?account_ids=#{ids_param}", options).read
|
81
|
+
|
82
|
+
mapping = JSON.parse(accounts)['accounts'].map { |acct| [acct['id'], acct['display_name']] }.to_h
|
83
|
+
|
84
|
+
mapping
|
85
|
+
end
|
86
|
+
|
35
87
|
def env_prx_auth_token
|
36
88
|
if !defined? @_prx_auth_token
|
37
89
|
@_prx_auth_token = request.env['prx.auth'] && PrxAuth::Rails::Token.new(request.env['prx.auth'])
|
@@ -32,9 +32,11 @@ module PrxAuth::Rails
|
|
32
32
|
|
33
33
|
test 'create should validate a token and set the session variable' do
|
34
34
|
@controller.stub(:validate_token, @stub_claims) do
|
35
|
-
|
36
|
-
|
37
|
-
|
35
|
+
@controller.stub(:lookup_and_register_accounts_names, nil) do
|
36
|
+
session[@nonce_session_key] = '123'
|
37
|
+
post :create, params: @token_params, format: :json
|
38
|
+
assert session['prx.auth']['id_token']['nonce'] == '123'
|
39
|
+
end
|
38
40
|
end
|
39
41
|
end
|
40
42
|
|
@@ -48,16 +50,18 @@ module PrxAuth::Rails
|
|
48
50
|
|
49
51
|
test 'create should reset the nonce after consumed' do
|
50
52
|
@controller.stub(:validate_token, @stub_claims) do
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
53
|
+
@controller.stub(:lookup_and_register_accounts_names, nil) do
|
54
|
+
session[@nonce_session_key] = '123'
|
55
|
+
post :create, params: @token_params, format: :json
|
56
|
+
|
57
|
+
assert session[@nonce_session_key] == nil
|
58
|
+
assert response.code == '302'
|
59
|
+
assert response.body.match?(/after-sign-in-path/)
|
60
|
+
end
|
57
61
|
end
|
58
62
|
end
|
59
63
|
|
60
|
-
test 'should respond with
|
64
|
+
test 'should respond with redirect to the auth error page / code if the nonce does not match' do
|
61
65
|
@controller.stub(:validate_token, @stub_claims) do
|
62
66
|
session[@nonce_session_key] = 'nonce-does-not-match'
|
63
67
|
post :create, params: @token_params, format: :json
|
@@ -82,13 +86,19 @@ module PrxAuth::Rails
|
|
82
86
|
@controller.stub(:id_claims, @stub_claims) do
|
83
87
|
@controller.stub(:access_claims, @stub_claims.merge('sub' => '444')) do
|
84
88
|
|
85
|
-
|
86
|
-
|
89
|
+
session[@nonce_session_key] = '123'
|
90
|
+
post :create, params: @token_params, format: :json
|
87
91
|
|
88
|
-
|
89
|
-
|
90
|
-
|
92
|
+
assert response.code == '302'
|
93
|
+
assert response.body.match?(/error=verification_failed/)
|
94
|
+
end
|
91
95
|
end
|
92
96
|
end
|
97
|
+
|
98
|
+
test 'should clear the user token on sign out' do
|
99
|
+
session[PrxAuth::Rails::Controller::PRX_TOKEN_SESSION_KEY] = 'some-token'
|
100
|
+
post :destroy
|
101
|
+
assert session[PrxAuth::Rails::Controller::PRX_TOKEN_SESSION_KEY] == nil
|
102
|
+
end
|
93
103
|
end
|
94
104
|
end
|
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: 1.
|
4
|
+
version: 1.7.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-01
|
11
|
+
date: 2021-03-01 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: actionpack
|
@@ -165,9 +165,14 @@ files:
|
|
165
165
|
- LICENSE.txt
|
166
166
|
- README.md
|
167
167
|
- Rakefile
|
168
|
+
- app/assets/config/prx_auth-rails_manifest.js
|
169
|
+
- app/assets/images/prx_auth-rails/user.svg
|
170
|
+
- app/assets/javascripts/prx_auth-rails/user_widget.js.erb
|
171
|
+
- app/assets/stylesheets/prx_auth-rails/user_widget.css
|
168
172
|
- app/controllers/prx_auth/rails/sessions_controller.rb
|
169
173
|
- app/views/prx_auth/rails/sessions/auth_error.html.erb
|
170
174
|
- app/views/prx_auth/rails/sessions/show.html.erb
|
175
|
+
- config/initializers/assets.rb
|
171
176
|
- config/routes.rb
|
172
177
|
- lib/prx_auth/rails.rb
|
173
178
|
- lib/prx_auth/rails/configuration.rb
|