---
title: Example routes created with Freeform Designer
description: The following sections give examples of how to use the templates provided by the FreeForm Designer:
component: pinggateway
version: 7.2
page_id: pinggateway:studio-guide:examples-ff
canonical_url: https://docs.pingidentity.com/pinggateway/2026/studio-guide/examples-ff.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-04-12T12:16:42Z
superseded_by: https://docs.pingidentity.com/pinggateway/2026/studio-guide/examples-ff.html
section_ids:
  example-SingleSignOnFilter-ff: Using a basic template in FreeForm Designer
  example-pep-sso-ff: Protecting a web app with Freeform Designer
  example-rsintrospect-ff: Protect an API with Freeform Designer
---

# Example routes created with Freeform Designer

The following sections give examples of how to use the templates provided by the FreeForm Designer:

In this release, routes generated in Studio do not use the Commons Secrets Service. Documentation examples generated with Studio use deprecated properties.

## Using a basic template in FreeForm Designer

This section describes how to use a basic template in FreeForm Designer to set up SSO. For more information about setting up and testing SSO, see [Single sign-on and cross-domain single sign-on](../gateway-guide/sso.html).

Use a Basic Template in FreeForm Designer

1. In IG Studio, create a route:

   1. Go to <http://ig.example.com:8080/openig/studio>, and select [icon: plus, set=fa]Create a route.

   2. Select ![freeform](_images/freeform.svg) Freeform to use the FreeForm Designer.

2. Select [icon: file, set=fa]Basic to create a route from a blank template.

3. Select Advanced options on the right, and create a route with the following options:

   * Base URI: `http://app.example.com:8081`

   * Condition: Path: `/home/sso-ff`

   * Name: `sso-ff`

     The route is displayed on the ![freeform](_images/freeform.svg) Flow tab of the canvas. Select the [icon: database, set=fa]All Objects tab to view a list of objects in the route.

     Double-click on any object to review or edit it. After double-clicking on an object, select the Decorations tab to decorate it.

4. Configure authentication with a SingleSignOnFilter:

   1. Select the ![freeform](_images/freeform.svg) Flow tab, and delete the connector between Start and ReverseProxyHandler.

   2. From the side bar, drag a [icon: chain, set=fa]Chain onto the canvas, and then drag a [icon: user, set=fa]SingleSignOnFilter into the chain.

      > **Collapse: See how to add objects to the canvas.**
      >
      > ![add chain sso](_images/add-chain-sso.gif)

   3. In the Edit SingleSignOnFilter page, click [icon: plus, set=fa], and create an AM service, with the following values:

      * URI: `http://am.example.com:8088/openam`

      * Agent:

        * Username: `ig_agent`

        * Password: `password`

   4. Connect Start to Chain-1, and Chain-1 to ReverseProxyHandler.

      > **Collapse: See how to connect components.**
      >
      > ![connect components](_images/connect-components.gif)

5. On the top-right of the screen, select [icon: ellipsis-v, set=fa]and [icon: share-square, set=fa]Display to review the route.

   ```json
   {
     "name": "sso-ff",
     "baseURI": "http://app.example.com:8081",
     "condition": "${find(request.uri.path, '^/home/sso-ff')}",
     "handler": "Chain-1",
     "heap": [
       {
         "name": "ReverseProxyHandler",
         "type": "ReverseProxyHandler"
       },
       {
         "type": "BaseUriDecorator",
         "name": "baseUri"
       },
       {
         "type": "TimerDecorator",
         "name": "timer",
         "config": {
           "timeUnit": "ms"
         }
       },
       {
         "type": "CaptureDecorator",
         "name": "capture",
         "config": {
           "captureEntity": false,
           "captureContext": false,
           "maxEntityLength": 524288
         }
       },
       {
         "name": "Chain-1",
         "type": "Chain",
         "config": {
           "handler": "ReverseProxyHandler",
           "filters": [
             "SingleSignOnFilter-1"
           ]
         }
       },
       {
         "name": "AmService-1",
         "type": "AmService",
         "config": {
           "url": "http://am.example.com:8088/openam",
           "realm": "/",
           "agent": {
             "username": "ig_agent",
             "password": "password"
           },
           "sessionCache": {
             "enabled": false
           }
         }
       },
       {
         "name": "SingleSignOnFilter-1",
         "type": "SingleSignOnFilter",
         "config": {
           "amService": "AmService-1"
         }
       }
     ]
   }
   ```

6. Select [icon: cloud-upload-alt, set=fa]Deploy to push the route to the IG configuration.

   You can check the `$HOME/.openig/config/routes` folder to see that the route is there.

## Protecting a web app with Freeform Designer

This section describes how to use FreeForm Designer to protect a web app, using AM for single sign-on and policy enforcement.

The generated route contains a chain of objects to authenticate the user, enforce an AM authorization policy, retrieve the user's profile, insert it into the request, and, finally, forward the request to the web app.

