IG 7.1.2

Configuration Templates

This chapter contains template routes for common configurations. To use a template, set up IG as described in the Getting Started, and modify the template for your deployment. Before you use a route in production, review the points in Security Guide.

Proxy and Capture

If you installed and configured IG with a router and default route as described in the Getting Started, then you already proxy and capture the application requests coming in and the server responses going out.

This template route uses a DispatchHandler to change the scheme to HTTPS on login:

{
  "heap": [
    {
      "name": "ReverseProxyHandler",
      "type": "ReverseProxyHandler",
      "comment": "Testing only: blindly trust the server cert for HTTPS.",
      "config": {
        "tls": {
          "type": "ClientTlsOptions",
          "config": {
            "trustManager": {
              "type": "TrustAllManager"
            }
          }
        },
        "hostnameVerifier": "ALLOW_ALL"
      }
    }
  ],
  "handler": {
    "type": "DispatchHandler",
    "config": {
      "bindings": [
        {
          "condition": "${request.uri.path == '/login'}",
          "handler": "ReverseProxyHandler",
          "baseURI": "https://app.example.com:8444"
        },
        {
          "condition": "${request.uri.scheme == 'http'}",
          "handler": "ReverseProxyHandler",
          "baseURI": "http://app.example.com:8081"
        },
        {
          "handler": "ReverseProxyHandler",
          "baseURI": "https://app.example.com:8444"
        }
      ]
    }
  },
  "condition": "${find(request.uri.query, 'demo=capture')}"
}

To try this example with the sample application:

  1. Add the following route to IG:

    • Linux

    • Windows

    $HOME/.openig/config/routes/20-capture.json
    appdata\OpenIG\config\routes\20-capture.json
  2. Add the following route to serve static resources, such as .css, for the sample application:

    • Linux

    • Windows

    $HOME/.openig/config/routes/static-resources.json
    appdata\OpenIG\config\routes\static-resources.json
    {
      "name" : "sampleapp-resources",
      "baseURI" : "http://app.example.com:8081",
      "condition": "${find(request.uri.path,'^/css')}",
      "handler": "ReverseProxyHandler"
    }
  3. Go to http://openig.example.com:8080/login?demo=capture.

    The login page of the sample application is displayed.

To use this as a default route with a real application:

  1. Replace the test ReverseProxyHandler with one that is configured to trust the application’s public key server certificate. Otherwise, use a ReverseProxyHandler that references a truststore holding the certificate.

    Configure the ReverseProxyHandler to strictly verifiy hostnames for outgoing SSL connections.

    In production, do not use TrustAllManager for TrustManager, or ALLOW_ALL for hostname verification. For information, see ReverseProxyHandler.

  2. Change the baseURI settings to match the target application.

  3. Remove the route-level condition on the handler that specifies a demo query string parameter.

Simple Login Form

This template route intercepts the login page request, replaces it with a login form, and logs the user into the target application with hard-coded username and password:

{
  "heap": [
    {
      "name": "ReverseProxyHandler",
      "type": "ReverseProxyHandler",
      "comment": "Testing only: blindly trust the server cert for HTTPS.",
      "config": {
        "tls": {
          "type": "ClientTlsOptions",
          "config": {
            "trustManager": {
              "type": "TrustAllManager"
            }
          }
        },
        "hostnameVerifier": "ALLOW_ALL"
      }
    }
  ],
  "handler": {
    "type": "Chain",
    "config": {
      "filters": [
        {
          "type": "PasswordReplayFilter",
          "config": {
            "loginPage": "${request.uri.path == '/login'}",
            "request": {
              "method": "POST",
              "uri": "https://app.example.com:8444/login",
              "form": {
                "username": [
                  "MY_USERNAME"
                ],
                "password": [
                  "MY_PASSWORD"
                ]
              }
            }
          }
        }
      ],
      "handler": "ReverseProxyHandler"
    }
  },
  "condition": "${find(request.uri.query, 'demo=simple')}"
}

