REST API#

The Permission Service provides two endpoints for applications and services:

  • POST /v1beta/authorization/ – checks if the specified principal has access to perform an action on the specified resource;

  • POST /v1beta/authorization/batch/ – checks if the principal has access to perform a list of specified actions;

The key words “MUST”, “MUST NOT”, “REQUIRED”, “SHALL”, “SHALL NOT”, “SHOULD”, “SHOULD NOT”, “RECOMMENDED”, “MAY”, and “OPTIONAL” in this section are to be interpreted as described in RFC 2119.

POST /v1beta/authorization/#

POST /v1beta/authorization/ HTTP/1.1
Authorization: Bearer <accessToken>
Content-Type: application/json

{
   "principal": <a valid JSON object with "sub" field>,
   "action": <a valid JSON object with "name" and "service" fields>,
   "resource": <a valid JSON object with "id", "type" and "data" fields>,
   "context": <any valid JSON object>
}

This API checks if the specified principal has access to perform the action on the specified resource.

The access token passed in the Authorization header MUST be a valid token received from the Identity Provider (either a user or service ID token). Customers MAY use different authentication like Basic Auth, API Keys or SAML2, and change how authentication information is passed to the Permission API and other services.

The underlying authorization system MAY support passing a payload in the principal field for a user different from the caller (e.g. the system administrator checking if a user has permissions to perform some operation). If this is not supported, the permission service MUST return an 403 error indicating that the caller is unauthorized to check permissions for the specified principal (see below).

The action field is a JSON object that must contain two fields – "name" to specify the action name and "service" to specify the service name where the action will be performed.

The resource field is a JSON object that must contain three fields called "id" to specify the unique resource identifier, "type" to specify the type of resource used for authorization (used by the Permission Service internally) and "data" to provide resource information that can be used to evaluate principal permissions.

The context field is optional and MAY be omitted. The reference implementation won’t utilize this field but customers MAY update services to send additional request information that can be required for authorization evaluation.

The request example:

POST /v1beta/authorization/ HTTP/1.1
Authorization: Bearer eyJraWQiOiJvYXV0aC1zaWduL[...]cc5IgUXhY66ML-CZVlRw
Content-Type: application/json

{
   "principal": {"sub": "DdxA9xDiqdUbv", "email": "user@test.com", "exp": 1727821346329},
   "action": {
      "name": "read",
      "service": "storage"
   },
   "resource": {
      "id": "/Projects/Scene.usd",
      "type": "File",
      "data": {
         "resourceIdentity": "/Projects/Scene.usd",
         "metadata": {
            "size": 1024,
         }
      }
   },
   "context": {
      "ip": "127.0.0.1",
      "location": {"lat": 54.32, "lon": 33.44}
   }
}

The principal field MAY be omitted if its content is the same as the payload of the token specified in the Authorization header:

GET /v1beta/authorization/ HTTP/1.1
Authorization: Bearer eyJraWQiOiJvYXV0aC1zaWduL[...]cc5IgUXhY66ML-CZVlRw
Content-Type: application/json

{
   "action": {
      "name": "download",
      "service": "storage"
   },
   "resource": {
      "id": "/Projects/Scene.usd",
      "type": "File",
      "data": {
         "resourceIdentity": "/Projects/Scene.usd",
         "metadata": {
            "size": 1024,
            "timestamp": 1726640120432
         }
      }
   }
}

The success response returns 200 HTTP status with the following body:

HTTP/1.1 200 OK
Content-Type: application/json

{
   "decision": "allow"
}

If the specified action is unauthorized for the principal, returns an HTTP 200 response with the following body:

HTTP/1.1 200 OK
Content-Type: application/json

{
   "decision": "deny"
}

Error conditions#

The following error conditions are defined:

Missing, invalid, or expired bearer or principal token

HTTP/1.1 401 Unauthorized
Content-Type: application/json

{
    "detail": "The principal token is expired."
}

The request body is invalid (missing required fields or fields represented in a wrong format)

HTTP/1.1 422 Unprocessable Content
Content-Type: application/json

