fix(backend): optional auth for share routes

Add auth.NewOptionalAuthMiddleware to run auth only when credentials are
present (Authorization header or auth cookies). Use it on share
consumption routes so public shares remain accessible unauthenticated,
while authenticated callers can resolve account-scoped shares. This
prevents a panic in share middleware when accountId was provided but the
request wasn’t authenticated (nil reqctx.AuthenticatedUser type
assertion).
This commit is contained in:
2025-12-29 00:07:44 +00:00
parent 51f1add4f0
commit f4620dff3a
2 changed files with 27 additions and 1 deletions

View File

@@ -102,3 +102,25 @@ func NewAuthMiddleware(s *Service, db *bun.DB, cookieConfig CookieConfig) fiber.
return c.Next() return c.Next()
} }
} }
// NewOptionalAuthMiddleware conditionally runs the given auth middleware only when
// the request contains auth credentials (Authorization header or auth cookies).
//
// This is useful for endpoints that are publicly accessible but can also behave
// differently for authenticated callers (e.g. share consumption routes that may
// resolve additional permissions for a specific account when credentials are
// present).
//
// Usage:
// authMiddleware := auth.NewAuthMiddleware(...)
// router.Use(auth.NewOptionalAuthMiddleware(authMiddleware))
func NewOptionalAuthMiddleware(authMiddleware fiber.Handler) fiber.Handler {
return func(c *fiber.Ctx) error {
hasAuthHeader := c.Get("Authorization") != ""
hasAuthCookies := c.Cookies(cookieKeyAccessToken) != "" || c.Cookies(cookieKeyRefreshToken) != ""
if !hasAuthHeader && !hasAuthCookies {
return c.Next()
}
return authMiddleware(c)
}
}

View File

@@ -5,6 +5,7 @@ import (
"time" "time"
"github.com/get-drexa/drexa/internal/account" "github.com/get-drexa/drexa/internal/account"
"github.com/get-drexa/drexa/internal/auth"
"github.com/get-drexa/drexa/internal/httperr" "github.com/get-drexa/drexa/internal/httperr"
"github.com/get-drexa/drexa/internal/nullable" "github.com/get-drexa/drexa/internal/nullable"
"github.com/get-drexa/drexa/internal/reqctx" "github.com/get-drexa/drexa/internal/reqctx"
@@ -50,7 +51,10 @@ func NewHTTPHandler(sharingService *Service, accountService *account.Service, vf
} }
func (h *HTTPHandler) RegisterShareConsumeRoutes(r fiber.Router) *virtualfs.ScopedRouter { func (h *HTTPHandler) RegisterShareConsumeRoutes(r fiber.Router) *virtualfs.ScopedRouter {
g := r.Group("/shares/:shareID", h.shareMiddleware) // Public shares should be accessible without authentication. However, if the client provides auth
// credentials (cookies or Authorization header), attempt auth so share scopes can be resolved for
// account-scoped shares.
g := r.Group("/shares/:shareID", auth.NewOptionalAuthMiddleware(h.authMiddleware), h.shareMiddleware)
return &virtualfs.ScopedRouter{Router: g} return &virtualfs.ScopedRouter{Router: g}
} }