Skip to main content
Protect legacy web applications without code changes by deploying the Orchestrator as an identity-aware reverse proxy. It intercepts HTTP traffic, applies authentication policies, and injects identity headers — so your backend apps receive authenticated user information with zero code modification.

Overview

The proxy app type is the most common application type in the Orchestrator. It acts as an identity-aware reverse proxy in HTTP Proxy mode, forwarding requests to a backend after applying authentication and authorization policies. Route patterns determine which incoming traffic matches the app, policies enforce authentication at specific URL paths, and headers inject identity attributes into upstream requests.

How It Works

The HTTP Proxy request flow follows these steps:
  1. Traffic interception — The Orchestrator listens on configured route patterns (hostname/path combinations) and intercepts all matching HTTP requests before they reach the upstream application.
  2. Policy evaluation — Each request is matched against location-based policies. The Orchestrator determines which authentication and authorization rules apply based on the request path.
  3. User authentication — If the user is not authenticated (no valid session), the Orchestrator redirects them to the configured identity provider. After successful authentication, a session cookie is established.
  4. Authorization check — The Orchestrator evaluates authorization rules against the authenticated user’s attributes. Rules use and/or conditions with operators like equals, contains, etc. Unauthorized users are redirected or receive a 403 response.
  5. Header injection — For authorized requests, the Orchestrator injects identity headers (e.g., SM_USER, X-Remote-User) into the upstream request using template syntax ({{ connector.claim }}). The upstream application receives these headers and uses them for its own identity decisions.
  6. Proxying and response — The request (with injected headers) is forwarded to the upstream backend. The response flows back through the Orchestrator to the client. Optional Service Extensions can modify the request or response at this stage.

Use Cases

  • Protecting legacy apps without code changes — deploy the Orchestrator in front of applications that lack modern authentication support, adding SSO and MFA without modifying application code
  • Header-based authentication injection — inject identity headers like SM_USER, REMOTE_USER, or X-Remote-User into upstream requests, enabling SiteMinder-to-modern-IdP migration with zero backend changes
  • Session management for stateless apps — the Orchestrator manages user sessions and authentication state on behalf of backend applications that do not track sessions themselves
  • Combining with LDAP Provider for legacy stacks — pair proxy apps with an LDAP attribute provider to load additional user attributes from a directory and inject them as headers, bridging legacy LDAP-dependent applications to modern identity providers

Key Concepts

Route Patterns and Upstreams

Route patterns define which traffic the proxy intercepts. Each proxy app maps one or more hostname/path patterns to an upstream backend URL. The Orchestrator acts as a transparent reverse proxy — the client connects to the Orchestrator, and the Orchestrator forwards to the backend.

Header Injection

Header injection is the primary mechanism for passing identity to legacy applications. Using {{ connector.claim }} template syntax, the Orchestrator maps claims from identity providers into HTTP headers that the upstream application expects. This replaces legacy access management products like SiteMinder without changing the application.

Header Security on Open Routes

The Orchestrator treats injected identity headers as trusted assertions, so it must never forward a client-supplied copy of a header it manages. How this is enforced depends on whether a route is protected or open. A route is open when its policy sets both allowUnauthenticated: true and allowAll: true, so unauthenticated requests are proxied straight to the upstream. Open routes are never enabled by default. You must explicitly configure them, and they are intended only for non-sensitive resources such as CSS, images, and login pages.
  • Protected routes strip any client-supplied copy of a managed header and then inject the Orchestrator’s own value, so the upstream never receives a spoofed identity header.
  • Open routes are proxied without header injection. To prevent spoofing, the Orchestrator strips client-supplied copies of every statically configured managed header name — the names under the app-level headers: and every policy’s headers: — before proxying. All other client headers are forwarded unchanged.
Header names produced dynamically by a createHeaderSE are not known when configuration loads, so they are not stripped on open routes. If you use a createHeaderSE to set an identity header — especially a single global createHeaderSE with no static headers: entries — the Orchestrator applies no managed-header filtering on open routes, and the upstream receives whatever header the client sends.Never mark a route open if it is sensitive or if the upstream trusts injected identity headers (for example, SiteMinder-style SM_USER). Under the shared-responsibility model, choosing which routes are open, and ensuring open routes do not front header-trusting upstreams, is the administrator’s responsibility.

Location-Based Policies

