lato 3.26.1 → 3.27.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/README.md +14 -32
- data/app/assets/config/lato_manifest.js +3 -1
- data/app/assets/fonts/lato/bootstrap-icons.woff +0 -0
- data/app/assets/fonts/lato/bootstrap-icons.woff2 +0 -0
- data/app/assets/javascripts/lato/controllers/lato_account_webauthn_controller.js +1 -1
- data/app/assets/javascripts/lato/controllers/lato_auto_submit_controller.js +8 -0
- data/app/assets/javascripts/lato/controllers/lato_input_autocomplete2_controller.js +2 -2
- data/app/assets/javascripts/lato/controllers/lato_input_autocomplete_controller.js +2 -2
- data/app/assets/javascripts/lato/controllers/lato_web3_sign_controller.js +30 -0
- data/app/assets/javascripts/lato/debounce.js +8 -0
- data/app/assets/javascripts/lato/vendor/ethers.esm.min.js +1 -0
- data/app/assets/stylesheets/lato/_bootstrap-icons.scss +2079 -0
- data/app/assets/stylesheets/lato/application.scss +1 -1
- data/app/controllers/concerns/lato/sessionable.rb +1 -0
- data/app/controllers/lato/authentication_controller.rb +1 -0
- data/app/models/lato/invitation.rb +9 -0
- data/app/models/lato/session.rb +30 -1
- data/app/models/lato/user.rb +20 -4
- data/app/views/lato/account/_form-web3.html.erb +6 -35
- data/app/views/lato/authentication/_form-verify-email.html.erb +1 -2
- data/app/views/lato/authentication/_form-web3-signin.html.erb +6 -35
- data/app/views/layouts/lato/application.html.erb +2 -2
- data/config/importmap.rb +4 -3
- data/config/locales/en.yml +1 -0
- data/config/locales/fr.yml +1 -0
- data/config/locales/it.yml +1 -0
- data/config/locales/ro.yml +1 -0
- data/lib/lato/config.rb +19 -0
- data/lib/lato/version.rb +1 -1
- metadata +8 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: ca0108e01aa5bff67ba259b762e004d4ec95615bbd4faf091c0087a4d8bc3cdc
|
|
4
|
+
data.tar.gz: feee33ccb082d681bc490a05ec77bdca6d55375c02d7f9d3807b1cd377ef19a6
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 05a6b79b4b4e5d91d431f0840607ed6abd23c7ae34f5dda501b5c8a417a03a056abacac65bc61044bf9831389755d367da3f099b64220e3e021a7f71f3db7cbe
|
|
7
|
+
data.tar.gz: f4a331bea0a0c6d9f1bafb16de41644fceb8bc34bf3f2aa8c627b9afec69d0742dfecf29a848cb0f0abb5d21ae7c55e4294041d28225d8c96f00ff931f57f67c
|
data/README.md
CHANGED
|
@@ -143,43 +143,25 @@ rails lato:install:migrations
|
|
|
143
143
|
rails db:migrate
|
|
144
144
|
```
|
|
145
145
|
|
|
146
|
-
|
|
146
|
+
Read [UPGRADING.md](UPGRADING.md) for the changes and extra steps required by each version.
|
|
147
147
|
|
|
148
|
-
|
|
149
|
-
- `lato_page_head(title)` now escapes the title. Pass an `html_safe` string to render HTML.
|
|
150
|
-
- `lato_form_item_input_check` escapes the label unless it is `html_safe`.
|
|
151
|
-
- `data-turbo-confirm` messages and `data-action-title` are rendered as plain text.
|
|
152
|
-
- New config `Lato.config.auth_password_min_length` (default 8), checked whenever a password is set.
|
|
153
|
-
- Rate limits are stricter: `limit_requests` allows exactly `limit` requests per IP and action, signin is also limited per email (10 failed attempts in 15 minutes) and second factor attempts are counted per user. The pending second factor step expires after 10 minutes or 5 wrong codes.
|
|
154
|
-
- TOTP codes can be used only once and the WebAuthn signature counter is enforced.
|
|
155
|
-
- Web3 signin uses a message bound to host, nonce and issue time (single use, 5 minutes) and requires `gem "eth"`.
|
|
156
|
-
- `switch_locale` redirects only to same-host referers. The GET route `switch_locale_get` is deprecated: use POST `lato.switch_locale_path(locale:)`.
|
|
157
|
-
- `Lato::Operation#start` only starts classes inheriting from `Lato::ApplicationJob`.
|
|
158
|
-
- Schedule the maintenance jobs `Lato::LatoOperationsCleanerJob` and `Lato::ActiveStorageCleanerJob` (see the operations documentation).
|
|
148
|
+
## Security recommendations for your application
|
|
159
149
|
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
Lato 3.25 requires Rails >= 8.1.3.1 and < 8.2. Install the new session migration before serving requests (`rails lato:install:migrations && rails db:migrate`).
|
|
163
|
-
|
|
164
|
-
Sessions are stored as revocable token hashes in the database. Existing cookies require a fresh sign-in after upgrading (global logout). Signing out revokes the current device; changing or recovering a password revokes all devices. Password recovery preserves existing second factors and does not disable them.
|
|
165
|
-
|
|
166
|
-
Account password, email, authentication factor, wallet, and account deletion changes require the current password plus an enrolled authenticator or security key. Authenticator enrollment requires confirmation with a valid code; an active authenticator's secret is never displayed again. API clients submit `user[current_password]` and, when enrolled, `user[current_authenticator_code]`. Security key clients first POST to `account/security_challenge`, then submit the assertion as `user[current_webauthn_credential]`. Enrollment continuations expire after five minutes and can only be used once.
|
|
167
|
-
|
|
168
|
-
Extensions updating session attributes must call `session_update(extra_params)` to preserve the revocable session and secure cookie attributes.
|
|
169
|
-
|
|
170
|
-
## Production security checklist
|
|
150
|
+
Lato ships secure defaults, but some settings belong to the Rails application that uses it. These recommendations help applications using Lato reach a higher security level in production:
|
|
171
151
|
|
|
172
152
|
- Set `config.force_ssl = true`: the session cookie is `secure` only when the request is SSL.
|
|
173
|
-
- Use a persistent `Rails.cache` shared across processes (Redis, Solid Cache, Memcached). Recovery codes, verification codes and
|
|
153
|
+
- Use a persistent `Rails.cache` shared across processes (Redis, Solid Cache, Memcached). Recovery codes, verification codes and rate limits depend on it.
|
|
174
154
|
- Set `config.action_controller.raise_on_open_redirects = true`.
|
|
175
|
-
- Content Security Policy
|
|
176
|
-
- `
|
|
177
|
-
-
|
|
178
|
-
-
|
|
179
|
-
-
|
|
180
|
-
-
|
|
181
|
-
- `
|
|
182
|
-
-
|
|
155
|
+
- Enable a Content Security Policy. Lato views need no inline scripts: enable nonces for the importmap tags (`config.content_security_policy_nonce_generator` and `content_security_policy_nonce_directives = %w[script-src]`) instead of `'unsafe-inline'`. Lato serves all its scripts, stylesheets and fonts through the asset pipeline, so `script-src`, `style-src` and `font-src` need no third-party CDN. Only these extra sources are needed:
|
|
156
|
+
- `hcaptcha.com` and `*.hcaptcha.com` (only with hCaptcha enabled): `script-src`, `frame-src`, `style-src` and `connect-src`.
|
|
157
|
+
- `data:` in `img-src` for the authenticator QR code. Views use inline `style` attributes, so `style-src` still needs `'unsafe-inline'`.
|
|
158
|
+
- Set `Lato.config.session_idle_timeout` (e.g. `30.minutes`) and review `session_lifetime` (default 30 days, absolute).
|
|
159
|
+
- Review `Lato.config.invitation_lifetime` (default 30 days) and destroy pending invitations that are no longer needed.
|
|
160
|
+
- WebAuthn: use HTTPS origins in `webauthn_origin`. Set `webauthn_user_verification = "required"` if all your users have authenticators with biometrics or PIN.
|
|
161
|
+
- Encrypt authenticator secrets: configure Active Record encryption keys (`bin/rails db:encryption:init`) and set `Lato.config.encrypt_authenticator_secret = true` in an initializer. With existing plaintext secrets, set `config.active_record.encryption.support_unencrypted_data = true` until they are re-encrypted.
|
|
162
|
+
- Configure hCaptcha (`hcaptcha_site_key`, `hcaptcha_secret`) to protect signup and password recovery.
|
|
163
|
+
- Schedule `Lato::LatoOperationsCleanerJob` and `Lato::ActiveStorageCleanerJob`: they are not scheduled automatically.
|
|
164
|
+
- Monitor failed signins: the per-email signin limit can be used to temporarily lock out a known email.
|
|
183
165
|
|
|
184
166
|
## Development
|
|
185
167
|
|
|
Binary file
|
|
Binary file
|
|
@@ -54,7 +54,7 @@ export default class extends Controller {
|
|
|
54
54
|
authenticatorSelection: {
|
|
55
55
|
authenticatorAttachment: 'platform',
|
|
56
56
|
requireResidentKey: false,
|
|
57
|
-
userVerification: 'preferred'
|
|
57
|
+
userVerification: options.authenticatorSelection?.userVerification || 'preferred'
|
|
58
58
|
},
|
|
59
59
|
attestation: 'none'
|
|
60
60
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Controller } from "@hotwired/stimulus"
|
|
2
|
-
import
|
|
2
|
+
import debounce from 'lato/debounce'
|
|
3
3
|
|
|
4
4
|
export default class extends Controller {
|
|
5
5
|
static values = {
|
|
@@ -11,7 +11,7 @@ export default class extends Controller {
|
|
|
11
11
|
*/
|
|
12
12
|
|
|
13
13
|
connect() {
|
|
14
|
-
this.search =
|
|
14
|
+
this.search = debounce(this.search, 500)
|
|
15
15
|
|
|
16
16
|
this.realInput = document.createElement('input')
|
|
17
17
|
this.realInput.type = 'hidden'
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Controller } from "@hotwired/stimulus"
|
|
2
|
-
import
|
|
2
|
+
import debounce from 'lato/debounce'
|
|
3
3
|
|
|
4
4
|
export default class extends Controller {
|
|
5
5
|
static values = {
|
|
@@ -11,7 +11,7 @@ export default class extends Controller {
|
|
|
11
11
|
*/
|
|
12
12
|
|
|
13
13
|
connect() {
|
|
14
|
-
this.search =
|
|
14
|
+
this.search = debounce(this.search, 500)
|
|
15
15
|
this.datalist = document.createElement('datalist')
|
|
16
16
|
this.datalist.id = Math.random().toString(36)
|
|
17
17
|
this.element.setAttribute('list', this.datalist.id)
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { Controller } from "@hotwired/stimulus"
|
|
2
|
+
|
|
3
|
+
// Asks the browser wallet to sign the server nonce, then submits the form with address and signature.
|
|
4
|
+
// Empty values are submitted when no wallet is available or the user rejects the request: the server handles the error.
|
|
5
|
+
export default class extends Controller {
|
|
6
|
+
static targets = ['nonce', 'address', 'signedNonce', 'submit']
|
|
7
|
+
|
|
8
|
+
async connect() {
|
|
9
|
+
const { ethers } = await import('ethers')
|
|
10
|
+
|
|
11
|
+
let address = ''
|
|
12
|
+
let signedNonce = ''
|
|
13
|
+
|
|
14
|
+
try {
|
|
15
|
+
if (window.ethereum) {
|
|
16
|
+
const provider = new ethers.providers.Web3Provider(window.ethereum)
|
|
17
|
+
await provider.send('eth_requestAccounts', [])
|
|
18
|
+
const signer = provider.getSigner()
|
|
19
|
+
address = await signer.getAddress()
|
|
20
|
+
signedNonce = await signer.signMessage(this.nonceTarget.textContent)
|
|
21
|
+
}
|
|
22
|
+
} catch (error) {
|
|
23
|
+
console.error(error)
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
this.addressTarget.value = address
|
|
27
|
+
this.signedNonceTarget.value = signedNonce
|
|
28
|
+
this.submitTarget.click()
|
|
29
|
+
}
|
|
30
|
+
}
|