---
title: URI fragments in redirect
description: "URI fragments are optional last parts of a URL for a document, typically used to identify or navigate to a particular part of the document. The fragment part follows the URL after a hash #, for example https://www.rfc-editor.org/rfc/rfc1234#section5."
component: pinggateway
version: 2026
page_id: pinggateway:gateway-guide:fragment
canonical_url: https://docs.pingidentity.com/pinggateway/2026/gateway-guide/fragment.html
revdate: 2025-10-15T18:45:22Z
keywords: ["Configuration", "URI"]
---

# URI fragments in redirect

URI fragments are optional last parts of a URL for a document, typically used to identify or navigate to a particular part of the document. The fragment part follows the URL after a hash `#`, for example `https://www.rfc-editor.org/rfc/rfc1234#section5`.

When an unauthenticated user requests a resource that includes a URI fragment, the user agent sends the URI but doesn't send the fragment. The fragment is lost during the authentication flow.

PingGateway provides a [FragmentFilter](../reference/FragmentFilter.html) to track the fragment part of a URI when a request triggers a login redirect.

The FragmentFilter doesn't handle multiple fragment captures in parallel. If a fragment capture is in progress while PingGateway performs another login redirect, a second fragment capture process isn't triggered and the fragment is lost.

|   |                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            |
| - | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
|   | When a browser request loads a favicon, it can lose the fragment part of a URI. Prevent problems by serving static resources with a separate route:- Linux

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

- Windows

  `%appdata%\OpenIG\config\routes\00-static-resources.json````json
{
  "name" : "00-static-resources",
  "baseURI" : "https://app.example.com:8444",
  "condition": "${find(request.uri.path,'^/css') or matchesWithRegex(request.uri.path, '^/.*\\\\.ico$') or matchesWithRegex(request.uri.path, '^/.*\\\\.gif$')}",
  "handler": "ReverseProxyHandler"
}
```Source: [00-static-resources.json](../_attachments/config/routes/00-static-resources.json) |

The following image shows the flow of information when the FragmentFilter is included in the SSO authentication flow:

![fragment](https://kroki.io/plantuml/svg/eNqNVc2S2jAMvvspNNvDtgdCu4d2hil0UvZnONDtADu97MUkSuJpYru2s8Aj9TX6ZJVN-AksC6cklvTp0yfJYd1rBkOlV0bkhYN_f-Hm46cv0KHHzWf4KWQOoxSlE25FbkYrw51QkjGYFcJColIEejoFc4TaYgq4TMraihcsVyAkeUiJiY-BhXDFG5BgVeYW3CAoAxbNi0jQRux0BChJOVSWobFg66R4FcFzKzHnJQQEgZbBolBQ8Bf0R2iItJDkxWEuZOqzlRQoLQLPDWJFTme4R-y6yxhJOXu8fWRxyrUj0MyoClyBkJVqARlxmk4fI_iFIJHMPmPqUwcfXDrDwTrUFkTmj5iinghJxJ8mI6-j40JaYpkZnntSISuvnZJ1NUfD5moJT1Q2xDlZmebGiURoTvSvhqWgsyvgFtavbfN3oxYUGezNO0OZEmJA9YU_cIcLvmrF3TdM7kVJOrZMVGpz2uC08nnAeBzSxeO2acorXSLEWgezDZ_0xfp9mOCfGq0LWu50CPpAv8_WlXUGTQW9h7vZsyyc07bX7XKtI1wGtChRVVcblYkS321QWBPVGbSrugiFeXZDantNw8dlSo1U9LZlSOTaqJ3OYKtQL65dMcFUGFqUIfWZZoFtrS1PeMX1WUZSOZGtRpXGML-jfOPy_kML6KCyjZcfxVMFlopm8Jj8AdIJXuKY0Q9PVWBKzA5At23zYIoWel6J0OrK88vRrXfpXLtgug4Mzj642Ry_uy2Aw_RHJaXproGJUr_Fus2-VH8FJLQQrzR2W8aeuuv58epWx-J-y5VT_SiKnokj3Z0pHqVdD_bXziAe9_bz-2szHu8pd5Tz3My2iiSZg0Lh0jEbKCrxpNa0G3AmzemqTvZ_cnc7mtwNZ5dUcX5_4aIFfmM9LwPY7dlge2ddJBDbureSTtBqRT-htxZ453Ray43Hf6Dk1WM=)

**1-2.** An unauthenticated client requests access to a fragment URL.

**3\.** The FragmentFilter adds the AuthRedirectContext, so that downstream filters can mark the response as redirected.

**4-5.** The SingleSignOnFilter adds to the context to notify upstream filters that a redirect is pending, and redirects the request for authentication.

**6-7.** The FragmentFilter is notified by the context that a redirect is pending, and returns a new response object containing the response cookies, an autosubmit HTML form, and Javascript.

**8\.** The user agent runs the Javascript or displays the form's submit button for the user to click on. This operation POSTs a form request back to a fragment endpoint URI, containing the following parts:

* Request URI path (`/profile`)

* Captured fragment (`#fragment`)

* Login URI (`http://am.example.com/login?goto=…​`)

**9\.** The FragmentFilter creates the fragment cookie.

**10-12.** The client authenticates with AM.

**13\.** The FragmentFilter intercepts the request because it contains a fragment cookie, and its URI matches the original request URI.

The filter redirects the client to the original request URI containing the fragment. The fragment cookie then expires.

**14-19.** The client follows the final redirect to the original request URI containing the fragment, and the sample app returns the response.

This procedure shows how to persist a URI fragment in an SSO authentication. Before you start, set up and test the example in [Using the default PingAM journey](proc-sso.html).

1. In PingGateway, replace `sso.json` with the following route:

   * Linux

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

   * Windows

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

   ```json
   {
     "name": "fragment",
     "baseURI": "https://app.example.com:8444",
     "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/"
         }
       }
     ],
     "handler": {
       "type": "Chain",
       "config": {
         "filters": [
           {
             "name": "FragmentFilter-1",
             "type": "FragmentFilter",
             "config": {
               "fragmentCaptureEndpoint": "/home/sso"
             }
           },
           {
             "name": "SingleSignOnFilter-1",
             "type": "SingleSignOnFilter",
             "config": {
               "amService": "AmService-1"
             }
           }
         ],
         "handler": "ReverseProxyHandler"
       }
     }
   }
   ```

   Source: [fragment.json](../_attachments/config/routes/fragment.json)

   Compared to `sso.json` the `FragmentFilter` captures the fragment form data from the route condition endpoint.

2. Test the setup:

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

      The SingleSignOnFilter redirects the request to AM for authentication.

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

      The SingleSignOnFilter passes the request to sample application, which returns the home page. Note that the URL of the page has preserved the fragment: `https://ig.example.com:8443/home/sso?_ig=true#fragment`

   3. Remove the FragmentFilter from the route and test the route again.

      Note that this time the URL of the page hasn't preserved the fragment.
