> 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/faq/gateway-and-federation.md).

# Gateway, SSO and federation

Short answers to questions administrators ask most often about gateway, sso and federation.

## What this is, and when you need it

Short answers to the questions this area generates most often, each linking to the page that carries the detail. If your question is not here, the section hubs route by outcome and the [error and symptom index](/administration-guide/error-and-symptom-index.md) routes by the exact message you were given.

### We have an old application with its own login form and no SAML or OIDC support. Can we still give people single sign-on to it?

Yes — the feature is called **form fill**, and it is what other vendors sell as form-based single sign-on, credential injection or password vaulting. You publish the application through the Access Gateway, create a URI pattern for the login form's **action** path, and add a **Form Post Processor** metadata entry naming each form field: the username comes from the user's profile, the password from their identity on the content provider's managed system, and hidden fields from static values. The gateway then converts the browser's GET of that path into a POST with the fields filled in, and the user never sees the application's login page. Two things stop it dead: a CAPTCHA, and any per-render token the server validates on POST.

[Full detail](/administration-guide/gateway/inject-identity.md#form-fill)

### Can a user sign in to OpenIAM without a password?

Yes. OpenIAM's sign-in page collects a login, not a credential, and then routes the browser to the page for whichever factor the authentication rule demands — so a rule that contains no `PASSWORD_AUTH` step is a passwordless sign-in. Several such rules ship ready to attach: `DEF_WEB_AUTH_RULE` (FIDO2 security key or Touch ID/Windows Hello), `DEF_CERT_AUTH_RULE` (client certificate or smart card), `DEF_KERB_AUTH_RULE` (domain-joined desktop SSO), `DEF_CRIIPTO_AUTH_RULE` and `DEF_DUO_AUTH_RULE`. It is passwordless, not usernameless — there is no discoverable-credential "passkey" flow — and a single FIDO step is phishing-resistant but still only one factor, because user verification is not enforced.

[Full detail](/administration-guide/security/authentication-model.md#passwordless-sign-in)

### After successful two-factor authentication the user lands on a 404 instead of the application. Why?

The landing page is the postback URL, and when nothing supplies one the login page falls back to a hard-coded `/selfservice/` path under whatever host the browser is already on — which, for an application with no context path of its own, is a path inside the OpenIAM UI. Set `OPENIAM_DefaultUrl` on the protected `<Location>`, and `OPENIAM_DefaultPostbackUrl` where the landing page differs from the default. Then retest through every interstitial screen, because one-time-password entry, secret-word capture and terms acceptance each perform their own redirect and each is a chance to lose the value.

[Full detail](/administration-guide/gateway/request-and-response-transformations.md#where-the-user-lands-after-authenticating)

### An application sends us a URL with another URL inside a query parameter and it breaks. Can OpenIAM handle it?

Not as sent, and this is not an OpenIAM defect. Once `?next=/a/b.action?k=v&title=X` is decoded there is no way for the gateway, the IdP or the browser to know whether `&title=X` belongs to the outer URL or the inner one, so the outer parse wins and the inner URL arrives truncated. The application that generates the link has to percent-encode the nested URL — `?next=%2Fa%2Fb.action%3Fk%3Dv%26title%3DX` — and the same applies to any value containing a space or a non-ASCII character, because the postback URL validator rejects those outright with a `401`.

[Full detail](/administration-guide/gateway/request-and-response-transformations.md#where-the-user-lands-after-authenticating)

### Can different SAML federations use different authentication levels when OpenIAM is the IdP?

Yes, using more than one URL for the same endpoint. The handler is mapped at both `/idp/saml2/idp/login` and `/idp/saml2/idp/login/{randomId}`, where the trailing segment is inert — so you can register `https://<OPENIAM_HOST>/idp/saml2/idp/login/<segment>` with one service provider, create a URI pattern for exactly that path, and set that pattern's authentication level independently of the generic one. Keep your own record of which segment belongs to which service provider, because nothing in the Webconsole associates them.

[Full detail](/administration-guide/federation/saml-identity-provider.md#one-sso-endpoint-per-authentication-level-loginrandomid)

### Can OpenIAM encrypt or decrypt SAML assertions, and where is that configured?

Outbound encryption is configured on the SAML identity provider with three attributes — `IDPSendEncryptedAssertion` plus the data and key algorithm attributes — and needs the service provider's own encryption certificate. There is no equivalent pair of algorithm fields on a SAML service provider: the SP-side attributes cover signing, bindings, relay state, chaining, NameID policy and a post-processor and nothing else, so decrypting an assertion someone else's IdP sent you turns on that provider's key material rather than on a field you set. Enabling encryption with the wrong certificate makes the assertion unreadable and produces no error on the OpenIAM side, so test it on a non-production trust with a rollback path.

[Full detail](/administration-guide/federation/saml-identity-provider/saml-identity-provider-reference.md#encryption)

### Certificate sign-in fails and the login page shows no error. Where is the error?

In the logs only, by design: when the ESB declines a certificate the gateway denies the request, sets no session cookie and returns the browser to the login page, which has nothing to display unless the URL carries a `loginErrorFromProxy=<CODE>` parameter — and even then only one code maps to a specific message, so everything else renders as a generic authentication error. Get the real cause from the ESB, where each rejection has its own `ResponseCode`. A log line ending `Could not parse certificate: java.io.IOException: Empty input` is the common one, and it means the gateway sent an **empty** certificate rather than a bad one.

[Full detail](/administration-guide/gateway/troubleshoot-the-gateway.md#certificate-authentication-fails-and-the-login-page-says-nothing)

### Change Password in the SelfService portal lands on the default page instead of the change-password screen. What do we check?

Check that `org.openiam.ui.password.change.url` still holds a **relative path**. Its shipped value is `/idp/changePassword`, and it is passed straight to a redirect, so a full `http://…` URL there hard-codes a scheme — which behind a TLS-terminating proxy is an HTTPS-to-HTTP downgrade and, to the user, a link that lands on the default page. Left relative, the absolute URL is derived per request from `x-openiam-proxy-scheme` falling back to `X-Forwarded-Proto`, with the port from `X-Forwarded-Port`, so those headers must survive the load balancer.

[Full detail](/administration-guide/gateway/request-and-response-transformations.md#where-the-user-lands-after-authenticating)

### How does the relay state Groovy script work, and can we compute the relay state per application?

Yes. `IDPRelayStateGenerator` names a Groovy script that replaces the default logic and returns the URL to redirect to; it is given the `HttpServletRequest`, the SAML object, the resolved user and the static relay state value, so you can compute the destination from a request parameter such as `issuer` or the inbound `RelayState`. The `log.info` lines in the shipped sample script are illustrative only — they print what is reachable inside the script and nothing reads a log. Extend `DefaultIdentityProviderRelayStateGenerator` for an IdP provider, because the shipped sample extends the service-provider class and uses a field that only exists there, and validate whatever you return: it is a redirect target.

[Full detail](/administration-guide/federation/saml-identity-provider.md#what-relay-state-resolves-to-and-what-a-script-can-change)

### Is there a way to refresh the OpenIAM session cookie without making the user sign in again?

Yes, but the renewal itself belongs to the application team rather than to you — the **Developer Guide** covers it. Your part is the pattern: **no shipped URI pattern covers renewal**, so it falls through to the seeded `/idp/*` pattern, which is restricted to role `9`, and no client can 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. Three of the consequences arrive as your support calls: a successful renewal invalidates the old session in the same step, so a client still using its previous token is refused — which presents as intermittent sign-outs straight after a renewal, not as a renewal failure; an already-expired token does not renew, it signs the session out; and a failure logs `Can't renew token via restful call` in the IdP log. Renewal is a stopgap for an existing integration; a mobile or native client that needs to survive long idle periods should move to OIDC with refresh tokens.

[Full detail](/administration-guide/gateway/access-gateway-reference.md#session-lifetime-and-renewing-the-session-cookie)

### One URL through the gateway returns 404 but the application is healthy. What does that mean?

A `404` from the gateway path usually means no URI pattern matched that URL, so authorization never reached the application — the ESB answered `NOT_FOUND` and the tier in front turned it into `404`. A `401` means a pattern matched and entitlement or an authentication level refused the request, and a `500` with `URI Syntax Exception:` in the ESB log means the URL is not a legal URI at all. The usual culprits are very long URLs and URLs carrying a nested URL whose `?` and `&` were not percent-encoded.

[Full detail](/administration-guide/gateway/troubleshoot-the-gateway.md#diagnosing-a-request-that-fails-through-the-gateway)

### Our URI pattern points at an application server that only accepts HTTPS, and every request returns an Internal Server Error. What is wrong?

Apache needs `SSLProxyEngine on` to speak HTTPS to an upstream, and in the shipped `mod_openiam.conf` that directive sits inside an `<ifModule ssl_module>` block. If `mod_ssl` is not loaded the block is skipped silently and the directive is never set, so httpd resolves your upstream and then finds no module willing to use it. Confirm the loaded modules with `httpd -M` rather than reading the configuration file, and load `mod_ssl` if it is missing — moving the directive outside the guard does not help, because `mod_ssl` is what provides it.

[Full detail](/administration-guide/gateway/troubleshoot-the-gateway.md#proxying-to-an-https-upstream)

### The UI log is full of "FATAL ERROR. No Authentiation Provider was found…" and a restart does not fix it. What is broken?

Not the database, despite what the message says. The last-resort default provider is read from a Redis cache that only ever holds a provider that is both flagged default **and** of type `OPENIAM_POLICY`, and the sweep that fills it evicts every key when its lookup returns nothing — so a period of ESB or RabbitMQ unavailability empties the cache and it stays empty until the ESB answers a sweep again, which is why restarting the UI changes nothing. Check ESB and message-bus health for the window in which it started, confirm exactly one `OPENIAM_POLICY` provider carries the default flag, and point health probes at the seeded actuator patterns so probe traffic stops amplifying it.

### What should we turn on before opening a support ticket about the Access Gateway?

Enable the module's debug directives as one block — `LogLevel debug` plus `OPENIAM_Verbose`, `OPENIAM_DebugESB`, `OPENIAM_DebugCookies`, `OPENIAM_DebugPatterns`, `OPENIAM_DebugRespHeaders`, `OPENIAM_PrintTimings`, `OPENIAM_DumpRequests`, `OPENIAM_DumpResponses` and `OPENIAM_AllowDumpHeaders` — reproduce the failure once, then turn them off. Add `OPENIAM_DebugCertAuth` only for certificate questions, and the two body-dump directives only on a non-production vhost, because they write credentials and tokens to the log. Collect the module log together with a HAR capture, the UI tier log at `DEBUG` and the ESB log for the same seconds; the decision that matters happens between the module and the ESB, where the browser cannot see it.

[Full detail](/administration-guide/gateway/troubleshoot-the-gateway.md#diagnosing-a-request-that-fails-through-the-gateway)

### When we protect the IdP SSO endpoint with an authentication level, the SAML request is lost. Which cookie should we be looking at?

`SPRING_SECURITY_SAVED_REQUEST`, not `lastSAMLMessageId`. An inbound `AuthnRequest` that has to pause for authentication is stored in Redis under a UUID carried in the `SPRING_SECURITY_SAVED_REQUEST` cookie, and it is single use — reading it deletes the Redis entry and expires the cookie. Only three code paths save it, and the one that runs before interstitial screens matches the bare `/idp/saml2/idp/login` path exactly, so a `/login/{randomId}` URL is not covered there. Confirm in a HAR capture whether the cookie was ever set before investigating the assertion; `lastSAMLMessageId` is a different cookie that correlates an `AuthnRequest` OpenIAM has *sent* with its response.

[Full detail](/administration-guide/federation/saml-identity-provider.md#how-an-interrupted-authnrequest-survives-authentication)

*Applies to OpenIAM 2026.8.1. Last reviewed 7 August 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/faq/gateway-and-federation.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.
