Authorizers

Authorizers ensure that the Subject obtained via an authenticator has the required permissions to submit the given HTTP request and thus to execute the corresponding logic in the upstream service. E.g. a specific endpoint of the upstream service might only be accessible to a "user" from the "admin" group, or to an HTTP request if a specific HTTP header is set.

Authorizer Types

The following sections describe the available authorizer types in more detail. Some of these may support or require additional configuration. The corresponding properties are annotated with mandatory, respectively optional to denote configuration requirement, as well as with overridable, not overriddable and partially overridable to indicate whether the property can be overridden in a rule pipeline.

Allow

As the name implies, this authorizer allows any request passing through. This authorizer type also doesn’t have any configuration options.

To enable the usage of this authorizer, you have to set the type property to allow.

Example 1. Configuration of Allow authorizer
id: allow_any_request
type: allow

Deny

As the name implies, this authorizer denies any request (on HTTP response code level this is then mapped to 403 Forbidden). It basically stops the successful execution of the pipeline resulting in the execution of the error handler mechanisms. This authorizer type doesn’t have any configuration options.

To enable the usage of this authorizer, you have to set the type property to deny.

Example 2. Configuration of Deny authorizer
id: deny_any_request
type: deny

Local (CEL)

This authorizer allows definition of authorization requirements based on information available about the authenticated subject, as well as the actual request by using CEL based authorization expressions. Each expression is expected to return true to signal success. Otherwise, the authorization fails, resulting in the execution of the error handler mechanisms.

To enable the usage of this authorizer, you have to set the type property to cel.

Configuration using the config property is mandatory. Following properties are available:

  • expressions: Authorization Expression array (mandatory, overridable)

    List of authorization expressions, which define the actual authorization logic. Each expression has access to the Subject and the Request objects.

Example 3. Authorization based on subject properties

In this example the subject is checked to be member of the "admin" group.

id: user_is_admin
type: cel
config:
  expressions:
    - expression: |
        has(Subject.Attributes.groups) &&
        Subject.Attributes.groups.exists(g, g == "admin")
      message: User is not admin

The first line of the expressions verifies that the property group exists. The second line checks, whether groups contains an entry named admin.

This example specifies also a message, which is logged, if the expression fails.

Example 4. Authorization based on subject and request properties

In this example the authorizer is configured to ensure anonymous access to a resource is possible for read requests only.

id: no_modification_allowed_by_anonymous
type: cel
config:
  expressions:
    - expression: |
        Request.Method in ["GET", "HEAD", "OPTIONS"] || Subject.ID != "anonymous"
      message: Anonymous non-read access is forbidden

The usage of this type of configuration makes sense in a pipeline, which combines multiple Authenticators, allowing anonymous and authenticated access.

Remote

This authorizer allows communication with other systems, like Open Policy Agent, Ory Keto, etc. for the actual authorization purpose. If the used endpoint answers with a not 2xx HTTP response code, this authorizer assumes, the authorization has failed, resulting in the execution of the error handler mechanisms. Otherwise, if no expressions for the verification of the response are defined, the authorizer assumes, the request has been authorized. If expressions are defined and do not fail, the authorization succeeds.

If your authorization system provides a payload in the response, heimdall inspects the Content-Type header to prepare the payload for further usage, e.g. for payload verification expressions, or for a Local (CEL) authorizer. If the content type does either end with json or is application/x-www-form-urlencoded, the payload is decoded, so key based access to the corresponding attributes is possible, otherwise it is made available as well, but as a simple string. In all cases this value is available for the authorization expressions as well as in the Subject’s Attributes property under a key named by the id of the authorizer (See also the example below).

To enable the usage of this authorizer, you have to set the type property to remote.

Configuration using the config property is mandatory. Following properties are available:

  • endpoint: Endpoint (mandatory, not overridable)

    The API endpoint of your authorization system. At least the url must be configured. This mechanism allows templating of the url and makes the Subject object, as well as the Values (see also below) objects available to it. By default, this authorizer will use HTTP POST to send the rendered payload to this endpoint. You can override this behavior by configuring method as well. Depending on the API requirements of your authorization system, you might need to configure further properties, like headers, etc.

  • payload: string (optional, overridable)

    Your template with definitions required to communicate to the authorization endpoint. The template can make use of Subject and Request objects.

  • expressions: Authorization Expression array (optional, overridable)

    List of CEL expressions which define the logic to be applied to the response returned by the endpoint. All expressions are expected to evaluate to true if the authorization was successful. If any of the expressions evaluates to false, the authorization fails and the message defined by the failed expression will be logged.

    Each expression has access to the Payload object.

  • forward_response_headers_to_upstream: string array (optional, overridable)

    Enables forwarding of any headers from the authorization endpoint response to the upstream service.

  • cache_ttl: Duration (optional, overridable)

    Allows caching of the authorization endpoint responses. Defaults to 0s, which means no caching. The cache key is calculated from the entire configuration of the authorizer instance and the available information about the current subject.

  • values map of strings (optional, overridable)

    A key value map, which is made accessible to the template rendering engine as Values object, to render parts of the URL or the payload.

Example 5. Configuration of Remote authorizer to communicate with Open Policy Agent (OPA)

Here the remote authorizer is configured to communicate with OPA. Since OPA expects the query to be formatted as JSON, the corresponding Content-Type header is set. Since the responses are JSON objects as well, the Accept header is also provided. In addition, this examples uses the basic_auth auth type to authenticate against the endpoint.

id: opa
type: remote
config:
  endpoint:
    url: https://opa.local/v1/data/{{ .Values.namespace }}/{{ .Values.policy }}
    headers:
      Content-Type: json
      Accept: json
    auth:
      type: basic_auth
      config:
        user: ${OPA_USER}
        password: ${OPA_PASSWORD}
  payload: |
    { "input": { "user": {{ quote .Subject.ID }} }, "some_data": {{ quote .Values.whatever }} }
  values:
    namespace: myapi/policy
    policy: allow_write
  expressions:
    - expression: |
        Payload.result == true
      message: User does not have required permissions

In this case, since an OPA response could look like { "result": true } or { "result": false }, heimdall makes the response also available under Subject.Attributes["opa"] as a map, with "opa" being the id of the authorizer in this example.

A specific rule could then use this authorizer in the following ways:

- id: rule1
  # other rule properties
  execute:
  - # other mechanisms
  - authorizer: opa # using defaults
  - # other mechanisms

- id: rule2
  # other rule properties
  execute:
  - # other mechanisms
  - authorizer: opa
    config: # overriding with rule specifics
      values:
        policy: allow_read
        whatever: foo
  - # other mechanisms

Last updated on Jun 29, 2023