Before you start, set up AM as described in [Enforce policy decisions from AM](../gateway-guide/pep.html).

1. In IG Studio, create a route:

   1. Go to <http://ig.example.com:8080/openig/studio>, and select [icon: plus, set=fa]Create a route.

   2. Select ![freeform](_images/freeform.svg) Freeform to use the FreeForm Designer.

2. Select [icon: globe, set=fa]Web SSO to use the template for protecting web apps.

3. Select Advanced options on the right, and create a route with the following options:

   * Base URI : `http://app.example.com:8081`

   * Condition: Path : `/home/pep-sso-ff`

   * Name : `pep-sso-ff`

   * AM Configuration :

     * URI : `http://am.example.com:8088/openam`

     * Username : `ig_agent`

     * Password : `password`

       The route is displayed on the ![freeform](_images/freeform.svg) Flow tab of the canvas. Select the [icon: database, set=fa]All Objects tab to view a list of objects in the route.

       Double-click on any object to review or edit it. After double-clicking on an object, select the Decorations tab to decorate it.

4. On the ![freeform](_images/freeform.svg) Flow tab, double-click the Policy Enforcement object, and add a policy set with the following values:

   * Policy set : `PEP-SSO`

   * AM SSO token : `${contexts.ssoToken.value}`

     Leave all other values as default.

5. On the top-right of the screen, select [icon: ellipsis-v, set=fa]and [icon: share-square, set=fa]Display to review the route.

   ```json
   {
     "name": "pep-sso-ff",
     "baseURI": "http://app.example.com:8081",
     "condition": "${find(request.uri.path, '^/home/pep-sso-ff')}",
     "handler": "Chain",
     "heap": [
       {
         "name": "Chain",
         "type": "Chain",
         "config": {
           "handler": "ReverseProxyHandler",
           "filters": [
             "SSO",
             "PolicyEnforcement",
             "GetEmail",
             "InjectEmail"
           ]
         }
       },
       {
         "name": "SSO",
         "type": "SingleSignOnFilter",
         "config": {
           "amService": "AmService"
         }
       },
       {
         "name": "ReverseProxyHandler",
         "type": "ReverseProxyHandler"
       },
       {
         "name": "AmService",
         "type": "AmService",
         "config": {
           "url": "http://am.example.com:8088/openam",
           "realm": "/",
           "agent": {
             "username": "ig_agent",
             "password": "password"
           },
           "sessionCache": {
             "enabled": false
           }
         }
       },
       {
         "name": "PolicyEnforcement",
         "type": "PolicyEnforcementFilter",
         "config": {
           "amService": "AmService",
           "ssoTokenSubject": "${contexts.ssoToken.value}",
           "cache": {
             "enabled": false
           },
           "application": "PEP-SSO"
         }
       },
       {
         "name": "GetEmail",
         "type": "UserProfileFilter",
         "config": {
           "username": "${contexts.ssoToken.info.uid}",
           "userProfileService": {
             "type": "UserProfileService",
             "config": {
               "amService": "AmService"
             }
           }
         }
       },
       {
         "name": "InjectEmail",
         "type": "HeaderFilter",
         "config": {
           "messageType": "REQUEST",
           "add": {
             "Email": [
               "${contexts.userProfile.username}"
             ]
           }
         }
       },
       {
         "type": "BaseUriDecorator",
         "name": "baseUri"
       },
       {
         "type": "TimerDecorator",
         "name": "timer",
         "config": {
           "timeUnit": "ms"
         }
       },
       {
         "type": "CaptureDecorator",
         "name": "capture",
         "config": {
           "captureEntity": false,
           "captureContext": false,
           "maxEntityLength": 524288
         }
       }
     ]
   }
   ```

6. Select [icon: cloud-upload-alt, set=fa]Deploy to push the route to the IG configuration.

   You can check the `$HOME/.openig/config/routes` folder to see that the route is there.

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/pep-sso-ff>.

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

   AM returns a policy decision that grants access to the sample application.

## Protect an API with Freeform Designer

This section describes how to use FreeForm Designer to protect APIs, using AM as an OAuth 2.0 authorization server.

The generated route contains a chain of objects to authenticate the user, throttle the rate of requests to the API, and, finally, forward the request to the sample app.

