rodauth-oauth 0.7.1 → 0.7.2

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 0e6a9da692805069b0250b975d86c02f81af6bd1cc80ce24ecbc92ea6d3fef14
4
- data.tar.gz: c4996d52e4119f6a2d8fde3f0149f8deadb609324fb894c99d5fbcdf836efd4c
3
+ metadata.gz: d000e6a25796dbdc8c58d378e93819343810f6089c33d02732443342ce721ec3
4
+ data.tar.gz: e61c19bd7e74c3f2b68541bf7aa78c143c669d5a745bf4efc389e786598fbcd8
5
5
  SHA512:
6
- metadata.gz: d8ec7872e8997019182b04a40c11f5db1e272de0bcceada11f870d706f2646aca911239d1f01876f26126e0936938a6ea233f312304410ce0c35d3964ebe7f1f
7
- data.tar.gz: 4a5df07c4da7c30803d7cb513c87ca6296b205dcdae89eb3ab475aa6780a4b37acd0e3b3bae5d43372eb8f9d3a92bd30a761ad7cda269d18d7bc16658f719768
6
+ metadata.gz: 9d727127c9e5a6d3a935b6194fbd0bd81358f3ea9876387d1639c3cf419b15246a0b89d57688d8ef15e830bd7b86f482463332c0fa843cb494ee56afe23c3e2e
7
+ data.tar.gz: 1d565e48e99b4897ca47a64c5b937405a5a10a9696893059d59670e58ae0dc1677daf17194ddfefcdd0d9fc33960ab5fd3a1fd3716cbe0e7fae961537ad46058
data/CHANGELOG.md CHANGED
@@ -2,6 +2,28 @@
2
2
 
3
3
  ## master
4
4
 
5
+ ### 0.7.2 (14/12/2021)
6
+
7
+ #### Features
8
+
9
+ * Revoking tokens from the OAuth Application management interface (@muellerj)
10
+
11
+ Token revocation was only possible when using the client ID and Secret, to aid "logout" functionality from client applications. Although the admin interface (available via `r.oauth_applications`) displayed a "Revoke" button alongside tokens in the list page, this was not working. The RFC does allow for the use case of application administrators being able to manually revoke tokens (as a result of client support, for example), so this functionality was enabled (only for the oauth application owner, for now).
12
+
13
+ #### Bugfixes
14
+
15
+ Default scope usage related bugfixes:
16
+
17
+ * Improved default scope conversion to avoid nested arrays (@muellerj);
18
+ * Authorize form shows a disabled checkbox and POST's no scope when default scope is to be used (@muellerj);
19
+ * example default scope fixed for example authorization server (should be string) (@muellerj);
20
+ * several param fixes in view templates (@muellerj);
21
+
22
+ OAuth Applications Management fixes:
23
+
24
+ * Access to OAuth Application page is now restricted to app owner;
25
+ * OAuth Applications page now lists the **only** the applications owned by the logged in user;
26
+
5
27
  ### 0.7.1 (05/12/2021)
6
28
 
7
29
  #### Improvements
@@ -66,6 +66,7 @@ module Rodauth
66
66
  notice_flash "Your oauth application has been registered", "create_oauth_application"
67
67
 
68
68
  notice_flash "The oauth token has been revoked", "revoke_oauth_token"
69
+ error_flash "You are not authorized to revoke this token", "revoke_unauthorized_account"
69
70
 
70
71
  view "authorize", "Authorize", "authorize"
71
72
  view "oauth_applications", "Oauth Applications", "oauth_applications"
@@ -279,7 +280,13 @@ module Rodauth
279
280
  next unless is_authorization_server?
280
281
 
281
282
  before_revoke_route
282
- require_oauth_application
283
+
284
+ if logged_in?
285
+ require_account
286
+ require_oauth_application_from_account
287
+ else
288
+ require_oauth_application
289
+ end
283
290
 
284
291
  r.post do
285
292
  catch_error do
@@ -386,7 +393,10 @@ module Rodauth
386
393
  end
387
394
 
388
395
  request.on(oauth_applications_id_pattern) do |id|
389
- oauth_application = db[oauth_applications_table].where(oauth_applications_id_column => id).first
396
+ oauth_application = db[oauth_applications_table]
397
+ .where(oauth_applications_id_column => id)
398
+ .where(oauth_applications_account_id_column => account_id)
399
+ .first
390
400
  next unless oauth_application
391
401
 
392
402
  scope.instance_variable_set(:@oauth_application, oauth_application)
@@ -407,7 +417,8 @@ module Rodauth
407
417
  end
408
418
 
409
419
  request.get do
