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 package misc
import ( import (
"encoding/json"
"errors" "errors"
"code.lila.network/adoralaura/go-urlsh/models"
"github.com/gofiber/fiber/v2" "github.com/gofiber/fiber/v2"
) )
@ -30,6 +33,11 @@ func New400Error() error {
return fiber.NewError(fiber.StatusBadRequest, "400 Bad Request") 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 { func New401Error() error {
return fiber.NewError(fiber.StatusUnauthorized, "401 Unauthorized") return fiber.NewError(fiber.StatusUnauthorized, "401 Unauthorized")
} }

View file

@ -21,14 +21,13 @@ func HandleAdminLoginMFAPost(c *fiber.Ctx) error {
return misc.New400Error() return misc.New400Error()
} }
var token models.TokenRequest token := new(models.TokenRequest)
var istotp bool var istotp bool
if err := c.BodyParser(&token); err != nil { if err := c.BodyParser(token); err != nil {
// TODO: Debug logging // TODO: Debug logging
return misc.New400Error() return misc.New400Error()
} }
if len(token.Token) == 6 { if len(token.Token) == 6 {
istotp = true istotp = true
} else if len(token.Token) == 8 { } else if len(token.Token) == 8 {
@ -42,7 +41,7 @@ func HandleAdminLoginMFAPost(c *fiber.Ctx) error {
if err != nil { if err != nil {
log.Println(err) log.Println(err)
// TODO: Debug logging // TODO: Debug logging
return misc.New500Error() return misc.New400Error()
} }
// check token/scratch validity // check token/scratch validity
@ -57,11 +56,10 @@ func HandleAdminLoginMFAPost(c *fiber.Ctx) error {
err = misc.SetLoginCookie(c, user, constants.LoginCookieExpiryDuration) err = misc.SetLoginCookie(c, user, constants.LoginCookieExpiryDuration)
if err != nil { if err != nil {
log.Printf("[HandleAdminLoginPost] Error setting cookie: %q\n", err) 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.Status(fiber.StatusOK)
c.Location("/admin/")
return nil 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> <title>Multi Factor Authentication - go-urlsh</title>
<meta name='viewport' content='width=device-width, initial-scale=1'> <meta name='viewport' content='width=device-width, initial-scale=1'>
<link rel="stylesheet" href="/admin/pico.min.css"> <link rel="stylesheet" href="/admin/pico.min.css">
<script src="/admin/main.js" defer></script>
<style> <style>
.hidden {
display: none;
}
</style> </style>
</head> </head>
@ -17,13 +20,16 @@
<article class="grid"> <article class="grid">
<div> <div>
<hgroup> <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> </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> <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="text" name="token" id="token" autocomplete="one-time-code">
<p id="error-message" class="hidden" style="color: red;">Error Message</p>
<input type="submit" value="Submit" class="contrast"> <input id="submit" type="submit" value="Submit" class="contrast">
</form> </form>
</div> </div>
</article> </article>

View file

@ -82,8 +82,7 @@ async function LinkAction(action){
async function HandleLinkFieldChange() { async function HandleLinkFieldChange() {
console.log("HandleChange") console.log("HandleChange")
let buttonactive = true let buttonactive = true
if (document.getElementById("link").value === "") if (document.getElementById("link").value === "") {
{
buttonactive = false buttonactive = false
} }
document.getElementById("submit").active = buttonactive document.getElementById("submit").active = buttonactive
@ -127,6 +126,7 @@ async function HandleMFASetupTokenSubmit() {
let response = await fetch("/admin/account/mfasetup", { let response = await fetch("/admin/account/mfasetup", {
credentials: "include", credentials: "include",
body: JSON.stringify(body), body: JSON.stringify(body),
headers: { "Content-Type": "application/json", },
mode: "same-origin", mode: "same-origin",
method: "POST" 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) { function HandleModalClose(redir) {
document.getElementById('dialog-success').close(); document.getElementById('dialog-success').close();
document.getElementById('dialog-error').close(); document.getElementById('dialog-error').close();