rodauth-oauth 0.10.4 → 1.0.0.pre.beta2
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/MIGRATION-GUIDE-v1.md +286 -0
- data/README.md +28 -35
- data/doc/release_notes/1_0_0_beta1.md +38 -0
- data/doc/release_notes/1_0_0_beta2.md +34 -0
- data/lib/generators/rodauth/oauth/install_generator.rb +0 -1
- data/lib/generators/rodauth/oauth/templates/app/views/rodauth/authorize.html.erb +21 -11
- data/lib/generators/rodauth/oauth/templates/app/views/rodauth/device_search.html.erb +1 -1
- data/lib/generators/rodauth/oauth/templates/app/views/rodauth/device_verification.html.erb +2 -2
- data/lib/generators/rodauth/oauth/templates/app/views/rodauth/new_oauth_application.html.erb +1 -6
- data/lib/generators/rodauth/oauth/templates/app/views/rodauth/oauth_application.html.erb +0 -2
- data/lib/generators/rodauth/oauth/templates/app/views/rodauth/oauth_application_oauth_grants.html.erb +41 -0
- data/lib/generators/rodauth/oauth/templates/app/views/rodauth/oauth_applications.html.erb +2 -2
- data/lib/generators/rodauth/oauth/templates/app/views/rodauth/oauth_grants.html.erb +37 -0
- data/lib/generators/rodauth/oauth/templates/db/migrate/create_rodauth_oauth.rb +57 -57
- data/lib/rodauth/features/oauth_application_management.rb +61 -74
- data/lib/rodauth/features/oauth_assertion_base.rb +19 -23
- data/lib/rodauth/features/oauth_authorization_code_grant.rb +62 -90
- data/lib/rodauth/features/oauth_authorize_base.rb +115 -22
- data/lib/rodauth/features/oauth_base.rb +397 -315
- data/lib/rodauth/features/oauth_client_credentials_grant.rb +20 -18
- data/lib/rodauth/features/{oauth_device_grant.rb → oauth_device_code_grant.rb} +62 -73
- data/lib/rodauth/features/oauth_dynamic_client_registration.rb +52 -31
- data/lib/rodauth/features/oauth_grant_management.rb +70 -0
- data/lib/rodauth/features/oauth_implicit_grant.rb +29 -27
- data/lib/rodauth/features/oauth_jwt.rb +53 -689
- data/lib/rodauth/features/oauth_jwt_base.rb +458 -0
- data/lib/rodauth/features/oauth_jwt_bearer_grant.rb +48 -17
- data/lib/rodauth/features/oauth_jwt_jwks.rb +47 -0
- data/lib/rodauth/features/oauth_jwt_secured_authorization_request.rb +116 -0
- data/lib/rodauth/features/oauth_management_base.rb +2 -0
- data/lib/rodauth/features/oauth_pkce.rb +22 -26
- data/lib/rodauth/features/oauth_resource_indicators.rb +33 -25
- data/lib/rodauth/features/oauth_resource_server.rb +59 -0
- data/lib/rodauth/features/oauth_saml_bearer_grant.rb +7 -1
- data/lib/rodauth/features/oauth_token_introspection.rb +76 -46
- data/lib/rodauth/features/oauth_token_revocation.rb +46 -33
- data/lib/rodauth/features/oidc.rb +382 -241
- data/lib/rodauth/features/oidc_dynamic_client_registration.rb +127 -51
- data/lib/rodauth/features/oidc_rp_initiated_logout.rb +115 -0
- data/lib/rodauth/oauth/database_extensions.rb +8 -6
- data/lib/rodauth/oauth/http_extensions.rb +74 -0
- data/lib/rodauth/oauth/railtie.rb +20 -0
- data/lib/rodauth/oauth/ttl_store.rb +2 -0
- data/lib/rodauth/oauth/version.rb +1 -1
- data/lib/rodauth/oauth.rb +29 -1
- data/locales/en.yml +34 -22
- data/locales/pt.yml +34 -22
- data/templates/authorize.str +19 -17
- data/templates/device_search.str +1 -1
- data/templates/device_verification.str +2 -2
- data/templates/jwks_field.str +1 -0
- data/templates/new_oauth_application.str +1 -2
- data/templates/oauth_application.str +2 -2
- data/templates/oauth_application_oauth_grants.str +54 -0
- data/templates/oauth_applications.str +2 -2
- data/templates/oauth_grants.str +52 -0
- metadata +23 -16
- data/lib/generators/rodauth/oauth/templates/app/models/oauth_token.rb +0 -4
- data/lib/generators/rodauth/oauth/templates/app/views/rodauth/oauth_application_oauth_tokens.html.erb +0 -39
- data/lib/generators/rodauth/oauth/templates/app/views/rodauth/oauth_tokens.html.erb +0 -35
- data/lib/rodauth/features/oauth.rb +0 -9
- data/lib/rodauth/features/oauth_http_mac.rb +0 -86
- data/lib/rodauth/features/oauth_token_management.rb +0 -81
- data/lib/rodauth/oauth/refinements.rb +0 -48
- data/templates/jwt_public_key_field.str +0 -4
- data/templates/oauth_application_oauth_tokens.str +0 -52
- data/templates/oauth_tokens.str +0 -50
@@ -0,0 +1,41 @@
|
|
1
|
+
<% oauth_grants = rodauth.scope.instance_variable_get(:@oauth_grants) %>
|
2
|
+
<% grants_count = oauth_grants.count %>
|
3
|
+
<% if grants_count.zero? %>
|
4
|
+
<p><%= rodauth.oauth_no_grants_text %></p>
|
5
|
+
<% else %>
|
6
|
+
<table class="table">
|
7
|
+
<thead>
|
8
|
+
<tr>
|
9
|
+
<th scope="col"><=% rodauth.oauth_grants_type_label %></th>
|
10
|
+
<th scope="col"><=% rodauth.oauth_grants_token_label %></th>
|
11
|
+
<th scope="col"><=% rodauth.oauth_grants_refresh_token_label %></th>
|
12
|
+
<th scope="col"><=% rodauth.oauth_grants_expires_in_label %></th>
|
13
|
+
<th scope="col"><=% rodauth.oauth_grants_revoked_at_label %></th>
|
14
|
+
<th scope="col"><=% rodauth.oauth_grants_scopes_label %></th>
|
15
|
+
<th scope="col"><span class="badge badge-pill badge-dark"><%= grants_count %></span>
|
16
|
+
</tr>
|
17
|
+
</thead>
|
18
|
+
<tbody>
|
19
|
+
<% oauth_grants.each do |oauth_grant| %>
|
20
|
+
<tr>
|
21
|
+
<td><%= oauth_grant[rodauth.oauth_grants_type_column] %></td>
|
22
|
+
<td><code class="token"><%= oauth_grant[rodauth.oauth_grants_token_column] %></code></td>
|
23
|
+
<td><code class="token"><%= oauth_grant[rodauth.oauth_grants_refresh_token_column] %></code></td>
|
24
|
+
<td><%= oauth_grant[rodauth.oauth_grants_expires_in_column] %></td>
|
25
|
+
<td><%= oauth_grant[rodauth.oauth_grants_revoked_at_column] %></td>
|
26
|
+
<td><%= oauth_grant[rodauth.oauth_grants_scopes_column] %></td>
|
27
|
+
<td>
|
28
|
+
<% if !oauth_grant[rodauth.oauth_grants_revoked_at_column] %>
|
29
|
+
<%= form_tag rodauth.revoke_path, method: :post do %>
|
30
|
+
<%= hidden_field_tag :token_type_hint, "access_token" %>
|
31
|
+
<%= hidden_field_tag :token, oauth_grant[rodauth.oauth_grants_token_column] %>
|
32
|
+
<%= submit_tag rodauth.oauth_grant_revoke_button, class: "btn btn-danger" %>
|
33
|
+
<% end %>
|
34
|
+
<% end %>
|
35
|
+
</td>
|
36
|
+
</tr>
|
37
|
+
<% end %>
|
38
|
+
</tbody>
|
39
|
+
</table>
|
40
|
+
<%= rodauth.oauth_management_pagination_links(@oauth_grants) %>
|
41
|
+
<% end %>
|
@@ -4,7 +4,7 @@
|
|
4
4
|
<%= link_to rodauth.new_oauth_application_page_title, "#{rodauth.oauth_applications_path}/new", class: "btn btn-secondary" %>
|
5
5
|
</div>
|
6
6
|
<% if apps_count.zero? %>
|
7
|
-
<p
|
7
|
+
<p><%= rodauth.oauth_no_applications_text %></p>
|
8
8
|
<% else %>
|
9
9
|
<table class="table">
|
10
10
|
<thead>
|
@@ -26,5 +26,5 @@
|
|
26
26
|
<% end %>
|
27
27
|
</tbody>
|
28
28
|
</table>
|
29
|
-
<%= rodauth.oauth_management_pagination_links(oauth_applications_ds) %>
|
29
|
+
<%= rodauth.oauth_management_pagination_links(oauth_applications_ds).html_safe %>
|
30
30
|
<% end %>
|
@@ -0,0 +1,37 @@
|
|
1
|
+
<% oauth_grants = rodauth.scope.instance_variable_get(:@oauth_grants) %>
|
2
|
+
<% grants_count = oauth_grants.count %>
|
3
|
+
<% if grants_count.zero? %>
|
4
|
+
<p><%= rodauth.oauth_no_grants_text %></p>
|
5
|
+
<% else %>
|
6
|
+
<table class="table">
|
7
|
+
<thead>
|
8
|
+
<tr>
|
9
|
+
<th scope="col"><=% rodauth.oauth_applications_name_label %></th>
|
10
|
+
<th scope="col"><=% rodauth.oauth_grants_type_label %></th>
|
11
|
+
<th scope="col"><=% rodauth.oauth_grants_token_label %></th>
|
12
|
+
<th scope="col"><=% rodauth.oauth_grants_refresh_token_label %></th>
|
13
|
+
<th scope="col"><=% rodauth.oauth_grants_expires_in_label %></th>
|
14
|
+
<th scope="col"><=% rodauth.oauth_grants_scopes_label %></th>
|
15
|
+
<th scope="col"><span class="badge badge-pill badge-dark"><%= grants_count %></span>
|
16
|
+
</tr>
|
17
|
+
</thead>
|
18
|
+
<tbody>
|
19
|
+
<% oauth_grants.each do |oauth_grant| %>
|
20
|
+
<tr>
|
21
|
+
<td><%= oauth_grant[rodauth.oauth_applications_name_column] %></td>
|
22
|
+
<td><%= oauth_grant[rodauth.oauth_grants_type_column] %></td>
|
23
|
+
<td><code class="token"><%= oauth_grant[rodauth.oauth_grants_token_column] %></code></td>
|
24
|
+
<td><code class="token"><%= oauth_grant[rodauth.oauth_grants_refresh_token_column] %></code></td>
|
25
|
+
<td><%= oauth_grant[rodauth.oauth_grants_expires_in_column] %></td>
|
26
|
+
<td><%= oauth_grant[rodauth.oauth_grants_scopes_column] %></td>
|
27
|
+
<td>
|
28
|
+
<%= form_tag rodauth.oauth_grant_path(oauth_grant[rodauth.oauth_grants_id_column]), method: :post do %>
|
29
|
+
<%= submit_tag rodauth.oauth_grant_revoke_button, class: "btn btn-danger" %>
|
30
|
+
<% end %>
|
31
|
+
</td>
|
32
|
+
</tr>
|
33
|
+
<% end %>
|
34
|
+
</tbody>
|
35
|
+
</table>
|
36
|
+
<%= rodauth.oauth_management_pagination_links(oauth_grants) %>
|
37
|
+
<% end %>
|
@@ -5,29 +5,48 @@ class CreateRodauthOauth < ActiveRecord::Migration<%= migration_version %>
|
|
5
5
|
t.foreign_key :accounts, column: :account_id
|
6
6
|
t.string :name, null: false
|
7
7
|
t.string :description, null: true
|
8
|
-
t.string :homepage_url, null:
|
8
|
+
t.string :homepage_url, null: true
|
9
9
|
t.string :redirect_uri, null: false
|
10
10
|
t.string :client_id, null: false, index: { unique: true }
|
11
11
|
t.string :client_secret, null: false, index: { unique: true }
|
12
12
|
t.string :scopes, null: false
|
13
13
|
t.datetime :created_at, null: false, default: -> { "CURRENT_TIMESTAMP" }
|
14
|
-
|
15
|
-
#
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
#
|
30
|
-
|
14
|
+
|
15
|
+
# :oauth_dynamic_client_configuration enabled, extra optional params
|
16
|
+
t.string :token_endpoint_auth_method, null: true
|
17
|
+
t.string :grant_types, null: true
|
18
|
+
t.string :response_types, null: true
|
19
|
+
t.string :client_uri, null: true
|
20
|
+
t.string :logo_uri, null: true
|
21
|
+
t.string :tos_uri, null: true
|
22
|
+
t.string :policy_uri, null: true
|
23
|
+
t.string :jwks_uri, null: true
|
24
|
+
t.string :jwks, null: true
|
25
|
+
t.string :contacts, null: true
|
26
|
+
t.string :software_id, null: true
|
27
|
+
t.string :software_version, null: true
|
28
|
+
|
29
|
+
# :oidc_dynamic_client_configuration enabled, extra optional params
|
30
|
+
t.string :sector_identifier_uri, null: true
|
31
|
+
t.string :application_type, null: true
|
32
|
+
|
33
|
+
# :oidc enabled
|
34
|
+
t.string :subject_type, null: true
|
35
|
+
t.string :id_token_signed_response_alg, null: true
|
36
|
+
t.string :id_token_encrypted_response_alg, null: true
|
37
|
+
t.string :id_token_encrypted_response_enc, null: true
|
38
|
+
t.string :userinfo_signed_response_alg, null: true
|
39
|
+
t.string :userinfo_encrypted_response_alg, null: true
|
40
|
+
t.string :userinfo_encrypted_response_enc, null: true
|
41
|
+
|
42
|
+
# :oauth_jwt_secured_authorization_request
|
43
|
+
t.string :request_object_signing_alg, null: true
|
44
|
+
t.string :request_object_encryption_alg, null: true
|
45
|
+
t.string :request_object_encryption_enc, null: true
|
46
|
+
t.string :request_uris, null: true
|
47
|
+
|
48
|
+
# :oidc_rp_initiated_logout enabled
|
49
|
+
t.string :post_logout_redirect_uris, null: false
|
31
50
|
end
|
32
51
|
|
33
52
|
create_table :oauth_grants do |t|
|
@@ -35,53 +54,34 @@ class CreateRodauthOauth < ActiveRecord::Migration<%= migration_version %>
|
|
35
54
|
t.foreign_key :accounts, column: :account_id
|
36
55
|
t.integer :oauth_application_id
|
37
56
|
t.foreign_key :oauth_applications, column: :oauth_application_id
|
38
|
-
t.string :
|
57
|
+
t.string :type, null: true
|
58
|
+
t.string :code, null: true
|
39
59
|
t.index(%i[oauth_application_id code], unique: true)
|
60
|
+
t.string :token, unique: true
|
61
|
+
t.string :refresh_token, unique: true
|
40
62
|
t.datetime :expires_in, null: false
|
41
63
|
t.string :redirect_uri
|
42
64
|
t.datetime :revoked_at
|
43
65
|
t.string :scopes, null: false
|
44
66
|
t.datetime :created_at, null: false, default: -> { "CURRENT_TIMESTAMP" }
|
45
|
-
# for using access_types
|
46
67
|
t.string :access_type, null: false, default: "offline"
|
47
|
-
# uncomment to enable PKCE
|
48
|
-
# t.string :code_challenge
|
49
|
-
# t.string :code_challenge_method
|
50
|
-
# uncomment to use OIDC nonce
|
51
|
-
# t.string :nonce
|
52
|
-
# device code grant
|
53
|
-
# t.string :user_code, null: true, unique: true
|
54
|
-
# t.datetime :last_polled_at, null: true
|
55
|
-
# when using :oauth_resource_indicators feature
|
56
|
-
# t.string :resource
|
57
|
-
end
|
58
68
|
|
59
|
-
|
60
|
-
t.
|
61
|
-
t.
|
62
|
-
|
63
|
-
|
64
|
-
t.
|
65
|
-
t.
|
66
|
-
|
67
|
-
|
68
|
-
t.string :
|
69
|
-
|
70
|
-
#
|
71
|
-
|
72
|
-
t.string :
|
73
|
-
|
74
|
-
|
75
|
-
# t.string :refresh_token_hash, token: true, unique: true
|
76
|
-
t.datetime :expires_in, null: false
|
77
|
-
t.datetime :revoked_at
|
78
|
-
t.string :scopes, null: false
|
79
|
-
t.datetime :created_at, null: false, default: -> { "CURRENT_TIMESTAMP" }
|
80
|
-
# uncomment to use OIDC nonce
|
81
|
-
# t.string :nonce
|
82
|
-
# t.datetime :auth_time
|
83
|
-
# when using :oauth_resource_indicators feature
|
84
|
-
# t.string :resource
|
69
|
+
# :oauth_pkce enabled
|
70
|
+
t.string :code_challenge
|
71
|
+
t.string :code_challenge_method
|
72
|
+
|
73
|
+
# :oauth_device_code_grant enabled
|
74
|
+
t.string :user_code, null: true, unique: true
|
75
|
+
t.datetime :last_polled_at, null: true
|
76
|
+
|
77
|
+
# :resource_indicators enabled
|
78
|
+
t.string :resource
|
79
|
+
|
80
|
+
# :oidc enabled
|
81
|
+
t.string :nonce
|
82
|
+
t.string :acr
|
83
|
+
t.string :claims_locales
|
84
|
+
t.string :claims
|
85
85
|
end
|
86
86
|
end
|
87
87
|
end
|
@@ -1,8 +1,10 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require "rodauth/oauth"
|
4
|
+
|
3
5
|
module Rodauth
|
4
6
|
Feature.define(:oauth_application_management, :OauthApplicationManagement) do
|
5
|
-
depends :oauth_management_base
|
7
|
+
depends :oauth_management_base, :oauth_token_revocation
|
6
8
|
|
7
9
|
before "create_oauth_application"
|
8
10
|
after "create_oauth_application"
|
@@ -13,7 +15,7 @@ module Rodauth
|
|
13
15
|
view "oauth_applications", "Oauth Applications", "oauth_applications"
|
14
16
|
view "oauth_application", "Oauth Application", "oauth_application"
|
15
17
|
view "new_oauth_application", "New Oauth Application", "new_oauth_application"
|
16
|
-
view "
|
18
|
+
view "oauth_application_oauth_grants", "Oauth Application Grants", "oauth_application_oauth_grants"
|
17
19
|
|
18
20
|
# Application
|
19
21
|
APPLICATION_REQUIRED_PARAMS = %w[name scopes homepage_url redirect_uri client_secret].freeze
|
@@ -21,12 +23,6 @@ module Rodauth
|
|
21
23
|
|
22
24
|
(APPLICATION_REQUIRED_PARAMS + %w[description client_id]).each do |param|
|
23
25
|
auth_value_method :"oauth_application_#{param}_param", param
|
24
|
-
configuration_module_eval do
|
25
|
-
define_method :"#{param}_label" do
|
26
|
-
warn "#{__method__} is deprecated, switch to oauth_applications_#{__method__}_label"
|
27
|
-
__send__(:"oauth_applications_#{param}_label")
|
28
|
-
end
|
29
|
-
end
|
30
26
|
end
|
31
27
|
|
32
28
|
translatable_method :oauth_applications_name_label, "Name"
|
@@ -41,36 +37,42 @@ module Rodauth
|
|
41
37
|
translatable_method :oauth_applications_redirect_uri_label, "Redirect URI"
|
42
38
|
translatable_method :oauth_applications_client_secret_label, "Client Secret"
|
43
39
|
translatable_method :oauth_applications_client_id_label, "Client ID"
|
40
|
+
|
41
|
+
%w[type token refresh_token expires_in revoked_at].each do |param|
|
42
|
+
translatable_method :"oauth_grants_#{param}_label", param.gsub("_", " ").capitalize
|
43
|
+
end
|
44
|
+
|
44
45
|
button "Register", "oauth_application"
|
45
|
-
button "Revoke", "
|
46
|
+
button "Revoke", "oauth_grant_revoke"
|
46
47
|
|
47
|
-
auth_value_method :
|
48
|
+
auth_value_method :oauth_applications_oauth_grants_path, "oauth-grants"
|
48
49
|
auth_value_method :oauth_applications_route, "oauth-applications"
|
49
50
|
auth_value_method :oauth_applications_per_page, 20
|
50
51
|
auth_value_method :oauth_applications_id_pattern, Integer
|
51
|
-
auth_value_method :
|
52
|
+
auth_value_method :oauth_grants_per_page, 20
|
52
53
|
|
53
54
|
translatable_method :invalid_url_message, "Invalid URL"
|
54
55
|
translatable_method :null_error_message, "is not filled"
|
55
56
|
|
56
|
-
|
57
|
-
|
58
|
-
end
|
57
|
+
translatable_method :oauth_no_applications_text, "No oauth applications yet!"
|
58
|
+
translatable_method :oauth_no_grants_text, "No oauth grants yet!"
|
59
59
|
|
60
|
-
def oauth_applications_url(opts = {})
|
61
|
-
route_url(oauth_applications_route, opts)
|
62
|
-
end
|
63
60
|
auth_value_methods(
|
64
61
|
:oauth_application_path
|
65
62
|
)
|
66
63
|
|
64
|
+
def oauth_applications_path(opts = {})
|
65
|
+
route_path(oauth_applications_route, opts)
|
66
|
+
end
|
67
|
+
|
67
68
|
def oauth_application_path(id)
|
68
69
|
"#{oauth_applications_path}/#{id}"
|
69
70
|
end
|
70
71
|
|
71
72
|
# /oauth-applications routes
|
72
|
-
def
|
73
|
+
def load_oauth_application_management_routes
|
73
74
|
request.on(oauth_applications_route) do
|
75
|
+
check_csrf if check_csrf?
|
74
76
|
require_account
|
75
77
|
|
76
78
|
request.get "new" do
|
@@ -92,57 +94,52 @@ module Rodauth
|
|
92
94
|
end
|
93
95
|
end
|
94
96
|
|
95
|
-
request.on(
|
97
|
+
request.on(oauth_applications_oauth_grants_path) do
|
96
98
|
page = Integer(param_or_nil("page") || 1)
|
97
|
-
per_page = per_page_param(
|
98
|
-
|
99
|
-
.where(
|
100
|
-
.order(Sequel.desc(
|
101
|
-
scope.instance_variable_set(:@
|
102
|
-
request.
|
103
|
-
|
99
|
+
per_page = per_page_param(oauth_grants_per_page)
|
100
|
+
oauth_grants = db[oauth_grants_table]
|
101
|
+
.where(oauth_grants_oauth_application_id_column => id)
|
102
|
+
.order(Sequel.desc(oauth_grants_id_column))
|
103
|
+
scope.instance_variable_set(:@oauth_grants, oauth_grants.paginate(page, per_page))
|
104
|
+
request.is do
|
105
|
+
request.get do
|
106
|
+
oauth_application_oauth_grants_view
|
107
|
+
end
|
104
108
|
end
|
105
109
|
end
|
106
110
|
end
|
107
111
|
|
108
|
-
request.
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
.
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
oauth_applications_view
|
117
|
-
end
|
112
|
+
request.is do
|
113
|
+
request.get do
|
114
|
+
page = Integer(param_or_nil("page") || 1)
|
115
|
+
per_page = per_page_param(oauth_applications_per_page)
|
116
|
+
scope.instance_variable_set(:@oauth_applications, db[oauth_applications_table]
|
117
|
+
.where(oauth_applications_account_id_column => account_id)
|
118
|
+
.order(Sequel.desc(oauth_applications_id_column))
|
119
|
+
.paginate(page, per_page))
|
118
120
|
|
119
|
-
|
120
|
-
|
121
|
-
validate_oauth_application_params
|
121
|
+
oauth_applications_view
|
122
|
+
end
|
122
123
|
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
124
|
+
request.post do
|
125
|
+
catch_error do
|
126
|
+
validate_oauth_application_params
|
127
|
+
|
128
|
+
transaction do
|
129
|
+
before_create_oauth_application
|
130
|
+
id = create_oauth_application
|
131
|
+
after_create_oauth_application
|
132
|
+
set_notice_flash create_oauth_application_notice_flash
|
133
|
+
redirect "#{request.path}/#{id}"
|
134
|
+
end
|
129
135
|
end
|
136
|
+
set_error_flash create_oauth_application_error_flash
|
137
|
+
new_oauth_application_view
|
130
138
|
end
|
131
|
-
set_error_flash create_oauth_application_error_flash
|
132
|
-
new_oauth_application_view
|
133
139
|
end
|
134
140
|
end
|
135
141
|
end
|
136
142
|
|
137
|
-
def check_csrf?
|
138
|
-
case request.path
|
139
|
-
when oauth_applications_path
|
140
|
-
only_json? ? false : super
|
141
|
-
else
|
142
|
-
super
|
143
|
-
end
|
144
|
-
end
|
145
|
-
|
146
143
|
private
|
147
144
|
|
148
145
|
def oauth_application_params
|
@@ -168,15 +165,15 @@ module Rodauth
|
|
168
165
|
value.each do |uri|
|
169
166
|
next if uri.empty?
|
170
167
|
|
171
|
-
set_field_error(key, invalid_url_message) unless
|
168
|
+
set_field_error(key, invalid_url_message) unless check_valid_no_fragment_uri?(uri)
|
172
169
|
end
|
173
170
|
else
|
174
|
-
set_field_error(key, invalid_url_message) unless
|
171
|
+
set_field_error(key, invalid_url_message) unless check_valid_no_fragment_uri?(value)
|
175
172
|
end
|
176
173
|
elsif key == oauth_application_scopes_param
|
177
174
|
|
178
175
|
value.each do |scope|
|
179
|
-
set_field_error(key,
|
176
|
+
set_field_error(key, oauth_invalid_scope_message) unless oauth_application_scopes.include?(scope)
|
180
177
|
end
|
181
178
|
end
|
182
179
|
end
|
@@ -196,28 +193,18 @@ module Rodauth
|
|
196
193
|
redirect_uris = oauth_application_params[oauth_application_redirect_uri_param]
|
197
194
|
redirect_uris = redirect_uris.to_a.reject(&:empty?).join(" ") if redirect_uris.respond_to?(:each)
|
198
195
|
create_params[oauth_applications_redirect_uri_column] = redirect_uris unless redirect_uris.empty?
|
199
|
-
# set client ID/secret pairs
|
200
196
|
|
201
|
-
|
202
|
-
|
203
|
-
secret_hash(oauth_application_params[oauth_application_client_secret_param])
|
197
|
+
# set client ID/secret pairs
|
198
|
+
set_client_secret(create_params, oauth_application_params[oauth_application_client_secret_param])
|
204
199
|
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
oauth_application_default_scope
|
209
|
-
end
|
200
|
+
if create_params[oauth_applications_scopes_column]
|
201
|
+
create_params[oauth_applications_scopes_column] = create_params[oauth_applications_scopes_column].join(oauth_scope_separator)
|
202
|
+
end
|
210
203
|
|
211
204
|
rescue_from_uniqueness_error do
|
212
205
|
create_params[oauth_applications_client_id_column] = oauth_unique_id_generator
|
213
206
|
db[oauth_applications_table].insert(create_params)
|
214
207
|
end
|
215
208
|
end
|
216
|
-
|
217
|
-
def oauth_server_metadata_body(*)
|
218
|
-
super.tap do |data|
|
219
|
-
data[:registration_endpoint] = oauth_applications_url
|
220
|
-
end
|
221
|
-
end
|
222
209
|
end
|
223
210
|
end
|
@@ -1,11 +1,9 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require "rodauth/oauth
|
3
|
+
require "rodauth/oauth"
|
4
4
|
|
5
5
|
module Rodauth
|
6
6
|
Feature.define(:oauth_assertion_base, :OauthAssertionBase) do
|
7
|
-
using PrefixExtensions
|
8
|
-
|
9
7
|
depends :oauth_base
|
10
8
|
|
11
9
|
auth_value_methods(
|
@@ -17,7 +15,7 @@ module Rodauth
|
|
17
15
|
|
18
16
|
private
|
19
17
|
|
20
|
-
def
|
18
|
+
def validate_token_params
|
21
19
|
return super unless assertion_grant_type?
|
22
20
|
|
23
21
|
redirect_response_error("invalid_grant") unless param_or_nil("assertion")
|
@@ -29,19 +27,16 @@ module Rodauth
|
|
29
27
|
elsif client_assertion_type?
|
30
28
|
@oauth_application = __send__(:"require_oauth_application_from_#{client_assertion_type}_assertion_subject",
|
31
29
|
param("client_assertion"))
|
32
|
-
else
|
33
|
-
return super
|
34
|
-
end
|
35
30
|
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
31
|
+
if (client_id = param_or_nil("client_id")) &&
|
32
|
+
client_id != @oauth_application[oauth_applications_client_id_column]
|
33
|
+
# If present, the value of the
|
34
|
+
# "client_id" parameter MUST identify the same client as is
|
35
|
+
# identified by the client assertion.
|
36
|
+
redirect_response_error("invalid_grant")
|
37
|
+
end
|
38
|
+
else
|
39
|
+
super
|
45
40
|
end
|
46
41
|
end
|
47
42
|
|
@@ -54,7 +49,7 @@ module Rodauth
|
|
54
49
|
)
|
55
50
|
end
|
56
51
|
|
57
|
-
def
|
52
|
+
def create_token(grant_type)
|
58
53
|
return super unless assertion_grant_type?(grant_type) && supported_grant_type?(grant_type)
|
59
54
|
|
60
55
|
account = __send__(:"account_from_#{assertion_grant_type}_assertion", param("assertion"))
|
@@ -62,19 +57,20 @@ module Rodauth
|
|
62
57
|
redirect_response_error("invalid_grant") unless account
|
63
58
|
|
64
59
|
grant_scopes = if param_or_nil("scope")
|
65
|
-
redirect_response_error("
|
60
|
+
redirect_response_error("invalid_scope") unless check_valid_scopes?
|
66
61
|
scopes
|
67
62
|
else
|
68
63
|
@oauth_application[oauth_applications_scopes_column]
|
69
64
|
end
|
70
65
|
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
66
|
+
grant_params = {
|
67
|
+
oauth_grants_type_column => grant_type,
|
68
|
+
oauth_grants_account_id_column => account[account_id_column],
|
69
|
+
oauth_grants_oauth_application_id_column => @oauth_application[oauth_applications_id_column],
|
70
|
+
oauth_grants_scopes_column => grant_scopes
|
75
71
|
}
|
76
72
|
|
77
|
-
|
73
|
+
generate_token(grant_params, false)
|
78
74
|
end
|
79
75
|
|
80
76
|
def assertion_grant_type?(grant_type = param("grant_type"))
|