From da3fefd42e109584811e5327bffae7e05ba263f3 Mon Sep 17 00:00:00 2001 From: Mechiel Lukkien Date: Mon, 27 Feb 2023 21:29:27 +0100 Subject: [PATCH] explain to user they should pick a random, unguessable password and help with a button to generate one. --- http/account.html | 25 ++++++++++++++++++++++++- http/admin.html | 28 ++++++++++++++++++++++++++-- 2 files changed, 50 insertions(+), 3 deletions(-) diff --git a/http/account.html b/http/account.html index 98f84ac..d42c8b4 100644 --- a/http/account.html +++ b/http/account.html @@ -15,6 +15,7 @@ ul { padding-left: 1rem; } .literal { background-color: #fdfdfd; padding: .5em 1em; border: 1px solid #eee; border-radius: 4px; white-space: pre-wrap; font-family: monospace; font-size: 15px; tab-size: 4; } table td, table th { padding: .2em .5em; } table > tbody > tr:nth-child(odd) { background-color: #f8f8f8; } +.text { max-width: 50em; } p { margin-bottom: 1em; max-width: 50em; } [title] { text-decoration: underline; text-decoration-style: dotted; } fieldset { border: 0; } @@ -296,7 +297,29 @@ const index = async () => { ), ' ', dom.button('Change password'), - passwordHint=dom.div(style({display: 'none', marginTop: '.5ex', fontStyle: 'italic'}), 'Password must be at least 8 characters.'), + ), + passwordHint=dom.div( + style({display: 'none', marginTop: '.5ex'}), + dom.button('Generate random password', attr({type: 'button'}), function click(e) { + e.preventDefault() + let b = new Uint8Array(1) + let s = '' + const chars = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!@#$%^&*-_;:,<.>/' + while (s.length < 12) { + self.crypto.getRandomValues(b) + if (Math.ceil(b[0]/chars.length)*chars.length > 255) { + continue // Prevent bias. + } + s += chars[b[0]%chars.length] + } + password1.type = 'text' + password2.type = 'text' + password1.value = s + password2.value = s + }), + dom('div.text', + box(yellow, 'Important: Bots will try to bruteforce your password. Connections with failed authentication attempts will be rate limited but attackers WILL find weak passwords. If your account is compromised, spammers are likely to abuse your system, spamming your address and the wider internet in your name. So please pick a random, unguessable password, preferrably at least 12 characters.'), + ), ), async function submit(e) { e.stopPropagation() diff --git a/http/admin.html b/http/admin.html index d6ae069..c1c9a3e 100644 --- a/http/admin.html +++ b/http/admin.html @@ -15,6 +15,7 @@ ul { padding-left: 1rem; } .literal { background-color: #fdfdfd; padding: .5em 1em; border: 1px solid #eee; border-radius: 4px; white-space: pre-wrap; font-family: monospace; font-size: 15px; tab-size: 4; } table td, table th { padding: .2em .5em; } table > tbody > tr:nth-child(odd) { background-color: #f8f8f8; } +.text { max-width: 50em; } p { margin-bottom: 1em; max-width: 50em; } [title] { text-decoration: underline; text-decoration-style: dotted; } fieldset { border: 0; } @@ -471,7 +472,7 @@ const account = async (name) => { const config = await api.Account(name) let form, fieldset, email - let formPassword, fieldsetPassword, password + let formPassword, fieldsetPassword, password, passwordHint const page = document.getElementById('page') dom._kids(page, @@ -578,11 +579,34 @@ const account = async (name) => { style({display: 'inline-block'}), 'New password', dom.br(), - password=dom.input(attr({type: 'password', required: ''})), + password=dom.input(attr({type: 'password', required: ''}), function focus() { + passwordHint.style.display = '' + }), ), ' ', dom.button('Change password'), ), + passwordHint=dom.div( + style({display: 'none', marginTop: '.5ex'}), + dom.button('Generate random password', attr({type: 'button'}), function click(e) { + e.preventDefault() + let b = new Uint8Array(1) + let s = '' + const chars = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!@#$%^&*-_;:,<.>/' + while (s.length < 12) { + self.crypto.getRandomValues(b) + if (Math.ceil(b[0]/chars.length)*chars.length > 255) { + continue // Prevent bias. + } + s += chars[b[0]%chars.length] + } + password.type = 'text' + password.value = s + }), + dom('div.text', + box(yellow, 'Important: Bots will try to bruteforce your password. Connections with failed authentication attempts will be rate limited but attackers WILL find weak passwords. If your account is compromised, spammers are likely to abuse your system, spamming your address and the wider internet in your name. So please pick a random, unguessable password, preferrably at least 12 characters.'), + ), + ), async function submit(e) { e.stopPropagation() e.preventDefault()