langflow-ai/langflow · error · HTTPException
Only the resource owner or a superuser may administer shares
Error message
Only the resource owner or a superuser may administer shares for this resource.
What it means
Raised by _ensure_can_administer_share in the /api/v1/authz/shares routes — the OSS ownership floor. If the caller is neither the resource owner nor a superuser and no cross-user-fetch-capable authorization plugin is active, share administration is refused with 403. When a plugin signals supports_cross_user_fetch() AND is_enabled(), this floor is bypassed and the plugin's ensure_share_permission() becomes the authoritative gate.
Source
Thrown at src/backend/base/langflow/api/v1/authz_shares.py:196
owner_id: UUID | None,
) -> None:
"""Require resource owner or superuser unless cross-user enforcement is active."""
if getattr(user, "is_superuser", False):
return
if owner_id is not None and owner_id == user.id:
return
authz = get_authorization_service()
if await authz.supports_cross_user_fetch() and await authz.is_enabled():
# Why: in OSS, ``supports_cross_user_fetch()`` is False (see
# LangflowAuthorizationService), so this early-return is dead and the
# explicit 403 below is the floor. When an authorization plugin signals
# cross-user fetch support, the plugin is the authoritative gate via
# the ``ensure_share_permission()`` call that every share route makes
# immediately after this helper. Removing that downstream call — or
# weakening the plugin's cross-user fetch contract — REOPENS the
# ownership gap. Keep the two in lockstep.
return
raise HTTPException(
status_code=status.HTTP_403_FORBIDDEN,
detail="Only the resource owner or a superuser may administer shares for this resource.",
)
@router.post("", response_model=ShareRead, status_code=status.HTTP_201_CREATED)
@router.post("/", response_model=ShareRead, status_code=status.HTTP_201_CREATED)
async def create_share(
payload: ShareCreate,
current_user: CurrentActiveUser,
session: DbSession,
) -> ShareRead:
"""Create an authz_share row for a resource."""
owner_id = await _resolve_resource_owner(
session,
resource_type=payload.resource_type,
resource_id=payload.resource_id,
)View on GitHub (pinned to 976ec789d2)
Solutions
- Perform share administration as the resource owner or as a superuser
- Install/register an authorization plugin via the lfx.services entry point (authorization_service) that sets SUPPORTS_CROSS_USER_FETCH=True and grants share permissions
- Do not attempt to bypass the floor — it exists so the OSS pass-through cannot let a non-owner mint share rows
Defensive patterns
Strategy: validation
Validate before calling
async function canAdministerShares(user, ownerId) {
return user.is_superuser || user.id === ownerId;
} Type guard
const canAdminShares = (u: {id: string; is_superuser: boolean}, ownerId: string): boolean =>
u.is_superuser || u.id === ownerId; Prevention
- On OSS (no authz plugin), only build share-management UI for the owner or superuser
- Do not expect LANGFLOW_AUTHZ_ENABLED=true alone to widen share administration — a registered plugin is required
When it happens
Trigger: POST/PATCH/DELETE /api/v1/authz/shares/{id} (or POST /authz/shares) as a non-owner, non-superuser while running the OSS pass-through authorization service (LANGFLOW_AUTHZ_ENABLED=false or no plugin registered).
Common situations: Team admin trying to manage another user's shares on OSS Langflow (no plugin installed); enabling LANGFLOW_AUTHZ_ENABLED=true but expecting it to widen share administration — without a registered plugin the floor stays; scripts using service accounts that are not superusers.
Related errors
- You don't have permission to edit this flow.
- You don't have permission to delete this flow.
- Resource not found
- Share could not be created: it may already exist or conflict
- Unknown scope {scope!r}
AI-assisted analysis of langflow-ai/langflow@976ec789d2 (2026-08-14).
Data as JSON: /api/errors/663cf5a3d8a3d1e6.
Report an issue: GitHub.