langflow-ai/langflow · error · HTTPException

Superuser required to administer role assignments.

Error message

Superuser required to administer role assignments.

What it means

Authorization gate on all /api/v1/authz/role-assignments routes: only superusers may list, create, or revoke role assignments. Any authenticated non-superuser gets HTTP 403 with detail 'Superuser required to administer role assignments.'

Source

Thrown at src/backend/base/langflow/api/v1/authz_role_assignments.py:40

    RoleAssignmentCreate,
    RoleAssignmentRead,
)
from langflow.services.authorization.invalidation import safe_invalidate_user
from langflow.services.authorization.utils import audit_decision
from langflow.services.database.models.auth import AuthzRole, AuthzRoleAssignment
from langflow.services.database.models.user.model import User
from langflow.services.deps import get_authorization_service

router = APIRouter(prefix="/authz/role-assignments", tags=["Authorization"])

# See ``authz_roles._LIST_MAX_LIMIT`` — same bound, applied to assignments.
_LIST_MAX_LIMIT = 200
_LIST_DEFAULT_LIMIT = 100


def _require_superuser(user) -> None:
    if not getattr(user, "is_superuser", False):
        raise HTTPException(
            status_code=status.HTTP_403_FORBIDDEN,
            detail="Superuser required to administer role assignments.",
        )


@router.get("", response_model=list[RoleAssignmentRead])
@router.get("/", response_model=list[RoleAssignmentRead])
async def list_assignments(
    session: DbSession,
    current_user: CurrentActiveUser,
    user_id: Annotated[UUID | None, Query(description="Filter by user")] = None,
    role_id: Annotated[UUID | None, Query(description="Filter by role")] = None,
    domain_type: Annotated[str | None, Query()] = None,
    domain_id: Annotated[UUID | None, Query()] = None,
    limit: Annotated[int, Query(ge=1, le=_LIST_MAX_LIMIT)] = _LIST_DEFAULT_LIMIT,
    offset: Annotated[int, Query(ge=0)] = 0,
) -> list[RoleAssignmentRead]:
    """List role assignments scoped to one user.

View on GitHub (pinned to 976ec789d2)

Solutions

  1. Log in as the seed superuser account (LANGFLOW_SUPERUSER/ LANGFLOW_SUPERUSER_PASSWORD env vars) and use its token
  2. Verify the user row: SELECT is_superuser FROM user WHERE id=... and flip it only if that user should genuinely be a superuser
  3. Have the frontend hide role-assignment admin UI for non-superusers to avoid the 403 entirely
Defensive patterns

Strategy: validation

Validate before calling

const me = await api.get('/users/whoami');
if (!me.is_superuser) throw new Error('superuser required');

Type guard

const isSuperuser = (u: { is_superuser?: boolean } | null): boolean =>
  Boolean(u?.is_superuser);

Try / catch

catch (e) { if (e.status === 403) redirect('/'); } // hide admin UI from non-superusers

Prevention

When it happens

Trigger: Any GET/POST/DELETE under /api/v1/authz/role-assignments with a valid JWT for a user whose is_superuser flag is False — e.g. a regular admin-pattern client reused against the authz admin API.

Common situations: Assuming the Langflow 'admin' login is a superuser when the DB user row has is_superuser=False, using a store API-key session cookie instead of a user login, or pointing a superuser-only ops script at the wrong instance where the login user was created via the normal signup flow.

Related errors


AI-assisted analysis of langflow-ai/langflow@976ec789d2 (2026-08-14). Data as JSON: /api/errors/59a2317bbae63cd0. Report an issue: GitHub.