410
- scope.instance_variable_set(:@oauth_applications, db[oauth_applications_table])
420
+ scope.instance_variable_set(:@oauth_applications, db[oauth_applications_table]
421
+ .where(oauth_applications_account_id_column => account_id))
411
422
  oauth_applications_view
412
423
  end
413
424
 
@@ -474,7 +485,7 @@ module Rodauth
474
485
  when String
475
486
  scope.split(" ")
476
487
  when nil
477
- [oauth_application_default_scope]
488
+ Array(oauth_application_default_scope)
478
489
  end
479
490
  end
480
491
 
@@ -684,6 +695,20 @@ module Rodauth
684
695
  authorization_required unless @oauth_application && secret_matches?(@oauth_application, client_secret)
685
696
  end
686
697
 
698
+ def require_oauth_application_from_account
699
+ ds = db[oauth_applications_table]
700
+ .join(oauth_tokens_table, Sequel[oauth_tokens_table][oauth_tokens_oauth_application_id_column] =>
701
+ Sequel[oauth_applications_table][oauth_applications_id_column])
702
+ .where(oauth_token_by_token_ds(param("token")).opts.fetch(:where, true))
703
+ .where(Sequel[oauth_applications_table][oauth_applications_account_id_column] => account_id)
704
+
705
+ @oauth_application = ds.qualify.first
706
+ return if @oauth_application
707
+
708
+ set_redirect_error_flash revoke_unauthorized_account_error_flash
709
+ redirect request.referer || "/"
710
+ end
711
+
687
712
  def secret_matches?(oauth_application, secret)
688
713
  BCrypt::Password.new(oauth_application[oauth_applications_client_secret_column]) == secret
689
714
  end
@@ -774,17 +799,21 @@ module Rodauth
774
799
  end
775
800
  end
776
801
 
777
- def oauth_token_by_token(token)
802
+ def oauth_token_by_token_ds(token)
778
803
  ds = db[oauth_tokens_table]
779
804
 
780
805
  ds = if oauth_tokens_token_hash_column
781
- ds.where(oauth_tokens_token_hash_column => generate_token_hash(token))
806
+ ds.where(Sequel[oauth_tokens_table][oauth_tokens_token_hash_column] => generate_token_hash(token))
782
807
  else
783
- ds.where(oauth_tokens_token_column => token)
808
+ ds.where(Sequel[oauth_tokens_table][oauth_tokens_token_column] => token)
784
809
  end
785
810
 
786
- ds.where(Sequel[oauth_tokens_expires_in_column] >= Sequel::CURRENT_TIMESTAMP)
787
- .where(oauth_tokens_revoked_at_column => nil).first
811
+ ds.where(Sequel[oauth_tokens_table][oauth_tokens_expires_in_column] >= Sequel::CURRENT_TIMESTAMP)
812
+ .where(Sequel[oauth_tokens_table][oauth_tokens_revoked_at_column] => nil)
813
+ end
814
+
815
+ def oauth_token_by_token(token)
816
+ oauth_token_by_token_ds(token).first
788
817
  end
789
818
 
790
819
  def oauth_token_by_refresh_token(token, revoked: false)
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Rodauth
4
4
  module OAuth
5
- VERSION = "0.7.1"
5
+ VERSION = "0.7.2"
6
6
  end
7
7
  end
data/locales/en.yml CHANGED
@@ -3,6 +3,7 @@ en:
3
3
  require_authorization_error_flash: "Please authorize to continue"
4
4
  create_oauth_application_error_flash: "There was an error registering your oauth application"
5
5
  create_oauth_application_notice_flash: "Your oauth application has been registered"
6
+ revoke_unauthorized_account_error_flash: "You are not authorized to revoke this token"
6
7
  revoke_oauth_token_notice_flash: "The oauth token has been revoked"
7
8
  oauth_authorize_title: "Authorize"
8
9
  oauth_oauth_applications_page_title: "Oauth Applications"
@@ -31,4 +32,4 @@ en:
31
32
  unsupported_transform_algorithm_message: "transform algorithm not supported"
32
33
  request_uri_not_supported_message: "request uri is unsupported"
33
34
  invalid_request_object_message: "request object is invalid"
34
- invalid_scope_message: "The Access Token expired"
35
+ invalid_scope_message: "The Access Token expired"
@@ -7,12 +7,22 @@
7
7
 
8
8
  #{
9
9
  rodauth.scopes.map do |scope|