{
    "detail": "'principal' field is required."
}

The caller is unauthorized to make the permission check for the specified principal

HTTP/1.1 403 Forbidden
Content-Type: application/json

The request body is larger than the maximum value specified for the service

HTTP/1.1 413 Payload Too Large
Content-Type: application/json

POST /v1beta/authorization/batch/#

POST /v1beta/authorization/batch/ HTTP/1.1
Authorization: Bearer <idToken>
Content-Type: application/json

{
  "condition": “none|and|or”
  "batches": [
     {
        "principal": <any valid JSON object>,
        "actions": [<a valid JSON object with "name" and "service" fields>, ..., <a valid JSON object with "name" and "service" fields>],
        "resource": <a valid JSON object with "id", "type" and "data" fields>,
        "context": <any valid JSON object>
     },
     ...
     {
        "principal": <any valid JSON object>,
        "actions": [<a valid JSON object with "name" and "service" fields>, ..., <a valid JSON object with "name" and "service" fields>],
        "resource": <a valid JSON object with "id", "type" and "data" fields>,
        "context": <any valid JSON object>
     }
  ]
}

This API is a batched variant of POST /v1beta/authorization/ API and allows checking multiple principals, actions and resources in one single request. Instead of passing the same resource multiple times, the client SHOULD specify all actions that need to be checked for a resource in one PARC object.

Accepts a list of PARC objects and returns 200 HTTP status with the request summary and the decisions map. Each decision can contain an optional reason field with the message describing the explicit deny reason.

The access token passed in the Authorization header MUST be a valid token received from the Identity Provider (either a user or service ID token). Customers MAY use different authentication like Basic Auth, API Keys or SAML2, and change how authentication information is passed to the Permission API and other services.

The condition field allows clients specifying how batches need to be analyzed and how the summary field needs to be calculated by the service:

  • “none” – Evaluates all requests in batches independently, same way as if the client would send separate authorization requests. The summary field MUST be omitted from the response.

  • “and” – Checks if all specified actions in batches are allowed and stops the request evaluation after the first “deny” decision. All skipped actions will have the decision field specified to “skip”.

  • “or” – Checks if any of the specified actions in batches are allowed and stops the request evaluation after the first “allow” decision. All skipped actions will have the decision field specified to “skip”.

If condition is not specified, then “none” condition is used by default and the summary field is not used.

Example:

HTTP/1.1 200 OK
Content-Type: application/json

{
   "summary": {“decision”: "deny"},
   "decisions": [
      {
         "<service>:<action>": {"decision": "allow"}, 
         ..., 
         "<service>:<action>": {"decision": "deny", "reason": "Invalid request."}
      },
      ...,
      {
         "<service>:<action>": {"decision": "allow"}, 
         ..., 
         "<service>:<action>": {"decision": "deny"}
      },
   ]
}

The underlying authorization system MAY support passing a payload in the principal field for a user different from the caller (e.g. the system administrator checking if a user has permissions to perform some operation). If this is not supported, the permission service MUST return an 403 error indicating that the caller is unauthorized to check permissions for the specified principal (see below).

The principal field in each batch MAY be omitted if its content is the same as the payload of the token specified in the Authorization header.

Examples#

Check that the specified user has access to multiple actions for a resource

POST /v1/authorization/batch HTTP/1.1
Authorization: Bearer "eyJraWQiOiJvYXV0aC1zaWduL[...]cc5IgUXhY66ML-CZVlRw"
Content-Type: application/json

{
  "batches": [
    {
      "principal": {"sub": "DdxA9xDiqdUbv", "email": "user@test.com", "exp": 1727821346329},
      "actions": [
         {"name": "read", "service": "storage"},
         {"name": "write", "service": "storage"},
         {"name": "set", "service": "tags"},
         {"name": "get", "service": "tags"}
      ],
      "resource": {
         "id": "/Projects/Scene.usd",
         "type": "File",
         "data": {
            "resourceIdentity": "/Projects/Scene.usd",
            "metadata": {
                "size": 1024,
                "timestamp": 1726640120432
            }
        }
      }
    }
  ]
}

