---
title: Signed/encrypted SAML v2.0 assertions
description: This example set up federation using AM as the identity provider with signed/encrypted assertions.
component: pinggateway
version: 2026
page_id: pinggateway:gateway-guide:federation-setup-signed-filter
canonical_url: https://docs.pingidentity.com/pinggateway/2026/gateway-guide/federation-setup-signed-filter.html
revdate: 2025-12-16
---

# Signed/encrypted SAML v2.0 assertions

This example set up federation using AM as the identity provider with signed/encrypted assertions.

Before you start, set up and test the example in [Unsigned/unencrypted SAML v2.0 assertions](federation-setup-filter.html).

1. Set up the SAML keystore:

   1. Find the values of AM's default SAML keypass and storepass:

      ```console
      $ more /path/to/am/secrets/default/.keypass
      $ more /path/to/am/secrets/default/.storepass
      ```

   2. Copy the SAML keystore from the AM configuration to PingGateway:

      ```console
      $ cp /path/to/am/secrets/keystores/keystore.jceks /path/to/ig/secrets/keystore.jceks
      ```

      |   |                                                                                                                        |
      | - | ---------------------------------------------------------------------------------------------------------------------- |
      |   | Legacy keystore types such as JKS and JCEKS are supported but aren't secure. Consider using the PKCS#12 keystore type. |

2. Configure the Fedlet in PingGateway:

   1. In `FederationConfig.properties`, make the following changes:

      1. Delete the following lines:

         * `com.sun.identity.saml.xmlsig.keystore=%BASE_DIR%/security/keystores/keystore.jks`

         * `com.sun.identity.saml.xmlsig.storepass=%BASE_DIR%/.storepass`

         * `com.sun.identity.saml.xmlsig.keypass=%BASE_DIR%/.keypass`

         * `com.sun.identity.saml.xmlsig.certalias=test`

         * `com.sun.identity.saml.xmlsig.storetype=JKS`

         * `am.encryption.pwd=@AM_ENC_PWD@`

      2. Add the following line:

         `org.forgerock.openam.saml2.credential.resolver.class=org.forgerock.openig.handler.saml.SecretsSaml2CredentialResolver`

         This class is responsible for resolving secrets and supplying credentials.

         |   |                                                   |
         | - | ------------------------------------------------- |
         |   | Be sure to leave no space at the end of the line. |

   2. In `sp.xml`, make the following changes:

      1. Change `AuthnRequestsSigned="false"` to `AuthnRequestsSigned="true"`.

      2. Add the following KeyDescriptor just before `</SPSSODescriptor>`

         ```xml
                 <KeyDescriptor use="signing">
                     <ds:KeyInfo xmlns:ds="http://www.w3.org/2000/09/xmldsig#" >
                         <ds:X509Data>
                             <ds:X509Certificate>

                             </ds:X509Certificate>
                         </ds:X509Data>
                     </ds:KeyInfo>
                 </KeyDescriptor>
             </SPSSODescriptor>
         ```

      3. Copy the value of the signing certificate from `idp.xml` to this file:

         ```xml
         <KeyDescriptor use="signing">
           <ds:KeyInfo>
             <ds:X509Data>
               <ds:X509Certificate>

                 MII...zA6

               </ds:X509Certificate>
         ```

         This is the public key used for signing so that the IdP can verify request signatures.

3. Replace the remote service provider in AM:

   1. Select Applications > Federation > Entity Providers, and remove the `sp` entity provider.

   2. Drag in or import the new `sp.xml` updated in the previous step.

   3. Select Circles of Trust: `Circle of Trust`.

4. Set up PingGateway

   1. In the PingGateway configuration, set environment variables for the following secrets, and then restart PingGateway:

      ```console
      $ export KEYSTORE_SECRET_ID='a2V5c3RvcmU='
      $ export SAML_KEYSTORE_STOREPASS_SECRET_ID='base64-encoded value of the SAML storepass'
      $ export SAML_KEYSTORE_KEYPASS_SECRET_ID='base64-encoded value of the SAML keypass'
      ```

      The passwords are retrieved by a SystemAndEnvSecretStore, and must be base64-encoded.

   2. Remove `saml-filter.json` from the configuration, and add the following route, replacing the path to `keystore.jceks` with your path:

      * Linux

        `$HOME/.openig/config/routes/saml-filter-secure.json`

      * Windows

        `%appdata%\OpenIG\config\routes\saml-filter-secure.json`

      ```json
      {
        "name": "saml-filter-secure",
        "baseURI": "https://app.example.com:8444",
        "condition": "${find(request.uri.path, '^/home')}",
        "heap": [
          {
            "name": "SystemAndEnvSecretStore-1",
            "type": "SystemAndEnvSecretStore"
          },
          {
            "name": "KeyStoreSecretStore-1",
            "type" : "KeyStoreSecretStore",
            "config" : {
              "file" : "/path/to/ig/keystore.jceks",
              "storeType" : "jceks",
              "storePasswordSecretId" : "saml.keystore.storepass.secret.id",
              "entryPasswordSecretId" : "saml.keystore.keypass.secret.id",
              "secretsProvider" : "SystemAndEnvSecretStore-1",
              "mappings" : [ {
                "secretId" : "sp.signing.sp",
                "aliases" : [ "rsajwtsigningkey" ]
              }, {
                "secretId" : "sp.decryption.sp",
                "aliases" : [ "test" ]
              } ]
            }
          }
        ],
        "handler": {
          "type": "Chain",
          "config": {
            "filters": [
              {
                "name": "SamlFilter",
                "type": "SamlFederationFilter",
                "config": {
                  "assertionMapping": {
                    "name": "cn",
                    "surname": "sn"
                  },
                  "subjectMapping": "sp-subject-name",
                  "redirectURI": "/home/saml-filter",
                  "secretsProvider" : "KeyStoreSecretStore-1"
                }
              },
              {
                "name": "SetSamlHeaders",
                "type": "HeaderFilter",
                "config": {
                  "messageType": "REQUEST",
                  "add": {
                    "x-saml-cn": [  "${toString(session.name)}" ],
                    "x-saml-sn": [  "${toString(session.surname)}" ]
                  }
                }
              }
            ],
            "handler": "ReverseProxyHandler"
          }
        }
      }
      ```

      Source: [saml-filter-secure.json](../_attachments/config/routes/saml-filter-secure.json)

      Notice the following features of the route compared to `saml-filter.json`:

      * The SamlFederationFilter refers to the KeyStoreSecretStore to provide the keys for the signed and encrypted SAML assertions.

      * The secret IDs, `sp.signing.sp` and `sp.decryption.sp`, follow a naming convention based on the name of the service provider, `sp`.

      * The alias for the signing key corresponds to the PEM in `keystore.jceks`.

   3. Restart PingGateway.

5. Test the setup:

   1. In your browser's privacy or incognito mode, go to <https://sp.example.com:8443/home>.

   2. Log in to AM as user `demo`, password `Ch4ng31t`. The request is redirected to the sample application.

|   |                                                                                                                                                                        |
| - | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|   | If a request returns an HTTP 414 URI Too Long error, consider the information in [URI Too Long error](../maintenance-guide/troubleshooting.html#troubleshoot-HTTP414). |
