PingGateway 2024.9

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 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 cause the fragment part of a URI to be lost. Prevent problems by serving static resources with a separate route. As an example, use the route in Serve static resources.

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

fragment

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 Use the default journey.

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

    • Linux

    • Windows

    $HOME/.openig/config/routes/fragment.json
    %appdata%\OpenIG\config\routes\fragment.json
    {
      "name": "fragment",
      "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/"
          }
        }
      ],
      "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"
        }
      }
    }

    Notice the following feature of the route 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.