diff --git a/apps/backend/internal/auth/middleware.go b/apps/backend/internal/auth/middleware.go index 8404751..d158cc6 100644 --- a/apps/backend/internal/auth/middleware.go +++ b/apps/backend/internal/auth/middleware.go @@ -102,3 +102,25 @@ func NewAuthMiddleware(s *Service, db *bun.DB, cookieConfig CookieConfig) fiber. 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) + } +} diff --git a/apps/backend/internal/sharing/http.go b/apps/backend/internal/sharing/http.go index 9d7da59..c979281 100644 --- a/apps/backend/internal/sharing/http.go +++ b/apps/backend/internal/sharing/http.go @@ -5,6 +5,7 @@ import ( "time" "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/nullable" "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 { - 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} }