User management guide
How to manage accounts, SSO, roles, permissions, and access control.
Overview
Cortega's user management is built on a role-based access control (RBAC) system with two independent permission axes:
| Axis | What it controls | Examples |
|---|---|---|
| Screen / action permissions | Which pages and actions a user can access | screen:user_management, screen:agents:write |
| Data visibility permissions | Whether sensitive (PII) fields are shown or redacted | data:pii:view |
Permissions are never assigned directly to a user. They are bundled into roles, and roles are assigned directly to users.
Every permission also has a scope, tenant or platform. On a
multi-tenant install, platform-scoped permissions (Gateways, Providers,
License, Platform Health, Tenant Management) only take effect for a user
in the System tenant (Tenant 0). A per-tenant administrator holds the
full set of tenant-scoped permissions but can never reach a platform
screen, whatever their role. See
Multi-tenant user management.
Cortega also supports SSO via OpenID Connect (OIDC), with an approval gate that requires an admin to vet every SSO-provisioned account before it can access anything.
Find this in the console under Users & Access (visible only to users with
the screen:user_management permission).
User account lifecycle
Every Cortega user account goes through a defined lifecycle: Created, Pending, Active, Suspended (which can be reactivated back to Active).
Account states
| State | Meaning | Can log in? | Can call APIs? |
|---|---|---|---|
| Pending | Account exists but hasn't been approved by an admin | Yes (SSO identity verified) | No, every request returns 403 account_pending_approval |
| Active | Approved with roles assigned | Yes | Yes, enforcement is based on permissions |
| Suspended | Admin-revoked; cannot access the platform | No, login returns the same 401 invalid credentials as a wrong password | No, existing sessions are rejected on the next request |
How accounts get created
| Method | Initial state | Vetting |
|---|---|---|
| Admin-created local account | Active immediately | Admin vets at creation time; sets roles |
| SSO auto-provisioned | Pending | Goes to the Pending Approval queue; admin must approve and assign roles |
SSO-provisioned accounts always land in Pending, even if the identity provider supplies role claims. Cortega does not auto-assign roles from those claims. An admin must explicitly approve each account and pick its roles.
Suspension takes effect at the next sign-in (a suspended account cannot obtain a new session) and on the user's very next API call for any session that already exists.
Single sign-on (SSO / OIDC)
Cortega supports browser login through any standard OpenID Connect (OIDC) provider, including Okta, Microsoft Entra ID, and Google Workspace.
The login flow uses the standard Authorization Code grant:
- The user clicks Continue with SSO on the login page.
- The browser redirects to the identity provider's authorization endpoint.
- The user authenticates with the identity provider.
- The identity provider redirects back to Cortega with an authorization code.
- Cortega validates state, exchanges the code for tokens, and verifies the ID token (issuer, audience, expiry, signature).
- Cortega finds or creates the user by verified email. An existing user gets an updated display name and last login time; existing role assignments are unchanged. A new user is created as pending with no roles, and a normal Cortega session is created so they can see the pending-approval screen.
- The webapp backend sets the
cortega_sessionHttpOnly cookie. - The user lands in the console. If pending, every API call returns 403
account_pending_approval.
SSO configuration
Set on the management backend:
| Variable | Required | Description |
|---|---|---|
SSO_ENABLED | Yes | Set to true to enable SSO |
SSO_PROVIDER_NAME | No | Friendly label shown on the login button |
SSO_ISSUER_URL | Yes | The identity provider's OIDC discovery URL |
SSO_CLIENT_ID | Yes | OAuth client ID from your identity provider |
SSO_CLIENT_SECRET | Yes | OAuth client secret from your identity provider |
SSO_REDIRECT_URL | Yes | Callback URL |
SSO_AUTO_CREATE_USERS | No | Default true, whether to auto-create accounts on first SSO login |
SSO_CALLBACK_SUCCESS_REDIRECT | No | Default /, webapp path after a successful SSO login |
SSO_CALLBACK_FAILURE_REDIRECT | No | Default /login?error=sso_failed |
Set on the login page (webapp backend):
| Variable | Required | Description |
|---|---|---|
SSO_ENABLED | Yes | Must match the management backend |
SSO_LABEL | No | Button label shown on the login page |
SSO does not change virtual key authentication for LLM/MCP traffic, does not auto-assign roles, and does not enable SCIM provisioning or SAML. Cortega logout is local only in the initial release, and the identity provider's access token is never stored or exposed to browser JavaScript.
To restrict which email domains can SSO into Cortega, use the Security tab under Users & Access (see Security settings). This is a runtime-editable list; no redeploy needed. Admin-created local accounts are always exempt from the domain allowlist; creating the account manually is itself the vetting step.
The RBAC permission model
Roles are named bundles of permissions. Cortega ships with four:
administrator (all permissions including data:pii:view),
operations_manager (all screen/action permissions, no
data:pii:view), operations (a subset of screens, read-only on most,
no data:pii:view), and tenant_admin (every tenant-scoped permission,
no platform screens).
Each permission carries a scope:
| Scope | Where it applies |
|---|---|
| tenant | Any tenant. The default for almost every permission. |
| platform | Only for a user in the System tenant (Tenant 0). Covers screen:gateways*, screen:providers*, screen:platform*, and screen:tenant_management*. |
On a single-tenant install every user is in Tenant 0, so the distinction
is invisible, administrator simply means everything. On a multi-tenant
install, give a per-tenant administrator the tenant_admin role (or a
custom role built only from tenant-scoped permissions); the platform
screens stay hidden and server-enforced no matter what.
A user's effective permission set is the union of permissions from every role assigned to them. There's no separate per-user permission override.
Enforcement happens at three layers: the server rejects with 403 if the
user's effective permission set lacks the required permission; the
server replaces PII fields with [redacted] before returning results if
the user lacks data:pii:view; and the console shows only the screens
and actions the user is allowed to access, with server-side permissions
remaining authoritative.
Permissions split into two categories: screen:<name> (can view the
page) and screen:<name>:write (can create/edit/delete on that page).
This split only matters for the operations role, which gets screen
permissions widely but write permissions only for agents, making it
read-only across most of the platform.
Pre-seeded system roles
System roles (is_system = true) can be edited (permissions added or
removed) but never deleted.
administrator
All screens, all write access (providers, models, keys, gateways, MCP servers, guardrails, rate tables, settings, agents), full PII visibility, and full user management. The superuser role.
operations_manager
Identical functional access to administrator, but PII fields are
redacted to [redacted]. Designed for team leads or IT managers who need
full operational control but should not see personally identifiable
information flowing through the platform.
operations
Most screens, but write access only for agents; read-only on providers, models, keys, gateways, MCP, guardrails, rate tables, and settings. PII fields are redacted. No user management. The day-to-day operator role.
tenant_admin
Every tenant-scoped screen, no platform screens (Gateways, Providers,
License, Platform Health, Tenants). Write access to all tenant-scoped
resources: models, keys, teams, guardrails, MCP, apps, Endpoint Guard,
and Cortega Agents. Full PII visibility. User management within their own
tenant, but cannot assign the administrator role (see
Multi-tenant user management). Providers
themselves are platform-scoped; a tenant_admin sees the models a
platform operator has made available but does not manage provider
credentials. This is the role for an administrator of a single tenant on
a multi-tenant install; on a single-tenant install it is rarely used, and
administrator is the norm.
What each role can and cannot do
| Screen / feature | administrator | operations_manager | operations | tenant_admin |
|---|---|---|---|---|
| A2A (Agents) | View + create/edit | View + create/edit | View + create/edit | View + create/edit |
| Gateways (platform) | View + manage | View + manage | View only | Hidden |
| Providers / provider budgets (platform) | View + manage | View + manage | View only | Hidden |
| Models | View + manage | View + manage | View only | View + manage |
| Identities | View + issue/revoke | View + issue/revoke | View only | View + issue/revoke |
| MCP Servers / MCP Authorization | View + manage | View + manage | View only | View + manage |
| Guardrails | View + manage | View + manage | View only | View + manage |
| Rate Tables | View + manage | View + manage | View only | View + manage |
| Applications / API Access | Manage | Manage | View only | Manage |
| Console (playgrounds, client setup) | Yes | Yes | Yes | Yes |
| Observability | Full access | Full access | No access | Full access |
| Insights | Full access | Full access | View only | Full access |
| Audit Log | Full access | Full access | No access | Full access |
| Users & Access | Full access | Full access | No access | Within own tenant |
| Tenants (platform) | Full access | Manage | View only | Hidden |
| License / Platform Health (platform) | Full access | Full access | View only | Hidden |
For tenant_admin, the write-access and data-visibility tables below
match administrator except that every platform action (managing
gateways, managing providers, creating tenants) is unavailable.
| Action | administrator | operations_manager | operations |
|---|---|---|---|
| Create/edit providers | Yes | Yes | No |
| Add/remove models | Yes | Yes | No |
| Create/delete named virtual models (API) | Yes | Yes | No |
| Issue/revoke/rotate keys | Yes | Yes | No |
| Manage gateways | Yes | Yes | No |
| Manage MCP servers | Yes | Yes | No |
| Manage guardrails | Yes | Yes | No |
| Manage rate tables | Yes | Yes | No |
| Create/edit/delete agents | Yes | Yes | Yes |
| Approve/pending users | Yes | Yes | No |
| Suspend/reactivate users | Yes | Yes | No |
| Assign roles | Yes | Yes | No |
| Create/edit/delete roles | Yes | Yes | No |
| Admin password reset | Yes | Yes | No |
| Change security settings | Yes | Yes | No |
| Data type | administrator | operations_manager | operations |
|---|---|---|---|
| User emails | Visible | Visible | Redacted |
| User display names | Visible | Visible | Redacted |
| Key metadata (user/agent tags) | Visible | Visible | Partially redacted |
| MCP server URLs | Visible | Visible | Visible |
| Provider endpoints | Visible | Visible | Visible |
| Audit log entries | Visible | Visible | Can't access page |
| Traffic telemetry (raw queries) | Visible | Visible | Can't access page |
Managing users
Navigate to Users & Access → Users.
To create an account: click Add user, choose SSO or Password, set the
user's email and display name (password accounts also require a
temporary password), and on a multi-tenant install a System-tenant
operator also picks the user's tenant. Assign roles at creation time; the
administrator role can only be assigned to a user in the System tenant,
and the form rejects it for any other tenant before the account is
created. The account is created directly as Active, no pending approval
needed.
Local accounts bypass the email-domain allowlist; an admin explicitly creating the account is the vetting step. SSO accounts created this way also skip pending approval, which only applies to SSO auto-provisioned accounts created during first login.
To edit a user's roles: click Edit access on a user row, select the desired roles in the Assignments modal, and click Save. A user who had no roles before and is assigned for the first time remains Active. If the user was Pending, use the Pending Approval tab instead.
To suspend a user: click Suspend on the user row. Their status changes to Suspended immediately, and their existing session is invalidated on the very next API call. A new sign-in with the correct password is refused with 401 invalid credentials.
To reactivate a suspended user: click Reactivate. This sets the user back to Active with their existing role assignments intact.
To delete a user: click Delete. This permanently removes the account and all its assignments and cannot be undone.
Managing pending approvals
Navigate to Users & Access → Pending Approval. When the tab shows a badge, there are SSO-provisioned accounts waiting for admin review.
To approve: click Approve on the user row, select at least one role in the Assignments modal, and click Approve. The user's status changes to Active and they gain access immediately. This is recorded in the audit log with who approved, when, and which roles were assigned.
To reject: click Reject and confirm in the dialog. The account is suspended and the user cannot sign in.
To delete a pending account: click Delete. This permanently removes it, appropriate for mistaken SSO signups or test accounts.
Managing roles
Navigate to Users & Access → Roles.
Each role card shows its name (with a system tag if it's a seed role that can't be deleted), a description, and permission badges for every permission in the role's bundle.
To create a role: click New Role, enter a name and description, check the permissions you want (organized by screen, action, and data categories), and click Save. New roles take effect immediately for any user they're assigned to, since the permission set is loaded from the database on every request.
To edit a role, including system roles: click Edit on any role card, add or remove permissions, and click Save. Removing a permission from a role that is the only source of that permission for some users immediately cuts off their access to that screen or action. Every role edit is recorded in the audit log.
To delete a non-system role: click Delete and confirm. Any user who only
had access through this role loses those permissions immediately. System
roles (administrator, operations_manager, operations) cannot be
deleted, only edited.
Security settings
Navigate to Users & Access → Security to control the signup email-domain
allowlist, which restricts which domains can SSO into Cortega. Empty
(the default) means no restriction; a comma-separated list like
cortega.ai, partner-hospital.org means only those domains can SSO
auto-provision. Admin-created local accounts are always exempt. The
allowlist is stored in the database, so changes take effect immediately
without a redeploy.
Password management
Cortega does not have a self-service "forgot password" flow. There is no outbound email infrastructure. All password resets are admin-initiated.
To reset a user's password: navigate to Users & Access → Users, click Reset password on the user row, and copy the one-time temporary password shown in the modal immediately, since it won't be shown again. Relay it to the user out-of-band. The temporary password is single-use; on the user's next login, they are forced to set their own password before accessing any Cortega page.
SSO-created accounts have no Cortega password hash. Password reset does not apply to them; if an SSO user needs access changes, use the identity provider. Users can change their own password at any time from within the app, and admins can also reset any local user's password as described above.
Data sensitivity and PII redaction
Cortega redacts personally identifiable information at the server level
for users who lack the data:pii:view permission. This is not a
client-side hiding mechanism; the server replaces PII fields with
[redacted] before results are returned to the browser or API client.
administrator sees full data. operations_manager and operations see
[redacted] in place of PII fields. PII is defined as fields tagged
sensitive:"pii" in the backend response structs, including but not
limited to user email addresses, user display names, and virtual key
metadata fields tagged as user or agent identifiers. The redaction is
consistent across all API responses; there's no client-side bug that can
accidentally expose PII to a user who shouldn't see it.
Full permission catalog reference
P marks a platform-scoped permission, effective only for a user in the
System tenant (Tenant 0). Everything else is tenant-scoped.
| Permission | Scope | Controls access to |
|---|---|---|
screen:user_management / :write | tenant | Users & Access page; create/approve/suspend users, manage roles |
screen:tenant_management / :write | P | Tenants page; create tenants and set their product entitlements |
screen:agents / :write | tenant | A2A (Agents) page |
screen:gateways / :write | P | Gateways page; register/drain/delete gateways |
screen:providers / :write | P | Providers, provider diagnostics, and provider budgets |
screen:llm / :write | tenant | Models page (concrete models, virtual models, Routing Policy) |
screen:keys / :write | tenant | Identities page; issue/rotate/revoke LLM key identities |
screen:mcp / :write | tenant | MCP Servers and MCP Authorization pages |
screen:guardrails / :write | tenant | Guardrails page |
screen:costs / :write | tenant | Rate Tables page; refresh/override the cost catalog |
screen:apps / :write | tenant | Applications (Agentic Applications) page |
screen:api_access / :write | tenant | API Access page; create/revoke Cortega API keys |
screen:edge_enrollment / :write | tenant | Endpoint Guard → Enrollment (CAs, SSO/invitations) |
screen:edge_admin:write | tenant | Create/update/delete Endpoint Guard devices, app rules, and guardrails |
screen:cra / :write / :advanced | tenant | Cortega Agents pages; :advanced gates the Tenant-0-only agent registry/scope controls |
screen:benchmarks / :run | tenant | AI Bench pages; :run starts a benchmark run |
screen:migration / :write | tenant | Gateway migration / import page |
screen:observability | tenant | Observability page (traffic queries, live logs) |
screen:insights | tenant | Insights page (spend, performance, recommendations, workload) |
screen:audit | tenant | Audit Log page (edition must include the audit-log feature) |
screen:platform / :write | P | Platform Health page and platform settings |
screen:console | tenant | Console (Client Setup, Model Playground, MCP Playground) |
data:pii:view | Whether PII-tagged fields are visible or redacted |
Audit trail
Every user management action is written to the audit log: user creation, approval, suspension, and reactivation; role assignment changes, role creation, edits, and deletion; sign-in and sign-out; self-service and admin-initiated password changes; and security setting changes. Each entry records the actor and, where relevant, the target user and the before/after values.
The audit log is tamper-evident and hash-chained. Use the Verify Chain button on the Audit Log page to cryptographically validate its integrity.
Multi-tenant user management
A single-tenant install has one implicit tenant and everything above applies unchanged. A multi-tenant install adds a System tenant (Tenant 0) that owns the shared platform: gateways, upstream providers, the license, platform health, and the tenant list. Only a user in Tenant 0 can hold a platform-scoped permission, so only Tenant 0 operators see the Gateways, Providers, License, Platform Health, and Tenants screens. Every other tenant is an ordinary customer boundary with its own users, teams, keys, budgets, guardrails, traffic, and telemetry.
Every user belongs to exactly one tenant. The Add user form (Tenant 0
operators) has a tenant selector; the account, its data, and its traffic
all live in that tenant. The pending SSO approval dialog also assigns the
tenant: Cortega first tries to place the account by email domain (a
per-tenant list of SSO domains can be set when a tenant is created or
edited) and otherwise leaves it for the operator to choose. A per-tenant
tenant_admin manages only their own tenant's users and cannot change
anyone's tenant.
administrator carries platform permissions, so Cortega refuses to
assign it to a user outside Tenant 0. The check runs on Add user (before
the account is created), on approve, and on edit access. Give a
per-tenant administrator the tenant_admin role instead.
Tenant 0 operators see the current record's tenant in the top bar and in list views, and can act across every tenant. Per-tenant users never see another tenant's name or data.
Shared (Tenant 0 manages): gateways, upstream providers, provider budgets; the license and edition features; the tenant list and entitlements; platform health and platform settings; console-login SSO and the signup email-domain allowlist; the rate tables cost catalog.
Per-tenant: teams, team budgets, LLM/MCP identities; guardrails, MCP servers, MCP authorization; agentic applications, Cortega API keys; Endpoint Guard devices/CAs, Cortega Agents config; per-tenant Endpoint Guard SSO/enrollment domains; observability and Insights data.