authelia/internal/handlers/handler_webauthn_devices.go

161 lines
4.1 KiB
Go
Raw Normal View History

package handlers
import (
"encoding/json"
"errors"
2022-12-31 07:27:43 +00:00
"fmt"
2023-02-11 15:47:03 +00:00
"net/url"
"strconv"
"github.com/valyala/fasthttp"
"github.com/authelia/authelia/v4/internal/middlewares"
2022-12-31 07:27:43 +00:00
"github.com/authelia/authelia/v4/internal/model"
"github.com/authelia/authelia/v4/internal/regulation"
"github.com/authelia/authelia/v4/internal/session"
"github.com/authelia/authelia/v4/internal/storage"
)
func getWebAuthnDeviceIDFromContext(ctx *middlewares.AutheliaCtx) (int, error) {
deviceIDStr, ok := ctx.UserValue("deviceID").(string)
if !ok {
ctx.SetStatusCode(fasthttp.StatusBadRequest)
return 0, errors.New("Invalid device ID type")
}
deviceID, err := strconv.Atoi(deviceIDStr)
if err != nil {
ctx.Error(err, messageOperationFailed)
ctx.SetStatusCode(fasthttp.StatusBadRequest)
return 0, err
}
return deviceID, nil
}
// WebAuthnDevicesGET returns all devices registered for the current user.
func WebAuthnDevicesGET(ctx *middlewares.AutheliaCtx) {
var (
userSession session.UserSession
2023-02-11 15:47:03 +00:00
origin *url.URL
err error
)
if userSession, err = ctx.GetSession(); err != nil {
ctx.Logger.WithError(err).Error("Error occurred retrieving user session")
ctx.ReplyForbidden()
return
}
2023-02-11 15:47:03 +00:00
if origin, err = ctx.GetOrigin(); err != nil {
ctx.Logger.WithError(err).Error("Error occurred retrieving origin")
ctx.ReplyForbidden()
return
}
devices, err := ctx.Providers.StorageProvider.LoadWebAuthnDevicesByUsername(ctx, origin.Hostname(), userSession.Username)
if err != nil && err != storage.ErrNoWebAuthnDevice {
ctx.Error(err, messageOperationFailed)
return
}
if err = ctx.SetJSONBody(devices); err != nil {
ctx.Error(err, messageOperationFailed)
return
}
}
// WebAuthnDevicePUT updates the description for a specific device for the current user.
func WebAuthnDevicePUT(ctx *middlewares.AutheliaCtx) {
2022-12-31 07:27:43 +00:00
var (
bodyJSON bodyEditWebAuthnDeviceRequest
id int
device *model.WebAuthnDevice
userSession session.UserSession
err error
2022-12-31 07:27:43 +00:00
)
if userSession, err = ctx.GetSession(); err != nil {
ctx.Logger.WithError(err).Error("Error occurred retrieving user session")
ctx.ReplyForbidden()
return
}
2022-12-31 07:27:43 +00:00
if err = json.Unmarshal(ctx.PostBody(), &bodyJSON); err != nil {
ctx.Logger.Errorf("Unable to parse %s update request data for user '%s': %+v", regulation.AuthTypeWebAuthn, userSession.Username, err)
ctx.SetStatusCode(fasthttp.StatusBadRequest)
ctx.Error(err, messageOperationFailed)
return
}
if id, err = getWebAuthnDeviceIDFromContext(ctx); err != nil {
2022-12-31 07:27:43 +00:00
return
}
if device, err = ctx.Providers.StorageProvider.LoadWebAuthnDeviceByID(ctx, id); err != nil {
2022-12-31 07:27:43 +00:00
ctx.Error(err, messageOperationFailed)
return
}
if device.Username != userSession.Username {
ctx.Error(fmt.Errorf("user '%s' tried to delete device with id '%d' which belongs to '%s", userSession.Username, device.ID, device.Username), messageOperationFailed)
return
}
if err = ctx.Providers.StorageProvider.UpdateWebAuthnDeviceDescription(ctx, userSession.Username, id, bodyJSON.Description); err != nil {
ctx.Error(err, messageOperationFailed)
return
}
}
// WebAuthnDeviceDELETE deletes a specific device for the current user.
func WebAuthnDeviceDELETE(ctx *middlewares.AutheliaCtx) {
2022-12-31 07:27:43 +00:00
var (
id int
device *model.WebAuthnDevice
userSession session.UserSession
err error
2022-12-31 07:27:43 +00:00
)
if id, err = getWebAuthnDeviceIDFromContext(ctx); err != nil {
2022-12-31 07:27:43 +00:00
return
}
if device, err = ctx.Providers.StorageProvider.LoadWebAuthnDeviceByID(ctx, id); err != nil {
2022-12-31 07:27:43 +00:00
ctx.Error(err, messageOperationFailed)
return
}
if userSession, err = ctx.GetSession(); err != nil {
ctx.Logger.WithError(err).Error("Error occurred retrieving user session")
ctx.ReplyForbidden()
return
}
2022-12-31 07:27:43 +00:00
if device.Username != userSession.Username {
ctx.Error(fmt.Errorf("user '%s' tried to delete device with id '%d' which belongs to '%s", userSession.Username, device.ID, device.Username), messageOperationFailed)
2022-12-31 07:27:43 +00:00
return
}
if err = ctx.Providers.StorageProvider.DeleteWebAuthnDevice(ctx, device.KID.String()); err != nil {
ctx.Error(err, messageOperationFailed)
return
}
2022-12-31 07:27:43 +00:00
ctx.ReplyOK()
}