Skip to main content

Identity Context

When an Authorizer evaluates a policy, it receives an Identity Context from the calling application. The Identity Context instructs the Authorizer whether and how to populate the input.user object when evaluating the policy. The process of identifying the user referred to by the Identity Context and loading it into the input.user object is known as "identity resolution".

An identity context contains two fields: type and identity.

The type of an Identity Context gives callers control over the identity resolution process:

  • IDENTITY_TYPE_NONE: the policy is evaluated without a user context (input.user is empty). This is most commonly used to authorize anonymous requests.
  • IDENTITY_TYPE_SUB: the identity field is a user identity such as email, username, or OAuth2 subject name.
  • IDENTITY_TYPE_JWT: the identity field is a JWT access token. The authorizer extracts the sub (subject) claim from the token and uses it as the user identity.
  • IDENTITY_TYPE_MANUAL: disables identity resolution. The identity context is available in the poilcy as input.identity but input.user is empty.

When using IDENTITY_TYPE_SUB or IDENTITY_TYPE_JWT, a user with the given identity must exist in the authorizer's directory. If no such user exists, the authorizer returns an error.

In a user-facing API (e.g. a back-end REST API that requires a JWT in the Authorization header), the token is typically decoded and validated during the authentication phase. The service can then extract the sub claim from the JWT and pass it to the authorizer with IDENTITY_TYPE_SUB. Alternately, the entire JWT can be forwarded to the authorizer with IDENTITY_TYPE_JWT but the authorizer would then decode and validate the token too.

Setting the Identity Context

The is, query, and decisiontree API calls all take an identityContext map:

POST .../api/v2/authz/is

{
"identityContext": {
"identity": "[topaz-user-guid]",
"type": "IDENTITY_TYPE_SUB"
}, ...
}

To access the properties of the user in a policy, you can use input.user:

package sample.GET.api.orders
default allowed = false

# only allow salespeople
allowed {
input.user.properties.department == "Sales"
}

Using other JWT claims in a policy

Note that the identityContext is available as input.identity. If the policy wants to extract additional claims out of a JWT and use them in the policy, it can readily do so.

Assuming the following identityContext:

POST .../api/v2/authz/is

{
"identityContext": {
"identity": "[JWT that could contain a 'manager' claim]",
"type": "IDENTITY_TYPE_JWT"
}, ...
}

The following policy will extract the JWT using the io.jwt.decode() Rego built-in, make it available as token.payload, and use claims in the payload within the policy:

package sample.GET.api.orders
default allowed = false

# Helper to get the token payload
token = {"payload": payload} {
[header, payload, signature] := io.jwt.decode(input.identity.identity)
}

# only allow sales managers
allowed {
input.user.properties.department == "Sales"
token.payload.manager
}