2FA: Ability to see original QR code again

face-detect
Noah Petherbridge 2023-11-15 18:01:34 -08:00
parent ebd63bcb0d
commit f0373285eb
3 changed files with 174 additions and 100 deletions

View File

@ -70,6 +70,9 @@ func Setup2FA() http.HandlerFunc {
}
}
// Are they (re)viewing their original QR code?
var isPairingSecondDevice bool
// POST form actions.
if r.Method == http.MethodPost {
var intent = r.PostFormValue("intent")
@ -84,8 +87,15 @@ func Setup2FA() http.HandlerFunc {
// Valid?
if !valid {
session.FlashError(w, r, "The passcode you submitted didn't seem correct. Try a new six-digit code.")
templates.Redirect(w, r.URL.Path)
return
// If they were reconfiguring a second device, go back to the re-setup screen.
if tf.Enabled {
isPairingSecondDevice = true
break
} else {
templates.Redirect(w, r.URL.Path)
return
}
}
// OK!
@ -120,12 +130,24 @@ func Setup2FA() http.HandlerFunc {
session.Flash(w, r, "Your 2FA settings have been cleared and disabled.")
}
}
case "resetup":
// View the original QR code to set up a new device.
var password = r.PostFormValue("password")
if err := currentUser.CheckPassword(password); err != nil {
session.FlashError(w, r, "Couldn't access your 2FA QR code: the password you entered is incorrect.")
} else {
session.Flash(w, r, "Password accepted. Your 2FA QR code and setup steps will be displayed below.")
isPairingSecondDevice = true
}
default:
session.FlashError(w, r, "Unknown intent: %s", intent)
}
templates.Redirect(w, r.URL.Path)
return
// All POST requests redirect away except resetup.
if !isPairingSecondDevice {
templates.Redirect(w, r.URL.Path)
return
}
}
// Generate the QR code.
@ -135,9 +157,10 @@ func Setup2FA() http.HandlerFunc {
}
var vars = map[string]interface{}{
"TwoFactor": tf,
"Key": key,
"QRCode": qrCode,
"TwoFactor": tf,
"Key": key,
"QRCode": qrCode,
"IsPairingSecondDevice": isPairingSecondDevice,
}
if err := tmpl.Execute(w, r, vars); err != nil {

View File

@ -134,7 +134,7 @@
{{end}}
<!-- New Feature: Two Factor Auth -->
{{if not .TwoFactorEnabled}}
<!--
<div class="card block">
<header class="card-header has-background-success-dark">
<p class="card-header-title has-text-light">
@ -162,7 +162,7 @@
</p>
</div>
</div>
{{end}}
-->
<div class="card block">
<header class="card-header has-background-link">

View File

@ -38,7 +38,13 @@
the time-limited six-digit code to log in.
</p>
<h4>Backup Codes</h4>
<!-- Are they reconfiguring their 2FA app (viewing the barcode)? -->
{{if .IsPairingSecondDevice}}
{{template "2fa-setup" .}}
<hr>
{{end}}
<h4 class="mt-4">Backup Codes</h4>
<p>
In case you lose access to your Authenticator App, please print off or write down these
@ -72,7 +78,12 @@
</button>
</form>
<h4 class="has-text-danger mt-4">Disable Two-Factor Auth</h4>
<hr>
<h4 class="has-text-danger mt-4">
<i class="fa fa-exclamation-triangle mr-1"></i>
Disable Two-Factor Auth
</h4>
<p>
If you wish to <strong>disable</strong> two-factor authentication for your account, please enter
@ -95,6 +106,43 @@
Disable Two-Factor Authentication
</button>
</form>
<hr>
<h4 class="has-text-warning mt-4">
<i class="fa fa-qrcode mr-1"></i>
Set Up Another Device
</h4>
<p>
If you wish to <strong>set up another authenticator device</strong> and view your original
QR code, you may do so by entering your current account password below. This may be useful
if you have bought a new phone or want to migrate your authenticator to a different device,
so that you may access the original QR code and configure the new authenticator.
</p>
<p>
<strong>Note:</strong> this will not change your 2FA security key or backup codes. If you
have lost your old authenticator, it will be more secure to <strong>disable and then set up
2FA from scratch</strong>, which will generate a new secret key and backup codes.
</p>
<form action="{{.Request.URL.Path}}" method="POST">
{{InputCSRF}}
<input type="hidden" name="intent" value="resetup">
<div class="field">
<label class="label" for="password">Your account password:</label>
<input type="password" class="input"
name="password"
placeholder="Password"
required>
</div>
<button type="submit" class="button is-warning">
View my original 2FA QR code
</button>
</form>
</div>
</div>
</div>
@ -144,95 +192,7 @@
setting up your Authenticator App.
</p>
<h2>Set up your Authenticator App</h2>
<p>
To set up Two-Factor Auth, you'll need to download and install a compatible
Authenticator App on your device. Some suggestions for apps that are compatible
with {{PrettyTitle}} are as follows:
</p>
<ul>
<li>
<strong>Google Authenticator:</strong>
for <a href="https://play.google.com/store/apps/details?id=com.google.android.apps.authenticator2" target="_blank">
<i class="fab fa-android"></i> Android
</a> or <a href="https://apps.apple.com/us/app/google-authenticator/id388497605" target="_blank">
<i class="fab fa-apple"></i> iOS
</a>
</li>
<li>
<strong>
<a href="https://authy.com/download/" target="_blank">Authy:</a>
</strong>
available for <i class="fab fa-android"></i> Android and <i class="fab fa-apple"></i> iOS
as well as Windows, macOS and Linux computers.
</li>
</ul>
<h3>Add {{PrettyTitle}} to your Authenticator App</h3>
<p>
When you have your Authenticator App ready, click on its "Add a new site" button and scan
the following QR code to enroll your device for {{PrettyTitle}}:
</p>
{{ToHTML .QRCode}}
<p>
Alternatively (if you can't scan the QR code), you may copy and paste this secret text
in to your Authenticator app:
</p>
<div class="columns is-mobile">
<div class="column is-half-tablet pr-1">
<input type="text" class="input"
id="totp-secret"
value="{{.Key.Secret}}"
readonly
onclick="copySecret()">
</div>
<div class="column is-narrow pl-0">
<button type="button"
class="button is-success"
id="copy-button"
onclick="copySecret()">
<i class="fa fa-copy mr-1"></i> Copy
</button>
</div>
</div>
<h3>Test your Authenticator App</h3>
<p>
After scanning the QR code (or copying the secret key) into your Authenticator app, you
should be able to generate temporary six-digit authentication codes.
</p>
<p>
Test that you have enrolled your authenticator correctly by entering the current six-digit
code below:
</p>
<form action="{{.Request.URL.Path}}" method="POST">
{{InputCSRF}}
<input type="hidden" name="intent" value="setup-verify">
<div class="field">
<label class="label" for="code">
Authentication Code:
</label>
<input type="text" class="input is-one-quarter"
name="code" id="code"
pattern="^[0-9]{6}$"
maxlength="6"
placeholder="000000"
style="max-width: 12em"
autocomplete="off">
</div>
<button type="submit" class="button is-primary">Confirm &amp; Continue</button>
</form>
{{template "2fa-setup" .}}
</div>
</div>
</div>
@ -241,6 +201,97 @@
</div>
{{end}}
{{define "2fa-setup"}}
<h2>Set up your Authenticator App</h2>
<p>
To set up Two-Factor Auth, you'll need to download and install a compatible
Authenticator App on your device. Some suggestions for apps that are compatible
with {{PrettyTitle}} are as follows:
</p>
<ul>
<li>
<strong>Google Authenticator:</strong>
for <a href="https://play.google.com/store/apps/details?id=com.google.android.apps.authenticator2" target="_blank">
<i class="fab fa-android"></i> Android
</a> or <a href="https://apps.apple.com/us/app/google-authenticator/id388497605" target="_blank">
<i class="fab fa-apple"></i> iOS
</a>
</li>
<li>
<strong>
<a href="https://authy.com/download/" target="_blank">Authy:</a>
</strong>
available for <i class="fab fa-android"></i> Android and <i class="fab fa-apple"></i> iOS
as well as Windows, macOS and Linux computers.
</li>
</ul>
<h3>Add {{PrettyTitle}} to your Authenticator App</h3>
<p>
When you have your Authenticator App ready, click on its "Add a new site" button and scan
the following QR code to enroll your device for {{PrettyTitle}}:
</p>
{{ToHTML .QRCode}}
<p>
Alternatively (if you can't scan the QR code), you may copy and paste this secret text
in to your Authenticator app:
</p>
<div class="columns is-mobile">
<div class="column is-half-tablet pr-1">
<input type="text" class="input"
id="totp-secret"
value="{{.Key.Secret}}"
readonly
onclick="copySecret()">
</div>
<div class="column is-narrow pl-0">
<button type="button"
class="button is-success"
id="copy-button"
onclick="copySecret()">
<i class="fa fa-copy mr-1"></i> Copy
</button>
</div>
</div>
<h3>Test your Authenticator App</h3>
<p>
After scanning the QR code (or copying the secret key) into your Authenticator app, you
should be able to generate temporary six-digit authentication codes.
</p>
<p>
Test that you have enrolled your authenticator correctly by entering the current six-digit
code below:
</p>
<form action="{{.Request.URL.Path}}" method="POST">
{{InputCSRF}}
<input type="hidden" name="intent" value="setup-verify">
<div class="field">
<label class="label" for="code">
Authentication Code:
</label>
<input type="text" class="input is-one-quarter"
name="code" id="code"
pattern="^[0-9]{6}$"
maxlength="6"
placeholder="000000"
style="max-width: 12em"
autocomplete="off">
</div>
<button type="submit" class="button is-primary">Confirm &amp; Continue</button>
</form>
{{end}}
{{define "scripts"}}
<script>
function copySecret() {