rodauth 2.8.0 → 2.9.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: a39430563fc9d81e610b8a28b5c044eedd7ebd361d6294f9bd02687ce2d24c27
4
- data.tar.gz: a852e9713602b807bb7566b3db4038a6fda0ae0d2b90bf4b1ce2e45429c8efd2
3
+ metadata.gz: a51cd006e762abd197f16ec9b8337cd54bf15206fcc2ce3a83cb1c424bb83845
4
+ data.tar.gz: 41e21158bee2b7ef8c75a93b035a5ff08c0245e5719aecbf783a818a860329b6
5
5
  SHA512:
6
- metadata.gz: ba8f83d3f9afc3f1bcca6f649e925b1b3f795002dc980ae5bfb219885a74c69c34bbacaccda83c153bf9f799f328970cd900a3abf5966b88956dc3476ef3f9f8
7
- data.tar.gz: 9d2042a183a7fdc941cd2b8716aba581861b9e1831574eac3241979ab32e2fe2076baf94e3ab0782487aa34d4e7f98f063035c22dcd7088f1a4fd1f1b83a7e6d
6
+ metadata.gz: fb2c83005f29f8e8f2ea36ae97111c2b2108dc370ce1fee624c6cd27fd96eaa70be8f1471d9b9cb4a8b652b55e2277cce3489514bf56624bceb2c4f52413b580
7
+ data.tar.gz: 6bf8b23187ab6935cd33259b4ee546281df100641b7927c9e03e531f591a451ba5d56b50b8621cbc7948ad8807253dbded5da0b85247e70db7aa5db1d2be765a
data/CHANGELOG CHANGED
@@ -1,3 +1,9 @@
1
+ === 2.9.0 (2021-01-22)
2
+
3
+ * Split jwt feature into json and jwt features, with the json feature using standard session support (janko, jeremyevans) (#145)
4
+
5
+ * Mark remember cookie as only transmitted over HTTPS by default if created via an HTTPS request (janko) (#144)
6
+
1
7
  === 2.8.0 (2021-01-06)
2
8
 
3
9
  * [SECURITY] Set HttpOnly on remember cookie by default so it cannot be accessed by Javascript (janko) (#142)
@@ -52,7 +52,8 @@ HTML and JSON API for all supported features.
52
52
  * Session Expiration
53
53
  * Active Sessions (Prevent session reuse after logout, allow logout of all sessions)
54
54
  * Single Session (Only one active session per account)
55
- * JWT (JSON API support for all other features)
55
+ * JSON (JSON API support for all other features)
56
+ * JWT (JSON Web Token support for all other features)
56
57
  * JWT Refresh (Access & Refresh Token)
57
58
  * JWT CORS (Cross-Origin Resource Sharing)
58
59
  * Update Password Hash (when hash cost changes)
@@ -872,6 +873,7 @@ view the appropriate file in the doc directory.
872
873
  * {Disallow Password Reuse}[rdoc-ref:doc/disallow_password_reuse.rdoc]
873
874
  * {Email Authentication}[rdoc-ref:doc/email_auth.rdoc]
874
875
  * {HTTP Basic Auth}[rdoc-ref:doc/http_basic_auth.rdoc]
876
+ * {JSON}[rdoc-ref:doc/json.rdoc]
875
877
  * {JWT CORS}[rdoc-ref:doc/jwt_cors.rdoc]
876
878
  * {JWT Refresh}[rdoc-ref:doc/jwt_refresh.rdoc]
877
879
  * {JWT}[rdoc-ref:doc/jwt.rdoc]
@@ -1320,7 +1322,13 @@ use the necessary *_email_body configuration options to specify
1320
1322
  the body of the emails.
1321
1323
 
1322
1324
  The JWT feature enables JSON API support for all of the other features
1323
- that Rodauth ships with.
1325
+ that Rodauth ships with. If you would like JSON API access that still uses
1326
+ rack session for storing session data, enable the JSON feature instead:
1327
+
1328
+ plugin :rodauth, :json=>true do
1329
+ enable :login, :logout, :json
1330
+ only_json? true # if you want to only handle JSON requests
1331
+ end
1324
1332
 
1325
1333
  === Adding Custom Methods to the +rodauth+ Object
1326
1334
 
@@ -0,0 +1,47 @@
1
+ = Documentation for JSON Feature
2
+
3
+ The json feature adds support for JSON API access for all other
4
+ features that ship with Rodauth.
5
+
6
+ When this feature is used, all other features become accessible via a
7
+ JSON API. The JSON API uses the POST method for all requests, using
8
+ the same parameter names as the features uses. JSON API requests to
9
+ Rodauth endpoints that use a method other than POST will result in a
10
+ 405 Method Not Allowed response.
11
+
12
+ Responses are returned as JSON hashes. In case of an error, the +error+
13
+ entry is set to an error message, and the <tt>field-error</tt> entry is set to
14
+ an array containing the field name and the error message for that field.
15
+ Successful requests by default store a +success+ entry with a success
16
+ message, though that can be disabled.
17
+
18
+ The session state is managed in the rack session, so make sure that
19
+ CSRF protection is enabled. This will be the case when passing the
20
+ <tt>json: true</tt> option when loading the rodauth plugin. If you
21
+ want to only handle JSON requests, set <tt>only_json? true</tt> in
22
+ your rodauth configuration.
23
+
24
+ If you want token-based authentication sent via the Authorization
25
+ header, consider using the jwt feature.
26
+
27
+ == Auth Value Methods
28
+
29
+ json_accept_regexp :: The regexp to use to check the Accept header for JSON if +json_check_accept?+ is true.
30
+ json_check_accept? :: Whether to check the Accept header to see if the client supports JSON responses, true by default.
31
+ json_non_post_error_message :: The error message to use when a JSON non-POST request is sent.
32
+ json_not_accepted_error_message :: The error message to display if +json_check_accept?+ is true and the Accept header is present but does not match +json_request_content_type_regexp+.
33
+ json_request_content_type_regexp :: The regexp to use to recognize a request as a json request.
34
+ json_response_content_type :: The content type to set for json responses, <tt>application/json</tt> by default.
35
+ json_response_custom_error_status? :: Whether to use custom error statuses, instead of always using +json_response_error_status+, true by default, can be set to false for backwards compatibility with Rodauth 1.
36
+ json_response_error_key :: The JSON result key containing an error message, +error+ by default.
37
+ json_response_error_status :: The HTTP status code to use for JSON error responses if not using custom error statuses, 400 by default.
38
+ json_response_field_error_key :: The JSON result key containing an field error message, <tt>field-error</tt> by default.
39
+ json_response_success_key :: The JSON result key containing a success message for successful request, if set. +success+ by default.
40
+ non_json_request_error_message :: The error message to use when a non-JSON request is sent and +only_json?+ is set.
41
+ only_json? :: Whether to have Rodauth only allow JSON requests. True by default if <tt>json: :only</tt> option was given when loading the plugin. If set, rodauth endpoints will issue an error for non-JSON requests.
42
+ use_json? :: Whether to return a JSON response. By default, a JSON response is returned if +only_json?+ is true, or if the request uses a json content type.
43
+
44
+ == Auth Methods
45
+
46
+ json_request? :: Whether the current request is a JSON request, looks at the Content-Type request header by default.
47
+ json_response_body(hash) :: The body to use for JSON response. By default just converts hash to JSON. Can be used to reformat JSON output in arbitrary ways.
@@ -2,19 +2,7 @@
2
2
 
3
3
  The jwt feature adds support for JSON API access for all other features
4
4
  that ship with Rodauth, using JWT (JSON Web Tokens) to hold the
5
- session information.
6
-
7
- When this feature is used, all other features become accessible via a
8
- JSON API. The JSON API uses the POST method for all requests, using
9
- the same parameter names as the features uses. JSON API requests to
10
- Rodauth endpoints that use a method other than POST will result in a
11
- 405 Method Not Allowed response.
12
-
13
- Responses are returned as JSON hashes. In case of an error, the +error+
14
- entry is set to an error message, and the <tt>field-error</tt> entry is set to
15
- an array containing the field name and the error message for that field.
16
- Successful requests by default store a +success+ entry with a success
17
- message, though that can be disabled.
5
+ session information. It depends on the json feature.
18
6
 
19
7
  In order to use this feature, you have to set the +jwt_secret+ configuration
20
8
  option the secret used to cryptographically protect the token.
@@ -41,32 +29,17 @@ from +rodauth.session+.
41
29
  == Auth Value Methods
42
30
 
43
31
  invalid_jwt_format_error_message :: The error message to use when a JWT with an invalid format is submitted in the Authorization header.
44
- json_accept_regexp :: The regexp to use to check the Accept header for JSON if +jwt_check_accept?+ is true.
45
- json_non_post_error_message :: The error message to use when a JSON non-POST request is sent.
46
- json_not_accepted_error_message :: The error message to display if +jwt_check_accept?+ is true and the Accept header is present but does not match +json_request_content_type_regexp+.
47
- json_request_content_type_regexp :: The regexp to use to recognize a request as a json request.
48
- json_response_content_type :: The content type to set for json responses, <tt>application/json</tt> by default.
49
- json_response_custom_error_status? :: Whether to use custom error statuses, instead of always using +json_response_error_status+, true by default, can be set to false for backwards compatibility with Rodauth 1.
50
- json_response_error_key :: The JSON result key containing an error message, +error+ by default.
51
- json_response_error_status :: The HTTP status code to use for JSON error responses if not using custom error statuses, 400 by default.
52
- json_response_field_error_key :: The JSON result key containing an field error message, <tt>field-error</tt> by default.
53
- json_response_success_key :: The JSON result key containing a success message for successful request, if set. +success+ by default.
54
32
  jwt_algorithm :: The JWT algorithm to use, +HS256+ by default.
55
33
  jwt_authorization_ignore :: A regexp matched against the Authorization header, which skips JWT processing if it matches. By default, HTTP Basic and Digest authentication are ignored.
56
34
  jwt_authorization_remove :: A regexp to remove from the Authorization header before processing the JWT. By default, a Bearer prefix is removed.
57
- jwt_check_accept? :: Whether to check the Accept header to see if the client supports JSON responses, true by default, can be set to false for backwards compatibility with Rodauth 1.
58
35
  jwt_decode_opts :: An optional hash to pass to +JWT.decode+. Can be used to set JWT verifiers.
59
36
  jwt_secret :: The JWT secret to use. Access to this should be protected the same as a session secret.
60
37
  jwt_session_key :: A key to nest the session hash under in the JWT payload. nil by default, for no nesting.
61
38
  jwt_symbolize_deeply? :: Whether to symbolize the session hash deeply. false by default.
62
- non_json_request_error_message :: The error message to use when a non-JSON request is sent and +only_json?+ is set.
63
- only_json? :: Whether to have Rodauth only allow JSON requests. True by default if <tt>json: :only</tt> option was given when loading the plugin. If set, rodauth endpoints will issue an error for non-JSON requests.
64
39
  use_jwt? :: Whether to use the JWT in the Authorization header for authentication information. If false, falls back to using the rack session. By default, the Authorization header is used if it is present, if +only_json?+ is true, or if the request uses a json content type.
65
40
 
66
41
  == Auth Methods
67
42
 
68
- json_request? :: Whether the current request is a JSON request, looks at the Content-Type request header by default.
69
- json_response_body(hash) :: The body to use for JSON response. By default just converts hash to JSON. Can be used to reformat JSON output in arbitrary ways.
70
43
  jwt_session_hash :: The session hash used to create the session_jwt. Can be used to set JWT claims.
71
44
  jwt_token :: Retrieve the JWT token from the request, by default taking it from the Authorization header.
72
45
  session_jwt :: An encoded JWT for the current session.
@@ -0,0 +1,21 @@
1
+ = New Features
2
+
3
+ * A json feature has been extracted from the existing jwt feature.
4
+ This feature allows for the same JSON API previously supported
5
+ by the JWT feature, but stores the session information in the
6
+ Rack session instead of in a separate JWT. This makes it
7
+ significantly easier to have certain pages use the JSON API,
8
+ and other pages the HTML forms.
9
+
10
+ = Other Improvements
11
+
12
+ * If the remember cookie is created in an SSL request, the Secure
13
+ flag is added by default, so the cookie will not be transmitted
14
+ in non-SSL requests.
15
+
16
+ = Backwards Compatibility
17
+
18
+ * Rodauth configurations that use the remember feature and support
19
+ requests over both http and https and want to have the remember
20
+ cookie transmitted over both should now include :secure=>false in
21
+ remember_cookie_options.
@@ -35,7 +35,7 @@ raw_remember_token_deadline :: A deadline before which to allow a raw remember t
35
35
  remember_additional_form_tags :: HTML fragment containing additional form tags to use on the change remember setting form.
36
36
  remember_button :: The text to use for the change remember settings button.
37
37
  remember_cookie_key :: The cookie name to use for the remember token.
38
- remember_cookie_options :: Any options to set for the remember cookie. By default, the `:path` cookie option is set to `/`, and `:httponly` is set to `true`.
38
+ remember_cookie_options :: Any options to set for the remember cookie. By default, the `:path` cookie option is set to `/` and `:httponly` is set to `true`. Also, `:secure` is set to `true` by default if the current request is an HTTPS request.
39
39
  remember_deadline_column :: The column name in the +remember_table+ storing the deadline after which the token will be ignored.
40
40
  remember_deadline_interval :: The amount of time for which to remember accounts, 14 days by default. Only used if +set_deadline_values?+ is true.
41
41
  remember_disable_label :: The label for disabling remembering.
@@ -0,0 +1,189 @@
1
+ # frozen-string-literal: true
2
+
3
+ module Rodauth
4
+ Feature.define(:json, :Json) do
5
+ translatable_method :json_not_accepted_error_message, 'Unsupported Accept header. Must accept "application/json" or compatible content type'
6
+ translatable_method :json_non_post_error_message, 'non-POST method used in JSON API'
7
+ auth_value_method :json_accept_regexp, /(?:(?:\*|\bapplication)\/\*|\bapplication\/(?:vnd\.api\+)?json\b)/i
8
+ auth_value_method :json_check_accept?, true
9
+ auth_value_method :json_request_content_type_regexp, /\bapplication\/(?:vnd\.api\+)?json\b/i
10
+ auth_value_method :json_response_content_type, 'application/json'
11
+ auth_value_method :json_response_custom_error_status?, true
12
+ auth_value_method :json_response_error_status, 400
13
+ auth_value_method :json_response_error_key, "error"
14
+ auth_value_method :json_response_field_error_key, "field-error"
15
+ auth_value_method :json_response_success_key, "success"
16
+ translatable_method :non_json_request_error_message, 'Only JSON format requests are allowed'
17
+
18
+ auth_value_methods(
19
+ :only_json?,
20
+ :use_json?,
21
+ )
22
+
23
+ auth_methods(
24
+ :json_request?,
25
+ )
26
+
27
+ auth_private_methods :json_response_body
28
+
29
+ def set_field_error(field, message)
30
+ return super unless use_json?
31
+ json_response[json_response_field_error_key] = [field, message]
32
+ end
33
+
34
+ def set_error_flash(message)
35
+ return super unless use_json?
36
+ json_response[json_response_error_key] = message
37
+ end
38
+
39
+ def set_redirect_error_flash(message)
40
+ return super unless use_json?
41
+ json_response[json_response_error_key] = message
42
+ end
43
+
44
+ def set_notice_flash(message)
45
+ return super unless use_json?
46
+ json_response[json_response_success_key] = message if include_success_messages?
47
+ end
48
+
49
+ def set_notice_now_flash(message)
50
+ return super unless use_json?
51
+ json_response[json_response_success_key] = message if include_success_messages?
52
+ end
53
+
54
+ def json_request?
55
+ return @json_request if defined?(@json_request)
56
+ @json_request = request.content_type =~ json_request_content_type_regexp
57
+ end
58
+
59
+ def use_json?
60
+ json_request? || only_json?
61
+ end
62
+
63
+ def view(page, title)
64
+ return super unless use_json?
65
+ return_json_response
66
+ end
67
+
68
+ private
69
+
70
+ def before_view_recovery_codes
71
+ super if defined?(super)
72
+ if use_json?
73
+ json_response[:codes] = recovery_codes
74
+ json_response[json_response_success_key] ||= "" if include_success_messages?
75
+ end
76
+ end
77
+
78
+ def before_webauthn_setup_route
79
+ super if defined?(super)
80
+ if use_json? && !param_or_nil(webauthn_setup_param)
81
+ cred = new_webauthn_credential
82
+ json_response[webauthn_setup_param] = cred.as_json
83
+ json_response[webauthn_setup_challenge_param] = cred.challenge
84
+ json_response[webauthn_setup_challenge_hmac_param] = compute_hmac(cred.challenge)
85
+ end
86
+ end
87
+
88
+ def before_webauthn_auth_route
89
+ super if defined?(super)
90
+ if use_json? && !param_or_nil(webauthn_auth_param)
91
+ cred = webauth_credential_options_for_get
92
+ json_response[webauthn_auth_param] = cred.as_json
93
+ json_response[webauthn_auth_challenge_param] = cred.challenge
94
+ json_response[webauthn_auth_challenge_hmac_param] = compute_hmac(cred.challenge)
95
+ end
96
+ end
97
+
98
+ def before_webauthn_login_route
99
+ super if defined?(super)
100
+ if use_json? && !param_or_nil(webauthn_auth_param) && account_from_login(param(login_param))
101
+ cred = webauth_credential_options_for_get
102
+ json_response[webauthn_auth_param] = cred.as_json
103
+ json_response[webauthn_auth_challenge_param] = cred.challenge
104
+ json_response[webauthn_auth_challenge_hmac_param] = compute_hmac(cred.challenge)
105
+ end
106
+ end
107
+
108
+ def before_webauthn_remove_route
109
+ super if defined?(super)
110
+ if use_json? && !param_or_nil(webauthn_remove_param)
111
+ json_response[webauthn_remove_param] = account_webauthn_usage
112
+ end
113
+ end
114
+
115
+ def before_otp_setup_route
116
+ super if defined?(super)
117
+ if use_json? && otp_keys_use_hmac? && !param_or_nil(otp_setup_raw_param)
118
+ _otp_tmp_key(otp_new_secret)
119
+ json_response[otp_setup_param] = otp_user_key
120
+ json_response[otp_setup_raw_param] = otp_key
121
+ end
122
+ end
123
+
124
+ def before_rodauth
125
+ if json_request?
126
+ if json_check_accept? && (accept = request.env['HTTP_ACCEPT']) && accept !~ json_accept_regexp
127
+ response.status = 406
128
+ json_response[json_response_error_key] = json_not_accepted_error_message
129
+ _return_json_response
130
+ end
131
+
132
+ unless request.post?
133
+ response.status = 405
134
+ response.headers['Allow'] = 'POST'
135
+ json_response[json_response_error_key] = json_non_post_error_message
136
+ return_json_response
137
+ end
138
+ elsif only_json?
139
+ response.status = json_response_error_status
140
+ response.write non_json_request_error_message
141
+ request.halt
142
+ end
143
+
144
+ super
145
+ end
146
+
147
+ def redirect(_)
148
+ return super unless use_json?
149
+ return_json_response
150
+ end
151
+
152
+ def return_json_response
153
+ _return_json_response
154
+ end
155
+
156
+ def _return_json_response
157
+ response.status ||= json_response_error_status if json_response[json_response_error_key]
158
+ response['Content-Type'] ||= json_response_content_type
159
+ response.write(_json_response_body(json_response))
160
+ request.halt
161
+ end
162
+
163
+ def include_success_messages?
164
+ !json_response_success_key.nil?
165
+ end
166
+
167
+ def _json_response_body(hash)
168
+ request.send(:convert_to_json, hash)
169
+ end
170
+
171
+ def json_response
172
+ @json_response ||= {}
173
+ end
174
+
175
+ def set_redirect_error_status(status)
176
+ if use_json? && json_response_custom_error_status?
177
+ response.status = status
178
+ end
179
+ end
180
+
181
+ def set_response_error_status(status)
182
+ if use_json? && !json_response_custom_error_status?
183
+ status = json_response_error_status
184
+ end
185
+
186
+ super
187
+ end
188
+ end
189
+ end
@@ -4,41 +4,29 @@ require 'jwt'
4
4
 
5
5
  module Rodauth
6
6
  Feature.define(:jwt, :Jwt) do
7
+ depends :json
8
+
7
9
  translatable_method :invalid_jwt_format_error_message, "invalid JWT format or claim in Authorization header"
8
- translatable_method :json_non_post_error_message, 'non-POST method used in JSON API'
9
- translatable_method :json_not_accepted_error_message, 'Unsupported Accept header. Must accept "application/json" or compatible content type'
10
- auth_value_method :json_accept_regexp, /(?:(?:\*|\bapplication)\/\*|\bapplication\/(?:vnd\.api\+)?json\b)/i
11
- auth_value_method :json_request_content_type_regexp, /\bapplication\/(?:vnd\.api\+)?json\b/i
12
- auth_value_method :json_response_content_type, 'application/json'
13
- auth_value_method :json_response_error_status, 400
14
- auth_value_method :json_response_custom_error_status?, true
15
- auth_value_method :json_response_error_key, "error"
16
- auth_value_method :json_response_field_error_key, "field-error"
17
- auth_value_method :json_response_success_key, "success"
18
10
  auth_value_method :jwt_algorithm, "HS256"
19
11
  auth_value_method :jwt_authorization_ignore, /\A(?:Basic|Digest) /
20
12
  auth_value_method :jwt_authorization_remove, /\ABearer:?\s+/
21
- auth_value_method :jwt_check_accept?, true
22
13
  auth_value_method :jwt_decode_opts, {}.freeze
23
14
  auth_value_method :jwt_session_key, nil
24
15
  auth_value_method :jwt_symbolize_deeply?, false
25
- translatable_method :non_json_request_error_message, 'Only JSON format requests are allowed'
26
16
 
27
17
  auth_value_methods(
28
- :only_json?,
29
18
  :jwt_secret,
30
19
  :use_jwt?
31
20
  )
32
21
 
33
22
  auth_methods(
34
- :json_request?,
35
23
  :jwt_session_hash,
36
24
  :jwt_token,
37
25
  :session_jwt,
38
26
  :set_jwt_token
39
27
  )
40
28
 
41
- auth_private_methods :json_response_body
29
+ def_deprecated_alias :json_check_accept?, :jwt_check_accept?
42
30
 
43
31
  def session
44
32
  return @session if defined?(@session)
@@ -48,10 +36,7 @@ module Rodauth
48
36
  if jwt_token
49
37
  unless session_data = jwt_payload
50
38
  json_response[json_response_error_key] ||= invalid_jwt_format_error_message
51
- response.status ||= json_response_error_status
52
- response['Content-Type'] ||= json_response_content_type
53
- response.write(_json_response_body(json_response))
54
- request.halt
39
+ _return_json_response
55
40
  end
56
41
 
57
42
  if jwt_session_key
@@ -79,36 +64,6 @@ module Rodauth
79
64
  end
80
65
  end
81
66
 
82
- def set_field_error(field, message)
83
- return super unless use_jwt?
84
- json_response[json_response_field_error_key] = [field, message]
85
- end
86
-
87
- def set_error_flash(message)
88
- return super unless use_jwt?
89
- json_response[json_response_error_key] = message
90
- end
91
-
92
- def set_redirect_error_flash(message)
93
- return super unless use_jwt?
94
- json_response[json_response_error_key] = message
95
- end
96
-
97
- def set_notice_flash(message)
98
- return super unless use_jwt?
99
- json_response[json_response_success_key] = message if include_success_messages?
100
- end
101
-
102
- def set_notice_now_flash(message)
103
- return super unless use_jwt?
104
- json_response[json_response_success_key] = message if include_success_messages?
105
- end
106
-
107
- def json_request?
108
- return @json_request if defined?(@json_request)
109
- @json_request = request.content_type =~ json_request_content_type_regexp
110
- end
111
-
112
67
  def jwt_secret
113
68
  raise ArgumentError, "jwt_secret not set"
114
69
  end
@@ -134,16 +89,15 @@ module Rodauth
134
89
  end
135
90
 
136
91
  def use_jwt?
137
- jwt_token || only_json? || json_request?
92
+ use_json?
138
93
  end
139
94
 
140
- def valid_jwt?
141
- !!(jwt_token && jwt_payload)
95
+ def use_json?
96
+ jwt_token || super
142
97
  end
143
98
 
144
- def view(page, title)
145
- return super unless use_jwt?
146
- return_json_response
99
+ def valid_jwt?
100
+ !!(jwt_token && jwt_payload)
147
101
  end
148
102
 
149
103
  private
@@ -153,85 +107,6 @@ module Rodauth
153
107
  super
154
108
  end
155
109
 
156
- def before_rodauth
157
- if json_request?
158
- if jwt_check_accept? && (accept = request.env['HTTP_ACCEPT']) && accept !~ json_accept_regexp
159
- response.status = 406
160
- json_response[json_response_error_key] = json_not_accepted_error_message
161
- response['Content-Type'] ||= json_response_content_type
162
- response.write(_json_response_body(json_response))
163
- request.halt
164
- end
165
-
166
- unless request.post?
167
- response.status = 405
168
- response.headers['Allow'] = 'POST'
169
- json_response[json_response_error_key] = json_non_post_error_message
170
- return_json_response
171
- end
172
- elsif only_json?
173
- response.status = json_response_error_status
174
- response.write non_json_request_error_message
175
- request.halt
176
- end
177
-
178
- super
179
- end
180
-
181
- def before_view_recovery_codes
182
- super if defined?(super)
183
- if use_jwt?
184
- json_response[:codes] = recovery_codes
185
- json_response[json_response_success_key] ||= "" if include_success_messages?
186
- end
187
- end
188
-
189
- def before_webauthn_setup_route
190
- super if defined?(super)
191
- if use_jwt? && !param_or_nil(webauthn_setup_param)
192
- cred = new_webauthn_credential
193
- json_response[webauthn_setup_param] = cred.as_json
194
- json_response[webauthn_setup_challenge_param] = cred.challenge
195
- json_response[webauthn_setup_challenge_hmac_param] = compute_hmac(cred.challenge)
196
- end
197
- end
198
-
199
- def before_webauthn_auth_route
200
- super if defined?(super)
201
- if use_jwt? && !param_or_nil(webauthn_auth_param)
202
- cred = webauth_credential_options_for_get
203
- json_response[webauthn_auth_param] = cred.as_json
204
- json_response[webauthn_auth_challenge_param] = cred.challenge
205
- json_response[webauthn_auth_challenge_hmac_param] = compute_hmac(cred.challenge)
206
- end
207
- end
208
-
209
- def before_webauthn_login_route
210
- super if defined?(super)
211
- if use_jwt? && !param_or_nil(webauthn_auth_param) && account_from_login(param(login_param))
212
- cred = webauth_credential_options_for_get
213
- json_response[webauthn_auth_param] = cred.as_json
214
- json_response[webauthn_auth_challenge_param] = cred.challenge
215
- json_response[webauthn_auth_challenge_hmac_param] = compute_hmac(cred.challenge)
216
- end
217
- end
218
-
219
- def before_webauthn_remove_route
220
- super if defined?(super)
221
- if use_jwt? && !param_or_nil(webauthn_remove_param)
222
- json_response[webauthn_remove_param] = account_webauthn_usage
223
- end
224
- end
225
-
226
- def before_otp_setup_route
227
- super if defined?(super)
228
- if use_jwt? && otp_keys_use_hmac? && !param_or_nil(otp_setup_raw_param)
229
- _otp_tmp_key(otp_new_secret)
230
- json_response[otp_setup_param] = otp_user_key
231
- json_response[otp_setup_raw_param] = otp_key
232
- end
233
- end
234
-
235
110
  def _jwt_decode_opts
236
111
  jwt_decode_opts
237
112
  end
@@ -247,15 +122,6 @@ module Rodauth
247
122
  @jwt_payload = false
248
123
  end
249
124
 
250
- def redirect(_)
251
- return super unless use_jwt?
252
- return_json_response
253
- end
254
-
255
- def include_success_messages?
256
- !json_response_success_key.nil?
257
- end
258
-
259
125
  def set_session_value(key, value)
260
126
  super
261
127
  set_jwt if use_jwt?
@@ -268,38 +134,13 @@ module Rodauth
268
134
  value
269
135
  end
270
136
 
271
- def json_response
272
- @json_response ||= {}
273
- end
274
-
275
- def _json_response_body(hash)
276
- request.send(:convert_to_json, hash)
277
- end
278
-
279
137
  def return_json_response
280
- response.status ||= json_response_error_status if json_response[json_response_error_key]
281
138
  set_jwt
282
- response['Content-Type'] ||= json_response_content_type
283
- response.write(_json_response_body(json_response))
284
- request.halt
139
+ super
285
140
  end
286
141
 
287
142
  def set_jwt
288
143
  set_jwt_token(session_jwt)
289
144
  end
290
-
291
- def set_redirect_error_status(status)
292
- if use_jwt? && json_response_custom_error_status?
293
- response.status = status
294
- end
295
- end
296
-
297
- def set_response_error_status(status)
298
- if use_jwt? && !json_response_custom_error_status?
299
- status = json_response_error_status
300
- end
301
-
302
- super
303
- end
304
145
  end
305
146
  end
@@ -51,11 +51,8 @@ module Rodauth
51
51
  end
52
52
  else
53
53
  json_response[json_response_error_key] = jwt_refresh_invalid_token_message
54
- response.status ||= json_response_error_status
55
54
  end
56
- response['Content-Type'] ||= json_response_content_type
57
- response.write(_json_response_body(json_response))
58
- request.halt
55
+ _return_json_response
59
56
  end
60
57
  end
61
58
 
@@ -134,6 +134,7 @@ module Rodauth
134
134
  opts[:expires] = convert_timestamp(active_remember_key_ds.get(remember_deadline_column))
135
135
  opts[:path] = "/" unless opts.key?(:path)
136
136
  opts[:httponly] = true unless opts.key?(:httponly)
137
+ opts[:secure] = true unless opts.key?(:secure) || !request.ssl?
137
138
  ::Rack::Utils.set_cookie_header!(response.headers, remember_cookie_key, opts)
138
139
  end
139
140
 
@@ -29,7 +29,7 @@ module Rodauth
29
29
 
30
30
  def before_verify_account
31
31
  super
32
- if features.include?(:jwt) && use_jwt? && !param_or_nil(webauthn_setup_param)
32
+ if features.include?(:json) && use_json? && !param_or_nil(webauthn_setup_param)
33
33
  cred = new_webauthn_credential
34
34
  json_response[webauthn_setup_param] = cred.as_json
35
35
  json_response[webauthn_setup_challenge_param] = cred.challenge
@@ -6,7 +6,7 @@ module Rodauth
6
6
  MAJOR = 2
7
7
 
8
8
  # The minor version of Rodauth, updated for new feature releases of Rodauth.
9
- MINOR = 8
9
+ MINOR = 9
10
10
 
11
11
  # The patch version of Rodauth, updated only for bug fixes from the last
12
12
  # feature release.
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rodauth
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.8.0
4
+ version: 2.9.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jeremy Evans
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-01-06 00:00:00.000000000 Z
11
+ date: 2021-01-23 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: sequel
@@ -252,6 +252,7 @@ extra_rdoc_files:
252
252
  - doc/email_auth.rdoc
253
253
  - doc/email_base.rdoc
254
254
  - doc/http_basic_auth.rdoc
255
+ - doc/json.rdoc
255
256
  - doc/jwt.rdoc
256
257
  - doc/jwt_cors.rdoc
257
258
  - doc/jwt_refresh.rdoc
@@ -311,6 +312,7 @@ extra_rdoc_files:
311
312
  - doc/release_notes/2.6.0.txt
312
313
  - doc/release_notes/2.7.0.txt
313
314
  - doc/release_notes/2.8.0.txt
315
+ - doc/release_notes/2.9.0.txt
314
316
  files:
315
317
  - CHANGELOG
316
318
  - MIT-LICENSE
@@ -352,6 +354,7 @@ files:
352
354
  - doc/guides/status_column.rdoc
353
355
  - doc/guides/totp_or_recovery.rdoc
354
356
  - doc/http_basic_auth.rdoc
357
+ - doc/json.rdoc
355
358
  - doc/jwt.rdoc
356
359
  - doc/jwt_cors.rdoc
357
360
  - doc/jwt_refresh.rdoc
@@ -398,6 +401,7 @@ files:
398
401
  - doc/release_notes/2.6.0.txt
399
402
  - doc/release_notes/2.7.0.txt
400
403
  - doc/release_notes/2.8.0.txt
404
+ - doc/release_notes/2.9.0.txt
401
405
  - doc/remember.rdoc
402
406
  - doc/reset_password.rdoc
403
407
  - doc/session_expiration.rdoc
@@ -430,6 +434,7 @@ files:
430
434
  - lib/rodauth/features/email_auth.rb
431
435
  - lib/rodauth/features/email_base.rb
432
436
  - lib/rodauth/features/http_basic_auth.rb
437
+ - lib/rodauth/features/json.rb
433
438
  - lib/rodauth/features/jwt.rb
434
439
  - lib/rodauth/features/jwt_cors.rb
435
440
  - lib/rodauth/features/jwt_refresh.rb