Unlike OIDC and SAML modes where authorization is per-app, HTTP Proxy supports location-based policies. Different URL paths within the same application can have different authentication requirements and authorization rules. For example, / might allow all authenticated users while /admin requires a specific role. location is a URL path used to map application resources to a policy. A request is matched to the most specific location, with regular expression (regex) locations taking priority. Simple policy location matching is case-insensitive. If you define a location of /EXAMPLE, it matches requests with a path of /example or /Example. If you want the policy match to be case-sensitive, use a regex. To apply regex matching to a location, add ~ before the pattern (note the trailing space). For example:
You can use tools such as regex101 (choose Golang) to test your regex against URL paths you would like to match.
Poorly constructed regexes can impact Orchestrator performance. Prefer specific patterns and counters or ranges (.{0,15}) over “greedy” wildcards (.*). Anchors (^ or $) help performance, but they are not a security control — see Securing locations before using a regex to protect a path.

Matching order

The Orchestrator evaluates locations in this order and uses the first match:
  1. Regex locations, in the order they appear in the configuration.
  2. Prefix (non-regex) locations, longest first.

Securing locations

Because a non-matching regex falls through to the next policy, a regex location can be bypassed by a crafted path if a broader policy is open. Use the following guidance to keep protected locations fail-safe.
  • Prefer default-deny. Protect / and use regex locations only to open specific exceptions, such as static assets. A request that misses the regex falls through to a stricter policy, which fails safe for any path trick, including ones not listed on this page.
  • Protect locations with a prefix. To protect a path, prefer a prefix location such as /admin over a regex.
  • If a regex must protect a location, add (?i) for case-insensitive matching, for example ~ (?i)^/admin, and do not end the pattern with $ or /. An end anchor lets any trailing variation the upstream ignores fall through to the next policy. A pattern such as ^/admin/ can be dodged by /admin./x in the same way $ is dodged by /admin..
  • Switch case sensitivity back on inside a pattern with the inline (?-i) flag. Go regex supports inline flags such as (?i) and (?-i).

Examples

Static assets such as images and stylesheets often need to load without a session, for example on a login page. Protect / and use a regex location only to open the asset extensions. A request that misses the regex, including one using a path trick, falls through to / and requires authentication.
Most users can reach the application, but /admin should be limited to administrators. Use a prefix location, which is case-insensitive and is not dodged by paths such as /ADMIN or /admin/. The longer prefix wins over /, so the stricter rules apply under /admin.
A load balancer or monitoring system probes /healthz without credentials. Open only that path with a prefix location and keep / protected.
Never open a route that is sensitive or fronts an upstream that trusts injected identity headers. See Header security on open routes.
Regex locations are checked in the order they are defined, and the first match wins. To open /assets/ but keep /assets/private protected, define the more specific regex first. The protecting regex uses (?i) so /ASSETS/PRIVATE cannot bypass it, and it does not end with $ or /.
This configuration looks like it protects /admin, but it can be bypassed. The regex is case-sensitive, so a request for /ADMIN does not match it and falls through to /, which is open. On a case-insensitive upstream (for example Windows/IIS), /ADMIN reaches the same resource as /admin, and the Orchestrator proxies it without authentication.
Fix it by protecting / so that a missed match fails safe, and by using a prefix location for /admin. Prefix locations are case-insensitive and cover everything under the path.If you must use a regex, make it case-insensitive and do not end it with $, for example ~ (?i)^/admin, and still keep / protected.
Some upstream servers treat different paths as the same resource. For example, a server on Windows serves /admin. as /admin. A request like that could reach a protected page while the Orchestrator applies a different, weaker policy to it. To prevent this, the Orchestrator returns a 403 when a path could mean a different location on the upstream than the one it appears to be.In this configuration, / is open and /admin is protected by an anchored regex:
Each of these requests returns a 403:None of these paths match ~ ^/admin$ as sent, so without this check each would fall through to the open / policy and be proxied without authentication.The 403 is a safety net, not a substitute for a secure configuration. Because / is open in this example, it is what lets these requests through when they miss the regex. Prefer a protected / so that a request that matches nothing more specific fails safe.

Session Management

The Orchestrator manages sessions for proxied applications using cookies. This is critical for applications that lack their own session management. Session configuration (cookie name, lifetime, idle timeout) is defined at the global level and applies to all proxy apps.

Upstream Login

Some legacy applications have their own login flows in addition to the identity headers. The upstream login feature automates posting credentials to the upstream’s login form after the Orchestrator has authenticated the user, handling the “double login” problem.

Setup

1

Navigate to Applications

Go to Applications in the sidebar and click Create. Select Proxied App from the application type list.
2

Set the application name

Enter a Name to identify this application. This name appears in the Console.
3

Set the upstream URL

