rodauth-oauth 1.0.0.pre.beta1 → 1.0.0.pre.beta2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +6 -5
- data/doc/release_notes/1_0_0_beta2.md +34 -0
- data/lib/generators/rodauth/oauth/templates/app/views/rodauth/authorize.html.erb +19 -7
- 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 -6
- data/lib/rodauth/features/oauth_authorize_base.rb +16 -6
- data/lib/rodauth/features/oauth_base.rb +35 -16
- data/lib/rodauth/features/oauth_dynamic_client_registration.rb +7 -4
- data/lib/rodauth/features/oauth_implicit_grant.rb +6 -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 +231 -183
- data/lib/rodauth/features/oidc_dynamic_client_registration.rb +65 -25
- data/lib/rodauth/features/oidc_rp_initiated_logout.rb +115 -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 +3 -1
- data/locales/pt.yml +3 -1
- data/templates/authorize.str +17 -10
- metadata +5 -2
@@ -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,115 @@
|
|
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
|
+
#
|
23
|
+
# why this is done:
|
24
|
+
#
|
25
|
+
# we need to decode the id token in order to get the application, because, if the
|
26
|
+
# signing key is application-specific, we don't know how to verify the signature
|
27
|
+
# beforehand. Hence, we have to do it twice: decode-and-do-not-verify, initialize
|
28
|
+
# the @oauth_application, and then decode-and-verify.
|
29
|
+
#
|
30
|
+
claims = jwt_decode(param("id_token_hint"), verify_claims: false)
|
31
|
+
|
32
|
+
redirect_logout_with_error(oauth_invalid_client_message) unless claims
|
33
|
+
|
34
|
+
oauth_application = db[oauth_applications_table].where(oauth_applications_client_id_column => claims["aud"]).first
|
35
|
+
oauth_grant = db[oauth_grants_table]
|
36
|
+
.where(
|
37
|
+
oauth_grants_oauth_application_id_column => oauth_application[oauth_applications_id_column],
|
38
|
+
oauth_grants_account_id_column => account_id
|
39
|
+
).first
|
40
|
+
|
41
|
+
# check whether ID token belongs to currently logged-in user
|
42
|
+
redirect_logout_with_error(oauth_invalid_client_message) unless oauth_grant && claims["sub"] == jwt_subject(oauth_grant,
|
43
|
+
oauth_application)
|
44
|
+
|
45
|
+
# When an id_token_hint parameter is present, the OP MUST validate that it was the issuer of the ID Token.
|
46
|
+
redirect_logout_with_error(oauth_invalid_client_message) unless claims && claims["iss"] == oauth_jwt_issuer
|
47
|
+
|
48
|
+
# now let's logout from IdP
|
49
|
+
transaction do
|
50
|
+
before_logout
|
51
|
+
logout
|
52
|
+
after_logout
|
53
|
+
end
|
54
|
+
|
55
|
+
error_message = logout_notice_flash
|
56
|
+
|
57
|
+
if (post_logout_redirect_uri = param_or_nil("post_logout_redirect_uri"))
|
58
|
+
error_message = catch(:default_logout_redirect) do
|
59
|
+
oauth_application = db[oauth_applications_table].where(oauth_applications_client_id_column => claims["client_id"]).first
|
60
|
+
|
61
|
+
throw(:default_logout_redirect, oauth_invalid_client_message) unless oauth_application
|
62
|
+
|
63
|
+
post_logout_redirect_uris = oauth_application[oauth_applications_post_logout_redirect_uris_column].split(" ")
|
64
|
+
|
65
|
+
unless post_logout_redirect_uris.include?(post_logout_redirect_uri)
|
66
|
+
throw(:default_logout_redirect,
|
67
|
+
oauth_invalid_post_logout_redirect_uri_message)
|
68
|
+
end
|
69
|
+
|
70
|
+
if (state = param_or_nil("state"))
|
71
|
+
post_logout_redirect_uri = URI(post_logout_redirect_uri)
|
72
|
+
params = ["state=#{CGI.escape(state)}"]
|
73
|
+
params << post_logout_redirect_uri.query if post_logout_redirect_uri.query
|
74
|
+
post_logout_redirect_uri.query = params.join("&")
|
75
|
+
post_logout_redirect_uri = post_logout_redirect_uri.to_s
|
76
|
+
end
|
77
|
+
|
78
|
+
redirect(post_logout_redirect_uri)
|
79
|
+
end
|
80
|
+
|
81
|
+
end
|
82
|
+
|
83
|
+
redirect_logout_with_error(error_message)
|
84
|
+
end
|
85
|
+
|
86
|
+
redirect_response_error("invalid_request")
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
private
|
91
|
+
|
92
|
+
# Logout
|
93
|
+
|
94
|
+
def validate_oidc_logout_params
|
95
|
+
redirect_logout_with_error(oauth_invalid_client_message) unless param_or_nil("id_token_hint")
|
96
|
+
# check if valid token hint type
|
97
|
+
return unless (redirect_uri = param_or_nil("post_logout_redirect_uri"))
|
98
|
+
|
99
|
+
return if check_valid_no_fragment_uri?(redirect_uri)
|
100
|
+
|
101
|
+
redirect_logout_with_error(oauth_invalid_client_message)
|
102
|
+
end
|
103
|
+
|
104
|
+
def redirect_logout_with_error(error_message = oauth_invalid_client_message)
|
105
|
+
set_notice_flash(error_message)
|
106
|
+
redirect(logout_redirect)
|
107
|
+
end
|
108
|
+
|
109
|
+
def oauth_server_metadata_body(*)
|
110
|
+
super.tap do |data|
|
111
|
+
data[:end_session_endpoint] = oidc_logout_url
|
112
|
+
end
|
113
|
+
end
|
114
|
+
end
|
115
|
+
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
@@ -55,6 +55,7 @@ en:
|
|
55
55
|
invalid_url_message: "Invalid URL"
|
56
56
|
oauth_unsupported_token_type_message: "Invalid token type hint"
|
57
57
|
null_error_message: "is not filled"
|
58
|
+
oauth_unsupported_response_type_message: "Unsupported response type"
|
58
59
|
oauth_already_in_use_message: "error generating unique token"
|
59
60
|
oauth_expired_token_message: "the device code has expired"
|
60
61
|
oauth_access_denied_message: "the authorization request has been denied"
|
@@ -62,6 +63,7 @@ en:
|
|
62
63
|
oauth_slow_down_message: "authorization request is still pending but poll interval should be increased"
|
63
64
|
oauth_code_challenge_required_message: "code challenge required"
|
64
65
|
oauth_unsupported_transform_algorithm_message: "transform algorithm not supported"
|
65
|
-
oauth_request_uri_not_supported_message: "request uri is unsupported"
|
66
66
|
oauth_invalid_request_object_message: "request object is invalid"
|
67
67
|
oauth_invalid_scope_message: "The Access Token expired"
|
68
|
+
oauth_authorize_parameter_required: "'%{parameter}' is a required parameter"
|
69
|
+
oauth_invalid_post_logout_redirect_uri_message: "Invalid post logout redirect URI"
|
data/locales/pt.yml
CHANGED
@@ -55,6 +55,7 @@ pt:
|
|
55
55
|
invalid_url_message: "URL inválido"
|
56
56
|
oauth_unsupported_token_type_message: "Sugestão de tipo de token inválida"
|
57
57
|
null_error_message: "não está preenchido"
|
58
|
+
oauth_unsupported_response_type_message: "Tipo de resposta inválido"
|
58
59
|
oauth_already_in_use_message: "erro ao gerar token único"
|
59
60
|
oauth_expired_token_message: "o código de dispositivo expirou"
|
60
61
|
oauth_access_denied_message: "o pedido de autorização foi negado"
|
@@ -62,6 +63,7 @@ pt:
|
|
62
63
|
oauth_slow_down_message: "o pedido de autorização ainda está pendente mas o intervalo de actualização deve ser aumentado"
|
63
64
|
oauth_code_challenge_required_message: "código de negociação necessário"
|
64
65
|
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
66
|
oauth_invalid_request_object_message: "request_object é inválido"
|
67
67
|
oauth_invalid_scope_message: "O Token de acesso expirou"
|
68
|
+
oauth_authorize_parameter_required: "'%{parameter}' é um parâmetro obrigatório"
|
69
|
+
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.pre.
|
4
|
+
version: 1.0.0.pre.beta2
|
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-11-09 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rodauth
|
@@ -67,6 +67,7 @@ extra_rdoc_files:
|
|
67
67
|
- doc/release_notes/0_9_2.md
|
68
68
|
- doc/release_notes/0_9_3.md
|
69
69
|
- doc/release_notes/1_0_0_beta1.md
|
70
|
+
- doc/release_notes/1_0_0_beta2.md
|
70
71
|
files:
|
71
72
|
- CHANGELOG.md
|
72
73
|
- LICENSE.txt
|
@@ -105,6 +106,7 @@ files:
|
|
105
106
|
- doc/release_notes/0_9_2.md
|
106
107
|
- doc/release_notes/0_9_3.md
|
107
108
|
- doc/release_notes/1_0_0_beta1.md
|
109
|
+
- doc/release_notes/1_0_0_beta2.md
|
108
110
|
- lib/generators/rodauth/oauth/install_generator.rb
|
109
111
|
- lib/generators/rodauth/oauth/templates/app/models/oauth_application.rb
|
110
112
|
- lib/generators/rodauth/oauth/templates/app/models/oauth_grant.rb
|
@@ -142,6 +144,7 @@ files:
|
|
142
144
|
- lib/rodauth/features/oauth_token_revocation.rb
|
143
145
|
- lib/rodauth/features/oidc.rb
|
144
146
|
- lib/rodauth/features/oidc_dynamic_client_registration.rb
|
147
|
+
- lib/rodauth/features/oidc_rp_initiated_logout.rb
|
145
148
|
- lib/rodauth/oauth.rb
|
146
149
|
- lib/rodauth/oauth/database_extensions.rb
|
147
150
|
- lib/rodauth/oauth/http_extensions.rb
|