rodauth-oauth 1.0.0.pre.beta1 → 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +1 -1
- data/MIGRATION-GUIDE-v1.md +12 -0
- data/README.md +30 -15
- data/doc/release_notes/0_1_0.md +2 -2
- data/doc/release_notes/0_2_0.md +1 -1
- data/doc/release_notes/0_3_0.md +1 -1
- data/doc/release_notes/0_5_0.md +2 -2
- data/doc/release_notes/0_8_0.md +2 -2
- data/doc/release_notes/1_0_0.md +79 -0
- data/lib/generators/rodauth/oauth/templates/app/views/rodauth/authorize.html.erb +19 -7
- data/lib/generators/rodauth/oauth/templates/app/views/rodauth/authorize_error.erb +10 -0
- data/lib/generators/rodauth/oauth/templates/db/migrate/create_rodauth_oauth.rb +54 -43
- data/lib/rodauth/features/oauth_application_management.rb +2 -2
- data/lib/rodauth/features/oauth_authorization_code_grant.rb +31 -7
- data/lib/rodauth/features/oauth_authorize_base.rb +32 -10
- data/lib/rodauth/features/oauth_base.rb +36 -16
- data/lib/rodauth/features/oauth_dynamic_client_registration.rb +7 -4
- data/lib/rodauth/features/oauth_implicit_grant.rb +16 -5
- data/lib/rodauth/features/oauth_jwt.rb +3 -3
- data/lib/rodauth/features/oauth_jwt_base.rb +29 -6
- data/lib/rodauth/features/oauth_jwt_bearer_grant.rb +7 -4
- data/lib/rodauth/features/oauth_jwt_secured_authorization_request.rb +64 -10
- data/lib/rodauth/features/oauth_resource_indicators.rb +0 -4
- data/lib/rodauth/features/oauth_resource_server.rb +3 -3
- data/lib/rodauth/features/oauth_saml_bearer_grant.rb +2 -0
- data/lib/rodauth/features/oidc.rb +263 -187
- data/lib/rodauth/features/oidc_dynamic_client_registration.rb +65 -25
- data/lib/rodauth/features/oidc_rp_initiated_logout.rb +118 -0
- data/lib/rodauth/oauth/http_extensions.rb +15 -2
- data/lib/rodauth/oauth/ttl_store.rb +2 -0
- data/lib/rodauth/oauth/version.rb +1 -1
- data/locales/en.yml +4 -1
- data/locales/pt.yml +4 -1
- data/templates/authorize.str +17 -10
- data/templates/authorize_error.str +12 -0
- metadata +15 -12
- data/doc/release_notes/1_0_0_beta1.md +0 -38
@@ -51,9 +51,25 @@ module Rodauth
|
|
51
51
|
end
|
52
52
|
end
|
53
53
|
|
54
|
+
if features.include?(:oauth_jwt_secured_authorization_request)
|
55
|
+
if (value = @oauth_application_params[oauth_applications_request_uris_column])
|
56
|
+
if value.is_a?(Array)
|
57
|
+
@oauth_application_params[oauth_applications_request_uris_column] = value.each do |req_uri|
|
58
|
+
unless check_valid_uri?(req_uri)
|
59
|
+
register_throw_json_response_error("invalid_redirect_uri", register_invalid_uri_message(req_uri))
|
60
|
+
end
|
61
|
+
end.join(" ")
|
62
|
+
else
|
63
|
+
register_throw_json_response_error("invalid_redirect_uri", register_invalid_uri_message(value))
|
64
|
+
end
|
65
|
+
elsif oauth_require_request_uri_registration
|
66
|
+
register_throw_json_response_error("invalid_client_metadata", register_required_param_message("request_uris"))
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
54
70
|
if (value = @oauth_application_params[oauth_applications_subject_type_column])
|
55
71
|
unless %w[pairwise public].include?(value)
|
56
|
-
register_throw_json_response_error("invalid_client_metadata",
|
72
|
+
register_throw_json_response_error("invalid_client_metadata", register_invalid_client_metadata_message("subject_type", value))
|
57
73
|
end
|
58
74
|
|
59
75
|
if value == "pairwise"
|
@@ -84,51 +100,75 @@ module Rodauth
|
|
84
100
|
register_throw_json_response_error("invalid_client_metadata", register_invalid_param_message("id_token_signed_response_alg"))
|
85
101
|
end
|
86
102
|
elsif !oauth_jwt_jws_algorithms_supported.include?(value)
|
87
|
-
register_throw_json_response_error("invalid_client_metadata",
|
103
|
+
register_throw_json_response_error("invalid_client_metadata",
|
104
|
+
register_invalid_client_metadata_message("id_token_signed_response_alg", value))
|
88
105
|
end
|
89
106
|
end
|
90
107
|
|
91
|
-
if (
|
92
|
-
|
93
|
-
|
94
|
-
|
108
|
+
if features.include?(:oauth_jwt_secured_authorization_request)
|
109
|
+
if defined?(oauth_applications_request_object_signing_alg_column) &&
|
110
|
+
(value = @oauth_application_params[oauth_applications_request_object_signing_alg_column]) &&
|
111
|
+
!oauth_jwt_jws_algorithms_supported.include?(value) && !(value == "none" && oauth_request_object_signing_alg_allow_none)
|
112
|
+
register_throw_json_response_error("invalid_client_metadata",
|
113
|
+
register_invalid_client_metadata_message("request_object_signing_alg", value))
|
114
|
+
end
|
95
115
|
|
96
|
-
|
97
|
-
|
98
|
-
|
116
|
+
if defined?(oauth_applications_request_object_encryption_alg_column) &&
|
117
|
+
(value = @oauth_application_params[oauth_applications_request_object_encryption_alg_column]) &&
|
118
|
+
!oauth_jwt_jwe_algorithms_supported.include?(value)
|
119
|
+
register_throw_json_response_error("invalid_client_metadata",
|
120
|
+
register_invalid_client_metadata_message("request_object_encryption_alg", value))
|
121
|
+
end
|
122
|
+
|
123
|
+
if defined?(oauth_applications_request_object_encryption_enc_column) &&
|
124
|
+
(value = @oauth_application_params[oauth_applications_request_object_encryption_enc_column]) &&
|
125
|
+
!oauth_jwt_jwe_encryption_methods_supported.include?(value)
|
126
|
+
register_throw_json_response_error("invalid_client_metadata",
|
127
|
+
register_invalid_client_metadata_message("request_object_encryption_enc", value))
|
128
|
+
end
|
99
129
|
end
|
100
130
|
|
101
|
-
if (
|
102
|
-
|
103
|
-
|
131
|
+
if features.include?(:oidc_rp_initiated_logout) && (defined?(oauth_applications_post_logout_redirect_uris_column) &&
|
132
|
+
(value = @oauth_application_params[oauth_applications_post_logout_redirect_uris_column]))
|
133
|
+
if value.is_a?(Array)
|
134
|
+
@oauth_application_params[oauth_applications_post_logout_redirect_uris_column] = value.each do |redirect_uri|
|
135
|
+
unless check_valid_uri?(redirect_uri)
|
136
|
+
register_throw_json_response_error("invalid_client_metadata", register_invalid_uri_message(redirect_uri))
|
137
|
+
end
|
138
|
+
end.join(" ")
|
139
|
+
else
|
140
|
+
register_throw_json_response_error("invalid_client_metadata", register_invalid_uri_message(value))
|
141
|
+
end
|
104
142
|
end
|
105
143
|
|
106
|
-
if (value = @oauth_application_params[
|
144
|
+
if (value = @oauth_application_params[oauth_applications_id_token_encrypted_response_alg_column]) &&
|
107
145
|
!oauth_jwt_jwe_algorithms_supported.include?(value)
|
108
|
-
register_throw_json_response_error("invalid_client_metadata",
|
146
|
+
register_throw_json_response_error("invalid_client_metadata",
|
147
|
+
register_invalid_client_metadata_message("id_token_encrypted_response_alg", value))
|
109
148
|
end
|
110
149
|
|
111
|
-
if (value = @oauth_application_params[
|
150
|
+
if (value = @oauth_application_params[oauth_applications_id_token_encrypted_response_enc_column]) &&
|
112
151
|
!oauth_jwt_jwe_encryption_methods_supported.include?(value)
|
113
|
-
register_throw_json_response_error("invalid_client_metadata",
|
152
|
+
register_throw_json_response_error("invalid_client_metadata",
|
153
|
+
register_invalid_client_metadata_message("id_token_encrypted_response_enc", value))
|
114
154
|
end
|
115
155
|
|
116
|
-
if
|
117
|
-
(value = @oauth_application_params[oauth_applications_request_object_signing_alg_column]) &&
|
156
|
+
if (value = @oauth_application_params[oauth_applications_userinfo_signed_response_alg_column]) &&
|
118
157
|
!oauth_jwt_jws_algorithms_supported.include?(value)
|
119
|
-
register_throw_json_response_error("invalid_client_metadata",
|
158
|
+
register_throw_json_response_error("invalid_client_metadata",
|
159
|
+
register_invalid_client_metadata_message("userinfo_signed_response_alg", value))
|
120
160
|
end
|
121
161
|
|
122
|
-
if
|
123
|
-
(value = @oauth_application_params[oauth_applications_request_object_encryption_alg_column]) &&
|
162
|
+
if (value = @oauth_application_params[oauth_applications_userinfo_encrypted_response_alg_column]) &&
|
124
163
|
!oauth_jwt_jwe_algorithms_supported.include?(value)
|
125
|
-
register_throw_json_response_error("invalid_client_metadata",
|
164
|
+
register_throw_json_response_error("invalid_client_metadata",
|
165
|
+
register_invalid_client_metadata_message("userinfo_encrypted_response_alg", value))
|
126
166
|
end
|
127
167
|
|
128
|
-
if
|
129
|
-
(value = @oauth_application_params[oauth_applications_request_object_encryption_enc_column]) &&
|
168
|
+
if (value = @oauth_application_params[oauth_applications_userinfo_encrypted_response_enc_column]) &&
|
130
169
|
!oauth_jwt_jwe_encryption_methods_supported.include?(value)
|
131
|
-
register_throw_json_response_error("invalid_client_metadata",
|
170
|
+
register_throw_json_response_error("invalid_client_metadata",
|
171
|
+
register_invalid_client_metadata_message("userinfo_encrypted_response_enc", value))
|
132
172
|
end
|
133
173
|
end
|
134
174
|
|
@@ -0,0 +1,118 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "rodauth/oauth"
|
4
|
+
|
5
|
+
module Rodauth
|
6
|
+
Feature.define(:oidc_rp_initiated_logout, :OidcRpInitiatedLogout) do
|
7
|
+
depends :oidc
|
8
|
+
|
9
|
+
auth_value_method :oauth_applications_post_logout_redirect_uris_column, :post_logout_redirect_uris
|
10
|
+
translatable_method :oauth_invalid_post_logout_redirect_uri_message, "Invalid post logout redirect URI"
|
11
|
+
|
12
|
+
# /oidc-logout
|
13
|
+
auth_server_route(:oidc_logout) do |r|
|
14
|
+
require_authorizable_account
|
15
|
+
before_oidc_logout_route
|
16
|
+
|
17
|
+
# OpenID Providers MUST support the use of the HTTP GET and POST methods
|
18
|
+
r.on method: %i[get post] do
|
19
|
+
catch_error do
|
20
|
+
validate_oidc_logout_params
|
21
|
+
|
22
|
+
oauth_application = nil
|
23
|
+
|
24
|
+
if (id_token_hint = param_or_nil("id_token_hint"))
|
25
|
+
#
|
26
|
+
# why this is done:
|
27
|
+
#
|
28
|
+
# we need to decode the id token in order to get the application, because, if the
|
29
|
+
# signing key is application-specific, we don't know how to verify the signature
|
30
|
+
# beforehand. Hence, we have to do it twice: decode-and-do-not-verify, initialize
|
31
|
+
# the @oauth_application, and then decode-and-verify.
|
32
|
+
#
|
33
|
+
claims = jwt_decode(id_token_hint, verify_claims: false)
|
34
|
+
|
35
|
+
redirect_logout_with_error(oauth_invalid_client_message) unless claims
|
36
|
+
|
37
|
+
oauth_application = db[oauth_applications_table].where(oauth_applications_client_id_column => claims["aud"]).first
|
38
|
+
oauth_grant = db[oauth_grants_table]
|
39
|
+
.where(
|
40
|
+
oauth_grants_oauth_application_id_column => oauth_application[oauth_applications_id_column],
|
41
|
+
oauth_grants_account_id_column => account_id
|
42
|
+
).first
|
43
|
+
|
44
|
+
# check whether ID token belongs to currently logged-in user
|
45
|
+
redirect_logout_with_error(oauth_invalid_client_message) unless oauth_grant && claims["sub"] == jwt_subject(oauth_grant,
|
46
|
+
oauth_application)
|
47
|
+
|
48
|
+
# When an id_token_hint parameter is present, the OP MUST validate that it was the issuer of the ID Token.
|
49
|
+
redirect_logout_with_error(oauth_invalid_client_message) unless claims && claims["iss"] == oauth_jwt_issuer
|
50
|
+
end
|
51
|
+
|
52
|
+
# now let's logout from IdP
|
53
|
+
transaction do
|
54
|
+
before_logout
|
55
|
+
logout
|
56
|
+
after_logout
|
57
|
+
end
|
58
|
+
|
59
|
+
error_message = logout_notice_flash
|
60
|
+
|
61
|
+
if (post_logout_redirect_uri = param_or_nil("post_logout_redirect_uri"))
|
62
|
+
error_message = catch(:default_logout_redirect) do
|
63
|
+
oauth_application = db[oauth_applications_table].where(oauth_applications_client_id_column => claims["client_id"]).first
|
64
|
+
|
65
|
+
throw(:default_logout_redirect, oauth_invalid_client_message) unless oauth_application
|
66
|
+
|
67
|
+
post_logout_redirect_uris = oauth_application[oauth_applications_post_logout_redirect_uris_column].split(" ")
|
68
|
+
|
69
|
+
unless post_logout_redirect_uris.include?(post_logout_redirect_uri)
|
70
|
+
throw(:default_logout_redirect,
|
71
|
+
oauth_invalid_post_logout_redirect_uri_message)
|
72
|
+
end
|
73
|
+
|
74
|
+
if (state = param_or_nil("state"))
|
75
|
+
post_logout_redirect_uri = URI(post_logout_redirect_uri)
|
76
|
+
params = ["state=#{CGI.escape(state)}"]
|
77
|
+
params << post_logout_redirect_uri.query if post_logout_redirect_uri.query
|
78
|
+
post_logout_redirect_uri.query = params.join("&")
|
79
|
+
post_logout_redirect_uri = post_logout_redirect_uri.to_s
|
80
|
+
end
|
81
|
+
|
82
|
+
redirect(post_logout_redirect_uri)
|
83
|
+
end
|
84
|
+
|
85
|
+
end
|
86
|
+
|
87
|
+
redirect_logout_with_error(error_message)
|
88
|
+
end
|
89
|
+
|
90
|
+
redirect_response_error("invalid_request")
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
private
|
95
|
+
|
96
|
+
# Logout
|
97
|
+
|
98
|
+
def validate_oidc_logout_params
|
99
|
+
# check if valid token hint type
|
100
|
+
return unless (redirect_uri = param_or_nil("post_logout_redirect_uri"))
|
101
|
+
|
102
|
+
return if check_valid_no_fragment_uri?(redirect_uri)
|
103
|
+
|
104
|
+
redirect_logout_with_error(oauth_invalid_client_message)
|
105
|
+
end
|
106
|
+
|
107
|
+
def redirect_logout_with_error(error_message = oauth_invalid_client_message)
|
108
|
+
set_notice_flash(error_message)
|
109
|
+
redirect(logout_redirect)
|
110
|
+
end
|
111
|
+
|
112
|
+
def oauth_server_metadata_body(*)
|
113
|
+
super.tap do |data|
|
114
|
+
data[:end_session_endpoint] = oidc_logout_url
|
115
|
+
end
|
116
|
+
end
|
117
|
+
end
|
118
|
+
end
|
@@ -16,6 +16,9 @@ module Rodauth
|
|
16
16
|
|
17
17
|
http = Net::HTTP.new(uri.host, uri.port)
|
18
18
|
http.use_ssl = uri.scheme == "https"
|
19
|
+
http.open_timeout = 15
|
20
|
+
http.read_timeout = 15
|
21
|
+
http.write_timeout = 15 if http.respond_to?(:write_timeout)
|
19
22
|
|
20
23
|
if form_data
|
21
24
|
request = Net::HTTP::Post.new(uri.request_uri)
|
@@ -44,9 +47,19 @@ module Rodauth
|
|
44
47
|
response = http_request(uri, *args)
|
45
48
|
ttl = if response.key?("cache-control")
|
46
49
|
cache_control = response["cache-control"]
|
47
|
-
cache_control
|
50
|
+
if cache_control.include?("no-cache")
|
51
|
+
nil
|
52
|
+
else
|
53
|
+
max_age = cache_control[/max-age=(\d+)/, 1].to_i
|
54
|
+
max_age.zero? ? nil : max_age
|
55
|
+
end
|
48
56
|
elsif response.key?("expires")
|
49
|
-
|
57
|
+
expires = response["expires"]
|
58
|
+
begin
|
59
|
+
Time.parse(expires).to_i - Time.now.to_i
|
60
|
+
rescue ArgumentError
|
61
|
+
nil
|
62
|
+
end
|
50
63
|
end
|
51
64
|
|
52
65
|
[JSON.parse(response.body, symbolize_names: true), ttl]
|
@@ -28,6 +28,8 @@ class Rodauth::OAuth::TtlStore
|
|
28
28
|
|
29
29
|
payload, ttl = block.call
|
30
30
|
|
31
|
+
return payload unless ttl
|
32
|
+
|
31
33
|
@store_mutex.synchronize do
|
32
34
|
# given that the block call triggers network, and two requests for the same key be processed
|
33
35
|
# at the same time, this ensures the first one wins.
|
data/locales/en.yml
CHANGED
@@ -9,6 +9,7 @@ en:
|
|
9
9
|
user_code_not_found_error_flash: "No device to authorize with the given user code"
|
10
10
|
authorize_page_title: "Authorize"
|
11
11
|
authorize_page_lead: "The application %{name} would like to access your data."
|
12
|
+
authorize_error_page_title: "Authorize Error"
|
12
13
|
oauth_cancel_button: "Cancel"
|
13
14
|
oauth_applications_page_title: "Oauth Applications"
|
14
15
|
oauth_application_page_title: "Oauth Application"
|
@@ -55,6 +56,7 @@ en:
|
|
55
56
|
invalid_url_message: "Invalid URL"
|
56
57
|
oauth_unsupported_token_type_message: "Invalid token type hint"
|
57
58
|
null_error_message: "is not filled"
|
59
|
+
oauth_unsupported_response_type_message: "Unsupported response type"
|
58
60
|
oauth_already_in_use_message: "error generating unique token"
|
59
61
|
oauth_expired_token_message: "the device code has expired"
|
60
62
|
oauth_access_denied_message: "the authorization request has been denied"
|
@@ -62,6 +64,7 @@ en:
|
|
62
64
|
oauth_slow_down_message: "authorization request is still pending but poll interval should be increased"
|
63
65
|
oauth_code_challenge_required_message: "code challenge required"
|
64
66
|
oauth_unsupported_transform_algorithm_message: "transform algorithm not supported"
|
65
|
-
oauth_request_uri_not_supported_message: "request uri is unsupported"
|
66
67
|
oauth_invalid_request_object_message: "request object is invalid"
|
67
68
|
oauth_invalid_scope_message: "The Access Token expired"
|
69
|
+
oauth_authorize_parameter_required: "Invalid or missing '%{parameter}'"
|
70
|
+
oauth_invalid_post_logout_redirect_uri_message: "Invalid post logout redirect URI"
|
data/locales/pt.yml
CHANGED
@@ -9,6 +9,7 @@ pt:
|
|
9
9
|
user_code_not_found_error_flash: "Não existe nenhum dispositivo a ser autorizado com o código de usuário inserido"
|
10
10
|
authorize_page_title: "Autorizar"
|
11
11
|
authorize_page_lead: "O aplicativo %{name} gostaria de aceder aos seus dados."
|
12
|
+
authorize_error_page_title: Erro de autorização
|
12
13
|
oauth_cancel_button: "Cancelar"
|
13
14
|
oauth_applications_page_title: "Aplicativos OAuth"
|
14
15
|
oauth_application_page_title: "Aplicativo Oauth"
|
@@ -55,6 +56,7 @@ pt:
|
|
55
56
|
invalid_url_message: "URL inválido"
|
56
57
|
oauth_unsupported_token_type_message: "Sugestão de tipo de token inválida"
|
57
58
|
null_error_message: "não está preenchido"
|
59
|
+
oauth_unsupported_response_type_message: "Tipo de resposta inválido"
|
58
60
|
oauth_already_in_use_message: "erro ao gerar token único"
|
59
61
|
oauth_expired_token_message: "o código de dispositivo expirou"
|
60
62
|
oauth_access_denied_message: "o pedido de autorização foi negado"
|
@@ -62,6 +64,7 @@ pt:
|
|
62
64
|
oauth_slow_down_message: "o pedido de autorização ainda está pendente mas o intervalo de actualização deve ser aumentado"
|
63
65
|
oauth_code_challenge_required_message: "código de negociação necessário"
|
64
66
|
oauth_unsupported_transform_algorithm_message: "algoritmo de transformação não suportado"
|
65
|
-
oauth_request_uri_not_supported_message: "request_uri não é suportado"
|
66
67
|
oauth_invalid_request_object_message: "request_object é inválido"
|
67
68
|
oauth_invalid_scope_message: "O Token de acesso expirou"
|
69
|
+
oauth_authorize_parameter_required: "'%{parameter}' inválido ou em falta"
|
70
|
+
oauth_invalid_post_logout_redirect_uri_message: "URI de redireccionamento pós-logout inválido"
|
data/templates/authorize.str
CHANGED
@@ -9,12 +9,13 @@
|
|
9
9
|
}
|
10
10
|
<p class="lead">
|
11
11
|
#{
|
12
|
-
rodauth.
|
13
|
-
|
12
|
+
application_uri = rodauth.oauth_application[rodauth.oauth_applications_homepage_url_column]
|
13
|
+
application_name = application_uri ? (<<-LINK) : rodauth.oauth_application[rodauth.oauth_applications_name_column]
|
14
|
+
<a target="_blank" href="#{h(application_uri)}">
|
14
15
|
#{h(rodauth.oauth_application[rodauth.oauth_applications_name_column])}
|
15
16
|
</a>
|
16
17
|
LINK
|
17
|
-
)
|
18
|
+
rodauth.authorize_page_lead(name: application_name)
|
18
19
|
}
|
19
20
|
</p>
|
20
21
|
<div class="list-group">
|
@@ -60,12 +61,16 @@
|
|
60
61
|
|
61
62
|
#{
|
62
63
|
rodauth.authorize_scopes.map do |scope|
|
63
|
-
|
64
|
-
<
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
64
|
+
if rodauth.features.include?(:oidc) && scope == "offline_access"
|
65
|
+
"<input type=\"hidden\" name=\"scope[]\" value=\"#{scope}\" />"
|
66
|
+
else
|
67
|
+
<<-HTML
|
68
|
+
<div class="form-check">
|
69
|
+
<input id="#{scope}" class="form-check-input" type="checkbox" name="scope[]" value="#{h(scope)}">
|
70
|
+
<label class="form-check-label" for="#{scope}">#{h(scope)}</label>
|
71
|
+
</div>
|
72
|
+
HTML
|
73
|
+
end
|
69
74
|
end.join
|
70
75
|
}
|
71
76
|
|
@@ -77,10 +82,12 @@
|
|
77
82
|
#{"<input type=\"hidden\" name=\"redirect_uri\" value=\"#{rodauth.redirect_uri}\"/>" if rodauth.param_or_nil("redirect_uri")}
|
78
83
|
#{"<input type=\"hidden\" name=\"code_challenge\" value=\"#{rodauth.param("code_challenge")}\"/>" if rodauth.features.include?(:oauth_pkce) && rodauth.param_or_nil("code_challenge")}
|
79
84
|
#{"<input type=\"hidden\" name=\"code_challenge_method\" value=\"#{rodauth.param("code_challenge_method")}\"/>" if rodauth.features.include?(:oauth_pkce) && rodauth.param_or_nil("code_challenge_method")}
|
85
|
+
#{"<input type=\"hidden\" name=\"prompt\" value=\"#{rodauth.param("prompt")}\"/>" if rodauth.features.include?(:oidc) && rodauth.param_or_nil("prompt")}
|
80
86
|
#{"<input type=\"hidden\" name=\"nonce\" value=\"#{rodauth.param("nonce")}\"/>" if rodauth.features.include?(:oidc) && rodauth.param_or_nil("nonce")}
|
81
87
|
#{"<input type=\"hidden\" name=\"ui_locales\" value=\"#{rodauth.param("ui_locales")}\"/>" if rodauth.features.include?(:oidc) && rodauth.param_or_nil("ui_locales")}
|
82
88
|
#{"<input type=\"hidden\" name=\"claims_locales\" value=\"#{rodauth.param("claims_locales")}\"/>" if rodauth.features.include?(:oidc) && rodauth.param_or_nil("claims_locales")}
|
83
|
-
#{"<input type=\"hidden\" name=\"
|
89
|
+
#{"<input type=\"hidden\" name=\"claims\" value=\"#{h(rodauth.param("claims"))}\"/>" if rodauth.features.include?(:oidc) && rodauth.param_or_nil("claims")}
|
90
|
+
#{"<input type=\"hidden\" name=\"acr_values\" value=\"#{rodauth.param("acr_values")}\"/>" if rodauth.features.include?(:oidc) && rodauth.param_or_nil("acr_values")}
|
84
91
|
#{
|
85
92
|
if rodauth.features.include?(:oauth_resource_indicators) && rodauth.resource_indicators
|
86
93
|
rodauth.resource_indicators.map do |resource|
|
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: 1.0.0
|
4
|
+
version: 1.0.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Tiago Cardoso
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2022-
|
11
|
+
date: 2022-12-15 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rodauth
|
@@ -66,7 +66,7 @@ extra_rdoc_files:
|
|
66
66
|
- doc/release_notes/0_9_1.md
|
67
67
|
- doc/release_notes/0_9_2.md
|
68
68
|
- doc/release_notes/0_9_3.md
|
69
|
-
- doc/release_notes/
|
69
|
+
- doc/release_notes/1_0_0.md
|
70
70
|
files:
|
71
71
|
- CHANGELOG.md
|
72
72
|
- LICENSE.txt
|
@@ -104,11 +104,12 @@ files:
|
|
104
104
|
- doc/release_notes/0_9_1.md
|
105
105
|
- doc/release_notes/0_9_2.md
|
106
106
|
- doc/release_notes/0_9_3.md
|
107
|
-
- doc/release_notes/
|
107
|
+
- doc/release_notes/1_0_0.md
|
108
108
|
- lib/generators/rodauth/oauth/install_generator.rb
|
109
109
|
- lib/generators/rodauth/oauth/templates/app/models/oauth_application.rb
|
110
110
|
- lib/generators/rodauth/oauth/templates/app/models/oauth_grant.rb
|
111
111
|
- lib/generators/rodauth/oauth/templates/app/views/rodauth/authorize.html.erb
|
112
|
+
- lib/generators/rodauth/oauth/templates/app/views/rodauth/authorize_error.erb
|
112
113
|
- lib/generators/rodauth/oauth/templates/app/views/rodauth/device_search.html.erb
|
113
114
|
- lib/generators/rodauth/oauth/templates/app/views/rodauth/device_verification.html.erb
|
114
115
|
- lib/generators/rodauth/oauth/templates/app/views/rodauth/new_oauth_application.html.erb
|
@@ -142,6 +143,7 @@ files:
|
|
142
143
|
- lib/rodauth/features/oauth_token_revocation.rb
|
143
144
|
- lib/rodauth/features/oidc.rb
|
144
145
|
- lib/rodauth/features/oidc_dynamic_client_registration.rb
|
146
|
+
- lib/rodauth/features/oidc_rp_initiated_logout.rb
|
145
147
|
- lib/rodauth/oauth.rb
|
146
148
|
- lib/rodauth/oauth/database_extensions.rb
|
147
149
|
- lib/rodauth/oauth/http_extensions.rb
|
@@ -152,6 +154,7 @@ files:
|
|
152
154
|
- locales/en.yml
|
153
155
|
- locales/pt.yml
|
154
156
|
- templates/authorize.str
|
157
|
+
- templates/authorize_error.str
|
155
158
|
- templates/client_secret_field.str
|
156
159
|
- templates/description_field.str
|
157
160
|
- templates/device_search.str
|
@@ -166,15 +169,15 @@ files:
|
|
166
169
|
- templates/oauth_grants.str
|
167
170
|
- templates/redirect_uri_field.str
|
168
171
|
- templates/scope_field.str
|
169
|
-
homepage: https://gitlab.com/
|
172
|
+
homepage: https://gitlab.com/os85/rodauth-oauth
|
170
173
|
licenses:
|
171
174
|
- Apache-2.0
|
172
175
|
metadata:
|
173
|
-
homepage_uri: https://
|
174
|
-
documentation_uri: https://
|
175
|
-
bug_tracker_uri: https://gitlab.com/
|
176
|
-
source_code_uri: https://gitlab.com/
|
177
|
-
changelog_uri: https://gitlab.com/
|
176
|
+
homepage_uri: https://os85.gitlab.io/rodauth-oauth/
|
177
|
+
documentation_uri: https://os85.gitlab.io/rodauth-oauth/rdoc/
|
178
|
+
bug_tracker_uri: https://gitlab.com/os85/rodauth-oauth/issues
|
179
|
+
source_code_uri: https://gitlab.com/os85/rodauth-oauth
|
180
|
+
changelog_uri: https://gitlab.com/os85/rodauth-oauth/-/blob/master/CHANGELOG.md
|
178
181
|
rubygems_mfa_required: 'true'
|
179
182
|
post_install_message:
|
180
183
|
rdoc_options: []
|
@@ -187,9 +190,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
187
190
|
version: 2.5.0
|
188
191
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
189
192
|
requirements:
|
190
|
-
- - "
|
193
|
+
- - ">="
|
191
194
|
- !ruby/object:Gem::Version
|
192
|
-
version:
|
195
|
+
version: '0'
|
193
196
|
requirements: []
|
194
197
|
rubygems_version: 3.2.32
|
195
198
|
signing_key:
|
@@ -1,38 +0,0 @@
|
|
1
|
-
## 1.0.0-beta1 (21/10/2022)
|
2
|
-
|
3
|
-
### Breaking changes
|
4
|
-
|
5
|
-
The full description of breaking changes, and suggestions on how to make the migration smoother, can be found in the [migration guide](https://gitlab.com/honeyryderchuck/rodauth-oauth/-/blob/6465b8522a78cf0037a55d3d4b81f68f7811be68/MIGRATION-GUIDE-v1.md).
|
6
|
-
|
7
|
-
A short list of the main highlights:
|
8
|
-
|
9
|
-
|
10
|
-
* Ruby 2.5 or higher is required.
|
11
|
-
* `oauth_http_mac` feature removed.
|
12
|
-
* `oauth_tokens` table (and resource) were removed (only `oauth_applications` and `oauth_grants`, access and refresh tokens are now properties of the latter).
|
13
|
-
* access and refresh tokens hashed by default when stored in the database.
|
14
|
-
* default oauth response mode is `"form_post"`.
|
15
|
-
* oauth specific features require explicit enablement of respective features (no more `enable :oauth`)
|
16
|
-
* refresh token policy is "rotation" by default
|
17
|
-
|
18
|
-
### Features
|
19
|
-
|
20
|
-
The following helpers are exposed in the `rodauth` object:
|
21
|
-
|
22
|
-
* `current_oauth_account` - returns the dataset row for the `rodauth` account associated to an oauth access token in the "authorization" header.
|
23
|
-
* `current_oauth_application` - returns the dataset row for the oauth application associated to an oauth access token in the "authorization" header.
|
24
|
-
|
25
|
-
When used in `rails` via `rodauth-rails`, both are exposed directly as controller helpers.
|
26
|
-
|
27
|
-
#### `oauth_resource_server` plugin
|
28
|
-
|
29
|
-
This plugin can be used as a convenience when configuring resource servers.
|
30
|
-
|
31
|
-
### Improvements
|
32
|
-
|
33
|
-
* `:oauth_introspect` plugin: OAuth introspection endpoint exposes the token's `"username"` claim.
|
34
|
-
* endpoint client authentication supports "client credentials grant" access tokens.
|
35
|
-
|
36
|
-
### Bugfixes
|
37
|
-
|
38
|
-
* fixed `oidc` calculation of `"auth_time"` claim.
|