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"))
         
     |