---
title: Single sign-on and cross-domain single sign-on
description: The following sections describe how to set up single sign-on for requests in the same domain and in a different domain:
component: pinggateway
version: 7.2
page_id: pinggateway:gateway-guide:sso
canonical_url: https://docs.pingidentity.com/pinggateway/2026/gateway-guide/sso.html
llms_txt: https://docs.pingidentity.com/pinggateway/llms.txt
docs_for_agents: https://developer.pingidentity.com/build-with-ai/docs-for-agents.md
revdate: 2022-05-16T14:11:21Z
superseded_by: https://docs.pingidentity.com/pinggateway/2026/gateway-guide/sso.html
section_ids:
  sso-auth: Authenticating with SSO
  proc-sso: SSO through the default authentication service
  proc-sso-authservice: SSO through an AM authentication tree
  cdsso-auth: Authenticate with CDSSO
  cdsso-sa: CDSSO for IG in standalone mode
  cdsso-wc: CDSSO for IG in web container mode
  evict-session-cache: Use WebSocket notifications to evict the session info cache
---

# Single sign-on and cross-domain single sign-on

The following sections describe how to set up single sign-on for requests in the same domain and in a different domain:

|   |                                                                                                                                                                                                                                                                                              |
| - | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|   | To require users to authenticate in the correct realm for security reasons, configure SSO or CDSSO with a PolicyEnforcementFilter, that refers to an AM policy where the realm is enforced. For an example, see [Require users to authenticate to a specific realm](pep.html#pep-sso-realm). |

## Authenticating with SSO

In SSO using the SingleSignOnFilter, IG processes a request using authentication provided by AM. IG and the authentication provider must run on the same domain.

The following sequence diagram shows the flow of information during SSO between IG and AM as the authentication provider.

![Flow of information for SSO.](_images/sso.svg)

* The browser sends an unauthenticated request to access the sample app.

* IG intercepts the request, and redirects the browser to AM for authentication.

* AM authenticates the user, creates an SSO token.

* AM redirects the request back to the original URI with the token in a cookie, and the browser follows the redirect to IG.

* IG validates the token it gets from the cookie. It then adds the AM session info to the request, and stores the SSO token in the context for use by downstream filters and handlers.

* IG forwards the request to the sample app, and the sample app returns the requested resource to the browser.

### SSO through the default authentication service

This section gives an example of how to authenticate by using SSO and the default authentication service provided in AM.

Before you start, prepare AM, IG, and the sample application as described in [Example installation for this guide](preface.html#preface-examples).

1. Set up AM:

   1. (From AM 6.5.3) Select Services > Add a Service, and add a Validation Service with the following Valid goto URL Resources:

      * `http://ig.example.com:8080/*`

      * `http://ig.example.com:8080/*?*`

   2. Select Applications > Agents > Identity Gateway, and add an agent with the following values:

      * Agent ID: `ig_agent`

      * Password: `password`

        For AM 6.5.x and earlier versions, set up an agent as described in [Set up an IG agent in AM 6.5 and earlier](preface.html#setup-agent-65).

   3. Select Configure > Global Services > Platform, and add `example.com` as an AM cookie domain.

      By default, AM sets host-based cookies. After authentication with AM, requests can be redirected to AM instead of to the resource.

2. Set up IG:

   1. Set an environment variable for the IG agent password, and then restart IG:

      ```bash
      $ export AGENT_SECRET_ID='cGFzc3dvcmQ='
      ```

      The password is retrieved by a SystemAndEnvSecretStore, and must be base64-encoded.

   2. Add the following route to IG, to serve .css and other static resources for the sample application:

      * Linux

      * Windows

      ```
      $HOME/.openig/config/routes/static-resources.json
      ```

      ```
      %appdata%\OpenIG\config\routes\static-resources.json
      ```

      ```json
      {
        "name" : "sampleapp-resources",
        "baseURI" : "http://app.example.com:8081",
        "condition": "${find(request.uri.path,'^/css')}",
        "handler": "ReverseProxyHandler"
      }
      ```

   3. Add the following route to IG:

      * Linux

      * Windows

      ```
      $HOME/.openig/config/routes/sso.json
      ```

      ```
      %appdata%\OpenIG\config\routes\sso.json
      ```

      ```json
      {
        "name": "sso",
        "baseURI": "http://app.example.com:8081",
        "condition": "${find(request.uri.path, '^/home/sso$')}",
        "heap": [
          {
            "name": "SystemAndEnvSecretStore-1",
            "type": "SystemAndEnvSecretStore"
          },
          {
            "name": "AmService-1",
            "type": "AmService",
            "config": {
              "agent": {
                "username": "ig_agent",
                "passwordSecretId": "agent.secret.id"
              },
              "secretsProvider": "SystemAndEnvSecretStore-1",
              "url": "http://am.example.com:8088/openam/",
              "version": "7.2"
            }
          }
        ],
        "handler": {
          "type": "Chain",
          "config": {
            "filters": [
              {
                "name": "SingleSignOnFilter-1",
                "type": "SingleSignOnFilter",
                "config": {
                  "amService": "AmService-1"
                }
              }
            ],
            "handler": "ReverseProxyHandler"
          }
        }
      }
      ```

      For information about how to set up the IG route in Studio, see [Policy enforcement in Structured Editor](../studio-guide/examples-se.html#example-pep-sso-se) or [Protecting a web app with Freeform Designer](../studio-guide/examples-ff.html#example-pep-sso-ff).

3. Test the setup:

   1. If you are logged in to AM, log out and clear any cookies.

   2. Go to <http://ig.example.com:8080/home/sso>, and log in to AM as user `demo`, password `Ch4ng31t`.

      The SingleSignOnFilter passes the request to sample app, which returns the profile page.

### SSO through an AM authentication tree

This section gives an example of how to authenticate by using SSO and the example authentication tree provided in AM, instead of the default authentication service.

1. Set up the example in [Authenticate with SSO through the default authentication service](#proc-sso).

2. Add the following route to IG:

   * Linux

   * Windows

   ```
   $HOME/.openig/config/routes/sso-authservice.json
   ```

   ```
   %appdata%\OpenIG\config\routes\sso-authservice.json
   ```

   ```json
   {
     "name": "sso-authservice",
     "baseURI": "http://app.example.com:8081",
     "condition": "${find(request.uri.path, '^/home/sso-authservice')}",
     "heap": [
       {
         "name": "SystemAndEnvSecretStore-1",
         "type": "SystemAndEnvSecretStore"
       },
       {
         "name": "AmService-1",
         "type": "AmService",
         "config": {
           "agent": {
             "username": "ig_agent",
             "passwordSecretId": "agent.secret.id"
           },
           "secretsProvider": "SystemAndEnvSecretStore-1",
           "url": "http://am.example.com:8088/openam/",
           "version": "7.2"
         }
       }
     ],
     "handler": {
       "type": "Chain",
       "config": {
         "filters": [
           {
             "name": "SingleSignOnFilter-1",
             "type": "SingleSignOnFilter",
             "config": {
               "amService": "AmService-1",
               "authenticationService": "Example"
             }
           }
         ],
         "handler": "ReverseProxyHandler"
       }
     }
   }
   ```

   Notice the features of the route compared to `sso.json`:

   * The route matches requests to `/home/sso-authservice`.

   * The `authenticationService` property of SingleSignOnFilter refers to `Example`, the name of the example authentication tree in AM. This authentication tree is used for authentication instead of the AM XUI.

3. Test the setup:

   1. If you are logged in to AM, log out and clear any cookies.

   2. Go to <http://ig.example.com:8080/home/sso-authservice>, and note that the login page is different to that returned in [Authenticate with SSO through the default authentication service](#proc-sso).

## Authenticate with CDSSO

The SSO mechanism described in [Authenticating with SSO](#sso-auth) can be used when IG and AM are running in the same domain. When IG and AM are running in different domains, AM cookies are not visible to IG because of the same-origin policy.

CDSSO using the CrossDomainSingleSignOnFilter, provides a mechanism to push tokens issued by AM to IG running in a different domain.

The following sequence diagram shows the flow of information between IG, AM, and the sample app during CDSSO. In this example, AM is running on `am.example.com`, and IG is running on `ig.ext.com`.

![Flow of information for CDSSO.](_images/cdsso.svg)

* The browser sends an unauthenticated request to access the sample app.

* IG intercepts the request, and redirects the browser to AM for authentication.

* AM authenticates the user and creates a CDSSO token.

* AM responds to a successful authentication with an HTML autosubmit form containing the issued token.

* The browser loads the HTML and autosubmit form parameters to the IG callback URL for the redirect endpoint.

* IG checks the nonce found inside the CDSSO token to confirm that the callback comes from an authentication initiated by IG. IG then constructs a cookie, and fulfills it with a cookie name, path, and domain, using the CrossDomainSingleSignOnFilter property `authCookie`. The domain must match that set in the AM J2EE agent.

* IG redirects the request back to the original URI, with the cookie, and the browser follows the redirect back to IG.

* IG validates the token it gets from the cookie. It adds the AM session info to the request, and stores the SSO token and CDSSO token in the contexts for use by downstream filters and handlers.

* IG forwards the request to the sample app, and the sample app returns the requested resource to the browser.

### CDSSO for IG in standalone mode

Before you start, prepare AM, IG, and the sample application, as described in [Download and start IG in standalone mode](../getting-started/start-product.html#starting-standalone).

1. Set up AM:

   1. Select Applications > Agents > Identity Gateway, add an agent with the following values:

      * Agent ID: `ig_agent_cdsso`

      * Password: `password`

      * Redirect URL for CDSSO: `https://ig.ext.com:8443/home/cdsso/redirect`

        For AM 6.5.x and earlier versions, set up an agent as described in [Set up an IG agent in AM 6.5 and earlier](preface.html#setup-agent-65).

   2. (From AM 6.5.3) Select Services > Add a Service, and add a Validation Service with the following Valid goto URL Resources:

      * `https://ig.ext.com:8443/*`

      * `https://ig.ext.com:8443/*?*`

   3. Select Configure > Global Services > Platform, and add `example.com` as an AM cookie domain.

      By default, AM sets host-based cookies. After authentication with AM, requests can be redirected to AM instead of to the resource.

2. Set up IG:

   1. Set up IG for HTTPS, as described in [Configure IG for HTTPS (server-side) in standalone mode](../installation-guide/install-standalone.html#standalone-https).

   2. Add the following `session` configuration to `admin.json`, to ensure that the browser passes the session cookie in the form-POST to the redirect endpoint (step 6 of [Information Flow During CDSSO](#figure-cdsso-auth)):

      ```
      {
        "connectors": […​],
        "session": {
          "cookie": {
            "sameSite": "none",
            "secure": true
          }
        },
        "heap": […​]
      }
      ```

      This step is required for the following reasons:

      * When `sameSite` is `strict` or `lax`, the browser does not send the session cookie, which contains the nonce used in validation. If IG doesn't find the nonce, it assumes that the authentication failed.

      * When `secure` is `false`, the browser is likely to reject the session cookie.

        For more information, see [admin.json](../reference/AdminHttpApplication.html).

   3. Set an environment variable for the IG agent password, and then restart IG:

      ```bash
      $ export AGENT_SECRET_ID='cGFzc3dvcmQ='
      ```

      The password is retrieved by a SystemAndEnvSecretStore, and must be base64-encoded.

   4. Add the following route to IG, to serve .css and other static resources for the sample application:

      * Linux

      * Windows

      ```
      $HOME/.openig/config/routes/static-resources.json
      ```

      ```
      %appdata%\OpenIG\config\routes\static-resources.json
      ```

      ```json
      {
        "name" : "sampleapp-resources",
        "baseURI" : "http://app.example.com:8081",
        "condition": "${find(request.uri.path,'^/css')}",
        "handler": "ReverseProxyHandler"
      }
      ```

   5. Add the following route to IG:

      * Linux

      * Windows

      ```
      $HOME/.openig/config/routes/cdsso.json
      ```

      ```
      %appdata%\OpenIG\config\routes\cdsso.json
      ```

      ```json
      {
        "name": "cdsso",
        "baseURI": "http://app.example.com:8081",
        "condition": "${find(request.uri.path, '^/home/cdsso')}",
        "heap": [
          {
            "name": "SystemAndEnvSecretStore-1",
            "type": "SystemAndEnvSecretStore"
          },
          {
            "name": "AmService-1",
            "type": "AmService",
            "config": {
              "url": "http://am.example.com:8088/openam",
              "realm": "/",
              "version": "7.2",
              "agent": {
                "username": "ig_agent_cdsso",
                "passwordSecretId": "agent.secret.id"
              },
              "secretsProvider": "SystemAndEnvSecretStore-1",
              "sessionCache": {
                "enabled": false
              }
            }
          }
        ],
        "handler": {
          "type": "Chain",
          "config": {
            "filters": [
              {
                "name": "CrossDomainSingleSignOnFilter-1",
                "type": "CrossDomainSingleSignOnFilter",
                "config": {
                  "redirectEndpoint": "/home/cdsso/redirect",
                  "authCookie": {
                    "path": "/home",
                    "name": "ig-token-cookie"
                  },
                  "amService": "AmService-1",
                  "verificationSecretId": "verify",
                  "secretsProvider": {
                    "type": "JwkSetSecretStore",
                    "config": {
                      "jwkUrl": "http://am.example.com:8088/openam/oauth2/connect/jwk_uri"
                    }
                  }
                }
              }
            ],
            "handler": "ReverseProxyHandler"
          }
        }
      }
      ```

      Notice the following features of the route:

      * The route matches requests to `/home/cdsso`.

      * The agent password for AmService is provided by a SystemAndEnvSecretStore in the heap.

      * The property `verificationSecretId` is configured with a value. If this property is not configured, the filter does not verify the signature of signed access tokens.

      * The JwkSetSecretStore specifies the URL to a JWK set on AM, that contains signing keys identified by a `kid`.

        The JwkSetSecretStore verifies the signature of the token when the value of a `kid` in the JWK set matches a `kid` in the the signed access token.

        If the JWT doesn't have a `kid`, or if the JWK set doesn't contain a key with the same value, the JwkSetSecretStore looks for valid secrets with the same purpose as the value of `verificationSecretId`.

3. Test the setup:

   1. If you are logged in to AM, log out and clear any cookies.

   2. Go to <https://ig.ext.com:8443/home/cdsso>.

      If you see warnings that the site is not secure, respond to the warnings to access the site.

      The CrossDomainSingleSignOnFilter redirects the request to AM for authentication.

   3. Log in to AM as user `demo`, password `Ch4ng31t`.

      When you have authenticated, AM calls `/home/cdsso/redirect`, and includes the CDSSO token. The CrossDomainSingleSignOnFilter passes the request to sample app, which returns the home page.

### CDSSO for IG in web container mode

Before you start, prepare AM, IG, and the sample application, as described in [Install IG in Apache Tomcat](../installation-guide/install-tomcat.html).

1. Set up AM:

   1. Select Applications > Agents > Identity Gateway, add an agent with the following values:

      * Agent ID: `ig_agent_cdsso`

      * Password: `password`

      * Redirect URL for CDSSO: `https://ig.ext.com:8443/home/cdsso/redirect`

        For AM 6.5.x and earlier versions, set up an agent as described in [Set up an IG agent in AM 6.5 and earlier](preface.html#setup-agent-65).

   2. (From AM 6.5.3) Select Services > Add a Service, and add a Validation Service with the following Valid goto URL Resources:

      * `https://ig.ext.com:8443/*`

      * `https://ig.ext.com:8443/*?*`

   3. Select Configure > Global Services > Platform, and add `example.com` as an AM cookie domain.

      By default, AM sets host-based cookies. After authentication with AM, requests can be redirected to AM instead of to the resource.

2. Set up IG:

   1. Configure Tomcat for HTTPS, as described in [Configure IG for HTTPS (server-side) in Tomcat](../installation-guide/install-tomcat.html#tomcat-https).

      For Jetty, see [Configure IG for HTTPS (server-side) in Jetty](../installation-guide/install-jetty.html#jetty-https).

      For JBoss, see [Configure IG for HTTPS (server-side) in JBoss](../installation-guide/install-jboss.html#jboss-https).

   2. Configure Tomcat's cookie processor element with the `sameSite` setting `none`, as decribed in [Configure SameSite for HTTP session cookies in Tomcat](../installation-guide/install-tomcat.html#tomcat-samesite).

      For Jetty, see [Configure SameSite for HTTP session cookies in Jetty](../installation-guide/install-jetty.html#jetty-samesite).

      For JBoss, see [Configure SameSite for HTTP session cookies in JBoss](../installation-guide/install-jboss.html#jboss-samesite).

      This step ensures that the browser passes session cookies in the form-POST to the redirect endpoint (step 6 of [Information flow during CDSSO](#figure-cdsso-auth)).

      When `sameSite` is `lax` or `strict`, the browser does not send the session cookie containing the nonce used in validation. If IG doesn't find the nonce, it assumes that the authentication failed. The resulting error is propagated through the CrossDomainSingleSignOnFilter's `failureHandler`, which, by default, returns a 200 response describing the error.

      When you access Tomcat through HTTPs, the cookie `secure` is automatically added.

   3. Set an environment variable for the IG agent password, and then restart IG:

      ```bash
      $ export AGENT_SECRET_ID='cGFzc3dvcmQ='
      ```

      The password is retrieved by a SystemAndEnvSecretStore, and must be base64-encoded.

   4. Add the following route to IG, to serve .css and other static resources for the sample application:

      * Linux

      * Windows

      ```
      $HOME/.openig/config/routes/static-resources.json
      ```

      ```
      %appdata%\OpenIG\config\routes\static-resources.json
      ```

      ```json
      {
        "name" : "sampleapp-resources",
        "baseURI" : "http://app.example.com:8081",
        "condition": "${find(request.uri.path,'^/css')}",
        "handler": "ReverseProxyHandler"
      }
      ```

   5. Add the following route to IG:

      * Linux

      * Windows

      ```
      $HOME/.openig/config/routes/cdsso.json
      ```

      ```
      %appdata%\OpenIG\config\routes\cdsso.json
      ```

      ```json
      {
        "name": "cdsso",
        "baseURI": "http://app.example.com:8081",
        "condition": "${find(request.uri.path, '^/home/cdsso')}",
        "heap": [
          {
            "name": "SystemAndEnvSecretStore-1",
            "type": "SystemAndEnvSecretStore"
          },
          {
            "name": "AmService-1",
            "type": "AmService",
            "config": {
              "url": "http://am.example.com:8088/openam",
              "realm": "/",
              "version": "7.2",
              "agent": {
                "username": "ig_agent_cdsso",
                "passwordSecretId": "agent.secret.id"
              },
              "secretsProvider": "SystemAndEnvSecretStore-1",
              "sessionCache": {
                "enabled": false
              }
            }
          }
        ],
        "handler": {
          "type": "Chain",
          "config": {
            "filters": [
              {
                "name": "CrossDomainSingleSignOnFilter-1",
                "type": "CrossDomainSingleSignOnFilter",
                "config": {
                  "redirectEndpoint": "/home/cdsso/redirect",
                  "authCookie": {
                    "path": "/home",
                    "name": "ig-token-cookie"
                  },
                  "amService": "AmService-1",
                  "verificationSecretId": "verify",
                  "secretsProvider": {
                    "type": "JwkSetSecretStore",
                    "config": {
                      "jwkUrl": "http://am.example.com:8088/openam/oauth2/connect/jwk_uri"
                    }
                  }
                }
              }
            ],
            "handler": "ReverseProxyHandler"
          }
        }
      }
      ```

      Notice the following features of the route:

      * The route matches requests to `/home/cdsso`.

      * The agent password for AmService is provided by a SystemAndEnvSecretStore in the heap.

      * The property `verificationSecretId` is configured with a value. If this property is not configured, the filter does not verify the signature of signed access tokens.

      * The JwkSetSecretStore specifies the URL to a JWK set on AM, that contains signing keys identified by a `kid`.

        The JwkSetSecretStore verifies the signature of the token when the value of a `kid` in the JWK set matches a `kid` in the the signed access token.

        If the JWT doesn't have a `kid`, or if the JWK set doesn't contain a key with the same value, the JwkSetSecretStore looks for valid secrets with the same purpose as the value of `verificationSecretId`.

3. Test the setup:

   1. If you are logged in to AM, log out and clear any cookies.

   2. Go to <https://ig.ext.com:8443/home/cdsso>.

      If you see warnings that the site is not secure, respond to the warnings to access the site.

      The CrossDomainSingleSignOnFilter redirects the request to AM for authentication.

   3. Log in to AM as user `demo`, password `Ch4ng31t`.

      When you have authenticated, AM calls `/home/cdsso/redirect`, and includes the CDSSO token.

      The CrossDomainSingleSignOnFilter passes the request to the sample application, which returns the home page.

## Use WebSocket notifications to evict the session info cache

When WebSocket notifications are enabled, IG receives notifications whenever a user logs out of AM, or when an AM session is modified, closed, or times out.

The following procedure gives an example of how to change the configuration in [Authenticating With SSO](#sso-auth) and [Authenticate With CDSSO](#cdsso-auth) to evict entries related to the event from the cache. For information about WebSocket notifications, see [WebSocket notifications](../maintenance-guide/tuning.html#amservice-websocket).

Before you start, set up and test the example in [Authenticating With SSO](#sso-auth).

1. Websocket notifications are enabled by default. If they are disabled, enable them by adding the following configuration to the [AmService](../reference/AmService.html) in your route:

   ```json
   "notifications": {
     "enabled": true
   }
   ```

2. Enable the session cache by adding the following configuration to the [AmService](../reference/AmService.html) in your route:

   ```json
   "sessionCache": {
     "enabled": true
   }
   ```

3. In `logback.xml` add the following logger for WebSocket notifications, and then restart IG:

   ```xml
   <logger name="org.forgerock.openig.tools.notifications.ws" level="TRACE" />
   ```

   For information, see [Changing the log level for different object types](../maintenance-guide/logging.html#logging-level-objects).

4. Go to <http://ig.example.com:8080/home/sso>, and log in to AM as user `demo`, password `Ch4ng31t`.

5. On the AM console, log the demo user out of AM to end the AM session.

6. Note that the IG system logs are updated with Websocket notifications about the logout:

   ```none
   ... | TRACE | vert.x-eventloop-thread-2 | o.f.o.t.n.w.SubscriptionService | @system | Received a message: { "topic": "/agent/session", "timestamp": "...", "body": { "sessionuid": "58c...573", "eventType": "LOGOUT" } }
   ... | TRACE | vert.x-eventloop-thread-2 | o.f.o.t.n.w.SubscriptionService | @system | Received a notification: { "topic": "/agent/session", "timestamp": "...", "body": { "sessionuid": "58c...573", "eventType": "LOGOUT" } }
   ```
