> For the complete documentation index, see [llms.txt](https://docs.openiam.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.openiam.com/administration-guide/gateway/access-gateway-reference.md).

# Access Gateway reference

Everything the Access Gateway exposes, in one place — metadata types and value sources, the calls it makes to OpenIAM, the headers it sends the UI, status codes, postback validation, session renewal,

## What this is, and when you need it

The values, names and enumerations the Access Gateway works with, for scanning rather than reading. The procedures that use them are [Protect an application behind the Access Gateway](/administration-guide/gateway/protect-an-application.md), [Give the application the authenticated identity](/administration-guide/gateway/inject-identity.md) and [Advanced request and response transformations](/administration-guide/gateway/request-and-response-transformations.md).

Field-by-field descriptions of the content provider and URI pattern screens are in [Content provider and URI pattern reference](/administration-guide/access/content-providers-and-uri-patterns/content-provider-reference.md) and are not repeated here.

The [directive catalogue](#apache-directive-catalogue) and the [container variables](#container-variables-you-will-need-to-name) at the end of this page are **read-only reference**. Changing any of them needs shell access to the proxy host or an edit to a container manifest, so the procedure belongs to the [Installation Guide](/installation/installation.md) and to whoever owns the deployment. They are listed so that you can read what the gateway is doing and name precisely what you need changed.

## URI pattern metadata types

Six types exist. Four inject, two suppress. The **Metadata Type** drop-down on a URI pattern is this list; there is no seventh.

| Label in the Webconsole      | Stored type id               | What it does                                   | Required field   | Since   |
| ---------------------------- | ---------------------------- | ---------------------------------------------- | ---------------- | ------- |
| **Set Header**               | `headerURIPatternRule`       | Adds request headers to the upstream request   | —                | 3.0.0.1 |
| **Set URI String Parameter** | `requestParamURIPatternRule` | Adds query-string parameters                   | —                | 3.0.0.1 |
| **Set Cookie**               | `cookieURIPatternRule`       | Sets cookies                                   | **Cookie Path**  | 3.0.0.1 |
| **Form Post Processor**      | `formPostURIPatternRule`     | Submits a form to the upstream                 | **Content Type** | 3.0.0.1 |
| **Exclude Headers**          | `excludeHeaderRule`          | Strips named inbound headers before forwarding | —                | 4.0.0.0 |
| **Exclude Cookies**          | `excludeCookieRule`          | Strips named inbound cookies before forwarding | —                | 4.0.0.0 |

The stored ids are what a break-glass query against `URI_PATTERN_META_TYPE` returns; the labels are what the **Metadata Type** drop-down shows.

The two **required** notes are enforced when you save, not when the request runs: a blank **Cookie Path** or **Content Type** is refused on the screen.

## Metadata value sources

Each metadata entry holds one or more values. A value has a name — the header, parameter, cookie or form field name — and one source. OpenIAM resolves the sources in a fixed order and the first non-null one wins, so a static value you left behind is shadowed rather than merged by a Groovy script added later.

| Order | Webconsole label            | Column on the stored value | What it supplies                                                    |
| ----- | --------------------------- | -------------------------- | ------------------------------------------------------------------- |
| 1     | **Empty Value**             | `IS_EMPTY_VALUE`           | Short-circuits and sends `""`                                       |
| 2     | **Groovy Script**           | `GROOVY_SCRIPT`            | Whatever the script returns; `null` means send nothing at all       |
| 3     | **Static Value**            | `STATIC_VALUE`             | The literal text you typed                                          |
| 4     | **Value from User Profile** | `AM_RES_ATTRIBUTE_ID`      | One of the six attributes below                                     |
| 5     | *Fetched value*             | `FETCHED_VALUE`            | An internally supplied value; not offered as a choice on the screen |

Two checkboxes sit at the bottom of every value:

**Propagate Through Proxy.** Ticked, the value is also added to the HTTP **response**, so the browser can see it. Unticked, it is added only to the request the proxy sends upstream. For an identity header that is the setting you want — an application-facing claim has no business being echoed to the client.

**Propagate on Error.** Unticked, the value is attached to successful responses only. Ticked, it is attached whatever the upstream status — a `404`, a `500`, anything.

**Set both explicitly rather than trusting a default.** The stored columns behind them default to `Y`, the current value dialog opens with both boxes clear, and older OpenIAM documentation describes the opposite. Tick or clear each one deliberately, save, reopen the value and read them back.

### Value from User Profile: the six attributes

The picker is not free text. It offers the rows of `AUTH_RESOURCE_AM_ATTRIBUTE`, and these six are the exhaustive list OpenIAM can resolve; anything else is refused with `reflection key: %s not supported`, so adding a row to that table by hand gains you nothing. For a seventh value, use a **Groovy Script**.

| Display name in the picker | Stored key        | Where the value comes from                                                   |
| -------------------------- | ----------------- | ---------------------------------------------------------------------------- |
| **Principal**              | `Login.login`     | The user's primary principal on the authentication provider's managed system |
| **Password**               | `Login.password`  | The decrypted password for that principal                                    |
| **User First Name**        | `User.firstName`  | The user's **First Name**                                                    |
| **User Last Name**         | `User.lastName`   | The user's **Last Name**                                                     |
| **Initials**               | `User.middleInit` | The user's **Middle Initial**                                                |
| **Functional Title**       | `User.title`      | The user's **Title**                                                         |

An email address is deliberately not among them — it was removed from the set as of 3.0.0.1 and a Groovy script is the supported way to inject one.

## What Add Default Patterns seeds

**Add Default Patterns** on the content provider applies a shipped set of **220** URI patterns. Read the full list under **URI Patterns** after running it; the groups that matter are:

| Group                                                                                                                                                                                                              | Treatment                                                                                                                                                                                                                                                                                               |
| ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `/selfservice/*`                                                                                                                                                                                                   | Public and cacheable                                                                                                                                                                                                                                                                                    |
| `/webconsole/*`, `/idp/*`                                                                                                                                                                                          | Restricted to role `9`                                                                                                                                                                                                                                                                                  |
| Every OAuth, SAML, one-time-password and password-reset endpoint the IdP needs                                                                                                                                     | Rules appropriate to each                                                                                                                                                                                                                                                                               |
| `/idp/401`, `/idp/404`, `/webconsole/401`, `/webconsole/404`, `/selfservice/selfRegistration`, `/idp/oauth2/.well-known/openid-configuration` (cached 1800 s)                                                      | **Def. None Auth Rule** (`DEF_NONE_AUTH_RULE`) — anonymous                                                                                                                                                                                                                                              |
| `/idp/actuator/health`, `/selfservice/actuator/health`, `/webconsole/actuator/health`                                                                                                                              | **Def. None Auth Rule** — anonymous, and the correct targets for load-balancer and orchestrator health probes                                                                                                                                                                                           |
| `/idp/oauth2/.well-known/oauth-authorization-server` (cached 1800 s), `/.well-known/oauth-protected-resource`, `/.well-known/oauth-protected-resource/mcp` (cached 1800 s), `/mcp` (cached 30 s) — since 2026.10.2 | **Def. None Auth Rule** — anonymous. The OAuth 2.0 discovery documents an MCP client reads before it has a token, and the MCP endpoint itself, which answers its own bearer-token challenge. `/mcp` and the two `/.well-known/oauth-protected-resource` paths are proxied to the MCP server (see below) |
| `/rabbitmq`, `/rabbitmq/*`, `/grafana`, `/grafana/*`                                                                                                                                                               | How the RabbitMQ management console and Grafana are published *through* the gateway, behind OpenIAM authorization                                                                                                                                                                                       |

Beneath the IdP's own service prefix, exactly **three** anonymous patterns are seeded, and no others. These are pattern values you read on the content provider's pattern list at `/webconsole/contentProviders`, not calls for you to make:

| Seeded anonymous URI pattern   | Covers                                                        |
| ------------------------------ | ------------------------------------------------------------- |
| `/idp/rest/api/auth/public/*`  | The paths a browser reaches during an unauthenticated sign-in |
| `/idp/rest/api/auth/questions` | The security-questions step                                   |
| `/idp/rest/api/auth/captcha`   | The CAPTCHA step                                              |

Everything else under that prefix falls through to the seeded `/idp/*` pattern and its role `9` restriction. That is why an unauthenticated flow needing a path under it that has no pattern of its own fails with an authorization error rather than a missing-page error — and why, when a factor's own page cannot complete, adding a narrowly scoped anonymous pattern on that screen is the fix rather than widening `/idp/*`.

OpenIAM recognises the RabbitMQ and Grafana prefixes by the properties `org.openiam.content.provider.rabbitmq.pattern`, which ships `/rabbitmq`, and `org.openiam.content.provider.grafana.pattern`, which ships `/grafana`, and attaches the upstream URL from `rabbitmq.full.url` and `grafana.full.url`. **Neither URL is visible on a Webconsole screen**, and `grafana.full.url` has no shipped default at all, so Grafana is not published until somebody sets it. If `/rabbitmq` authorizes and then fails to load, that value is what to ask the deployment owner for.

The MCP (Model Context Protocol) server, since 2026.10.2, is published without an upstream of its own. Its four patterns use the content provider's servers, like `/webconsole` and `/selfservice`, and the OpenIAM nginx in front of the UI applications forwards `/mcp` and the two `/.well-known/oauth-protected-resource` paths to the MCP server, which serves its own protected-resource metadata (RFC 9728). `/idp/oauth2/.well-known/oauth-authorization-server` is served by the IdP. Deploying the server, the nginx routes and connecting clients are in [Connect AI assistants through the MCP server](/administration-guide/federation/mcp-server.md).

{% hint style="warning" %}
The seed is applied only when a content provider is first set up, or when an administrator presses **Create default URI patterns** on it. A deployment upgraded to 2026.10.2 does not get the four new patterns until somebody presses that button — or adds the patterns by hand, with **Def. None Auth Rule** and the cache values above. Pressing the button also re-applies the shipped flags to every other default pattern, so read the pattern list afterwards if any of them was customised.
{% endhint %}

## What the gateway asks OpenIAM, on every request

The gateway decides nothing itself. It asks the ESB, at least once per protected request, which is why the ESB's health is the gateway's health and why an ESB that is merely slow presents as a slow application.

| When                                       | What it asks                                                                    |
| ------------------------------------------ | ------------------------------------------------------------------------------- |
| Essentially every request                  | May this user have this URI by this method?                                     |
| After authorization succeeds               | What should I inject for this user on this URI?                                 |
| Kerberos and other principal-only sign-ins | Given this principal on this content provider's managed system, issue a session |
| Certificate authentication                 | Which identity does this client certificate belong to?                          |

None of these is yours to make. What you own is what they resolve against — the content provider, the URI pattern, its authentication levels and its metadata — and the one log line that reports the answer, in [Diagnosing a request that fails through the gateway](/administration-guide/gateway/troubleshoot-the-gateway.md#diagnosing-a-request-that-fails-through-the-gateway).

## The headers the gateway sends the UI

The gateway tells the UI what it decided, in request headers the UI reads case-insensitively. Read them off a HAR capture or a request dump; they are the gateway's own answer, before any log.

| Header                     | Carries                                                                                                                 |
| -------------------------- | ----------------------------------------------------------------------------------------------------------------------- |
| `x-openiam-cp-id`          | The content provider that matched the host                                                                              |
| `x-openiam-uri-pattern-id` | The URI pattern that matched the path                                                                                   |
| `x-openiam-uri-method-id`  | The per-method row of that pattern, when one applies                                                                    |
| `x-openiam-auth-level-ids` | The authentication levels already satisfied, each optionally `id:lifetime`                                              |
| `x-openiam-proxy-host`     | The hostname the user actually typed                                                                                    |
| `x-openiam-proxy-scheme`   | `http` or `https` as the user saw it, falling back to `X-Forwarded-Proto`                                               |
| `x-openiam-client-cert`    | The client certificate, where it arrives in a header rather than the TLS handshake                                      |
| `x-openiam-login-uri`      | On responses: the sign-in path, `/idp/login`. Its presence is the cheapest proof that the gateway is in the path at all |

`x-openiam-proxy-host` is not `Host`, and it is not `X-Forwarded-Host`. OpenIAM prefers it over the request's own `Host` header, so every absolute URL the UI generates — redirects, SAML endpoints, links in email — uses the public hostname rather than an internal container name. The port comes from `X-Forwarded-Port`. A third use is a yes/no: OpenIAM decides "did this request arrive through the gateway" from the presence of the same header.

{% hint style="warning" %}
**Do not compensate for a lost `x-openiam-proxy-host` by rewriting `Host`.** The mechanism that carries the public hostname to the UI is that header, not `Host`; setting `Host` fixes one URL and leaves the rest wrong. Anything between the gateway and the UI — a load balancer, a service mesh, a hand-written reverse proxy — must pass both `x-openiam-proxy-*` headers through untouched.
{% endhint %}

## Status codes and authorization decisions

OpenIAM returns an authorization decision and the tier in front of it turns that into a status code, so the status code you see is one step removed from the reason.

| You see | Decision       | What it means                                                                                                                                                                                                      |
| ------- | -------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `401`   | `UNAUTHORIZED` | The user is not entitled to the pattern, to the content provider, or to the matched HTTP method; or an authentication level declined the request; or the request carries no user at all and the level requires one |
| `404`   | `NOT_FOUND`    | **No URI pattern matched this URL** — authorization never got as far as asking the application                                                                                                                     |
| `500`   | `INVALID_URI`  | The proxied URL is not a legal URI, or something unexpected happened                                                                                                                                               |

Certificate authentication has its own response codes, checked in this order. The **first** one you see is the earliest thing wrong, and each is a different configuration mistake.

| Rejection, in the order it is checked                                               | Response code and message                                                     |
| ----------------------------------------------------------------------------------- | ----------------------------------------------------------------------------- |
| Metadata lookup for the proxied URI failed — no content provider or pattern matched | `METADATA_INVALID`                                                            |
| The content provider names an authentication provider that is not in cache          | `CERT_CONFIG_INVALID` — `Can not find Auth provider for id : <id>`            |
| That provider does not have certificate authentication enabled                      | `CERT_CONFIG_INVALID` — `Auth provider not support Certificate authorization` |
| The provider defines neither a DN regex nor a certificate Groovy script             | `CERT_CONFIG_INVALID` — `Not define regex and regexScript`                    |
| The CA certificate stored on the provider will not parse                            | `CERT_CA_INVALID` — `Can not parse CA Cert`                                   |
| The **client** certificate will not parse                                           | `CANNOT_GET_CERTIFICATE_CONTENT`, carrying the underlying parse message       |

## Postback URL validation

The postback URL is the path the IdP returns the browser to once authentication has finished. OpenIAM validates it strictly and refuses the request outright rather than sanitising it, returning `401` and logging `not valid - doesn't start with a '/' - XSS detected. Returning 401`. The same check guards six other IdP entry points, so the line can appear on a request that is not the initial sign-in.

The rules the validator applies:

* Blank is allowed; `//` or `///` at the start is not.
* The path — everything before the first `?` — must start with `/` and must not contain `//`.
* The path must not contain `=`.
* Each parameter name must match `^[a-zA-Z0-9_-]+$`.
* No parameter value may contain a space (the sole exception is `response_type` on an OAuth path) or a tab, or any non-ASCII character, and each must contain at least one alphanumeric character or `/`.
* No value may begin `javascript:`, contain `%2f%2f` other than as part of `%3a%2f%2f`, end with `//`, or contain `http:/` / `https:/` with a single slash.

The parameter's *name* is per content provider — `CONTENT_PROVIDER.POSTBACK_URL_PARAM_NAME`, which the gateway is told along with the rest of the pattern's metadata — and defaults to `postbackUrl` through `org.openiam.postback.url.param.name.default`. When nothing supplies a postback URL at all, the IdP falls back silently to `/selfservice/`.

## Session lifetime and renewing the session cookie

Through the gateway, the **proxy owns the session cookie** and the UI deliberately keeps its hands off it. On a proxied request the UI returns the cookie exactly as it arrived and logs `Is proxy request - using cookie from proxy` — that log line is the cheapest way to confirm a request is being treated as proxied. On a request that reaches the UI tier directly, the UI renews the cookie on **every** request. So an idle timeout is a sliding window in both cases: it expires only when nothing is being requested.

That is why a client which holds a session but stops making requests — a mobile application sitting on a biometric prompt is the usual example — has to renew explicitly. The IdP offers two ways to do that, and both belong to the application team rather than to you; the **Developer Guide** covers them.

Three of their consequences are yours, because they arrive as support calls. A successful renewal **invalidates the old session in the same step**, so a client that keeps using its previous token after renewing is refused — that presents as intermittent sign-outs immediately after a renewal, not as a renewal failure. An already-expired token does not renew: it signs the session out. And a failure on that path logs `Can't renew token via restful call` in the IdP log, which is the line to search for when a mobile population reports being signed out while idle.

{% hint style="warning" %}
**No shipped URI pattern covers renewal.** It falls through to the seeded `/idp/*` pattern, which is restricted to role `9`, so a client cannot renew until you add a URI pattern for the exact path the application team gives you and entitle the population that needs it. Treat that pattern as sensitive: it converts possession of a live token into a fresh one.
{% endhint %}

{% hint style="info" %}
**Unverified field guidance on the response shape.** As shipped, the renewal endpoint returns the new token in the **JSON body** and adds no `Set-Cookie` header of its own; the cookie is written on the normal authentication paths. Field reports describe a deployment where the same call answered with a `404` status while the renewed value arrived in a `Set-Cookie` header — which is consistent with a gateway in front rewriting both, but has not been verified on a running system and is not the shipped behaviour. Do not build a client against the status code. Read the new token from whichever of the two places your own deployment actually returns it in, verify it with a subsequent authenticated request, and treat the absence of a new token as "session gone, re-authenticate".
{% endhint %}

{% hint style="warning" %}
Renewal is a stopgap, not an architecture. A native or mobile client that needs to keep a session alive across long idle periods wants OAuth 2 / OIDC with a refresh token, where token lifetime, rotation and revocation are part of the protocol rather than a side effect of a cookie — see [OAuth 2.0 and OpenID Connect](/administration-guide/federation/oauth-and-oidc.md). Reach for cookie renewal to keep an existing integration working while that migration is planned, and record it as debt.
{% endhint %}

## Properties that govern the gateway

**None of these is on a Webconsole screen.** Not one of them has a row on **Administration → System Configuration**, so the values below are what ships, and you cannot read what your deployment is actually running from the console — they are supplied to the gateway and UI artifacts by the deployment. Changing any of them is the deployment owner's job and belongs to the [Installation Guide](/installation/installation.md); ask them for the effective value before concluding a cache interval or a pattern is wrong. What you can observe is the behaviour each one governs, which is what the third column names.

| Property                                        | Ships                             | What it governs                                                                  |
| ----------------------------------------------- | --------------------------------- | -------------------------------------------------------------------------------- |
| `org.openiam.am.uri.federation.threadsweep`     | `30000` ms                        | How long a URI pattern change takes to take effect                               |
| `org.openiam.content.provider.threadsweep`      | `300000` ms                       | The five minutes the save message warns about                                    |
| `org.openiam.auth.provider.sweep.time`          | `60000` ms                        | How often the cached authentication providers are refreshed                      |
| `org.openiam.postback.url.param.name.default`   | `postbackUrl`                     | The default name of the postback URL parameter                                   |
| `org.openiam.auth.level.kerberos.id`            | `KERB_AUTH`                       | The authentication level whose presence tells OpenIAM to skip the password check |
| `org.openiam.ui.password.change.url`            | resolves to `/idp/changePassword` | The **Change password** target; keep it relative                                 |
| `org.openiam.content.provider.rabbitmq.pattern` | `/rabbitmq`                       | The prefix under which the broker console is published                           |
| `org.openiam.content.provider.grafana.pattern`  | `/grafana`                        | The prefix under which Grafana is published                                      |
| `org.openiam.content.provider.mcp.pattern`      | `/mcp`                            | The prefix under which the MCP server is published (since 2026.10.2)             |
| `rabbitmq.full.url`                             | —                                 | The upstream for `/rabbitmq`                                                     |
| `grafana.full.url`                              | no shipped default                | The upstream for `/grafana`                                                      |

## Apache directive catalogue

Every directive name, type and default below is taken from the module's own directive reference. **global** = outside `<VirtualHost>`, **vhost** = inside `<VirtualHost>`, **location** = inside `<Location>`. A dash in **Default** means the module documents no default and the directive is simply absent from the shipped configuration.

{% hint style="info" %}
This catalogue is for naming, not for editing. Setting any of these is proxy-host configuration — see the [Installation Guide](/installation/installation.md). The **Context** column is the one thing here that is not authoritative: the module publishes types and defaults but not a per-directive context declaration, so the contexts are read off placement in the shipped example configurations. A directive placed at vhost level where the module wants global scope fails configuration validation, so have the config validated rather than trusting the column.
{% endhint %}

### Core and ESB connectivity

| Directive                  | Type             | Context | Default | Example                             |
| -------------------------- | ---------------- | ------- | ------- | ----------------------------------- |
| `OPENIAM_ESBPath`          | URL              | global  | —       | `http://esb:9080`                   |
| `OPENIAM_ConfigureBackend` | URL              | vhost   | —       | `http://ui:8080`                    |
| `OPENIAM_ConfigureHost`    | Path             | vhost   | —       | `/webconsole/setup`                 |
| `OPENIAM_ConfigureUrls`    | Path, repeatable | vhost   | —       | `/webconsole/setup/contentprovider` |

### Authentication and session

| Directive                   | Type            | Context  | Default              | Example                |
| --------------------------- | --------------- | -------- | -------------------- | ---------------------- |
| `OPENIAM_AuthCookieName`    | String          | location | `OPENIAM_AUTH_TOKEN` | `OPENIAM_AUTH_TOKEN`   |
| `OPENIAM_AuthProvider`      | String          | location | —                    | `OPENIAM_DEFAULT_AUTH` |
| `OPENIAM_AuthAuthoritative` | on/off          | location | —                    | `on`                   |
| `OPENIAM_SetCookiesSecure`  | on/off          | vhost    | —                    | `on`                   |
| `OPENIAM_ReadCookiesFrom`   | String          | location | `Cookie`             | `X-Original-Cookie`    |
| `OPENIAM_LogoutRedirect`    | URL, repeatable | vhost    | —                    | `/legacy/signout`      |

`OPENIAM_AUTH_TOKEN` is the default at both ends independently: it is the name the UI falls back to, and it is the value the content provider's **Authentication Cookie Name** has held and been required to hold since 4.0.0.0. The UI resolves the name as *the content provider's override, else that default*, appending the current user id when a user id cookie is present. So if the proxy sets `OPENIAM_AuthCookieName`, the content provider's **Authentication Cookie Name** must match, or the two ends look for different cookies and you get a login loop. You can read the content provider's value at `/webconsole/editContentProvider?providerId=<id>`; the proxy side is only visible on the gateway host.

### URL routing and redirects

| Directive                          | Type               | Context         | Default | Example               |
| ---------------------------------- | ------------------ | --------------- | ------- | --------------------- |
| `OPENIAM_DefaultUrl`               | URL                | location, vhost | —       | `/selfservice/`       |
| `OPENIAM_DefaultPostbackUrl`       | URL                | location        | —       | `/legacy/home`        |
| `OPENIAM_DefaultTimeout`           | Integer (s)        | vhost           | —       | `60`                  |
| `OPENIAM_DefaultUrlForLang`        | URL                | vhost           | —       | `/selfservice/`       |
| `OPENIAM_NoAuth`                   | Path, repeatable   | vhost           | —       | `/legacy/public`      |
| `OPENIAM_NoAuthOnPath`             | Path               | location        | —       | `/legacy/ping`        |
| `OPENIAM_Redirect`                 | URL                | location        | —       | `/legacy/home`        |
| `OPENIAM_RedirectWithAuth`         | URL                | location        | —       | `/legacy/dashboard`   |
| `OPENIAM_RedirectWithoutAuth`      | URL                | location        | —       | `/idp/login`          |
| `OPENIAM_RedirectBackUrl`          | URL                | location        | —       | `/legacy/report`      |
| `OPENIAM_RedirectBackForLang`      | String             | vhost           | —       | `en`                  |
| `OPENIAM_FixRedirectForLang`       | on/off             | vhost           | —       | `off`                 |
| `OPENIAM_FixLocationList`          | String, repeatable | location        | —       | `Location`            |
| `OPENIAM_ProxyPassReverse`         | URL                | location        | —       | `http://legacy:8443/` |
| `OPENIAM_OutHeadersRedirectName`   | String             | location        | —       | `X-App-State`         |
| `OPENIAM_OutHeadersRedirectValues` | Two args           | location        | —       | `expired /idp/login`  |

### Security headers

| Directive                     | Type               | Context  | Default | Example                                       |
| ----------------------------- | ------------------ | -------- | ------- | --------------------------------------------- |
| `OPENIAM_CSPEnabled`          | on/off             | location | —       | `on`                                          |
| `OPENIAM_CSPOverride`         | String             | location | —       | `"default-src 'self' data:;"`                 |
| `OPENIAM_CSPOverrideWithCors` | String             | location | —       | `"default-src 'self'; form-action 'self' *;"` |
| `OPENIAM_CSPReportEnalbed`    | on/off             | location | —       | `on`                                          |
| `OPENIAM_CSPReportOnly`       | on/off             | location | —       | `on`                                          |
| `OPENIAM_CORSAllowAll`        | on/off             | location | —       | `off`                                         |
| `OPENIAM_AddHSTSHeaders`      | on/off             | vhost    | —       | `on`                                          |
| `OPENIAM_DefaultRespHeader`   | String, repeatable | vhost    | —       | `Referrer-Policy strict-origin`               |
| `OPENIAM_RandomIV`            | on/off             | vhost    | `off`   | `on`                                          |

`OPENIAM_CSPReportEnalbed` is spelled with the typo in the module. Use it exactly as written.

### Kerberos

| Directive                    | Type   | Context  | Default | Example        |
| ---------------------------- | ------ | -------- | ------- | -------------- |
| `OPENIAM_Kerberos`           | on/off | location | —       | `on`           |
| `OPENIAM_KrbPrincipalOnly`   | on/off | location | —       | `on`           |
| `OPENIAM_KrbPrincipalPrefix` | String | location | —       | `CORP\`        |
| `OPENIAM_KrbPrincipalSuffix` | String | location | —       | `@example.com` |

### Client certificate authentication

| Directive                               | Type   | Context  | Default                 | Example                 |
| --------------------------------------- | ------ | -------- | ----------------------- | ----------------------- |
| `OPENIAM_CertPromptUrl`                 | URL    | vhost    | —                       | `/idp/auth-cert`        |
| `OPENIAM_ClientCertHeaderName`          | String | location | `x-openiam-client-cert` | `x-openiam-client-cert` |
| `OPENIAM_ReadClientCertFromHeader`      | on/off | location | —                       | `on`                    |
| `OPENIAM_NoAuthHeaderForCertAuth`       | String | location | —                       | `on`                    |
| `OPENIAM_NoAuthHeaderForCertFromHeader` | String | location | —                       | `on`                    |
| `OPENIAM_NoCookieForCertAuth`           | on/off | location | —                       | `on`                    |
| `OPENIAM_NoCookieForCertFromHeader`     | on/off | location | —                       | `on`                    |

### Forwarded headers, SOAP and header-based auth

| Directive                      | Type   | Context  | Default           | Example                                 |
| ------------------------------ | ------ | -------- | ----------------- | --------------------------------------- |
| `OPENIAM_Client_Ip_Header`     | String | vhost    | —                 | `X-Real-IP`                             |
| `OPENIAM_Forwarded_For_Header` | String | vhost    | `X-Forwarded-For` | `X-Forwarded-For`                       |
| `OPENIAM_Forwarded_By_Header`  | String | vhost    | `X-Forwarded-By`  | `X-Forwarded-By`                        |
| `OPENIAM_SoapHeader`           | String | location | —                 | `//*[local-name()='authentication'][1]` |
| `OPENIAM_SoapAuthHeaders`      | on/off | location | —                 | `on`                                    |
| `OPENIAM_AuthHeaderUsername`   | String | location | —                 | `X-Remote-User`                         |
| `OPENIAM_AutnHeaderPassword`   | String | location | —                 | `X-Remote-Password`                     |
| `OPENIAM_UserParam`            | String | location | —                 | `username`                              |
| `OPENIAM_PasswordParam`        | String | location | —                 | `password`                              |

`OPENIAM_AutnHeaderPassword` is also misspelled in the module (`Autn`, not `Auth`).

### Transport, worker pool and debug

| Directive                        | Type        | Context | Default | Example         |
| -------------------------------- | ----------- | ------- | ------- | --------------- |
| `OPENIAM_UseCurl`                | on/off      | vhost   | `off`   | `on`            |
| `OPENIAM_CurlPoolEnable`         | on/off      | global  | —       | `On`            |
| `OPENIAM_CurlPoolSize`           | Integer     | global  | `32`    | `32`            |
| `OPENIAM_CurlConnectTimeout`     | Integer (s) | global  | `2`     | `2`             |
| `OPENIAM_CurlTimeout`            | Integer (s) | global  | `10`    | `10`            |
| `OPENIAM_WorkerPooEnabled`       | On/Off      | global  | —       | `On`            |
| `OPENIAM_WorkerPoolMin`          | Integer     | global  | —       | `25`            |
| `OPENIAM_WorkerPoolMax`          | Integer     | global  | —       | `100`           |
| `OPENIAM_WorkerPoolSoftMax`      | Integer     | global  | —       | `100`           |
| `OPENIAM_WorkerPoolTTL`          | Integer (s) | global  | —       | `600`           |
| `OPENIAM_WorkerPoolTimeout`      | Integer (s) | global  | —       | `300`           |
| `OPENIAM_WorkerPoolKeepAlive`    | On/Off      | global  | —       | `On`            |
| `OPENIAM_WorkerPoolRetry`        | Integer     | global  | —       | `0`             |
| `OPENIAM_Verbose`                | on/off      | vhost   | `off`   | `on`            |
| `OPENIAM_DebugESB`               | on/off      | vhost   | `off`   | `on`            |
| `OPENIAM_DebugCookies`           | on/off      | vhost   | `off`   | `on`            |
| `OPENIAM_DebugPatterns`          | on/off      | vhost   | `off`   | `on`            |
| `OPENIAM_DebugRespHeaders`       | on/off      | vhost   | `off`   | `on`            |
| `OPENIAM_DebugCertAuth`          | on/off      | vhost   | `off`   | `on`            |
| `OPENIAM_PrintTimings`           | on/off      | vhost   | `off`   | `on`            |
| `OPENIAM_AllowDumpHeaders`       | on/off      | vhost   | `off`   | `on`            |
| `OPENIAM_DumpRequests`           | on/off      | vhost   | `off`   | `on`            |
| `OPENIAM_DumpRequestsBody`       | on/off      | vhost   | `off`   | `on`            |
| `OPENIAM_DumpRequestBody_filter` | String      | vhost   | —       | `/legacy/login` |
| `OPENIAM_DumpNoAuth`             | on/off      | vhost   | `off`   | `on`            |
| `OPENIAM_DumpResponses`          | on/off      | vhost   | `off`   | `on`            |
| `OPENIAM_DumpResponsesBody`      | on/off      | vhost   | `off`   | `on`            |

`OPENIAM_WorkerPooEnabled` is the third shipped typo (`Poo`, not `Pool`). The recommended container worker-pool block is `Min 25 / Max 100 / SoftMax 100 / TTL 600 / Timeout 300 / KeepAlive On / Retry 0`, with cURL pooling on and `CurlPoolSize 32`.

{% hint style="warning" %}
**Four names established only by the shipped example configuration.** `AuthType openiam`, `Require valid-openiam-federation` and `Require openiam-configure` are Apache core directives taking module-supplied values; they appear in every shipped example but not in the module's own directive reference. The same applies to `OPENIAM_Substitute`, which does response-body substitution at vhost level using `mod_substitute` syntax and appears only commented out in the shipped configuration. Prefer the URI pattern's **HTML Substitution List** to `OPENIAM_Substitute` in every case — it is stored with the content provider, visible on screen, scoped to one pattern, and changeable without a configuration reload.
{% endhint %}

## Container variables you will need to name

In a container deployment the image renders the whole Apache configuration itself, so nothing in the catalogue above is editable there — a change is a manifest edit belonging to whoever owns the deployment. Five variable names are worth carrying anyway, because you will need to name them.

| Variable                                                                     | What it does                                               | Why you will name it                                             |
| ---------------------------------------------------------------------------- | ---------------------------------------------------------- | ---------------------------------------------------------------- |
| `OPENIAM_RPROXY_DEBUG`, `_VERBOSE`, `_DEBUG_ESB`, `_DEBUG_AUTH`, `_DUMP_ALL` | The container equivalents of the module's debug directives | All five ship as `1` — see the warning below                     |
| `OPENIAM_LOG_LEVEL`                                                          | The proxy's log level                                      | Ships `debug`                                                    |
| `OPENIAM_DISABLE_CONFIGURE`                                                  | `1` closes the bootstrap hole to `/webconsole/setup`       | Set it back to `0` to recover from a lockout                     |
| `OPENIAM_RPROXY_ERROR_LOG` / `_ACCESS_LOG`                                   | Send the proxy's logs to container stderr and stdout       | Without them the logs are inside the container only              |
| `OPENIAM_SSL_VERIFY_CLIENT`                                                  | Whether the TLS layer requests a client certificate        | The first thing to check when a client certificate never arrives |

{% hint style="danger" %}
**The shipped starter turns every debug and dump variable on, and sets the log level to `debug`.** That is a developer default, not a production one. `OPENIAM_RPROXY_DUMP_ALL=1` writes request **and response bodies** to the container log, which means passwords and session tokens in whatever aggregates that log.

The symptom is on your side even though the fix is not: search your log aggregator for a sign-in request and see whether the posted body is there. If it is, ask for `OPENIAM_RPROXY_DEBUG`, `_VERBOSE`, `_DEBUG_ESB`, `_DEBUG_AUTH` and `_DUMP_ALL` to be set to `0` and `OPENIAM_LOG_LEVEL` to `warn`, and treat every log already captured with them on as a secret.
{% endhint %}

## Related

* [How the Access Gateway works](/administration-guide/gateway/access-gateway.md) — the model these values belong to
* [Content provider and URI pattern reference](/administration-guide/access/content-providers-and-uri-patterns/content-provider-reference.md) — the two screens, field by field
* [Content providers and URI patterns](/administration-guide/access/content-providers-and-uri-patterns.md) — how routing resolves, and the inheritance rules
* [Troubleshoot the Access Gateway](/administration-guide/gateway/troubleshoot-the-gateway.md) — where these codes and log lines are used
* [System properties](/administration-guide/reference/system-properties.md) — the full property catalogue
* [Where settings live](/administration-guide/start/where-settings-live.md) — which gateway value is a directive, an environment variable, a database row or a Webconsole field

*Applies to OpenIAM 2026.8.1. Last reviewed 17 October 2026.*


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation by asking a question.

Perform an HTTP GET request on the following URL with the `ask` and `goal` query parameters:

```
GET https://docs.openiam.com/administration-guide/gateway/access-gateway-reference.md?ask=<question>&goal=<user_goal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is what the user is ultimately trying to achieve, the reason they need the answer. Sharing it helps GitBook give you a better, more relevant answer. A goal is most helpful when it describes the outcome the user wants rather than restating the question. For example, with `ask=how do I create an API token`, a goal like `automate deployments from our CI pipeline` lets GitBook tailor the answer to that use case.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
