mirror of
https://github.com/thomiceli/opengist.git
synced 2025-01-14 20:02:42 +00:00
151 lines
4.1 KiB
Go
151 lines
4.1 KiB
Go
package auth
|
|
|
|
import (
|
|
"bytes"
|
|
gojson "encoding/json"
|
|
"github.com/thomiceli/opengist/internal/auth/webauthn"
|
|
"github.com/thomiceli/opengist/internal/db"
|
|
"github.com/thomiceli/opengist/internal/web/context"
|
|
"io"
|
|
)
|
|
|
|
func BeginWebAuthnBinding(ctx *context.Context) error {
|
|
credsCreation, jsonWaSession, err := webauthn.BeginBinding(ctx.User)
|
|
if err != nil {
|
|
return ctx.ErrorRes(500, "Cannot begin WebAuthn registration", err)
|
|
}
|
|
|
|
sess := ctx.GetSession()
|
|
sess.Values["webauthn_registration_session"] = jsonWaSession
|
|
sess.Options.MaxAge = 5 * 60 // 5 minutes
|
|
ctx.SaveSession(sess)
|
|
|
|
return ctx.JSON(200, credsCreation)
|
|
}
|
|
|
|
func FinishWebAuthnBinding(ctx *context.Context) error {
|
|
sess := ctx.GetSession()
|
|
jsonWaSession, ok := sess.Values["webauthn_registration_session"].([]byte)
|
|
if !ok {
|
|
return ctx.ErrorRes(401, "Cannot get WebAuthn registration session", nil)
|
|
}
|
|
|
|
user := ctx.User
|
|
|
|
// extract passkey name from request
|
|
body, err := io.ReadAll(ctx.Request().Body)
|
|
if err != nil {
|
|
return ctx.ErrorRes(400, "Failed to read request body", err)
|
|
}
|
|
ctx.Request().Body.Close()
|
|
ctx.Request().Body = io.NopCloser(bytes.NewBuffer(body))
|
|
|
|
dto := new(db.CrendentialDTO)
|
|
_ = gojson.Unmarshal(body, &dto)
|
|
|
|
if err = ctx.Validate(dto); err != nil {
|
|
return ctx.ErrorRes(400, "Invalid request", err)
|
|
}
|
|
passkeyName := dto.PasskeyName
|
|
if passkeyName == "" {
|
|
passkeyName = "WebAuthn"
|
|
}
|
|
|
|
waCredential, err := webauthn.FinishBinding(user, jsonWaSession, ctx.Request())
|
|
if err != nil {
|
|
return ctx.ErrorRes(403, "Failed binding attempt for passkey", err)
|
|
}
|
|
|
|
if _, err = db.CreateFromCrendential(user.ID, passkeyName, waCredential); err != nil {
|
|
return ctx.ErrorRes(500, "Cannot create WebAuthn credential on database", err)
|
|
}
|
|
|
|
delete(sess.Values, "webauthn_registration_session")
|
|
ctx.SaveSession(sess)
|
|
|
|
ctx.AddFlash(ctx.Tr("flash.auth.passkey-registred", passkeyName), "success")
|
|
return ctx.JSON_([]string{"OK"})
|
|
}
|
|
|
|
func BeginWebAuthnLogin(ctx *context.Context) error {
|
|
credsCreation, jsonWaSession, err := webauthn.BeginDiscoverableLogin()
|
|
if err != nil {
|
|
return ctx.ErrorRes(401, "Cannot begin WebAuthn login", err)
|
|
}
|
|
|
|
sess := ctx.GetSession()
|
|
sess.Values["webauthn_login_session"] = jsonWaSession
|
|
sess.Options.MaxAge = 5 * 60 // 5 minutes
|
|
ctx.SaveSession(sess)
|
|
|
|
return ctx.JSON_(credsCreation)
|
|
}
|
|
|
|
func FinishWebAuthnLogin(ctx *context.Context) error {
|
|
sess := ctx.GetSession()
|
|
sessionData, ok := sess.Values["webauthn_login_session"].([]byte)
|
|
if !ok {
|
|
return ctx.ErrorRes(401, "Cannot get WebAuthn login session", nil)
|
|
}
|
|
|
|
userID, err := webauthn.FinishDiscoverableLogin(sessionData, ctx.Request())
|
|
if err != nil {
|
|
return ctx.ErrorRes(403, "Failed authentication attempt for passkey", err)
|
|
}
|
|
|
|
sess.Values["user"] = userID
|
|
sess.Options.MaxAge = 60 * 60 * 24 * 365 // 1 year
|
|
|
|
delete(sess.Values, "webauthn_login_session")
|
|
ctx.SaveSession(sess)
|
|
|
|
return ctx.JSON_([]string{"OK"})
|
|
}
|
|
|
|
func BeginWebAuthnAssertion(ctx *context.Context) error {
|
|
sess := ctx.GetSession()
|
|
|
|
ogUser, err := db.GetUserById(sess.Values["mfaID"].(uint))
|
|
if err != nil {
|
|
return ctx.ErrorRes(500, "Cannot get user", err)
|
|
}
|
|
|
|
credsCreation, jsonWaSession, err := webauthn.BeginLogin(ogUser)
|
|
if err != nil {
|
|
return ctx.ErrorRes(401, "Cannot begin WebAuthn login", err)
|
|
}
|
|
|
|
sess.Values["webauthn_assertion_session"] = jsonWaSession
|
|
sess.Options.MaxAge = 5 * 60 // 5 minutes
|
|
ctx.SaveSession(sess)
|
|
|
|
return ctx.JSON_(credsCreation)
|
|
}
|
|
|
|
func FinishWebAuthnAssertion(ctx *context.Context) error {
|
|
sess := ctx.GetSession()
|
|
sessionData, ok := sess.Values["webauthn_assertion_session"].([]byte)
|
|
if !ok {
|
|
return ctx.ErrorRes(401, "Cannot get WebAuthn assertion session", nil)
|
|
}
|
|
|
|
userId := sess.Values["mfaID"].(uint)
|
|
|
|
ogUser, err := db.GetUserById(userId)
|
|
if err != nil {
|
|
return ctx.ErrorRes(500, "Cannot get user", err)
|
|
}
|
|
|
|
if err = webauthn.FinishLogin(ogUser, sessionData, ctx.Request()); err != nil {
|
|
return ctx.ErrorRes(403, "Failed authentication attempt for passkey", err)
|
|
}
|
|
|
|
sess.Values["user"] = userId
|
|
sess.Options.MaxAge = 60 * 60 * 24 * 365 // 1 year
|
|
|
|
delete(sess.Values, "webauthn_assertion_session")
|
|
delete(sess.Values, "mfaID")
|
|
ctx.SaveSession(sess)
|
|
|
|
return ctx.JSON_([]string{"OK"})
|
|
}
|