10
- <<-HTML
11
- <div class="form-check">
12
- <input id="#{scope}" class="form-check-input" type="checkbox" name="scope[]" value="#{scope}" #{"checked disabled" if scope == rodauth.oauth_application_default_scope}>
13
- <label class="form-check-label" for="#{scope}">#{scope}</label>
14
- </div>
15
- HTML
10
+ if scope == rodauth.oauth_application_default_scope
11
+ <<-HTML
12
+ <div class="form-check">
13
+ <input id="#{scope}" class="form-check-input" type="checkbox" name="scope[]" value="#{scope}" checked disabled>
14
+ <label class="form-check-label" for="#{scope}">#{scope}</label>
15
+ <input type="hidden" name="scope[]" value="#{scope}">
16
+ </div>
17
+ HTML
18
+ else
19
+ <<-HTML
20
+ <div class="form-check">
21
+ <input id="#{scope}" class="form-check-input" type="checkbox" name="scope[]" value="#{scope}">
22
+ <label class="form-check-label" for="#{scope}">#{scope}</label>
23
+ </div>
24
+ HTML
25
+ end
16
26
  end.join
17
27
  }
18
28
 
@@ -31,4 +41,4 @@
31
41
  <input type="submit" class="btn btn-outline-primary" value="#{h(rodauth.oauth_authorize_button)}"/>
32
42
  <a href="#{rodauth.redirect_uri}?error=access_denied&error_description=The+resource+owner+or+authorization+server+denied+the+request#{ "&state=#{rodauth.param("state")}" if rodauth.param_or_nil("state")}" class="btn btn-outline-danger">Cancel</a>
33
43
  </p>
34
- </form>
44
+ </form>
@@ -10,7 +10,8 @@
10
10
  <th scope="col">Token</th>
11
11
  <th scope="col">Refresh Token</th>
12
12
  <th scope="col">Expires in</th>
13
- <th scope="col">Revoke</th>
13
+ <th scope="col">Revoked at</th>
14
+ <th scope="col">Scopes</th>
14
15
  <th scope="col"><span class="badge badge-pill badge-dark">#{@oauth_tokens.count}</span>
15
16
  </tr>
16
17
  </thead>
@@ -19,13 +20,14 @@
19
20
  @oauth_tokens.map do |oauth_token|
20
21
  <<-HTML
21
22
  <tr>
22
- <td>#{oauth_token[rodauth.oauth_tokens_token_column]}</td>
23
- <td>#{oauth_token[rodauth.oauth_tokens_refresh_token_column]}</td>
23
+ <td><code class="token">#{oauth_token[rodauth.oauth_tokens_token_column]}</code></td>
24
+ <td><code class="token">#{oauth_token[rodauth.oauth_tokens_refresh_token_column]}</code></td>
24
25
  <td>#{oauth_token[rodauth.oauth_tokens_expires_in_column]}</td>
25
26
  <td>#{oauth_token[rodauth.oauth_tokens_revoked_at_column]}</td>
27
+ <td>#{oauth_token[rodauth.oauth_tokens_scopes_column]}</td>
26
28
  <td>
27
29
  #{
28
- if !oauth_token[rodauth.oauth_tokens_revoked_at_param] && !oauth_token[rodauth.oauth_tokens_token_hash_column]
30
+ if !oauth_token[rodauth.oauth_tokens_revoked_at_column] && !oauth_token[rodauth.oauth_tokens_token_hash_column]
29
31
  <<-HTML
30
32
  <form method="post" action="#{rodauth.revoke_path}" class="form-horizontal" role="form" id="revoke-form">
31
33
  #{csrf_tag(rodauth.revoke_path) if respond_to?(:csrf_tag)}
@@ -46,4 +48,4 @@
46
48
  HTML
47
49
  end
48
50
  }
49
- </div>
51
+ </div>
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rodauth-oauth
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.7.1
4
+ version: 0.7.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Tiago Cardoso
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-12-05 00:00:00.000000000 Z
11
+ date: 2021-12-14 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description: Implementation of the OAuth 2.0 protocol on top of rodauth.
14
14
  email:
@@ -52,7 +52,8 @@ files:
52
52
  - templates/redirect_uri_field.str
53
53
  - templates/scope_field.str
54
54
  homepage: https://gitlab.com/honeyryderchuck/rodauth-oauth
55
- licenses: []
55
+ licenses:
56
+ - Apache 2.0
56
57
  metadata:
57
58
  homepage_uri: https://gitlab.com/honeyryderchuck/rodauth-oauth
58
59
  source_code_uri: https://gitlab.com/honeyryderchuck/rodauth-oauth
@@ -72,7 +73,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
72
73
  - !ruby/object:Gem::Version
73
74
  version: '0'
74
75
  requirements: []
75
- rubygems_version: 3.1.6
76
+ rubygems_version: 3.2.22
76
77
  signing_key:
77
78
  specification_version: 4
78
79
  summary: Implementation of the OAuth 2.0 protocol on top of rodauth.