prx_auth-rails 1.2.0 → 1.3.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/.gitignore +4 -0
- data/README.md +25 -6
- data/Rakefile +12 -4
- data/app/controllers/prx_auth/rails/sessions_controller.rb +108 -0
- data/app/views/prx_auth/rails/sessions/auth_error.html.erb +15 -0
- data/app/views/prx_auth/rails/sessions/show.html.erb +38 -0
- data/config/routes.rb +7 -0
- data/lib/prx_auth/rails.rb +1 -0
- data/lib/prx_auth/rails/configuration.rb +15 -4
- data/lib/prx_auth/rails/engine.rb +5 -0
- data/lib/prx_auth/rails/ext/controller.rb +29 -4
- data/lib/prx_auth/rails/token.rb +5 -1
- data/lib/prx_auth/rails/version.rb +1 -1
- data/prx_auth-rails.gemspec +3 -1
- data/test/dummy/Rakefile +6 -0
- data/test/dummy/app/assets/config/manifest.js +2 -0
- data/test/dummy/app/assets/images/.keep +0 -0
- data/test/dummy/app/assets/stylesheets/application.css +15 -0
- data/test/dummy/app/channels/application_cable/channel.rb +4 -0
- data/test/dummy/app/channels/application_cable/connection.rb +4 -0
- data/test/dummy/app/controllers/application_controller.rb +8 -0
- data/test/dummy/app/controllers/concerns/.keep +0 -0
- data/test/dummy/app/helpers/application_helper.rb +2 -0
- data/test/dummy/app/javascript/packs/application.js +15 -0
- data/test/dummy/app/jobs/application_job.rb +7 -0
- data/test/dummy/app/mailers/application_mailer.rb +4 -0
- data/test/dummy/app/models/application_record.rb +3 -0
- data/test/dummy/app/models/concerns/.keep +0 -0
- data/test/dummy/app/views/layouts/application.html.erb +15 -0
- data/test/dummy/app/views/layouts/mailer.html.erb +13 -0
- data/test/dummy/app/views/layouts/mailer.text.erb +1 -0
- data/test/dummy/bin/rails +5 -0
- data/test/dummy/bin/rake +5 -0
- data/test/dummy/bin/setup +33 -0
- data/test/dummy/bin/spring +10 -0
- data/test/dummy/config.ru +6 -0
- data/test/dummy/config/application.rb +22 -0
- data/test/dummy/config/boot.rb +5 -0
- data/test/dummy/config/cable.yml +10 -0
- data/test/dummy/config/database.yml +25 -0
- data/test/dummy/config/environment.rb +5 -0
- data/test/dummy/config/environments/development.rb +76 -0
- data/test/dummy/config/environments/production.rb +120 -0
- data/test/dummy/config/environments/test.rb +60 -0
- data/test/dummy/config/initializers/application_controller_renderer.rb +8 -0
- data/test/dummy/config/initializers/assets.rb +12 -0
- data/test/dummy/config/initializers/backtrace_silencers.rb +8 -0
- data/test/dummy/config/initializers/content_security_policy.rb +28 -0
- data/test/dummy/config/initializers/cookies_serializer.rb +5 -0
- data/test/dummy/config/initializers/filter_parameter_logging.rb +6 -0
- data/test/dummy/config/initializers/inflections.rb +16 -0
- data/test/dummy/config/initializers/mime_types.rb +4 -0
- data/test/dummy/config/initializers/permissions_policy.rb +11 -0
- data/test/dummy/config/initializers/prx_auth.rb +8 -0
- data/test/dummy/config/initializers/wrap_parameters.rb +14 -0
- data/test/dummy/config/locales/en.yml +33 -0
- data/test/dummy/config/puma.rb +43 -0
- data/test/dummy/config/routes.rb +3 -0
- data/test/dummy/config/spring.rb +6 -0
- data/test/dummy/config/storage.yml +34 -0
- data/test/dummy/lib/assets/.keep +0 -0
- data/test/dummy/log/.keep +0 -0
- data/test/dummy/public/404.html +67 -0
- data/test/dummy/public/422.html +67 -0
- data/test/dummy/public/500.html +66 -0
- data/test/dummy/public/apple-touch-icon-precomposed.png +0 -0
- data/test/dummy/public/apple-touch-icon.png +0 -0
- data/test/dummy/public/favicon.ico +0 -0
- data/test/dummy/storage/.keep +0 -0
- data/test/prx_auth/rails/configuration_test.rb +18 -12
- data/test/prx_auth/rails/sessions_controller_test.rb +94 -0
- data/test/prx_auth/rails/token_test.rb +1 -1
- data/test/test_helper.rb +20 -9
- metadata +153 -7
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 3405e4e72d2c39585111bef4fca339a73ce11ec86a2c288f5c82d8934c0620fe
|
4
|
+
data.tar.gz: 3450063f4c4fdae2464f755222fafee08c627eda3aa8fee1d267db1474db58de
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: edf33f5cf4bc105818bb069554506f0b2d9ef5b8bb18cd1602b2ceb6384991804b5b3268c6bd5c519c08e8503df51c132a9bec045f13995c1d55088194fff489
|
7
|
+
data.tar.gz: 4aa62706ee892c2335756e2c3ae61171b77acc69bfe0ec06433449726f8e884cee4af2031e55e418c6780e9aedc8bfb1c78359c072c089389422a2d4aa15c95b
|
data/.gitignore
CHANGED
data/README.md
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
# PrxAuth::Rails
|
2
2
|
|
3
|
-
Rails integration for next generation PRX Authorization system.
|
3
|
+
Rails integration for next generation PRX Authorization system. This
|
4
|
+
provides common OpenId authorization patterns used in PRX apps.
|
4
5
|
|
5
6
|
## Installation
|
6
7
|
|
@@ -14,17 +15,32 @@ And then execute:
|
|
14
15
|
|
15
16
|
## Usage
|
16
17
|
|
17
|
-
Installing the gem in a Rails project will automatically add the
|
18
|
+
Installing the gem in a Rails project will automatically add the
|
19
|
+
appropriate Rack middleware to your Rails application and add two
|
20
|
+
methods to your controllers. These methods are:
|
18
21
|
|
19
|
-
* `prx_auth_token`: returns a token (similar to PrxAuth::Token) which
|
22
|
+
* `prx_auth_token`: returns a token (similar to PrxAuth::Token) which
|
23
|
+
automatically namespaces queries. The main methods you will be
|
24
|
+
interested in are `authorized?`, `globally_authorized?` and `resources`.
|
25
|
+
More information can be found in PrxAuth.
|
20
26
|
|
21
|
-
* `prx_authenticated?`: returns whether or not this request includes a
|
27
|
+
* `prx_authenticated?`: returns whether or not this request includes a
|
28
|
+
valid PrxAuth token.
|
29
|
+
|
30
|
+
This will let set up the Rails app to be ready for HTTP requests
|
31
|
+
associated with an OpenId access token.
|
22
32
|
|
23
33
|
### Configuration
|
24
34
|
|
25
|
-
Generally, configuration is not required and the gem aims for great
|
35
|
+
Generally, configuration is not required and the gem aims for great
|
36
|
+
defaults, but you can override some settings if you need to change the
|
37
|
+
default behavior.
|
38
|
+
|
39
|
+
If you're using the Rails server-side session flow, you must supply the
|
40
|
+
client_id via configuration.
|
26
41
|
|
27
|
-
In your rails app, add a file to config/initializers called
|
42
|
+
In your rails app, add a file to config/initializers called
|
43
|
+
`prx_auth.rb`:
|
28
44
|
|
29
45
|
```ruby
|
30
46
|
PrxAuth::Rails.configure do |config|
|
@@ -36,6 +52,9 @@ PrxAuth::Rails.configure do |config|
|
|
36
52
|
# as .authorized?(:my_great_ns, :foo). Has no impact on unscoped queries.
|
37
53
|
config.namespace = :my_great_ns # default: derived from Rails::Application name.
|
38
54
|
# e.g. class Feeder < Rails::Application => :feeder
|
55
|
+
|
56
|
+
# Set up the PRX OpenID client_id if using the backend rails sessions flow.
|
57
|
+
config.client_id = '<some client id>'
|
39
58
|
end
|
40
59
|
```
|
41
60
|
|
data/Rakefile
CHANGED
@@ -1,10 +1,18 @@
|
|
1
|
-
require
|
1
|
+
require "bundler/setup"
|
2
|
+
|
3
|
+
APP_RAKEFILE = File.expand_path("test/dummy/Rakefile", __dir__)
|
4
|
+
load "rails/tasks/engine.rake"
|
5
|
+
|
6
|
+
load "rails/tasks/statistics.rake"
|
7
|
+
|
8
|
+
require "bundler/gem_tasks"
|
2
9
|
require 'rake'
|
3
|
-
require
|
10
|
+
require "rake/testtask"
|
4
11
|
|
5
|
-
Rake::TestTask.new do |t|
|
12
|
+
Rake::TestTask.new(:test) do |t|
|
6
13
|
t.libs << 'test'
|
7
|
-
t.pattern = 'test/**/*
|
14
|
+
t.pattern = 'test/**/*_test.rb'
|
15
|
+
t.verbose = false
|
8
16
|
end
|
9
17
|
|
10
18
|
task default: :test
|
@@ -0,0 +1,108 @@
|
|
1
|
+
require 'open-uri'
|
2
|
+
|
3
|
+
module PrxAuth::Rails
|
4
|
+
class SessionsController < ApplicationController
|
5
|
+
include PrxAuth::Rails::Engine.routes.url_helpers
|
6
|
+
|
7
|
+
skip_before_action :authenticate!
|
8
|
+
|
9
|
+
before_action :set_nonce!, only: :show
|
10
|
+
|
11
|
+
ID_NONCE_SESSION_KEY = 'id_prx_openid_nonce'.freeze
|
12
|
+
|
13
|
+
def new
|
14
|
+
set_nonce! unless fetch_nonce.present?
|
15
|
+
|
16
|
+
config = PrxAuth::Rails.configuration
|
17
|
+
|
18
|
+
id_auth_params = {
|
19
|
+
client_id: config.prx_client_id,
|
20
|
+
nonce: fetch_nonce,
|
21
|
+
response_type: 'id_token token',
|
22
|
+
scope: 'openid apps',
|
23
|
+
prompt: 'necessary'
|
24
|
+
}
|
25
|
+
|
26
|
+
redirect_to '//' + config.id_host + '/authorize?' + id_auth_params.to_query
|
27
|
+
end
|
28
|
+
|
29
|
+
def show
|
30
|
+
end
|
31
|
+
|
32
|
+
def auth_error
|
33
|
+
@auth_error_message = params.require(:error)
|
34
|
+
end
|
35
|
+
|
36
|
+
def create
|
37
|
+
jwt_id_claims = id_claims
|
38
|
+
jwt_access_claims = access_claims
|
39
|
+
|
40
|
+
jwt_access_claims['id_token'] = jwt_id_claims.as_json
|
41
|
+
|
42
|
+
result_path = if valid_nonce?(jwt_id_claims['nonce']) &&
|
43
|
+
users_match?(jwt_id_claims, jwt_access_claims)
|
44
|
+
sign_in_user(jwt_access_claims)
|
45
|
+
after_sign_in_path_for(current_user)
|
46
|
+
else
|
47
|
+
auth_error_sessions_path(error: 'verification_failed')
|
48
|
+
end
|
49
|
+
reset_nonce!
|
50
|
+
|
51
|
+
redirect_to result_path
|
52
|
+
end
|
53
|
+
|
54
|
+
private
|
55
|
+
|
56
|
+
def after_sign_in_path_for(_)
|
57
|
+
return super if defined?(super)
|
58
|
+
|
59
|
+
"/"
|
60
|
+
end
|
61
|
+
|
62
|
+
def id_claims
|
63
|
+
id_token = params.require('id_token')
|
64
|
+
validate_token(id_token)
|
65
|
+
end
|
66
|
+
|
67
|
+
def access_claims
|
68
|
+
access_token = params.require('access_token')
|
69
|
+
validate_token(access_token)
|
70
|
+
end
|
71
|
+
|
72
|
+
def reset_nonce!
|
73
|
+
session[ID_NONCE_SESSION_KEY] = nil
|
74
|
+
end
|
75
|
+
|
76
|
+
def set_nonce!
|
77
|
+
n = session[ID_NONCE_SESSION_KEY]
|
78
|
+
return n if n.present?
|
79
|
+
|
80
|
+
session[ID_NONCE_SESSION_KEY] = SecureRandom.hex
|
81
|
+
end
|
82
|
+
|
83
|
+
def fetch_nonce
|
84
|
+
session[ID_NONCE_SESSION_KEY]
|
85
|
+
end
|
86
|
+
|
87
|
+
def valid_nonce?(nonce)
|
88
|
+
return false if fetch_nonce.nil?
|
89
|
+
|
90
|
+
fetch_nonce == nonce
|
91
|
+
end
|
92
|
+
|
93
|
+
def users_match?(claims1, claims2)
|
94
|
+
return false if claims1['sub'].nil? || claims2['sub'].nil?
|
95
|
+
|
96
|
+
claims1['sub'] == claims2['sub']
|
97
|
+
end
|
98
|
+
|
99
|
+
def validate_token(token)
|
100
|
+
id_host = PrxAuth::Rails.configuration.id_host
|
101
|
+
prx_auth_cert = Rack::PrxAuth::Certificate.new("https://#{id_host}/api/v1/certs")
|
102
|
+
auth_validator = Rack::PrxAuth::AuthValidator.new(token, prx_auth_cert, id_host)
|
103
|
+
auth_validator.
|
104
|
+
claims.
|
105
|
+
with_indifferent_access
|
106
|
+
end
|
107
|
+
end
|
108
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
<div class='main'>
|
2
|
+
<section>
|
3
|
+
<h3>Not authorized for this application.</h3>
|
4
|
+
|
5
|
+
<p>Message was: <pre><%= @auth_error_message %></pre>
|
6
|
+
<% if @auth_error_message == 'invalid_scope' %>
|
7
|
+
Did you add a row in the account_applications table on id.prx?
|
8
|
+
<% end %>
|
9
|
+
</p>
|
10
|
+
|
11
|
+
<p>
|
12
|
+
<a href="<%= new_sessions_path %>">Try logging in again</a>
|
13
|
+
</p>
|
14
|
+
</section>
|
15
|
+
</div>
|
@@ -0,0 +1,38 @@
|
|
1
|
+
<div style="display:none;">
|
2
|
+
<%= form_for(:sessions, :url => PrxAuth::Rails::Engine.routes.url_helpers.sessions_path) do |f| %>
|
3
|
+
<%= hidden_field_tag :access_token, '', id: 'access-token-field' %>
|
4
|
+
<%= hidden_field_tag :id_token, '', id: 'id-token-field' %>
|
5
|
+
<%= f.submit id: 'sessions-form-submit' %>
|
6
|
+
<% end %>
|
7
|
+
</div>
|
8
|
+
|
9
|
+
<script type='application/javascript'>
|
10
|
+
|
11
|
+
function parseURLFragment() {
|
12
|
+
let hashParams = {};
|
13
|
+
let e,
|
14
|
+
a = /\+/g, // Regex for replacing addition symbol with a space
|
15
|
+
r = /([^&;=]+)=?([^&;]*)/g,
|
16
|
+
d = function (s) { return decodeURIComponent(s.replace(a, " ")); },
|
17
|
+
q = window.location.hash.substring(1);
|
18
|
+
|
19
|
+
while (e = r.exec(q))
|
20
|
+
hashParams[d(e[1])] = d(e[2]);
|
21
|
+
|
22
|
+
return hashParams;
|
23
|
+
}
|
24
|
+
|
25
|
+
window.addEventListener("load", () => {
|
26
|
+
var idToken = document.querySelector("#id-token-field");
|
27
|
+
var accessToken = document.querySelector("#access-token-field");
|
28
|
+
var submit = document.querySelector("input#sessions-form-submit[type=submit]");
|
29
|
+
|
30
|
+
var hashParams = parseURLFragment();
|
31
|
+
|
32
|
+
accessToken.value = hashParams['access_token'];
|
33
|
+
idToken.value = hashParams['id_token'];
|
34
|
+
|
35
|
+
submit.click();
|
36
|
+
});
|
37
|
+
|
38
|
+
</script>
|
data/config/routes.rb
ADDED
data/lib/prx_auth/rails.rb
CHANGED
@@ -1,17 +1,28 @@
|
|
1
1
|
class PrxAuth::Rails::Configuration
|
2
|
-
attr_accessor :install_middleware,
|
2
|
+
attr_accessor :install_middleware,
|
3
|
+
:namespace,
|
4
|
+
:prx_client_id,
|
5
|
+
:id_host
|
6
|
+
|
3
7
|
|
4
8
|
def initialize
|
5
9
|
@install_middleware = true
|
6
10
|
if defined?(::Rails)
|
7
11
|
klass = ::Rails.application.class
|
8
|
-
|
9
|
-
|
12
|
+
parent_name = if ::Rails::VERSION::MAJOR >= 6
|
13
|
+
klass.module_parent_name
|
14
|
+
else
|
15
|
+
klass.parent_name
|
16
|
+
end
|
17
|
+
klass_name = if parent_name.present?
|
18
|
+
parent_name
|
10
19
|
else
|
11
20
|
klass.name
|
12
21
|
end
|
13
22
|
|
14
23
|
@namespace = klass_name.underscore.intern
|
24
|
+
@prx_client_id = nil
|
25
|
+
@id_host = nil
|
15
26
|
end
|
16
27
|
end
|
17
|
-
end
|
28
|
+
end
|
@@ -4,16 +4,41 @@ module PrxAuth
|
|
4
4
|
module Rails
|
5
5
|
module Controller
|
6
6
|
def prx_auth_token
|
7
|
+
rack_auth_token = env_prx_auth_token
|
8
|
+
return rack_auth_token if rack_auth_token.present?
|
9
|
+
|
10
|
+
session['prx.auth'] && Rack::PrxAuth::TokenData.new(session['prx.auth'])
|
11
|
+
end
|
12
|
+
|
13
|
+
def prx_authenticated?
|
14
|
+
!!prx_auth_token
|
15
|
+
end
|
16
|
+
|
17
|
+
def authenticate!
|
18
|
+
return true if current_user.present?
|
19
|
+
|
20
|
+
redirect_to PrxAuth::Rails::Engine.routes.url_helpers.new_sessions_path
|
21
|
+
end
|
22
|
+
|
23
|
+
def current_user
|
24
|
+
return if prx_auth_token.nil?
|
25
|
+
|
26
|
+
PrxAuth::Rails::Token.new(prx_auth_token)
|
27
|
+
end
|
28
|
+
|
29
|
+
def sign_in_user(token)
|
30
|
+
session['prx.auth'] = token
|
31
|
+
end
|
32
|
+
|
33
|
+
private
|
34
|
+
|
35
|
+
def env_prx_auth_token
|
7
36
|
if !defined? @_prx_auth_token
|
8
37
|
@_prx_auth_token = request.env['prx.auth'] && PrxAuth::Rails::Token.new(request.env['prx.auth'])
|
9
38
|
else
|
10
39
|
@_prx_auth_token
|
11
40
|
end
|
12
41
|
end
|
13
|
-
|
14
|
-
def prx_authenticated?
|
15
|
-
!!prx_auth_token
|
16
|
-
end
|
17
42
|
end
|
18
43
|
end
|
19
44
|
end
|
data/lib/prx_auth/rails/token.rb
CHANGED
data/prx_auth-rails.gemspec
CHANGED
@@ -29,7 +29,9 @@ Gem::Specification.new do |spec|
|
|
29
29
|
spec.add_development_dependency 'coveralls', '~> 0'
|
30
30
|
spec.add_development_dependency 'guard'
|
31
31
|
spec.add_development_dependency 'guard-minitest'
|
32
|
-
spec.add_development_dependency
|
32
|
+
spec.add_development_dependency "rails", "~> 6.1.0"
|
33
|
+
spec.add_development_dependency 'pry'
|
34
|
+
spec.add_development_dependency 'sqlite3'
|
33
35
|
|
34
36
|
|
35
37
|
|
data/test/dummy/Rakefile
ADDED
File without changes
|
@@ -0,0 +1,15 @@
|
|
1
|
+
/*
|
2
|
+
* This is a manifest file that'll be compiled into application.css, which will include all the files
|
3
|
+
* listed below.
|
4
|
+
*
|
5
|
+
* Any CSS and SCSS file within this directory, lib/assets/stylesheets, vendor/assets/stylesheets,
|
6
|
+
* or any plugin's vendor/assets/stylesheets directory can be referenced here using a relative path.
|
7
|
+
*
|
8
|
+
* You're free to add application-wide styles to this file and they'll appear at the bottom of the
|
9
|
+
* compiled file so the styles you add here take precedence over styles defined in any other CSS/SCSS
|
10
|
+
* files in this directory. Styles in this file should be added after the last require_* statement.
|
11
|
+
* It is generally better to create a new file per style scope.
|
12
|
+
*
|
13
|
+
*= require_tree .
|
14
|
+
*= require_self
|
15
|
+
*/
|