Handle 2fa setup error handling in JS (#6)

This commit is contained in:
Adora Laura Kalb 2024-05-10 11:44:42 +02:00
parent 4073a8eaca
commit 4c42d23cf4
Signed by: adoralaura
SSH key fingerprint: SHA256:3XrkbR8ikAZJVtYfaUliX1MhmJYVAe/ocIb/MiDHBJ8
4 changed files with 48 additions and 28 deletions

View file

@ -10,8 +10,8 @@ func addWebRoutes(f *fiber.App) {
f.Get("/admin/", web.HandleAdminLinkIndexGet)
f.Get("/admin/account/", web.HandleAdminAccountGet)
f.Get("/admin/account/mfasetup", web.HandleAdminAccountMFASetupGet)
f.Post("/admin/account/mfasetup", web.HandleAdminAccountMFASetupPost)
f.Get("/admin/account/setup-multifactor", web.HandleAdminAccountMFASetupGet)
f.Post("/admin/account/mfa/confirm", web.HandleAdminAccountMFASetupPost)
f.Delete("/admin/account/mfa", web.HandleAdminAccountMFARemove)
f.Get("/admin/login", web.HandleAdminLoginGet)

View file

@ -60,7 +60,7 @@
{{if .MFAEnabled}}
<a href="#" onclick="HandleMFARemovalRequest()" role="button">disable Two-Factor Authentication</a>
{{else}}
<a href="/admin/account/mfasetup" role="button">Setup Two-Factor Authentication</a>
<a href="/admin/account/setup-multifactor" role="button">Setup Two-Factor Authentication</a>
{{end}}
<dialog id="mfa-disable-dialog" style="flex-direction: column;">
<h2 id="dialog-heading">⚠️ Are you sure you want to disable two-factor authentication?</h2>

View file

@ -4,30 +4,43 @@
<head>
<meta charset='utf-8'>
<meta http-equiv='X-UA-Compatible' content='IE=edge'>
<title>Setup MFA - go-urlsh</title>
<title>Set up Two-Factor authentication - go-urlsh</title>
<meta name='viewport' content='width=device-width, initial-scale=1'>
<link rel="stylesheet" href="/admin/pico.min.css">
<link rel="stylesheet" href="/admin/pico.colors.min.css">
<link rel="stylesheet" href="/admin/custom.css">
<script src="/admin/main.js" defer></script>
<style>
h1, h2, h3, h4, h5, h6 {
margin-bottom: 30px;
h1,
h2,
h3,
h4,
h5,
h6 {
margin-bottom: 30px;
}
i {
font-style: normal;
margin: 15px;
}
input {
margin-top: 15px;
}
img {
margin: 15px;
}
#token {
width: 15em;
margin-right: 15px;
}
.hidden {
display: none;
}
</style>
</head>
@ -47,7 +60,7 @@
<a href="/admin/apikeys/">API Keys</a>
</li>
<li>
<a href="javascript: void(0)" >Users (coming soon)</a>
<a href="javascript: void(0)">Users (coming soon)</a>
</li>
<li>
<a href="javascript: Logout()" style="color: red;">Logout</a>
@ -55,21 +68,23 @@
</ul>
</nav>
<main class="container" style="padding: 0">
<h1>Setup Multifactor Authentication</h1>
Scan this image with your authentication application:<br/>
<img src="data:image/png;base64,{{ .Image }}" alt="TOTP QR-Code" width="200" height="200"><br/>
<h1>Setup Two-Factor authentication</h1>
In order to setup Two-Factor authentication, please scan this image with your authentication application:<br />
<img src="data:image/png;base64,{{ .Image }}" alt="TOTP QR-Code" width="200" height="200"><br />
Or enter the secret manually into your TOTP application:
<br/>
<br />
<i class="monospace">{{ .Key }}</i>
<br/><br/>
<br /><br />
Afterwards please enter the passcode shown in the TOTP application here for confirmation:
<br/>
<form method="post" action="javascript:HandleMFASetupTokenSubmit();" style="width: fit-content;" autocomplete="off">
<br />
<form action="javascript:HandleMFASetupTokenSubmit();" style="width: fit-content;" autocomplete="off">
<p id="error-message" class="hidden" style="color: var(--pico-color-red-500)">
The TOTP code you provided is not correct. Please try again</p>
<div style="display: flex;">
<input type="text" name="token" id="token" inputmode="numeric" pattern="[0-9]{6}" autocomplete="one-time-code">
<input type="text" name="token" id="token" inputmode="numeric" autocomplete="one-time-code">
<input type="submit" value="Submit" class="contrast" style="width: fit-content;">
<input id="button-submit" type="submit" value="Submit" class="contrast" style="width: fit-content;">
</div>
</form>
<dialog id="user-dialog" style="flex-direction: column;">

View file

@ -118,12 +118,16 @@ async function HandleApiKeyNewSubmit() {
async function HandleMFASetupTokenSubmit() {
let token = document.getElementById("token").value
let button = document.getElementById("button-submit")
button.disabled = true
button.setAttribute('aria-busy', 'true')
let body = {
"token": token
}
let response = await fetch("/admin/account/mfasetup", {
let response = await fetch("/admin/account/mfa/confirm", {
credentials: "include",
body: JSON.stringify(body),
headers: { "Content-Type": "application/json", },
@ -135,13 +139,14 @@ async function HandleMFASetupTokenSubmit() {
let data = await response.json()
document.getElementById("dialog-tokens").textContent = data["recovery_tokens"].join(" ")
document.getElementById('dialog-success').showModal()
} else {
document.cookie = 'gourlsh_mfa_setup=; Max-Age=-1; path=/; domain=' + location.hostname;
document.getElementById('user-dialog').showModal()
} else if (response.status == 400) {
// document.cookie = 'gourlsh_mfa_setup=; Max-Age=-1; path=/; domain=' + location.hostname;
document.getElementById("dialog-heading").textContent = "Error!"
document.getElementById("dialog-text").textContent = "Something didnt work!"
document.getElementById('dialog-error').showModal()
document.getElementById('token').setAttribute('aria-invalid', 'true')
button.setAttribute('aria-busy', 'false')
button.disabled = false
document.getElementById('error-message').setAttribute('class', '')
}
}