Many applications running inside an enterprise — internal portals, billing systems, ops consoles, vendor-supplied admin panels, legacy line-of-business tools — were built before SAML or OIDC became mainstream. They typically recognise the user not via modern tokens, but through an HTTP header, a Basic-Auth credential, or a session cookie they already trust.
Migrating these apps to modern SSO sounds straightforward in theory: rewrite the backend authentication path, add SAML/OIDC support, and wire the app to the central identity provider. In practice it almost never happens. The source may be old, the app may be vendor-owned, the change may break a regulated workflow, or the cost is simply not justified for an internal tool that works.
Organisations are then stuck choosing between two bad options: leave legacy apps outside the modern identity perimeter, or build a separate fragile integration for each one. The end result is a fractured user experience, decentralised access control, and identity logic scattered across each backend's own legacy model.
The right approach is to position the modern access layer in front of the app. The user first passes through central identity, MFA, conditional access, and device-trust checks; the authenticated identity is then translated into a shape the backend already understands. The app gets a modern SSO experience without any code change.
But this transition has to be done carefully. If spoofed identity headers from the user are forwarded to the backend without being stripped, anyone can add their own X-Auth-User header to their request and impersonate another user. The gateway must remove untrusted inbound values, inject only the trusted identity it produces itself, and scope this strictly per route.
Logout, session-loss, and backend-driven identity state also have to flow through the same engine. Otherwise the user can appear logged out at the portal while the backend session stays alive, or the backend session can drop without the access layer noticing.
Backend SSO is not about forcing legacy apps to be rewritten — it is about putting modern identity control in front of the app, and safely translating the authenticated user identity into the language the backend already accepts.
One configuration object per backend, five injection shapes, coordinated with the rest of the access engine.
Every injection rule first strips any inbound copy of the target header, cookie, or Authorization value, then injects the version derived from the authenticated session. A user who sends their own "X-Auth-User" cannot impersonate someone else — their header is removed before the gateway adds the trusted one.
Custom headers (X-Auth-User, X-Forwarded-User, anything the backend expects), Authorization Basic for apps that want a username:password pair, Authorization Bearer for token-friendly backends, Cookie value merge for apps that read a named cookie, and SAML-SP for backends that expect a signed SAML assertion. Each injection has its own configuration; one backend can use several shapes at once.
Each injection rule carries its own condition expression — only apply on the admin path, only when a specific session attribute is present, only for one tenant. The same backend can receive richer identity on privileged routes and a minimal subset on public ones.
When the backend reports the user's session is gone (a known response shape per service), or when the backend itself logs the user out, AAM detects the signal, cleans up the gateway-side session, and redirects according to the configured policy. Logout-wins precedence ensures cleanup always runs before any further injection.
Five shipping injection shapes, the input-stripping discipline that makes them safe, plus the roadmap for higher-protocol injections.
The simplest and most common shape. Configure a header name (X-Auth-User, X-Forwarded-User, REMOTE_USER, anything the backend reads) and the smart variable that produces the value (username, email, group list, display name). The header is stripped from inbound requests, then re-added from the authenticated session before the request reaches the backend.
For legacy apps that authenticate via HTTP Basic, the gateway injects Authorization: Basic
For backends that already speak Bearer tokens (internal APIs, microservices, modern intranet apps) AAM injects Authorization: Bearer
Apps that read identity from a named cookie are accommodated with cookie-value injection. The gateway merges the injected name=value pair into the request's Cookie header without clobbering the other cookies — the most error-prone of the four header-style shapes, handled with explicit merge logic rather than naïve overwrites.
For backends that expect a signed SAML assertion on every request, the gateway mints a SAML 2.0 assertion from the authenticated session, signs it with AAM's SAML signing key, and forwards it on the configured header to the backend. Typical for public-sector identity federation integrations and enterprise SaaS backends. The user signs in with a modern IdP; the backend receives a fresh, scoped SAML assertion on every request.
Every injection is paired with an inbound strip of the same target. A user who sets X-Auth-User in their own request, who sends a forged Cookie with a tampered identity value, or who replays an Authorization header from somewhere else cannot make the value survive past the gateway. The injection only runs after the strip has cleared the slot.
Each injection rule can attach a condition — same expression language as conditional access policy. Only inject on the admin path; only inject when the user is in a specific group; only inject the privileged variant when an attribute is present. Conditions are compiled in an ACL-precedence-safe way so multiple rules on one backend compose correctly.
All injections are gated behind the authenticated state — they run only when the request carries a valid AAM session. A user who sneaks past authentication via a misconfigured route cannot accidentally receive injected backend credentials; an anonymous request always reaches the backend without injection.
Higher-protocol injection shapes — Kerberos constrained delegation to backends that require a service ticket, NTLM for older Windows estates — are on the roadmap. The configuration object and conditional plumbing already accommodate them; the protocol-specific runtime is the work that remains.
The mechanics that make header-grade injection safe at the access edge.
Per-injection conditions compose with the gateway's other ACL-driven decisions (authentication state, access policy, backend selection). The condition compiler uses an extra-entries pattern so injection conditions always evaluate after authentication and policy, never before — a per-injection rule cannot accidentally invert the result of a higher-precedence policy decision.
When an injection needs a value that is not in the session bag — a value derived from a per-request fetch (group expansion, attribute lookup) — the dispatcher emits a conditional fetch that runs only when the injection's condition matches. Backends that never see an injection never pay the cost of fetching the value.
Each service can declare the response signature that means "my session is gone" — a specific status code, a specific response header, a body marker. When the gateway sees that signature, it sets a session-lost flag, cleans up the gateway-side session, and redirects per the configured policy.
When the backend itself logs the user out — typically by responding with a known logout signature — the gateway runs a three-step cleanup: clear the gateway-side cookies, delete the session record, and redirect via the configured target. Logout-wins precedence ensures this path beats any in-flight injection.
Credentials and tokens used by injections are stored encrypted in the configuration store and are never written to access logs in cleartext. Audit entries record that an injection ran on a request, not what value it carried. Operators see the policy; the wire payload stays on the wire.
A silent re-auth flow that uses a 302 to the AAM daemon to re-establish a backend session without bouncing the user to a login page is on the roadmap. AAM-initiated logout propagation — pushing a logout signal forward to every backend that received an injected identity — is also on the roadmap.
An internal portal that has trusted X-Remote-User for a decade keeps reading X-Remote-User. The gateway runs modern SAML/OIDC at the edge, then injects the same header it always saw. No backend deploy, no migration cutover.
A cluster of internal microservices wants Bearer-token authentication but doesn't want to run an identity flow per service. The gateway issues a signed token per request and injects it; each service verifies the token against the gateway's keys.
A multi-app deployment includes one app that wants Basic Auth, one that wants a custom header, and one that wants a cookie. One AAM gateway handles login once; each backend gets the shape it expects, simultaneously, with per-route conditions.
Compliance regimes that require a clear identity chain — "who was authenticated when this request hit the backend" — get that chain produced by the gateway's audit stream. Header values, injection conditions, and the authenticated subject are recorded together.
We'll deploy backend SSO against your real applications — keeping their existing trust model, removing the credential from the user's hands, and producing an audit-grade identity chain for every request.