To try this example with the sample application:

  1. Add the following route to IG:

    • Linux

    • Windows

    $HOME/.openig/config/routes/21-simple.json
    appdata\OpenIG\config\routes\21-simple.json
  2. Replace MY_USERNAME with demo, and MY_PASSWORD with Ch4ng31t.

  3. Add the following route to serve static resources, such as .css, for the sample application:

    • Linux

    • Windows

    $HOME/.openig/config/routes/static-resources.json
    appdata\OpenIG\config\routes\static-resources.json
    {
      "name" : "sampleapp-resources",
      "baseURI" : "http://app.example.com:8081",
      "condition": "${find(request.uri.path,'^/css')}",
      "handler": "ReverseProxyHandler"
    }
  4. Go to http://openig.example.com:8080/login?demo=simple.

    The sample application profile page for the demo user displays the following information about the request:

    Method	POST
    URI	/login
    Cookies
    Headers	content-type: application/x-www-form-urlencoded
    content-length: 31
    host: app.example.com:8444
    connection: Keep-Alive
    user-agent: Apache-HttpAsyncClient/4.1.2 (Java/1.8.0_144)

To use this as a default route with a real application:

  1. Replace the test ReverseProxyHandler with one that is configured to trust the application’s public key server certificate. Otherwise, use a ReverseProxyHandler that references a truststore holding the certificate.

    Configure the ReverseProxyHandler to strictly verifiy hostnames for outgoing SSL connections.

    In production, do not use TrustAllManager for TrustManager, or ALLOW_ALL for hostname verification. For information, see ReverseProxyHandler.

  2. Change the uri, form, and baseURI to match the target application.

  3. Remove the route-level condition on the handler that specifies a demo query string parameter.

Like the previous route, this template route intercepts the login page request, replaces it with the login form, and logs the user into the target application with hard-coded username and password. This route also adds a CookieFilter to manage cookies.

The route uses a default CookieFilter to manage cookies. In this default configuration, cookies from the protected application are intercepted and stored in the IG session. They are not sent to the browser. For information, see CookieFilter.

{
  "heap": [
    {
      "name": "ReverseProxyHandler",
      "type": "ReverseProxyHandler",
      "comment": "Testing only: blindly trust the server cert for HTTPS.",
      "config": {
        "tls": {
          "type": "ClientTlsOptions",
          "config": {
            "trustManager": {
              "type": "TrustAllManager"
            }
          }
        },
        "hostnameVerifier": "ALLOW_ALL"
      }
    }
  ],
  "handler": {
    "type": "Chain",
    "config": {
      "filters": [
        {
          "type": "PasswordReplayFilter",
          "config": {
            "loginPage": "${request.uri.path == '/login'}",
            "request": {
              "method": "POST",
              "uri": "https://app.example.com:8444/login",
              "form": {
                "username": [
                  "MY_USERNAME"
                ],
                "password": [
                  "MY_PASSWORD"
                ]
              }
            }
          }
        },
        {
          "type": "CookieFilter"
        }
      ],
      "handler": "ReverseProxyHandler"
    }
  },
  "condition": "${find(request.uri.query, 'demo=cookie')}"
}

To try this example with the sample application:

  1. Add the following route to IG:

    • Linux

    • Windows

    $HOME/.openig/config/routes/22-cookie.json
    appdata\OpenIG\config\routes\22-cookie.json
  2. Replace MY_USERNAME with kramer, and MY_PASSWORD with N3wman12.

  3. Add the following route to serve static resources, such as .css, for the sample application:

    • Linux

    • Windows

    $HOME/.openig/config/routes/static-resources.json
    appdata\OpenIG\config\routes\static-resources.json
    {
      "name" : "sampleapp-resources",
      "baseURI" : "http://app.example.com:8081",
      "condition": "${find(request.uri.path,'^/css')}",
      "handler": "ReverseProxyHandler"
    }
  4. Go to http://openig.example.com:8080/login?demo=cookie.

    The sample application page is displayed.

    Method 	  POST
    URI 	  /login
    Cookies
    Headers  content-type: application/x-www-form-urlencoded
             content-length: 31
             host: app.example.com:8444
             connection: Keep-Alive
             user-agent: Apache-HttpAsyncClient/…​ (Java/…​)
  5. Refresh your connection to http://openig.example.com:8080/login?demo=cookie.

    Compared to the example in Login Form With Cookie From Login Page, this example displays additional information about the session cookie:

    Cookies  session-cookie=123…​

