rodauth-oauth 0.5.1 → 0.7.1
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/CHANGELOG.md +49 -0
- data/README.md +15 -8
- data/lib/generators/rodauth/oauth/views_generator.rb +1 -1
- data/lib/rodauth/features/oauth.rb +29 -22
- data/lib/rodauth/features/oauth_http_mac.rb +1 -1
- data/lib/rodauth/features/oauth_jwt.rb +3 -3
- data/lib/rodauth/features/oauth_saml.rb +1 -1
- data/lib/rodauth/features/oidc.rb +14 -2
- data/lib/rodauth/oauth/version.rb +1 -1
- data/locales/en.yml +34 -0
- data/templates/authorize.str +1 -1
- data/templates/oauth_application.str +2 -2
- data/templates/oauth_tokens.str +3 -3
- metadata +4 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 0e6a9da692805069b0250b975d86c02f81af6bd1cc80ce24ecbc92ea6d3fef14
|
4
|
+
data.tar.gz: c4996d52e4119f6a2d8fde3f0149f8deadb609324fb894c99d5fbcdf836efd4c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: d8ec7872e8997019182b04a40c11f5db1e272de0bcceada11f870d706f2646aca911239d1f01876f26126e0936938a6ea233f312304410ce0c35d3964ebe7f1f
|
7
|
+
data.tar.gz: 4a5df07c4da7c30803d7cb513c87ca6296b205dcdae89eb3ab475aa6780a4b37acd0e3b3bae5d43372eb8f9d3a92bd30a761ad7cda269d18d7bc16658f719768
|
data/CHANGELOG.md
CHANGED
@@ -2,6 +2,55 @@
|
|
2
2
|
|
3
3
|
## master
|
4
4
|
|
5
|
+
### 0.7.1 (05/12/2021)
|
6
|
+
|
7
|
+
#### Improvements
|
8
|
+
|
9
|
+
* Adapted the `rodauth-i18n` configuration to comply with the guidelines for `v0.2.0` (which is the defacto minimmal supported version).
|
10
|
+
|
11
|
+
#### Bugfixes
|
12
|
+
|
13
|
+
* `convert_timestamp` was removed from the templates, as it's private API.
|
14
|
+
* Several missing or wrong URLs in templates fixed (authorize form was wrongly processing scopes when none was selected).
|
15
|
+
|
16
|
+
### 0.7.0 (02/12/2021)
|
17
|
+
|
18
|
+
#### Features
|
19
|
+
|
20
|
+
* Internationalization (i18n) support by hooking on [rodauth-i18n](https://github.com/janko/rodauth-i18n).
|
21
|
+
* Sets all text using `translatable_method`.
|
22
|
+
* Provides english translations for all `rodauth-oauth` related user facing text.
|
23
|
+
|
24
|
+
#### Improvements
|
25
|
+
|
26
|
+
* Enable CORS requests for OpenID configuration endpoint (@ianks)
|
27
|
+
* Introspect endpoint now exposes the `exp` token property (@gmanley)
|
28
|
+
|
29
|
+
#### Bugfixes
|
30
|
+
|
31
|
+
* on rotation policy, although the first refresh token was invalidated, a new one wasn't being provided. This change allows a new refresh token to be generated and exposed in the response (@gmanley)
|
32
|
+
|
33
|
+
#### Chore
|
34
|
+
|
35
|
+
Setting `rodauth` minimal supported version to `2.0.0`.
|
36
|
+
|
37
|
+
### 0.6.1 (08/09/2021)
|
38
|
+
|
39
|
+
#### Bugfixes
|
40
|
+
|
41
|
+
* Fixed rails view templates escaping.
|
42
|
+
* Fixed declaration of authorize template in the generator.
|
43
|
+
|
44
|
+
### 0.6.0 (21/05/2021)
|
45
|
+
|
46
|
+
### Improvements
|
47
|
+
|
48
|
+
* RBS signatures
|
49
|
+
|
50
|
+
### Chore
|
51
|
+
|
52
|
+
* Ruby 3 and Truffleruby are now officially supported and tested in CI.
|
53
|
+
|
5
54
|
### 0.5.1 (19/03/2021)
|
6
55
|
|
7
56
|
#### Improvements
|
data/README.md
CHANGED
@@ -173,7 +173,7 @@ puts payload #=> {"access_token" => "awr23f3h8f9d2h89...", "token_type" => "Bear
|
|
173
173
|
|
174
174
|
#### Revoking tokens
|
175
175
|
|
176
|
-
Token revocation can be done both by the
|
176
|
+
Token revocation can be done both by the identity owner or the application owner, and can therefore be done either online (browser-based form) or server-to-server. Here's an example using server-to-server:
|
177
177
|
|
178
178
|
```ruby
|
179
179
|
require "httpx"
|
@@ -516,7 +516,7 @@ payload = json.parse(response.to_s)
|
|
516
516
|
puts payload #=> {
|
517
517
|
# "access_token" => ....
|
518
518
|
# "mac_key" => ....
|
519
|
-
# "mac_algorithm" =>
|
519
|
+
# "mac_algorithm" =>
|
520
520
|
```
|
521
521
|
|
522
522
|
which you'll be able to use to generate the mac signature to send in the "Authorization" header.
|
@@ -565,7 +565,7 @@ plugin :rodauth do
|
|
565
565
|
enable :oauth_jwt
|
566
566
|
oauth_jwt_key rsa_private
|
567
567
|
oauth_jwt_public_key rsa_public
|
568
|
-
oauth_jwt_algorithm "RS256"
|
568
|
+
oauth_jwt_algorithm "RS256"
|
569
569
|
end
|
570
570
|
```
|
571
571
|
|
@@ -581,7 +581,7 @@ plugin :rodauth do
|
|
581
581
|
enable :oauth_jwt
|
582
582
|
oauth_jwt_jwk_key rsa_private
|
583
583
|
oauth_jwt_jwk_public_key rsa_public
|
584
|
-
oauth_jwt_jwk_algorithm "RS256"
|
584
|
+
oauth_jwt_jwk_algorithm "RS256"
|
585
585
|
end
|
586
586
|
```
|
587
587
|
|
@@ -627,17 +627,25 @@ puts payload #=> {
|
|
627
627
|
|
628
628
|
You'll still need the "oauth_tokens" table, however you can remove the "token" column.
|
629
629
|
|
630
|
+
#### Internationalization (i18n)
|
631
|
+
|
632
|
+
`rodauth-oauth` supports translating all user-facing text found in all pages and forms, by integrating with [rodauth-i18n](https://github.com/janko/rodauth-i18n). Just set it up in your application and `rodauth` configuration.
|
633
|
+
|
634
|
+
Default translations shipping with `rodauth-oauth` can be found [in this directory](https://gitlab.com/honeyryderchuck/rodauth-oauth/-/tree/master/locales). If they're not available for the languages you'd like to support, consider getting them translated from the english text, and contributing them to this repository via a Merge Request.
|
635
|
+
|
636
|
+
(This feature is available since `v0.7`.)
|
637
|
+
|
630
638
|
#### Caveats
|
631
639
|
|
632
640
|
Although very handy for the mentioned use case, one can't revoke a JWT token on demand (it must expire first).
|
633
641
|
|
634
642
|
## Ruby support policy
|
635
643
|
|
636
|
-
The minimum Ruby version required to run `rodauth-oauth` is 2.3 . Besides that, it should support all rubies that rodauth and roda support, including JRuby and
|
644
|
+
The minimum Ruby version required to run `rodauth-oauth` is 2.3 . Besides that, it should support all rubies that rodauth and roda support, including JRuby and truffleruby.
|
637
645
|
|
638
|
-
###
|
646
|
+
### Rails
|
639
647
|
|
640
|
-
If you're interested in using this library
|
648
|
+
If you're interested in using this library with rails, be sure to check `rodauth-rails` policy, as it supports rails 5.2 upwards.
|
641
649
|
|
642
650
|
## Development
|
643
651
|
|
@@ -646,4 +654,3 @@ After checking out the repo, run `bundle install` to install dependencies. Then,
|
|
646
654
|
## Contributing
|
647
655
|
|
648
656
|
Bug reports and pull requests are welcome on Gitlab at https://gitlab.com/honeyryderchuck/rodauth-oauth.
|
649
|
-
|
@@ -9,7 +9,7 @@ module Rodauth::OAuth
|
|
9
9
|
source_root "#{__dir__}/templates"
|
10
10
|
namespace "rodauth:oauth:views"
|
11
11
|
|
12
|
-
DEFAULT = %w[
|
12
|
+
DEFAULT = %w[authorize].freeze
|
13
13
|
VIEWS = {
|
14
14
|
oauth_authorize: DEFAULT,
|
15
15
|
oauth_applications: %w[oauth_applications oauth_application new_oauth_application]
|
@@ -9,7 +9,7 @@ require "rodauth/oauth/ttl_store"
|
|
9
9
|
require "rodauth/oauth/database_extensions"
|
10
10
|
|
11
11
|
module Rodauth
|
12
|
-
Feature.define(:oauth) do
|
12
|
+
Feature.define(:oauth, :Oauth) do
|
13
13
|
# RUBY EXTENSIONS
|
14
14
|
unless Regexp.method_defined?(:match?)
|
15
15
|
# If you wonder why this is there: the oauth feature uses a refinement to enhance the
|
@@ -168,24 +168,24 @@ module Rodauth
|
|
168
168
|
auth_value_method :oauth_token_type, "bearer"
|
169
169
|
auth_value_method :oauth_refresh_token_protection_policy, "none" # can be: none, sender_constrained, rotation
|
170
170
|
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
171
|
+
translatable_method :invalid_client_message, "Invalid client"
|
172
|
+
translatable_method :invalid_grant_type_message, "Invalid grant type"
|
173
|
+
translatable_method :invalid_grant_message, "Invalid grant"
|
174
|
+
translatable_method :invalid_scope_message, "Invalid scope"
|
175
175
|
|
176
|
-
|
177
|
-
|
176
|
+
translatable_method :invalid_url_message, "Invalid URL"
|
177
|
+
translatable_method :unsupported_token_type_message, "Invalid token type hint"
|
178
178
|
|
179
|
-
|
180
|
-
|
181
|
-
|
179
|
+
translatable_method :unique_error_message, "is already in use"
|
180
|
+
translatable_method :null_error_message, "is not filled"
|
181
|
+
translatable_method :already_in_use_message, "error generating unique token"
|
182
182
|
auth_value_method :already_in_use_error_code, "invalid_request"
|
183
183
|
|
184
184
|
# PKCE
|
185
185
|
auth_value_method :code_challenge_required_error_code, "invalid_request"
|
186
|
-
|
186
|
+
translatable_method :code_challenge_required_message, "code challenge required"
|
187
187
|
auth_value_method :unsupported_transform_algorithm_error_code, "invalid_request"
|
188
|
-
|
188
|
+
translatable_method :unsupported_transform_algorithm_message, "transform algorithm not supported"
|
189
189
|
|
190
190
|
# METADATA
|
191
191
|
auth_value_method :oauth_metadata_service_documentation, nil
|
@@ -466,10 +466,6 @@ module Rodauth
|
|
466
466
|
end
|
467
467
|
end
|
468
468
|
|
469
|
-
def initialize(scope)
|
470
|
-
@scope = scope
|
471
|
-
end
|
472
|
-
|
473
469
|
def scopes
|
474
470
|
scope = request.params["scope"]
|
475
471
|
case scope
|
@@ -568,13 +564,14 @@ module Rodauth
|
|
568
564
|
self.class.__send__(:include, Rodauth::OAuth::ExtendDatabase(db))
|
569
565
|
|
570
566
|
# Check whether we can reutilize db entries for the same account / application pair
|
571
|
-
one_oauth_token_per_account =
|
572
|
-
|
573
|
-
definition[:
|
574
|
-
definition[:columns] == oauth_tokens_unique_columns
|
575
|
-
end
|
567
|
+
one_oauth_token_per_account = db.indexes(oauth_tokens_table).values.any? do |definition|
|
568
|
+
definition[:unique] &&
|
569
|
+
definition[:columns] == oauth_tokens_unique_columns
|
576
570
|
end
|
571
|
+
|
577
572
|
self.class.send(:define_method, :__one_oauth_token_per_account) { one_oauth_token_per_account }
|
573
|
+
|
574
|
+
i18n_register(File.expand_path(File.join(__dir__, "..", "..", "..", "locales"))) if features.include?(:i18n)
|
578
575
|
end
|
579
576
|
|
580
577
|
def use_date_arithmetic?
|
@@ -1108,6 +1105,14 @@ module Rodauth
|
|
1108
1105
|
oauth_tokens_scopes_column => oauth_token[oauth_tokens_scopes_column]
|
1109
1106
|
}
|
1110
1107
|
|
1108
|
+
refresh_token = oauth_unique_id_generator
|
1109
|
+
|
1110
|
+
if oauth_tokens_refresh_token_hash_column
|
1111
|
+
insert_params[oauth_tokens_refresh_token_hash_column] = generate_token_hash(refresh_token)
|
1112
|
+
else
|
1113
|
+
insert_params[oauth_tokens_refresh_token_column] = refresh_token
|
1114
|
+
end
|
1115
|
+
|
1111
1116
|
# revoke the refresh token
|
1112
1117
|
oauth_tokens_ds.where(oauth_tokens_id_column => oauth_token[oauth_tokens_id_column])
|
1113
1118
|
.update(oauth_tokens_revoked_at_column => Sequel::CURRENT_TIMESTAMP)
|
@@ -1121,6 +1126,7 @@ module Rodauth
|
|
1121
1126
|
end
|
1122
1127
|
|
1123
1128
|
oauth_token[oauth_tokens_token_column] = token
|
1129
|
+
oauth_token[oauth_tokens_refresh_token_column] = refresh_token if refresh_token
|
1124
1130
|
oauth_token
|
1125
1131
|
end
|
1126
1132
|
end
|
@@ -1146,7 +1152,8 @@ module Rodauth
|
|
1146
1152
|
scope: token[oauth_tokens_scopes_column],
|
1147
1153
|
client_id: oauth_application[oauth_applications_client_id_column],
|
1148
1154
|
# username
|
1149
|
-
token_type: oauth_token_type
|
1155
|
+
token_type: oauth_token_type,
|
1156
|
+
exp: token[oauth_tokens_expires_in_column].to_i
|
1150
1157
|
}
|
1151
1158
|
end
|
1152
1159
|
|
@@ -3,7 +3,7 @@
|
|
3
3
|
require "rodauth/oauth/ttl_store"
|
4
4
|
|
5
5
|
module Rodauth
|
6
|
-
Feature.define(:oauth_jwt) do
|
6
|
+
Feature.define(:oauth_jwt, :OauthJwt) do
|
7
7
|
depends :oauth
|
8
8
|
|
9
9
|
JWKS = OAuth::TtlStore.new
|
@@ -33,8 +33,8 @@ module Rodauth
|
|
33
33
|
auth_value_method :oauth_jwt_jwe_copyright, nil
|
34
34
|
auth_value_method :oauth_jwt_audience, nil
|
35
35
|
|
36
|
-
|
37
|
-
|
36
|
+
translatable_method :request_uri_not_supported_message, "request uri is unsupported"
|
37
|
+
translatable_method :invalid_request_object_message, "request object is invalid"
|
38
38
|
|
39
39
|
auth_value_methods(
|
40
40
|
:jwt_encode,
|
@@ -1,7 +1,7 @@
|
|
1
1
|
# frozen-string-literal: true
|
2
2
|
|
3
3
|
module Rodauth
|
4
|
-
Feature.define(:oidc) do
|
4
|
+
Feature.define(:oidc, :Oidc) do
|
5
5
|
# https://openid.net/specs/openid-connect-core-1_0.html#StandardClaims
|
6
6
|
OIDC_SCOPES_MAP = {
|
7
7
|
"profile" => %i[name family_name given_name middle_name nickname preferred_username
|
@@ -68,7 +68,7 @@ module Rodauth
|
|
68
68
|
auth_value_method :oauth_grants_nonce_column, :nonce
|
69
69
|
auth_value_method :oauth_tokens_nonce_column, :nonce
|
70
70
|
|
71
|
-
|
71
|
+
translatable_method :invalid_scope_message, "The Access Token expired"
|
72
72
|
|
73
73
|
auth_value_method :webfinger_relation, "http://openid.net/specs/connect/1.0/issuer"
|
74
74
|
|
@@ -186,6 +186,8 @@ module Rodauth
|
|
186
186
|
|
187
187
|
def openid_configuration(alt_issuer = nil)
|
188
188
|
request.on(".well-known/openid-configuration") do
|
189
|
+
allow_cors(request)
|
190
|
+
|
189
191
|
request.get do
|
190
192
|
json_response_success(openid_configuration_body(alt_issuer), cache: true)
|
191
193
|
end
|
@@ -493,5 +495,15 @@ module Rodauth
|
|
493
495
|
(val.respond_to?(:empty?) && val.empty?)
|
494
496
|
end
|
495
497
|
end
|
498
|
+
|
499
|
+
def allow_cors(request)
|
500
|
+
return unless request.request_method == "OPTIONS"
|
501
|
+
|
502
|
+
response["Access-Control-Allow-Origin"] = "*"
|
503
|
+
response["Access-Control-Allow-Methods"] = "GET, OPTIONS"
|
504
|
+
response["Access-Control-Max-Age"] = "3600"
|
505
|
+
response.status = 200
|
506
|
+
request.halt
|
507
|
+
end
|
496
508
|
end
|
497
509
|
end
|
data/locales/en.yml
ADDED
@@ -0,0 +1,34 @@
|
|
1
|
+
en:
|
2
|
+
rodauth:
|
3
|
+
require_authorization_error_flash: "Please authorize to continue"
|
4
|
+
create_oauth_application_error_flash: "There was an error registering your oauth application"
|
5
|
+
create_oauth_application_notice_flash: "Your oauth application has been registered"
|
6
|
+
revoke_oauth_token_notice_flash: "The oauth token has been revoked"
|
7
|
+
oauth_authorize_title: "Authorize"
|
8
|
+
oauth_oauth_applications_page_title: "Oauth Applications"
|
9
|
+
oauth_oauth_application_page_title: "Oauth Application"
|
10
|
+
oauth_new_oauth_application_page_title: "New Oauth Application"
|
11
|
+
oauth_oauth_tokens_page_title: "Oauth Tokens"
|
12
|
+
name_label: "Name"
|
13
|
+
description_label: "Description"
|
14
|
+
scopes_label: "Scopes"
|
15
|
+
homepage_url_label: "Homepage URL"
|
16
|
+
redirect_uri_label: "Redirect URL"
|
17
|
+
client_secret_label: "Client Secret"
|
18
|
+
client_id_label: "Client ID"
|
19
|
+
oauth_applications_button: "Register"
|
20
|
+
oauth_authorize_button: "Authorize"
|
21
|
+
oauth_token_revoke_button: "Revoke"
|
22
|
+
oauth_authorize_post_button: "Back to Client Application"
|
23
|
+
invalid_grant_message: "Invalid grant"
|
24
|
+
invalid_scope_message: "Invalid scope"
|
25
|
+
invalid_url_message: "Invalid URL"
|
26
|
+
unsupported_token_type_message: "Invalid token type hint"
|
27
|
+
unique_error_message: "is already in use"
|
28
|
+
null_error_message: "is not filled"
|
29
|
+
already_in_use_message: "error generating unique token"
|
30
|
+
code_challenge_required_message: "code challenge required"
|
31
|
+
unsupported_transform_algorithm_message: "transform algorithm not supported"
|
32
|
+
request_uri_not_supported_message: "request uri is unsupported"
|
33
|
+
invalid_request_object_message: "request object is invalid"
|
34
|
+
invalid_scope_message: "The Access Token expired"
|
data/templates/authorize.str
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
<form method="post" class="form-horizontal" role="form" id="authorize-form">
|
1
|
+
<form method="post" action="#{rodauth.authorize_path}" class="form-horizontal" role="form" id="authorize-form">
|
2
2
|
#{csrf_tag(rodauth.authorize_path) if respond_to?(:csrf_tag)}
|
3
3
|
<p class="lead">The application #{rodauth.oauth_application[rodauth.oauth_applications_name_column]} would like to access your data.</p>
|
4
4
|
|
@@ -7,5 +7,5 @@
|
|
7
7
|
end.join
|
8
8
|
}
|
9
9
|
</dl>
|
10
|
-
<a href="
|
11
|
-
</div>
|
10
|
+
<a href="#{rodauth.oauth_applications_path}/#{@oauth_application[:id]}/#{rodauth.oauth_tokens_path}" class="btn btn-outline-secondary">Oauth Tokens</a>
|
11
|
+
</div>
|
data/templates/oauth_tokens.str
CHANGED
@@ -21,14 +21,14 @@
|
|
21
21
|
<tr>
|
22
22
|
<td>#{oauth_token[rodauth.oauth_tokens_token_column]}</td>
|
23
23
|
<td>#{oauth_token[rodauth.oauth_tokens_refresh_token_column]}</td>
|
24
|
-
<td>#{
|
25
|
-
<td>#{
|
24
|
+
<td>#{oauth_token[rodauth.oauth_tokens_expires_in_column]}</td>
|
25
|
+
<td>#{oauth_token[rodauth.oauth_tokens_revoked_at_column]}</td>
|
26
26
|
<td>
|
27
27
|
#{
|
28
28
|
if !oauth_token[rodauth.oauth_tokens_revoked_at_param] && !oauth_token[rodauth.oauth_tokens_token_hash_column]
|
29
29
|
<<-HTML
|
30
30
|
<form method="post" action="#{rodauth.revoke_path}" class="form-horizontal" role="form" id="revoke-form">
|
31
|
-
#{csrf_tag(rodauth.
|
31
|
+
#{csrf_tag(rodauth.revoke_path) if respond_to?(:csrf_tag)}
|
32
32
|
#{rodauth.input_field_string("token_type_hint", "revoke-token-type-hint", :value => "access_token", :type=>"hidden")}
|
33
33
|
#{rodauth.input_field_string("token", "revoke-token", :value => oauth_token[rodauth.oauth_tokens_token_column], :type=>"hidden")}
|
34
34
|
#{rodauth.button(rodauth.oauth_token_revoke_button)}
|
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.
|
4
|
+
version: 0.7.1
|
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-
|
11
|
+
date: 2021-12-05 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:
|
@@ -39,6 +39,7 @@ files:
|
|
39
39
|
- lib/rodauth/oauth/railtie.rb
|
40
40
|
- lib/rodauth/oauth/ttl_store.rb
|
41
41
|
- lib/rodauth/oauth/version.rb
|
42
|
+
- locales/en.yml
|
42
43
|
- templates/authorize.str
|
43
44
|
- templates/client_secret_field.str
|
44
45
|
- templates/description_field.str
|
@@ -71,7 +72,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
71
72
|
- !ruby/object:Gem::Version
|
72
73
|
version: '0'
|
73
74
|
requirements: []
|
74
|
-
rubygems_version: 3.
|
75
|
+
rubygems_version: 3.1.6
|
75
76
|
signing_key:
|
76
77
|
specification_version: 4
|
77
78
|
summary: Implementation of the OAuth 2.0 protocol on top of rodauth.
|