---
title: Protecting PingAM with PingGateway
description: In its role as a reverse proxy, PingGateway can protect PingAM.
component: pinggateway
version: 2026
page_id: pinggateway:gateway-guide:protect-am
canonical_url: https://docs.pingidentity.com/pinggateway/2026/gateway-guide/protect-am.html
revdate: 2025-04-01T17:53:34Z
section_ids:
  choose_what_you_allow: Choose what you allow
  example_route: Example route
  before_you_begin: Before you begin
  allow_only_route: Allow-only route
  validation: Validation
---

# Protecting PingAM with PingGateway

In its role as a reverse proxy, PingGateway can protect PingAM.

## Choose what you allow

The best practice is to allow access only to required AM services:

* Limit access to specified AM realms.

* Prevent AM admin UI access.

Learn more about this process in the following articles:

* [Best practice for blocking the top-level realm in a proxy for PingAM](https://support.pingidentity.com/s/article/Best-practice-for-blocking-the-top-level-realm-in-a-proxy-for-PingAM)

* [How do I remove admin UI access in PingAM?](https://support.pingidentity.com/s/article/How-do-I-remove-admin-UI-access-in-PingAM)

## Example route

The following example allows access to the following:

* Key services in the `customers` realm.

* Authentication and logout through XUI and the legacy UI.

* SAML v2.0 services.

### Before you begin

* Install and run PingGateway as described in the [Getting started with PingGateway](../getting-started/preface.html).

* Install and configure AM with a `customers` subrealm of the top-level realm.

### Allow-only route

Add the following route to PingGateway:

* Linux

  `$HOME/.openig/config/routes/protect-am.json`

* Windows

  `%appdata%\OpenIG\config\routes\protect-am.json`

```json
{
  "name": "protect-am",
  "comment": "Allow authentication and subrealm access only (not the top-level realm or admin UI)",
  "properties": {
    "amBase": "/am",
    "amInstanceUrl": "http://am.example.com:8088/am",
    "subrealm": "customers"
  },
  "baseURI": "&{amInstanceUrl}",
  "condition": "${find(request.uri.path, '^&{amBase}')}",
  "handler": {
    "type": "Chain",
    "config": {
      "filters": [
        {
          "type": "AllowOnlyFilter",
          "config": {
            "rules": [
              {
                "comment": "Allow authentication to the subrealm",
                "destination": [
                  {
                    "paths": [
                      "&{amBase}/json/realms/root/realms/&{subrealm}/authenticate"
                    ],
                    "when": "${find(request.queryParams, 'realm') and !(contains(request.queryParams['realm'], '/') or contains(request.queryParams['realm'], '2F') or contains(request.queryParams['authIndexValue'], 'Application') or contains(request.queryParams['module'], 'Application'))}"
                  }
                ]
              },
              {
                "comment": "Allow authentication to the legacy UI",
                "destination": [
                  {
                    "paths": [
                      "&{amBase}/UI/Login"
                    ],
                    "when": "${find(request.queryParams, 'realm') and !(contains(request.queryParams['realm'], '/') or contains(request.queryParams['realm'], '2F') or contains(request.queryParams['authIndexValue'], 'Application') or contains(request.queryParams['module'], 'Application'))}"
                  }
                ]
              },
              {
                "comment": "Allow OAuth 2.0 and OID to the subrealm",
                "destination": [
                  {
                    "paths": [
                      "&{amBase}/oauth2/realms/root/realms/&{subrealm}/authorize",
                      "&{amBase}/oauth2/realms/root/realms/&{subrealm}/access_token",
                      "&{amBase}/oauth2/realms/root/realms/&{subrealm}/userinfo",
                      "&{amBase}/oauth2/realms/root/realms/&{subrealm}/connect/endSession"
                    ]
                  }
                ]
              },
              {
                "comment": "Allow base requests for sessions and users",
                "destination": [
                  {
                    "paths": [
                      "&{amBase}/json/sessions",
                      "&{amBase}/json/users"
                    ]
                  }
                ]
              },
              {
                "comment": "Allow base action requests for sessions",
                "destination": [
                  {
                    "paths": [
                      "&{amBase}/json/realms/root/sessions"
                    ]
                  }
                ],
                "when": "${(request.queryParams['_action'] == 'getMaxIdle') or (request.queryParams['_action'] == 'logout') or (request.queryParams['_action'] == 'validate')}"
              },
              {
                "comment": "Allow base action requests for users",
                "destination": [
                  {
                    "paths": [
                      "&{amBase}/json/realms/root/users"
                    ]
                  }
                ],
                "when": "${request.queryParams['_action'] == 'idFromSession'}"
              },
              {
                "comment": "Allow subrealm requests for sessions, serverinfo, and users",
                "destination": [
                  {
                    "paths": [
                      "&{amBase}/json/realms/root/realms/&{subrealm}/sessions",
                      "&{amBase}/json/realms/root/realms/&{subrealm}/serverinfo/*",
                      "^&{amBase}/json/realms/root/realms/&{subrealm}/users"
                    ]
                  }
                ]
              },
              {
                "comment": "Allow access to the XUI",
                "destination": [
                  {
                    "paths": [
                      "^&{amBase}/XUI"
                    ]
                  }
                ]
              },
              {
                "comment": "Allow access to the legacy UI for logout",
                "destination": [
                  {
                    "paths": [
                      "&{amBase}/UI/Logout"
                    ]
                  }
                ]
              },
              {
                "comment": "Allow SAML v2.0 requests",
                "destination": [
                  {
                    "paths": [
                      "^&{amBase}/ArtifactResolver/",
                      "^&{amBase}/Consumer/",
                      "^&{amBase}/IDPSloPOST/",
                      "^&{amBase}/IDPSloRedirect/",
                      "^&{amBase}/IDPSloSoap/",
                      "^&{amBase}/SSORedirect/",
                      "^&{amBase}/idpsaehandler/",
                      "^&{amBase}/saml2/jsp/"
                    ]
                  }
                ]
              }
            ],
            "failureHandler": {
              "type": "StaticResponseHandler",
              "config": {
                "status": 404,
                "headers": {
                  "Content-Type": [
                    "text/html; charset=UTF-8"
                  ]
                },
                "entity": "<html><p>HTTP 404 Not Found</p></html>"
              }
            }
          }
        }
      ],
      "handler": "ReverseProxyHandler"
    }
  }
}
```

Source: [protect-am.json](../_attachments/config/routes/protect-am.json)

Notice the key features of the route:

* An [AllowOnlyFilter](../reference/AllowOnlyFilter.html) defines the rules for requests PingGateway allows; PingGateway denies all requests not explicitly allowed.

  |   |                                                                                                                       |
  | - | --------------------------------------------------------------------------------------------------------------------- |
  |   | Adapt the route for the deployment, for example, by setting the `amBase`, `amInstanceUrl`, and `subrealm` properties. |

* When access to a resource is denied, PingGateway returns HTTP 404 Not Found.

  |   |                                                                                                           |
  | - | --------------------------------------------------------------------------------------------------------- |
  |   | In deployment, avoid leaking information by returning the same response for missing and denied resources. |

When you save the updated route file, PingGateway reloads it.

### Validation

1. Try an allowed request.

   In your browser's privacy or incognito mode, go to the XUI login page for the subrealm, such as <https://ig.example.com:8443/am/XUI/?realm=/customers#login> in this example.

   PingGateway displays the login page for the realm.

2. Try a request that's not allowed.

   In your browser's privacy or incognito mode, go to the top-level realm server version information resource, such as <https://ig.example.com:8443/am/json/serverinfo/version>.

   PingGateway returns 404 and displays a message: `HTTP 404 Not Found`.

3. Notice you can still access AM directly, as long as you don't traverse PingGateway.

   For example, go to the base URL for AM, such as <http://am.example.com:8088/am>.

   AM displays the login page.

   |   |                                                                                                                                         |
   | - | --------------------------------------------------------------------------------------------------------------------------------------- |
   |   | In deployment, route client traffic to AM through PingGateway, as for other protected applications. Don't expose AM endpoints directly. |