To use this as a default route with a real application:

  1. Replace the test ReverseProxyHandler with one that is configured to trust the application’s public key server certificate. Otherwise, use a ReverseProxyHandler that references a truststore holding the certificate.

    Configure the ReverseProxyHandler to strictly verifiy hostnames for outgoing SSL connections.

    In production, do not use TrustAllManager for TrustManager, or ALLOW_ALL for hostname verification. For information, see ReverseProxyHandler.

  2. Change the uri and form to match the target application.

  3. Remove the route-level condition on the handler that specifies a demo query string parameter.

When a user without a valid session tries to access a protected application, this template route works with an application to return a login page.

The route uses a PasswordReplayFilter to find the login page by using a pattern that matches a mock AM Classic UI page.

Cookies sent by the user-agent are retained in the CookieFilter, and not forwarded to the protected application. Similarly, set-cookies sent by the protected application are retained in the CookieFilter and not forwarded back to the user-agent.

The route uses a default CookieFilter to manage cookies. In this default configuration, cookies from the protected application are intercepted and stored in the IG session. They are not sent to the browser. For information, see CookieFilter.

{
  "handler": {
    "type": "Chain",
    "config": {
      "filters": [
        {
          "type": "PasswordReplayFilter",
          "config": {
            "loginPageContentMarker": "OpenAM\\s\\(Login\\)",
            "request": {
              "comments": [
                "An example based on OpenAM classic UI: ",
                "uri is for the OpenAM login page; ",
                "IDToken1 is the username field; ",
                "IDToken2 is the password field; ",
                "host takes the OpenAM FQDN:port.",
                "The sample app simulates OpenAM."
              ],
              "method": "POST",
              "uri": "http://app.example.com:8081/openam/UI/Login",
              "form": {
                "IDToken0": [
                  ""
                ],
                "IDToken1": [
                  "demo"
                ],
                "IDToken2": [
                  "Ch4ng31t"
                ],
                "IDButton": [
                  "Log+In"
                ],
                "encoded": [
                  "false"
                ]
              },
              "headers": {
                "host": [
                  "app.example.com:8081"
                ]
              }
            }
          }
        },
        {
          "type": "CookieFilter"
        }
      ],
      "handler": "ReverseProxyHandler"
    }
  },
  "condition": "${find(request.uri.query, 'demo=classic')}"
}

To try this example with the sample application:

  1. Save the file as $HOME/.openig/config/routes/23-classic.json.

  2. Use the following curl command to check that it works:

    $ curl -D- http://openig.example.com:8080/login?demo=classic
    
    HTTP/1.1 200 OK
    Set-Cookie: IG_SESSIONID=24446BA29E866F840197C8E0EAD57A89; Path=/; HttpOnly
    ...

To use this as a default route with a real application:

  1. Change the uri and form to match the target application.

  2. Remove the route-level condition on the handler that specifies a demo query string parameter.

Login Which Requires a Hidden Value From the Login Page

This template route extracts a hidden value from the login page, and includes it the static login form that it then POSTs to the target application.

