handle 2fa code submit via JS (#6)

This commit is contained in:
Adora Laura Kalb 2024-05-06 13:11:46 +02:00
parent 7f4239cfbf
commit e6073c9023
Signed by: adoralaura
SSH key fingerprint: SHA256:3XrkbR8ikAZJVtYfaUliX1MhmJYVAe/ocIb/MiDHBJ8
5 changed files with 70 additions and 24 deletions

View file

@ -1,7 +1,10 @@
package misc
import (
"encoding/json"
"errors"
"code.lila.network/adoralaura/go-urlsh/models"
"github.com/gofiber/fiber/v2"
)
@ -30,6 +33,11 @@ func New400Error() error {
return fiber.NewError(fiber.StatusBadRequest, "400 Bad Request")
}
func New400WithMessageError(msg string) error {
body, _ := json.Marshal(models.HttpErrorBody{Message: msg})
return fiber.NewError(fiber.StatusBadRequest, string(body[:]))
}
func New401Error() error {
return fiber.NewError(fiber.StatusUnauthorized, "401 Unauthorized")
}

View file

@ -21,14 +21,13 @@ func HandleAdminLoginMFAPost(c *fiber.Ctx) error {
return misc.New400Error()
}
var token models.TokenRequest
token := new(models.TokenRequest)
var istotp bool
if err := c.BodyParser(&token); err != nil {
if err := c.BodyParser(token); err != nil {
// TODO: Debug logging
return misc.New400Error()
}
if len(token.Token) == 6 {
istotp = true
} else if len(token.Token) == 8 {
@ -42,7 +41,7 @@ func HandleAdminLoginMFAPost(c *fiber.Ctx) error {
if err != nil {
log.Println(err)
// TODO: Debug logging
return misc.New500Error()
return misc.New400Error()
}
// check token/scratch validity
@ -57,11 +56,10 @@ func HandleAdminLoginMFAPost(c *fiber.Ctx) error {
err = misc.SetLoginCookie(c, user, constants.LoginCookieExpiryDuration)
if err != nil {
log.Printf("[HandleAdminLoginPost] Error setting cookie: %q\n", err)
return fiber.NewError(fiber.StatusInternalServerError, "500 Internal Server Error")
return misc.New500Error()
}
c.Status(fiber.StatusSeeOther)
c.Location("/admin/")
c.Status(fiber.StatusOK)
return nil
}

5
models/error.go Normal file
View file

@ -0,0 +1,5 @@
package models
type HttpErrorBody struct {
Message string `json:"message"`
}

View file

@ -7,8 +7,11 @@
<title>Multi Factor Authentication - go-urlsh</title>
<meta name='viewport' content='width=device-width, initial-scale=1'>
<link rel="stylesheet" href="/admin/pico.min.css">
<script src="/admin/main.js" defer></script>
<style>
.hidden {
display: none;
}
</style>
</head>
@ -17,13 +20,16 @@
<article class="grid">
<div>
<hgroup>
<h1 style='--color: var(--h1-color); font-weight: var(--font-weight); font-size: var(--font-size); font-family: var(--font-family);'>Multi Factor Authentication</h1>
<h1
style='--color: var(--h1-color); font-weight: var(--font-weight); font-size: var(--font-size); font-family: var(--font-family);'>
Multi Factor Authentication</h1>
</hgroup>
<form method="post" action="/admin/login/multifactor" style="margin-bottom: 0;" autocomplete="off">
<form action="javascript:HandleMFALoginTokenPost()" style="margin-bottom: 0;" autocomplete="off">
<label for="token">Authentication Code (Format: 123456 or a1b2c3d4 for recovery codes)</label>
<input type="text" name="token" id="token" autocomplete="one-time-code">
<input type="submit" value="Submit" class="contrast">
<p id="error-message" class="hidden" style="color: red;">Error Message</p>
<input id="submit" type="submit" value="Submit" class="contrast">
</form>
</div>
</article>

View file

@ -1,6 +1,6 @@
// Link overview
async function HandleLinkIndexDelete(id){
async function HandleLinkIndexDelete(id) {
let response = await fetch("/api/v1/links/" + id, {
credentials: "include",
mode: "same-origin",
@ -30,7 +30,7 @@ async function HandleLinkEditSubmit() {
await LinkAction("edit")
}
async function LinkAction(action){
async function LinkAction(action) {
document.getElementById("submit").active = false
let slug = document.getElementById("linkname").value
let url = document.getElementById("link").value
@ -38,22 +38,22 @@ async function LinkAction(action){
let method, endpoint = ""
let body;
switch(action) {
switch (action) {
case "add":
method = "POST"
endpoint = "/api/v1/links/"
body = {
"id" : slug,
"url" : url,
"description" : description
"id": slug,
"url": url,
"description": description
}
break;
case "edit":
method = "PUT"
endpoint = "/api/v1/links/" + slug
body = {
"url" : url,
"description" : description
"url": url,
"description": description
}
break;
default:
@ -82,8 +82,7 @@ async function LinkAction(action){
async function HandleLinkFieldChange() {
console.log("HandleChange")
let buttonactive = true
if (document.getElementById("link").value === "")
{
if (document.getElementById("link").value === "") {
buttonactive = false
}
document.getElementById("submit").active = buttonactive
@ -98,7 +97,7 @@ async function HandleApiKeyNewSubmit() {
button.setAttribute("aria-busy", "true")
let body = {
"description" : description
"description": description
}
let response = await fetch("/api/v1/apikeys", {
@ -121,12 +120,13 @@ async function HandleMFASetupTokenSubmit() {
let token = document.getElementById("token").value
let body = {
"token" : token
"token": token
}
let response = await fetch("/admin/account/mfasetup", {
credentials: "include",
body: JSON.stringify(body),
headers: { "Content-Type": "application/json", },
mode: "same-origin",
method: "POST"
});
@ -145,6 +145,35 @@ async function HandleMFASetupTokenSubmit() {
}
}
async function HandleMFALoginTokenPost() {
document.getElementById("submit").disabled = true;
document.getElementById("token").disabled = true;
let token = document.getElementById("token").value
let body = {
"token": token
}
let response = await fetch("/admin/login/multifactor", {
credentials: "include",
headers: { "Content-Type": "application/json", },
body: JSON.stringify(body),
mode: "same-origin",
method: "POST"
});
if (response.ok) {
document.location = "/admin/"
} else {
document.getElementById("submit").disabled = false;
document.getElementById("token").disabled = false;
document.getElementById('error-message').innerHTML = "Two Factor Authentication failed. Please try again."
document.getElementById('error-message').setAttribute("class", "")
document.getElementById('token').value = ""
document.getElementById('token').setAttribute("aria-invalid", "true")
}
}
function HandleModalClose(redir) {
document.getElementById('dialog-success').close();
document.getElementById('dialog-error').close();