diff --git a/platform/internal/handlers/workspace.go b/platform/internal/handlers/workspace.go index 580cc0d3..82ac6d4b 100644 --- a/platform/internal/handlers/workspace.go +++ b/platform/internal/handlers/workspace.go @@ -12,6 +12,7 @@ import ( "github.com/Molecule-AI/molecule-monorepo/platform/internal/db" "github.com/Molecule-AI/molecule-monorepo/platform/internal/events" + "github.com/Molecule-AI/molecule-monorepo/platform/internal/middleware" "github.com/Molecule-AI/molecule-monorepo/platform/internal/models" "github.com/Molecule-AI/molecule-monorepo/platform/internal/provisioner" "github.com/Molecule-AI/molecule-monorepo/platform/internal/wsauth" @@ -488,6 +489,9 @@ func (h *WorkspaceHandler) Update(c *gin.Context) { } tok := wsauth.BearerTokenFromHeader(c.GetHeader("Authorization")) if tok == "" { + if middleware.IsSameOriginCanvas(c) { + break // tenant canvas — trusted same-origin + } c.JSON(http.StatusUnauthorized, gin.H{"error": "admin auth required for field: " + field}) return } diff --git a/platform/internal/middleware/wsauth_middleware.go b/platform/internal/middleware/wsauth_middleware.go index 0553cdf6..5b06c576 100644 --- a/platform/internal/middleware/wsauth_middleware.go +++ b/platform/internal/middleware/wsauth_middleware.go @@ -209,6 +209,13 @@ func canvasOriginAllowed(origin string) bool { // on every request. var canvasProxyActive = os.Getenv("CANVAS_PROXY_URL") != "" +// IsSameOriginCanvas is the exported version for use outside the middleware +// package (e.g. workspace.go field-level auth). Same logic as the internal +// callers in AdminAuth/WorkspaceAuth/CanvasOrBearer. +func IsSameOriginCanvas(c *gin.Context) bool { + return isSameOriginCanvas(c) +} + func isSameOriginCanvas(c *gin.Context) bool { if !canvasProxyActive { return false