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.
Files changed (38) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +1 -1
  3. data/MIGRATION-GUIDE-v1.md +12 -0
  4. data/README.md +30 -15
  5. data/doc/release_notes/0_1_0.md +2 -2
  6. data/doc/release_notes/0_2_0.md +1 -1
  7. data/doc/release_notes/0_3_0.md +1 -1
  8. data/doc/release_notes/0_5_0.md +2 -2
  9. data/doc/release_notes/0_8_0.md +2 -2
  10. data/doc/release_notes/1_0_0.md +79 -0
  11. data/lib/generators/rodauth/oauth/templates/app/views/rodauth/authorize.html.erb +19 -7
  12. data/lib/generators/rodauth/oauth/templates/app/views/rodauth/authorize_error.erb +10 -0
  13. data/lib/generators/rodauth/oauth/templates/db/migrate/create_rodauth_oauth.rb +54 -43
  14. data/lib/rodauth/features/oauth_application_management.rb +2 -2
  15. data/lib/rodauth/features/oauth_authorization_code_grant.rb +31 -7
  16. data/lib/rodauth/features/oauth_authorize_base.rb +32 -10
  17. data/lib/rodauth/features/oauth_base.rb +36 -16
  18. data/lib/rodauth/features/oauth_dynamic_client_registration.rb +7 -4
  19. data/lib/rodauth/features/oauth_implicit_grant.rb +16 -5
  20. data/lib/rodauth/features/oauth_jwt.rb +3 -3
  21. data/lib/rodauth/features/oauth_jwt_base.rb +29 -6
  22. data/lib/rodauth/features/oauth_jwt_bearer_grant.rb +7 -4
  23. data/lib/rodauth/features/oauth_jwt_secured_authorization_request.rb +64 -10
  24. data/lib/rodauth/features/oauth_resource_indicators.rb +0 -4
  25. data/lib/rodauth/features/oauth_resource_server.rb +3 -3
  26. data/lib/rodauth/features/oauth_saml_bearer_grant.rb +2 -0
  27. data/lib/rodauth/features/oidc.rb +263 -187
  28. data/lib/rodauth/features/oidc_dynamic_client_registration.rb +65 -25
  29. data/lib/rodauth/features/oidc_rp_initiated_logout.rb +118 -0
  30. data/lib/rodauth/oauth/http_extensions.rb +15 -2
  31. data/lib/rodauth/oauth/ttl_store.rb +2 -0
  32. data/lib/rodauth/oauth/version.rb +1 -1
  33. data/locales/en.yml +4 -1
  34. data/locales/pt.yml +4 -1
  35. data/templates/authorize.str +17 -10
  36. data/templates/authorize_error.str +12 -0
  37. metadata +15 -12
  38. 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", register_invalid_param_message("subject_type"))
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", register_invalid_param_message("id_token_signed_response_alg"))
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 (value = @oauth_application_params[oauth_applications_id_token_encrypted_response_alg_column]) &&
92
- !oauth_jwt_jwe_algorithms_supported.include?(value)
93
- register_throw_json_response_error("invalid_client_metadata", register_invalid_param_message("id_token_encrypted_response_alg"))
94
- end
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
- if (value = @oauth_application_params[oauth_applications_id_token_encrypted_response_enc_column]) &&
97
- !oauth_jwt_jwe_encryption_methods_supported.include?(value)
98
- register_throw_json_response_error("invalid_client_metadata", register_invalid_param_message("id_token_encrypted_response_enc"))
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 (value = @oauth_application_params[oauth_applications_userinfo_signed_response_alg_column]) &&
102
- !oauth_jwt_jws_algorithms_supported.include?(value)
103
- register_throw_json_response_error("invalid_client_metadata", register_invalid_param_message("userinfo_signed_response_alg"))
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[oauth_applications_userinfo_encrypted_response_alg_column]) &&
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", register_invalid_param_message("userinfo_encrypted_response_alg"))
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[oauth_applications_userinfo_encrypted_response_enc_column]) &&
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", register_invalid_param_message("userinfo_encrypted_response_enc"))
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 defined?(oauth_applications_request_object_signing_alg_column) &&
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", register_invalid_param_message("request_object_signing_alg"))
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 defined?(oauth_applications_request_object_encryption_alg_column) &&
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", register_invalid_param_message("request_object_encryption_alg"))
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 defined?(oauth_applications_request_object_encryption_enc_column) &&
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", register_invalid_param_message("request_object_encryption_enc"))
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[/max-age=(\d+)/, 1].to_i
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
- Time.parse(response["expires"]).to_i - Time.now.to_i
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.
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Rodauth
4
4
  module OAuth
5
- VERSION = "1.0.0-beta1"
5
+ VERSION = "1.0.0"
6
6
  end
7
7
  end
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"
@@ -9,12 +9,13 @@
9
9
  }
10
10
  <p class="lead">
11
11
  #{
12
- rodauth.authorize_page_lead(name: <<-LINK
13
- <a target="_blank" href="#{h(rodauth.oauth_application[rodauth.oauth_applications_homepage_url_column])}">
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
- <<-HTML
64
- <div class="form-check">
65
- <input id="#{scope}" class="form-check-input" type="checkbox" name="scope[]" value="#{h(scope)}">
66
- <label class="form-check-label" for="#{scope}">#{h(scope)}</label>
67
- </div>
68
- HTML
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=\"acr\" value=\"#{rodauth.param("acr_values")}\"/>" if rodauth.features.include?(:oidc) && rodauth.param_or_nil("acr_values")}
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|
@@ -0,0 +1,12 @@
1
+ <div class="container">
2
+ <div class="alert alert-danger">
3
+ <p>
4
+ #{@error}
5
+ </p>
6
+ </div>
7
+ <p class="text-center">
8
+ <a href="#{@back_url}" class="btn btn-outline-danger">
9
+ #{rodauth.oauth_cancel_button}
10
+ </a>
11
+ </p>
12
+ </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: 1.0.0.pre.beta1
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-10-21 00:00:00.000000000 Z
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/1_0_0_beta1.md
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/1_0_0_beta1.md
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/honeyryderchuck/rodauth-oauth
172
+ homepage: https://gitlab.com/os85/rodauth-oauth
170
173
  licenses:
171
174
  - Apache-2.0
172
175
  metadata:
173
- homepage_uri: https://honeyryderchuck.gitlab.io/rodauth-oauth/
174
- documentation_uri: https://honeyryderchuck.gitlab.io/rodauth-oauth/rdoc/
175
- bug_tracker_uri: https://gitlab.com/honeyryderchuck/rodauth-oauth/issues
176
- source_code_uri: https://gitlab.com/honeyryderchuck/rodauth-oauth
177
- changelog_uri: https://gitlab.com/honeyryderchuck/rodauth-oauth/-/blob/master/CHANGELOG.md
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: 1.3.1
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.