{
  "properties": {
    "appBaseUri":  "https://app.example.com:8444"
  },
  "heap": [
    {
      "name": "ReverseProxyHandler",
      "type": "ReverseProxyHandler",
      "comment": "Testing only: blindly trust the server cert for HTTPS.",
      "config": {
        "tls": {
          "type": "ClientTlsOptions",
          "config": {
            "trustManager": {
              "type": "TrustAllManager"
            }
          }
        },
        "hostnameVerifier": "ALLOW_ALL"
      }
    }
  ],
  "handler": {
    "type": "Chain",
    "config": {
      "filters": [
        {
          "type": "PasswordReplayFilter",
          "config": {
            "loginPage": "${request.uri.path == '/login'}",
            "loginPageExtractions": [
              {
                "name": "hidden",
                "pattern": "loginToken\\s+value=\"(.*)\""
              }
            ],
            "request": {
              "method": "POST",
              "uri": "${appBaseUri}/login",
              "form": {
                "username": [
                  "MY_USERNAME"
                ],
                "password": [
                  "MY_PASSWORD"
                ],
                "hiddenValue": [
                  "${attributes.extracted.hidden}"
                ]
              }
            }
          }
        }
      ],
      "handler": "ReverseProxyHandler"
    }
  },
  "condition": "${find(request.uri.query, 'demo=hidden')}",
  "baseURI": "${appBaseUri}"
}

The parameters in the PasswordReplayFilter form, MY_USERNAME and MY_PASSWORD, can have string values or can use expressions.

To try this example with the sample application:

  1. Add the following route to IG:

    • Linux

    • Windows

    $HOME/.openig/config/routes/24-hidden.json
    appdata\OpenIG\config\routes\24-hidden.json
  2. Replace MY_USERNAME with scarter, and MY_PASSWORD with S9rain12.

  3. Add the following route to serve static resources, such as .css, for the sample application:

    • Linux

    • Windows

    $HOME/.openig/config/routes/static-resources.json
    appdata\OpenIG\config\routes\static-resources.json
    {
      "name" : "sampleapp-resources",
      "baseURI" : "http://app.example.com:8081",
      "condition": "${find(request.uri.path,'^/css')}",
      "handler": "ReverseProxyHandler"
    }
  4. Go to http://openig.example.com:8080/login?demo=hidden.

To use this as a default route with a real application:

  1. Replace the test ReverseProxyHandler with one that is configured to trust the application’s public key server certificate. Otherwise, use a ReverseProxyHandler that references a truststore holding the certificate.

    Configure the ReverseProxyHandler to strictly verifiy hostnames for outgoing SSL connections.

    In production, do not use TrustAllManager for TrustManager, or ALLOW_ALL for hostname verification. For information, see ReverseProxyHandler.

  2. Change the loginPage, loginPageExtractions, uri, and form to match the target application.

  3. Remove the route-level condition on the handler that specifies a demo query string parameter.

HTTP and HTTPS Application

This template route proxies traffic to an application with both HTTP and HTTPS ports. The application uses HTTPS for authentication and HTTP for the general application features. Assuming that all login requests are made over HTTPS, you must add the login filters and handlers to the chain.

{
  "heap": [
    {
      "name": "ReverseProxyHandler",
      "type": "ReverseProxyHandler",
      "comment": "Testing only: blindly trust the server cert for HTTPS.",
      "config": {
        "tls": {
          "type": "ClientTlsOptions",
          "config": {
            "trustManager": {
              "type": "TrustAllManager"
            }
          }
        },
        "hostnameVerifier": "ALLOW_ALL"
      }
    }
  ],
  "handler": {
    "type": "DispatchHandler",
    "config": {
      "bindings": [
        {
          "condition": "${request.uri.scheme == 'http'}",
          "handler": "ReverseProxyHandler",
          "baseURI": "http://app.example.com:8081"
        },
        {
          "condition": "${request.uri.path == '/login'}",
          "handler": {
            "type": "Chain",
            "config": {
              "comment": "Add one or more filters to handle login.",
              "filters": [],
              "handler": "ReverseProxyHandler"
            }
          },
          "baseURI": "https://app.example.com:8444"
        },
        {
          "handler": "ReverseProxyHandler",
          "baseURI": "https://app.example.com:8444"
        }
      ]
    }
  },
  "condition": "${find(request.uri.query, 'demo=https')}"
}