Before you start, set up AM as described in [Validate access tokens through the introspection endpoint](../gateway-guide/oauth2-rs.html#oauth2-rs-introspect). In addition, create an OAuth 2.0 Client authorized to introspect tokens, with the following values:

* Client ID : `resource-server`

* Client secret : `password`

* Scope(s) : `am-introspect-all-tokens`

1. In IG Studio, create a route:

   1. Go to <http://ig.example.com:8080/openig/studio>, and select [icon: plus, set=fa]Create a route.

   2. Select ![freeform](_images/freeform.svg) Freeform to use the FreeForm Designer.

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

   * Agent ID : `ig_agent`

   * Password : `password`

   * Token Introspection : `Realm Only`

3. Select Advanced options on the right, and create a route with the following options:

   * Base URI : `http://app.example.com:8081`

   * Condition: Path : `/home/rs-introspect-ff`

   * Name : `rs-introspect-ff`

   * AM Configuration :

     * URI : `http://am.example.com:8088/openam`

     * Username : `ig_agent`

     * Password : `password`

     * Scopes : `mail`, `employeenumber`

       The route is displayed on the ![freeform](_images/freeform.svg) Flow tab of the canvas.

       Notice that the Start, Chain, and ReverseProxyHandler objects are connected by solid lines, but other objects, such as Authenticate to Am Chain, are connected by a fading line. Objects connected by a fading line are used by other objects in the route.

       Select the [icon: database, set=fa]All Objects tab to view a list of objects in the route. Double-click on any object to review or edit it. After double-clicking on an object, select the Decorations tab to decorate it.

4. On the ![freeform](_images/freeform.svg) Flow tab, double-click the OAuth2RS object, and edit it as follows:

   * Require HTTPS : Deselect this option

   * Realm : `OpenIG`

     Leave the other values as they are.

5. On the top-right of the screen, select [icon: ellipsis-v, set=fa]and [icon: share-square, set=fa]Display to review the route.

   ```json
   {
     "name": "rs-introspect-ff",
     "baseURI": "http://app.example.com:8081",
     "condition": "${find(request.uri.path, '^/home/rs-introspect-ff')}",
     "handler": "Chain",
     "properties": {
       "amUsername": "ig_agent",
       "amPassword": "password"
     },
     "heap": [
       {
         "name": "ClientHandler",
         "type": "ClientHandler"
       },
       {
         "name": "Chain",
         "type": "Chain",
         "config": {
           "handler": "ReverseProxyHandler",
           "filters": [
             "OAuth2RS",
             "Throttling"
           ]
         }
       },
       {
         "type": "OAuth2ResourceServerFilter",
         "name": "OAuth2RS",
         "config": {
           "requireHttps": false,
           "realm": "OpenIG",
           "scopes": [
             "mail",
             "employeenumber"
           ],
           "accessTokenResolver": "TokenIntrospectionAccessTokenResolver"
         }
       },
       {
         "type": "TokenIntrospectionAccessTokenResolver",
         "name": "TokenIntrospectionAccessTokenResolver",
         "config": {
           "amService": "AmService",
           "providerHandler": "Authenticate to AM Chain"
         }
       },
       {
         "name": "ReverseProxyHandler",
         "type": "ReverseProxyHandler"
       },
       {
         "name": "AmService",
         "type": "AmService",
         "config": {
           "url": "http://am.example.com:8088/openam",
           "realm": "/",
           "agent": {
             "username": "${amUsername}",
             "password": "${amPassword}"
           },
           "sessionCache": {
             "enabled": false
           }
         }
       },
       {
         "name": "Authenticate to AM Chain",
         "type": "Chain",
         "config": {
           "handler": "ClientHandler",
           "filters": [
             "Authenticate to AM Filter"
           ]
         }
       },
       {
         "name": "Authenticate to AM Filter",
         "type": "HeaderFilter",
         "config": {
           "messageType": "REQUEST",
           "add": {
             "Authorization": [
               "Basic ${encodeBase64(join(array(amUsername, amPassword), ':'))}"
             ]
           }
         }
       },
       {
         "name": "Throttling",
         "type": "ThrottlingFilter",
         "config": {
           "requestGroupPolicy": "${contexts.oauth2.info.sub}",
           "rate": {
             "numberOfRequests": 60,
             "duration": "60 s"
           }
         }
       },
       {
         "type": "BaseUriDecorator",
         "name": "baseUri"
       },
       {
         "type": "TimerDecorator",
         "name": "timer",
         "config": {
           "timeUnit": "ms"
         }
       },
       {
         "type": "CaptureDecorator",
         "name": "capture",
         "config": {
           "captureEntity": false,
           "captureContext": false,
           "maxEntityLength": 524288
         }
       }
     ]
   }
   ```

6. Select [icon: cloud-upload-alt, set=fa]Deploy to push the route to the IG configuration.

   You can check the `$HOME/.openig/config/routes` folder to see that the route is there.

7. Test the setup:

   1. In a terminal window, use a `curl` command similar to the following to retrieve an access token:

      ```bash
      $ mytoken=$(curl -s \
      --user "client-application:password" \
      --data "grant_type=password&username=demo&password=Ch4ng31t&scope=mail%20employeenumber" \
      http://am.example.com:8088/openam/oauth2/access_token | jq -r ".access_token")
      ```

   2. Validate the access token returned in the previous step:

      ```bash
      $ curl -v http://ig.example.com:8080/home/rs-introspect-ff --header "Authorization: Bearer ${mytoken}"
      ```

      The HTML of the sample application is returned.
