{"record":{"id":"59a2317bbae63cd0","repo":"langflow-ai/langflow","slug":"superuser-required-to-administer-role-assignments","errorCode":null,"errorMessage":"Superuser required to administer role assignments.","messagePattern":"Superuser required to administer role assignments\\.","errorType":"http","errorClass":"HTTPException","httpStatus":403,"severity":"error","filePath":"src/backend/base/langflow/api/v1/authz_role_assignments.py","lineNumber":40,"sourceCode":"    RoleAssignmentCreate,\n    RoleAssignmentRead,\n)\nfrom langflow.services.authorization.invalidation import safe_invalidate_user\nfrom langflow.services.authorization.utils import audit_decision\nfrom langflow.services.database.models.auth import AuthzRole, AuthzRoleAssignment\nfrom langflow.services.database.models.user.model import User\nfrom langflow.services.deps import get_authorization_service\n\nrouter = APIRouter(prefix=\"/authz/role-assignments\", tags=[\"Authorization\"])\n\n# See ``authz_roles._LIST_MAX_LIMIT`` — same bound, applied to assignments.\n_LIST_MAX_LIMIT = 200\n_LIST_DEFAULT_LIMIT = 100\n\n\ndef _require_superuser(user) -> None:\n    if not getattr(user, \"is_superuser\", False):\n        raise HTTPException(\n            status_code=status.HTTP_403_FORBIDDEN,\n            detail=\"Superuser required to administer role assignments.\",\n        )\n\n\n@router.get(\"\", response_model=list[RoleAssignmentRead])\n@router.get(\"/\", response_model=list[RoleAssignmentRead])\nasync def list_assignments(\n    session: DbSession,\n    current_user: CurrentActiveUser,\n    user_id: Annotated[UUID | None, Query(description=\"Filter by user\")] = None,\n    role_id: Annotated[UUID | None, Query(description=\"Filter by role\")] = None,\n    domain_type: Annotated[str | None, Query()] = None,\n    domain_id: Annotated[UUID | None, Query()] = None,\n    limit: Annotated[int, Query(ge=1, le=_LIST_MAX_LIMIT)] = _LIST_DEFAULT_LIMIT,\n    offset: Annotated[int, Query(ge=0)] = 0,\n) -> list[RoleAssignmentRead]:\n    \"\"\"List role assignments scoped to one user.","sourceCodeStart":22,"sourceCodeEnd":58,"githubUrl":"https://github.com/langflow-ai/langflow/blob/976ec789d2886a86de109c044d089d68e96c9a35/src/backend/base/langflow/api/v1/authz_role_assignments.py#L22-L58","documentation":"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.'","triggerScenarios":"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.","commonSituations":"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.","solutions":["Log in as the seed superuser account (LANGFLOW_SUPERUSER/ LANGFLOW_SUPERUSER_PASSWORD env vars) and use its token","Verify the user row: SELECT is_superuser FROM user WHERE id=... and flip it only if that user should genuinely be a superuser","Have the frontend hide role-assignment admin UI for non-superusers to avoid the 403 entirely"],"exampleFix":null,"handlingStrategy":"validation","validationCode":"const me = await api.get('/users/whoami');\nif (!me.is_superuser) throw new Error('superuser required');","typeGuard":"const isSuperuser = (u: { is_superuser?: boolean } | null): boolean =>\n  Boolean(u?.is_superuser);","tryCatchPattern":"catch (e) { if (e.status === 403) redirect('/'); } // hide admin UI from non-superusers","preventionTips":["Gate role-assignment admin UI on is_superuser from whoami","Use the seed superuser account for ops scripts","Test admin flows with a non-superuser token to confirm 403 handling"],"tags":["authz","rbac","http-403","authorization"],"backgroundTag":null,"analyzedSha":"976ec789d2886a86de109c044d089d68e96c9a35","analyzedAt":"2026-08-14T18:23:12.227Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}