To try this example with the sample application:

  1. Add the following route to IG:

    • Linux

    • Windows

    $HOME/.openig/config/routes/25-https.json
    appdata\OpenIG\config\routes\25-https.json
  2. Add the following route to serve static resources, such as .css, for the sample application:

    • Linux

    • Windows

    $HOME/.openig/config/routes/static-resources.json
    appdata\OpenIG\config\routes\static-resources.json
    {
      "name" : "sampleapp-resources",
      "baseURI" : "http://app.example.com:8081",
      "condition": "${find(request.uri.path,'^/css')}",
      "handler": "ReverseProxyHandler"
    }
  3. Go to http://openig.example.com:8080/login?demo=https.

    The login page of the sample application is displayed.

To use this as a default route with a real application: :leveloffset: +2

  1. Replace the test ReverseProxyHandler with one that is configured to trust the application’s public key server certificate. Otherwise, use a ReverseProxyHandler that references a truststore holding the certificate.

    Configure the ReverseProxyHandler to strictly verifiy hostnames for outgoing SSL connections.

    In production, do not use TrustAllManager for TrustManager, or ALLOW_ALL for hostname verification. For information, see ReverseProxyHandler.

  1. Change the loginPage, loginPageExtractions, uri, and form to match the target application.

  2. Remove the route-level condition on the handler that specifies a demo query string parameter.

AM Integration With Headers

This template route logs the user into the target application by using headers such as those passed in from an AM policy agent. If the passed in header contains only a user name or subject and requires a lookup to an external data source, you must add an attribute filter to the chain to retrieve the credentials.

{
  "heap": [
    {
      "name": "ReverseProxyHandler",
      "type": "ReverseProxyHandler",
      "comment": "Testing only: blindly trust the server cert for HTTPS.",
      "config": {
        "tls": {
          "type": "ClientTlsOptions",
          "config": {
            "trustManager": {
              "type": "TrustAllManager"
            }
          }
        },
        "hostnameVerifier": "ALLOW_ALL"
      }
    }
  ],
  "handler": {
    "type": "Chain",
    "config": {
      "filters": [
        {
          "type": "PasswordReplayFilter",
          "config": {
            "loginPage": "${request.uri.path == '/login'}",
            "request": {
              "method": "POST",
              "uri": "https://app.example.com:8444/login",
              "form": {
                "username": [
                  "${request.headers['username'][0]}"
                ],
                "password": [
                  "${request.headers['password'][0]}"
                ]
              }
            }
          }
        }
      ],
      "handler": "ReverseProxyHandler"
    }
  },
  "condition": "${find(request.uri.query, 'demo=headers')}"
}

To try this example with the sample application:

  1. Add the route to IG:

    • Linux

    • Windows

    $HOME/.openig/config/routes/26-headers.json
    appdata\OpenIG\config\routes\26-headers.json
  2. Use the curl command to simulate the headers being passed in from an AM policy agent, as in the following example:

    $ curl \
    --header "username: kvaughan" \
    --header "password: B5ibery12" \
    http://openig.example.com:8080/login?demo=headers
    
    ...
    <title id="welcome">Howdy, kvaughan</title>
    ...

To use this as a default route with a real application:

  1. Replace the test ReverseProxyHandler with one that is configured to trust the application’s public key server certificate. Otherwise, use a ReverseProxyHandler that references a truststore holding the certificate.

    Configure the ReverseProxyHandler to strictly verifiy hostnames for outgoing SSL connections.

    In production, do not use TrustAllManager for TrustManager, or ALLOW_ALL for hostname verification. For information, see ReverseProxyHandler.

  2. Change the loginPage, uri, and form to match the target application.

  3. Remove the route-level condition on the handler that specifies a demo query string parameter.

Copyright © 2010-2023 ForgeRock, all rights reserved.