Enter the Upstream URL — the backend server the Orchestrator forwards requests to after authentication (e.g., https://internal-hr.example.com).
4

Add route patterns

Click Route Pattern to add URL patterns that map incoming requests to this app. Patterns support hostnames (example.com), paths (/app), or both (example.com/app).
5

Configure TLS settings

Optionally set a CA Path for self-signed certificates on the upstream. Enable Skip TLS Verification only for testing.
6

Configure mTLS (optional)

For upstream servers requiring client certificate authentication, provide the TLS Cert and TLS Key file paths or secret provider references.
7

Set the unauthorized page

Optionally enter an Unauthorized Page URL where users are redirected when a policy evaluation denies access (e.g., https://example.com/403).
8

Configure preserve host

Enable the Preserve Host toggle to keep the original Host header on proxied requests. Enable this when the upstream expects the original hostname (e.g., behind another reverse proxy like Apache).
9

Configure logout settings (optional)

Set the Logout Callback URL — the endpoint that facilitates logout for application users. Optionally set the Post Logout Redirect URL for where users go after successful logout.
10

Save

Click Save to create the application. You can now configure its authentication policies, headers, and identity provider bindings.

Troubleshooting

Symptoms: The upstream application does not see injected headers. User identity is missing from the request.Causes:
  • Header template syntax error — missing {{ }} delimiters or incorrect spacing.
  • Connector name typo in the template (e.g., {{ my_idp.email }} when the connector is named my-idp).
  • The upstream application or an intermediate proxy is stripping custom or X- headers.
Resolution:
  • Verify template syntax uses the {{ connector.attribute }} format exactly, with double curly braces and a dot separator.
  • Confirm the connector name in the template matches a connectors[].name entry in your configuration.
  • Check whether the upstream application or any intermediate load balancer strips custom headers. Some application servers discard headers with underscores or specific prefixes by default.
Symptoms: The browser loops endlessly between the Orchestrator and the identity provider, never completing authentication.Causes:
  • Session cookie domain mismatch — the cookie is set for a domain that does not cover the Orchestrator’s hostname.
  • The IdP callback URL does not match the oauthLoginRedirect.urls configured on the connector.
  • The routePatterns do not cover the callback path, so the Orchestrator does not intercept the callback.
Resolution:
  • Verify session.cookie.domain covers the Orchestrator’s hostname (e.g., .example.com for app.example.com).
  • Ensure the callback URL registered at the IdP is listed in oauthLoginRedirect.urls on the connector.
  • Check that routePatterns include the callback path so the Orchestrator can process the authentication response.
Symptoms: The user authenticates successfully but receives a 403 response on specific paths.Causes:
  • Location-based policy mismatch — the location path in the policy does not match the actual request path.
  • Authorization rules reference a connector attribute that does not return the expected value.
  • rulesAggregationMethod is set to and when or is needed (all rules must pass vs. any rule).
Resolution:
  • Verify the location path in the policy matches the request path. Regex locations (starting with ~ ) are checked first, in config order, then prefix locations, longest first. See Location-Based Policies.
  • Check that the connector.attribute references in rules return expected values by inspecting the connector’s claims.
  • Review the rulesAggregationMethod setting — use or if any single rule should grant access, or and if all rules must pass.
Symptoms: 502 Bad Gateway or connection timeout after the user successfully authenticates.Causes:
  • The upstream URL is unreachable from the Orchestrator host.
  • TLS certificate mismatch on the upstream — the Orchestrator cannot verify the upstream’s certificate.
  • Wrong port in the upstream URL.
Resolution:
  • Verify the Orchestrator can reach the upstream URL from its host (test with curl or equivalent).
  • If using HTTPS for the upstream, check the TLS profile configuration and ensure the upstream’s certificate is trusted.
  • Confirm the port in the upstream URL matches the port the backend application is listening on.
Symptoms: Users are forced to re-authenticate frequently, even during active use.Causes:
  • session.lifetime.idleTimeout or maxTimeout is set too low for the expected user activity pattern.
  • A load balancer in front of multiple Orchestrator instances is not using sticky sessions, causing requests to hit instances that do not have the user’s session.
Resolution:
  • Adjust session.lifetime.idleTimeout and session.lifetime.maxTimeout to match your expected user session duration.
  • Configure sticky sessions on the load balancer using the maverics_session cookie so that requests from the same user are routed to the same Orchestrator instance.

Applications

Overview of application types, route patterns, and shared configuration

HTTP Proxy

HTTP Proxy mode configuration for proxy app deployments

Identity Fabric

Configure the identity providers referenced in app policies

Authorization

Authorization rules, operators, and rule aggregation

Service Extensions

Custom request/response modification via Service Extensions

Transport Layer Security (TLS)

Named TLS profiles for upstream connections