Concepts

Everything you need to know.

Pipeline

As described in the Welcome section and also shown in the diagram below, heimdall authenticates and authorizes incoming HTTP requests, rejecting unauthenticated or unauthorized ones, as well as enriches the valid requests with further contextual information and transforms resulting subject information into a format, required by the upstream services. This is done in upstream service specific rules, which assemble the required individual pipelines by making use of different mechanisms.

Diagram
Figure 1. Request Pipeline

Each rule defines which mechanisms are required for its pipeline and executed in which order.

In general each rule contains

  • an identifier - to uniquely identify a rule

  • an url pattern - to match the incoming request against

  • a list of allowed HTTP methods for the matched requests

  • a regular pipeline, consisting of a list with

    • authentication mechanisms, so-called Authenticators, to be executed (if multiple are defined, they are executed as fallbacks) - step 1 in the figure above.

      Here, heimdall typically communicates with the actual authentication systems to get information about the authenticated subject, or to get key material to verify the authentication information provided in the request, or perform other activities related to authentication.

    • contextualization mechanisms, so-called Contextualizers, to be executed (if multiple are defined, they are executed in the order of their definition; can be mixed with authorization mechanisms) - step 2 in the figure above.

      Here, heimdall communicates with other systems as well, either to get further information about the subject, like specific attributes required by the upstream service and not available in the authentication information or the request itself. An example would be information about the request IP, like provided by AbuseIPDB, etc.

    • authorization mechanisms, so-called Authorizers, to be executed (if multiple are defined, they are executed in the order of their definition; can be mixed with contextualization mechanisms) - step 3 in the figure above.

      Here, heimdall performs authorization checks, either locally, or by communicating with yet again further systems, like Open Policy Agent, Ory Keto and alike.

    • unification mechanisms, so-called Unifiers, to be executed (if multiple are defined, they are executed in the order of their definition) - step 4 in the figure above.

      This step unifies the information collected so far about the subject and the request by transforming it into an object expected by the upstream service. That reaches from a simple custom header, carrying e.g. the id of the subject, to a JWT carried in the Authorization header.

  • an error pipeline, consisting of error handler mechanisms (if multiple are defined, they are executed as fallbacks), which are executed if any of the regular pipeline mechanisms fail. These mechanisms range from a simple error response to the client (which sent the request), to sophisticated ones supporting complex logic and redirects.

The diagram below sketches the related execution logic

Diagram
  1. Url matches rule? - This is the first step executed by heimdall. The information about the scheme, host, path and query is taken either from the URL itself, or if present and allowed, from the X-Forwarded-Proto, X-Forwarded-Host, X-Forwarded-Path, or X-Forwarded-Uri headers of the incoming request. The request is denied if there is no matching rule. Otherwise, the rule specific pipeline is executed. When heimdall is evaluating the rules against the request url it takes the first matching one. That allows simpler matching expressions and supports ordering of rules in rule set with most specific matchig expressions first.

  2. Method allowed? - As soon as a rule matching the request is found, a verification is done whether the used HTTP method is allowed or not. The information about the HTTP method is either taken from the request itself or, if present and allowed, from the X-Forwarded-Method header.

  3. Execute regular pipeline - when the above steps succeed, the regular pipeline mechanisms defined in the matched rule are executed.

  4. Forward request, respectively respond to the API gateway - when the above steps succeed, heimdall, depending on the operating mode, responds with, respectively forwards whatever was defined in the pipeline (usually this is a set of HTTP headers). Otherwise

  5. Execute error pipeline is executed if any of the mechanisms, defined in the regular pipeline fail. This again results in a response, this time however, based on the definition in the used error handler.

Operating Modes

To support different deployment scenarios, heimdall supports two operating modes:

Proxy Mode

Diagram
Figure 2. Proxy Deployment

In this mode heimdall forwards requests to the upstream service if these satisfy the conditions defined in matched rules. Otherwise, heimdall returns an error to the client. If the execution of the rule was successful, it also forwards additional headers, specified in the rule to the upstream service.

Starting heimdall in this mode happens via the serve proxy command. Head over to the description of CLI as well as Configuration options for more details.

Example 1. Reverse Proxy Example

Imagine following request hits heimdall

GET /my-service/api HTTP/1.1
Host: heimdall:4455

Some payload

And there is a rule, which allows anonymous requests and sets a header with subject id set to anonymous like this

id: rule:my-service:anonymous-api-access
match:
  url: <**>/my-service/api
forward_to:
  host: my-backend-service:8888
methods:
  - GET
execute:
  - authenticator: anonymous-authn
  - unifier: id-header

Then the request will be forwarded as follows:

GET /my-service/api HTTP/1.1
Host: my-backend-service:8888
X-User-ID: anonymous

Some payload

Decision Mode

Diagram
Figure 3. Decision Deployment

In this mode heimdall can be integrated with most probably all modern API gateways and reverse proxies as a so-called "authentication middleware". Here the reverse proxy, respectively API gateway integrating with heimdall, will forward requests to heimdall by making use of its decision service endpoint for authentication and authorization purposes. As in the Reverse Proxy mode, heimdall will check if these requests match and satisfy the conditions defined in the available rules. If not, heimdall returns an error to its client (here API gateway/reverse proxy). If the rule execution was successful, it also responds to the API gateway/reverse proxy with 200 OK (can be overridden if required) and sets headers/cookies, specified in the matched rule, which are then forwarded to the upstream service.

Starting heimdall in this mode happens via the serve decision command. Head over to the description of CLI as well as to Configuration options for more details.

Example 2. Decision Service Example

Imagine following request hits heimdall (sent to it by an API gateway)

GET /my-service/api HTTP/1.1
Host: heimdall:4455
X-Forwarded-Host: my-backend-service

Some payload

And there is a rule, which allows anonymous requests and sets a header with subject id set to anonymous like this

id: rule:my-service:anonymous-api-access
match:
  url: http://my-backend-service/my-service/api
methods:
  - GET
execute:
  - authenticator: anonymous-authn
  - unifier: id-header

Then heimdall will respond with:

HTTP/1.1 200 OK
X-User-ID: anonymous

Last updated on Aug 7, 2023