Authorization with the Permission Service#
User Info Service can optionally delegate authorization to the Omniverse Storage Permission Service. When the integration is enabled, every directory request is authorized against a named action before it runs, and each item in a list response is checked individually so that callers only ever see the users and groups they are permitted to see. This page describes the actions the service uses, how each endpoint is validated, how list responses are filtered, which endpoints are exempt, how decisions are cached, and how the service behaves when the Permission Service is unavailable.
The integration is off by default. When it is off, nothing on this page applies: the service performs no authorization calls and serves every request that reaches it, relying on the platform’s authentication gateway to reject unauthenticated callers. Enabling it does not change the service’s own view of the directory — it only decides which of the directory records a given caller is allowed to receive.
Authorization Model#
Authorization is evaluated per request against the caller’s bearer token — the same token the platform’s authentication gateway validates. The service never inspects or trusts the token’s contents for the authorization decision; it forwards the token to the Permission Service and lets the Permission Service decide. Each check names three things:
The caller — identified by the bearer token, forwarded unchanged.
The action — a named operation such as
list-usersorget-user, qualified by the service name the deployment is configured with (userinfoby default).The resource — for actions that target a specific user or group, the stable identifier and kind (
UserorGroup) of that target. List actions that are not tied to a single target carry no resource.
The Permission Service returns one of three decisions for each check:
Decision |
Meaning |
Effect |
|---|---|---|
|
The caller is explicitly permitted. |
The request proceeds, or the item is kept. |
|
No policy applies; the Permission Service defers to the service. |
Treated as permitted — the request proceeds, or the item is kept. |
|
The caller is explicitly refused. |
The request is rejected, or the item is removed from the response. |
Both allow and skip let the request or item through; only deny blocks it.
Actions and the Endpoints They Guard#
Each endpoint maps to exactly one named action. The same action names apply to both the REST and gRPC surfaces, because the two APIs are equivalent. The table below lists every action, the REST path and gRPC method it guards, and the resource the pre-check names.
Action |
REST endpoint |
gRPC method |
Pre-check resource |
|---|---|---|---|
|
|
|
(none) |
|
|
|
the target user |
|
|
|
the user whose groups are listed |
|
|
|
the user whose membership is checked |
|
|
|
(none) |
|
|
|
the target group |
|
|
|
the group whose members are listed |
|
|
|
the group whose membership is checked |
For the membership endpoints the pre-check names the container being queried — the user for
list-user-groups and get-user-group, the group for list-group-members and get-group-member
— not the items that will be returned. Those returned items are authorized separately, as
described below.
How Requests Are Validated#
Every authorized request goes through a single pre-check before the request handler runs:
The service determines the action and, where applicable, the target resource from the matched route and its path parameters. Requests to unrecognized paths are not authorized here and fall through to normal request handling.
The bearer token is read from the request. If the integration is enabled and no bearer token is present, the request is rejected as unauthorized (
401/UNAUTHENTICATED) before any Permission Service call is made.The service asks the Permission Service whether the caller may perform the action on the resource.
On
alloworskip, the request proceeds to the handler. Ondeny, the request is rejected as forbidden (403/PERMISSION_DENIED) and the handler never runs.
Because the pre-check runs before the handler, a caller who is not permitted to perform an operation never causes the underlying directory to be read.
How List Responses Are Filtered#
The pre-check authorizes the operation as a whole; it does not decide which individual users or groups a caller may see. For that, every list endpoint additionally applies a per-item check to the page it is about to return:
After a list handler produces a page of results, each item on that page is checked against the matching per-item action —
get-userfor every returned user,get-groupfor every returned group.Items the caller is not permitted to see (
deny) are removed from the page. Items that arealloworskipare kept.Filtering is applied to the current page only; pagination is unchanged. A page may therefore return fewer items than the requested page size while still reporting a next-page cursor.
The per-item checks carry the full attributes of each candidate item, not just its identifier, so that Permission Service policies can decide based on the record’s contents. The mapping of list endpoint to per-item action is:
List endpoint |
Per-item action |
Applied to |
|---|---|---|
|
|
each returned user |
|
|
each returned group |
|
|
each returned member |
|
|
each returned group |
The single-item get endpoints (get-user, get-group, get-user-group, get-group-member) do
not need a separate filtering step: their pre-check already authorizes the one record they return.
To keep per-item checks efficient, all items on a page are authorized together in a single batch request to the Permission Service rather than one call per item.
Exempt Endpoints#
Some endpoints are never subject to permission checks, regardless of whether the integration is enabled:
Health and readiness probes (
GET /healthz,GET /readyz) — infrastructure endpoints that carry no directory data and must remain reachable by the platform.Current-user requests (
GET /users/meand theGetCurrentUsergRPC method) — a caller is always allowed to retrieve their own directory record. The identity is taken from the caller’s own token, so there is nothing to authorize beyond the authentication the gateway has already performed. See Microsoft Entra ID Integration for how the caller is resolved from the token.
Decision Caching#
To avoid calling the Permission Service repeatedly for the same caller and operation, the service caches each decision in memory. A cached entry is keyed by the combination of:
a fingerprint of the bearer token — the token is hashed rather than stored directly, so raw credentials never sit in the cache;
the action; and
the target resource, where one applies.
Both pre-check and per-item decisions are cached the same way. When a page is filtered, items whose decision is already cached are served from the cache and only the remaining items are sent to the Permission Service in a batch. Entries expire after a configurable time-to-live, and the cache is bounded by a configurable maximum number of entries; once the limit is reached, the least-recently used entries are evicted.
Because decisions are cached per caller and action, a policy change on the Permission Service takes effect for an already-cached caller only after the cached entry expires. Choose the time-to-live to balance responsiveness to policy changes against the load placed on the Permission Service.
Behavior When the Permission Service Is Unavailable#
Authorization fails closed. If the service cannot obtain a decision, it refuses the request rather than serving data the caller might not be entitled to:
Situation |
Result |
|---|---|
Permission Service rejects the token ( |
Request rejected as unauthorized ( |
Permission Service reports the caller is refused ( |
Request rejected as forbidden ( |
Permission Service reports rate limiting ( |
Request rejected as rate-limited ( |
Permission Service unreachable, times out, or returns any other error |
Request rejected as an internal error ( |
During per-item filtering, a batch check that cannot be completed fails the whole list request as an internal error for the same reason: the service will not return a partially authorized page.
Configuration#
The integration is configured under the permission section of the Helm chart’s values, which the
chart translates into the settings below. When authorization is disabled, none of the other
settings have any effect.
Setting |
Environment variable |
Helm value ( |
Default |
Description |
|---|---|---|---|---|
Enable authorization |
|
|
|
Authorize every non-exempt request against the Permission Service. |
Permission Service URL |
|
|
(empty) |
Base URL of the Permission Service. Required when authorization is enabled. |
Service name |
|
|
|
Name that qualifies the action in authorization requests; identifies this service in Permission Service policies. |
Decision cache time-to-live |
|
|
|
How long a cached decision remains valid before it is re-evaluated. |
Decision cache capacity |
|
|
|
Maximum number of cached decisions before least-recently-used entries are evicted. |
The Permission Service must contain policies and service metadata for the configured service name before the integration is enabled; otherwise every request is refused.
Configuring Authorization in the Helm Chart#
Authorization is configured under the permission section of userinfo-values.yaml. It is off by
default; set enabled to true and point url at the Permission Service to turn it on:
permission:
enabled: true
url: "http://permission-service.storage-apis.svc.cluster.local:3000/"
serviceName: "userinfo"
cacheTtl: "5m"
cacheMaxCapacity: 10000
Only url must be set; the remaining values default as listed in the table above. The chart
passes these settings to the reader pods only — the writer performs background synchronization and
does not serve the read APIs, so it makes no authorization calls. When enabled is false, the
chart omits the rest of the section entirely and no authorization environment is set on the pods.
Install or upgrade the release with the same commands used for the synchronized directory deployment in User Info Service Configuration.
When authorization is enabled together with directory scoping, the two features are complementary: scoping decides which groups and memberships exist in the served directory, while authorization decides which of those the caller may see. Because scoping aligns the served groups with the enterprise application’s assignments, it matches the view the Permission Service itself has of the caller’s groups; see Directory Scoping for details.