added on WebSTLs (webstls.com) at 2026-07-01 22:27:06
| 1 | <!-- Two-factor authentication setup. RFC 6238 TOTP backed by the | |
| 2 | server-side helpers in twofa.cgi. The candidate secret is shown | |
| 3 | here for the seller to add to their authenticator app, then a | |
| 4 | 6-digit code proves they can read it; only then do we commit. --> | |
| 5 | ||
| 6 | <div class="page-shell" style="max-width:720px;margin:0 auto"> | |
| 7 | ||
| 8 | <div class="mb-3"> | |
| 9 | <a href="/profile.cgi#security" class="text-secondary text-xs" style="text-decoration:none">← Back to Profile</a> | |
| 10 | </div> | |
| 11 | ||
| 12 | [if:$has_err] | |
| 13 | <div class="banner danger mb-3"> | |
| 14 | <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="12" cy="12" r="10"/><line x1="12" y1="8" x2="12" y2="12"/><line x1="12" y1="16" x2="12.01" y2="16"/></svg> | |
| 15 | <div class="text-sm fw-600">$err</div> | |
| 16 | </div> | |
| 17 | [/if] | |
| 18 | ||
| 19 | [if:$is_enabled] | |
| 20 | <!-- Already enabled: status + disable form --> | |
| 21 | <div class="module"> | |
| 22 | <div class="module-head"> | |
| 23 | <div class="left"> | |
| 24 | <div class="module-icon" style="background:rgba(34,197,94,0.18);color:#86efac"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M9 12l2 2 4-4"/><path d="M21 12c0 5-4 9-9 9s-9-4-9-9 4-9 9-9c2.5 0 4.7 1 6.4 2.6"/></svg></div> | |
| 25 | <div> | |
| 26 | <div class="module-title">Two-factor authentication is on</div> | |
| 27 | <div class="module-sub">Your sign-ins require both your password and a 6-digit code from your authenticator app.</div> | |
| 28 | </div> | |
| 29 | </div> | |
| 30 | </div> | |
| 31 | <div class="module-body"> | |
| 32 | <div class="text-sm" style="line-height:1.7;color:var(--col-text-2);margin-bottom:18px"> | |
| 33 | <p>If you ever lose access to your authenticator app, contact <a href="/support.cgi?new=1" class="text-brand">support</a> with proof of identity and we can disable 2FA on your account. Don't disable 2FA preemptively unless you've already verified you can re-enroll.</p> | |
| 34 | </div> | |
| 35 | <form method="POST" action="/twofa.cgi" autocomplete="off"> | |
| 36 | <input type="hidden" name="action" value="disable"> | |
| 37 | <div class="form-group"> | |
| 38 | <label class="form-label" style="color:#fca5a5;font-weight:700"> | |
| 39 | Type <code style="background:rgba(239,68,68,0.18);padding:2px 8px;border-radius:4px;color:#fca5a5">DISABLE</code> to confirm: | |
| 40 | </label> | |
| 41 | <input class="input" type="text" name="confirm" required placeholder="DISABLE" style="font-family:var(--font-mono,monospace);text-transform:uppercase"> | |
| 42 | </div> | |
| 43 | <div style="display:flex;gap:10px;margin-top:8px"> | |
| 44 | <button type="submit" class="btn btn-danger">Disable 2FA</button> | |
| 45 | <a href="/profile.cgi#security" class="btn btn-secondary">Cancel</a> | |
| 46 | </div> | |
| 47 | </form> | |
| 48 | </div> | |
| 49 | </div> | |
| 50 | [/if] | |
| 51 | ||
| 52 | [if:$is_disabled] | |
| 53 | <!-- Not yet enabled: setup flow --> | |
| 54 | <div class="module"> | |
| 55 | <div class="module-head"> | |
| 56 | <div class="left"> | |
| 57 | <div class="module-icon"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><rect x="3" y="11" width="18" height="11" rx="2"/><path d="M7 11V7a5 5 0 0 1 10 0v4"/></svg></div> | |
| 58 | <div> | |
| 59 | <div class="module-title">Set up two-factor authentication</div> | |
| 60 | <div class="module-sub">Adds a 6-digit code on top of your password · takes about 60 seconds</div> | |
| 61 | </div> | |
| 62 | </div> | |
| 63 | </div> | |
| 64 | <div class="module-body"> | |
| 65 | <div class="text-sm" style="line-height:1.7;color:var(--col-text-2)"> | |
| 66 | <p><strong style="color:var(--col-text)">Step 1.</strong> Install an authenticator app on your phone if you don't have one. Good free options: <strong>Google Authenticator</strong>, <strong>Authy</strong>, <strong>1Password</strong>, <strong>Bitwarden</strong>.</p> | |
| 67 | ||
| 68 | <p style="margin-top:18px"><strong style="color:var(--col-text)">Step 2.</strong> Add WebSTLs to your authenticator. Easiest is to scan a QR code, but most apps also accept manual entry — here's the secret to paste in:</p> | |
| 69 | ||
| 70 | <div style="background:var(--col-surface-2);border:1px solid var(--col-border);border-radius:10px;padding:18px;margin:14px 0"> | |
| 71 | <div class="text-xs text-dim" style="letter-spacing:1.5px;text-transform:uppercase;margin-bottom:8px">Account label</div> | |
| 72 | <div class="font-mono fw-700" style="color:var(--col-text);margin-bottom:14px">WebSTLs : $email</div> | |
| 73 | ||
| 74 | <div class="text-xs text-dim" style="letter-spacing:1.5px;text-transform:uppercase;margin-bottom:8px">Secret key</div> | |
| 75 | <div class="font-mono fw-700" style="color:var(--col-text);letter-spacing:2px;word-spacing:8px;font-size:15px;user-select:all;margin-bottom:14px">$candidate_chunked</div> | |
| 76 | ||
| 77 | <div class="text-xs text-dim" style="letter-spacing:1.5px;text-transform:uppercase;margin-bottom:8px">Or scan / paste this URI</div> | |
| 78 | <div class="font-mono text-xs" style="color:var(--col-text-2);user-select:all;word-break:break-all;background:rgba(0,0,0,0.25);padding:10px 12px;border-radius:6px">$otpauth_uri</div> | |
| 79 | </div> | |
| 80 | ||
| 81 | <p><strong style="color:var(--col-text)">Step 3.</strong> Enter the 6-digit code your app shows for "WebSTLs" right now to prove the setup worked:</p> | |
| 82 | </div> | |
| 83 | ||
| 84 | <form method="POST" action="/twofa.cgi" autocomplete="off" style="margin-top:18px"> | |
| 85 | <input type="hidden" name="action" value="enable"> | |
| 86 | <input type="hidden" name="candidate_secret" value="$candidate_secret"> | |
| 87 | <div class="form-group"> | |
| 88 | <label class="form-label">6-digit code</label> | |
| 89 | <input class="input" type="text" name="code" inputmode="numeric" pattern="[0-9]{6}" maxlength="6" required placeholder="000000" style="font-family:var(--font-mono,monospace);letter-spacing:4px;font-size:18px;text-align:center;max-width:200px"> | |
| 90 | <div class="form-help">The code rotates every 30 seconds. If yours just changed, wait a moment and try again.</div> | |
| 91 | </div> | |
| 92 | ||
| 93 | <div style="display:flex;gap:10px;margin-top:18px"> | |
| 94 | <button type="submit" class="btn btn-primary">Turn on 2FA</button> | |
| 95 | <a href="/profile.cgi#security" class="btn btn-secondary">Cancel</a> | |
| 96 | </div> | |
| 97 | </form> | |
| 98 | ||
| 99 | <div class="text-xs text-dim mt-3" style="margin-top:22px;line-height:1.6"> | |
| 100 | <strong style="color:var(--col-text)">Save your secret somewhere safe.</strong> If you lose your phone AND haven't backed up the secret, you'll need to contact <a href="/support.cgi?new=1" class="text-brand">support</a> to recover the account. | |
| 101 | </div> | |
| 102 | </div> | |
| 103 | </div> | |
| 104 | [/if] | |
| 105 | ||
| 106 | </div> |