Response:

HTTP/1.1 200 OK
Content-Type: application/json

{
  "decisions": [
    {
      "storage:read": {"decision: "allow"},
      "storage:write": {"decision: "deny"}, 
      "tags:set": {"decision: "deny", "reason": "Invalid action."}, 
      "tags:get": {"decision: "allow"} 
    }
  ]
}

Check that the current user has storage:read access to any of the specified resources

POST /v1/authorization/batch HTTP/1.1
Authorization: Bearer "eyJraWQiOiJvYXV0aC1zaWduL[...]cc5IgUXhY66ML-CZVlRw"
Content-Type: application/json

{
  "condition": "or",
  "batches": [
    {
      "actions": [{"name": "read", "service": "storage"}],
      "resource": {
        "id": "/Projects/Astronaut/Astronaut.usd",
        "type": "File",
        "data": {
          "resourceIdentity": "/Projects/Astronaut/Astronaut.usd",
          "metadata": {
            "size": 28563210,
            "timestamp": 1726640120432
           }
         }
       }
     },
     {
       "actions": [{"name": "read", "service": "storage"}],
       "resource": {
         "id": "/Projects/Marbles/Marbles_Assets.usd",
         "type": "File",
         "data": {
           "resourceIdentity": "/Projects/Marbles/Marbles_Assets.usd",
           "metadata": {
             "size": 47104,
             "timestamp": 1726640120432
           }
         }
       }
     }
   ]
}

Response:

HTTP/1.1 200 OK
Content-Type: application/json

{
   "summary": {“decision”: "allow"},
   "decisions": [
      {“storage:read": {"decision: "allow"}},
      {"storage:read": {"decision: "skip"}}
   ]
}

Check that the current user has access to all specified actions for a resource

POST /v1/authorization/batch HTTP/1.1
Authorization: Bearer "eyJraWQiOiJvYXV0aC1zaWduL[...]cc5IgUXhY66ML-CZVlRw"
Content-Type: application/json

{
  "condition": "and",
  "batches": [
    {
      "actions": [
         {"name": "read", "service": "storage"},
         {"name": "write", "service": "storage"},
         {"name": "set", "service": "tags"},
         {"name": "get", "service": "tags"}
      ],
      "resource": {
         "id": "/Projects/Scene.usd",
         "type": "File",
         "data": {
            "resourceIdentity": "/Projects/Scene.usd",
            "metadata": {
                "size": 1024,
                "timestamp": 1726640120432
            }
        }
      }
    }
  ]
}

Response:

HTTP/1.1 200 OK
Content-Type: application/json

{
  "summary": {"decision": “deny”}
  "decisions": [
    {
      "storage:read": {"decision: "allow"},
      "storage:write": {"decision: "deny"}, 
      "tags:set": {"decision: "skip"}, 
      "tags:get": {"decision: "skip"} 
    }
  ]
}

Error conditions#

The following error conditions are defined:

Missing, invalid, or expired bearer or principal token

HTTP/1.1 401 Unauthorized
Content-Type: application/json

{
   "detail": "The principal token is expired."
}

The request body is invalid (missing required fields or fields represented in a wrong format)

HTTP/1.1 422 Unprocessable Content
Content-Type: application/json

{
    "detail": "'principal' field is required."
}

The caller is unauthorized to make the permission check for the specified principal

HTTP/1.1 403 Forbidden
Content-Type: application/json

The request body is larger than the maximum value specified for the service

HTTP/1.1 413 Payload Too Large
Content-Type: application/json

{
   "detail": "Maximum allowed size is 4MB"
}

The resource quota has been exhausted - the client sent too many requests and must slow down The service MAY send the Retry-After header to indicate that requests will be allowed for this client again in the specified amount of seconds.

HTTP/1.1 429 Too Many Requests
Content-Type: application/json
Retry-After: 3600

{
    "detail": "Too many requests have been set. Try again later."
}

See next#