Getting Login Credentials From Data Sources

In Getting Started you learned how to configure OpenIG to proxy traffic and capture request and response data. You also learned how to configure OpenIG to use a static request to log in with hard-coded credentials. In this chapter, you will learn to:

  • Configure OpenIG to look up credentials in a file

  • Configure OpenIG to look up credentials in a relational database

Before You Start

Before you start this tutorial, prepare OpenIG and the minimal HTTP server as shown in Getting Started.

OpenIG should be running in Jetty, configured to access the minimal HTTP server as described in that chapter.

Log in With Credentials From a File

This sample shows you how to configure OpenIG to get credentials from a file.

The sample uses a comma-separated value file, userfile:

username,password,fullname,email
george,costanza,George Costanza,george@example.com
kramer,newman,Kramer,kramer@example.com
bjensen,hifalutin,Babs Jensen,bjensen@example.com
demo,changeit,Demo User,demo@example.com
kvaughan,bribery,Kirsten Vaughan,kvaughan@example.com
scarter,sprain,Sam Carter,scarter@example.com

OpenIG looks up the user credentials based on the user’s email address. OpenIG uses a FileAttributesFilter to look up the credentials. Follow these steps to set up log in with credentials from a file:

  1. Add the user file on your system:

    $ vi /tmp/userfile
    $ cat /tmp/userfile
    username,password,fullname,email
    george,costanza,George Costanza,george@example.com
    kramer,newman,Kramer,kramer@example.com
    bjensen,hifalutin,Babs Jensen,bjensen@example.com
    demo,changeit,Demo User,demo@example.com
    kvaughan,bribery,Kirsten Vaughan,kvaughan@example.com
    scarter,sprain,Sam Carter,scarter@example.com

    On Windows systems, use an appropriate path such as C:\Temp\userfile.

  2. Add a new route to the OpenIG configuration to obtain the credentials from the file.

    To add the route, add the following route configuration file as $HOME/.openig/config/routes/02-file.json:

    {
      "handler": {
        "type": "Chain",
        "config": {
          "filters": [
            {
              "type": "PasswordReplayFilter",
              "config": {
                "loginPage": "${true}",
                "credentials": {
                  "type": "FileAttributesFilter",
                  "config": {
                    "file": "/tmp/userfile",
                    "key": "email",
                    "value": "george@example.com",
                    "target": "${attributes.credentials}"
                  }
                },
                "request": {
                  "method": "POST",
                  "uri": "http://app.example.com:8081",
                  "form": {
                    "username": [
                      "${attributes.credentials.username}"
                    ],
                    "password": [
                      "${attributes.credentials.password}"
                    ]
                  }
                }
              }
            }
          ],
          "handler": "ClientHandler"
        }
      },
      "condition": "${matches(request.uri.path, '^/file')}"
    }

    On Windows, the file name should be %appdata%\OpenIG\config\routes\02-file.json.

    Notice the following features of the new route:

    • The FileAttributesFilter specifies the file to access, the key and value to look up to retrieve the user’s record, and where to store the results in the request context attributes map.

    • The PasswordReplayFilter creates a request by retrieving the username and password from the attributes map and replacing your browser’s original HTTP GET request with an HTTP POST login request that contains the credentials to authenticate.

    • The route matches requests to /file.

  3. On Windows systems, edit the path name to the user file.

If everything is configured correctly, OpenIG logs you in as George.

What’s happening behind the scenes?

login from file

OpenIG intercepts your browser’s HTTP GET request. The request matches the new route configuration. The PasswordReplayFilter’s `FileAttributesFilter looks up credentials in a file, and stores the credentials it finds in the request context attributes map. The `PasswordReplayFilter’s request pulls the credentials out of the attributes map, builds the login form, and performs the HTTP POST request to the HTTP server. The HTTP server validates the credentials, and responds with a profile page. OpenIG then passes the response from the HTTP server to your browser.

Log in With Credentials From a Database

This sample shows you how to configure OpenIG to get credentials from H2. This sample was developed with Jetty and with H2 1.4.178.

Although this sample uses H2, OpenIG also works with other database software. OpenIG relies on the application server where it runs to connect to the database. Configuring OpenIG to retrieve data from a database is therefore a question of configuring the application server to connect to the database, and configuring OpenIG to choose the appropriate data source, and to send the appropriate SQL request to the database. As a result, the OpenIG configuration depends more on the data structure than on any particular database drivers or connection configuration.

Preparing the Database

Follow these steps to prepare the database:

  1. On the system where OpenIG runs, download and unpack H2 database.

  2. Start H2:

    $ sh /path/to/h2/bin/h2.sh

    H2 starts, listening on port 8082, and opens a browser console page.

  3. In the browser console page, select Generic H2 (Server) under Saved Settings. This sets the Driver Class, org.h2.Driver, the JDBC URL, jdbc:h2:tcp://localhost/~/test, the User Name, sa.

    In the Password field, type password.

    Then click Connect to access the console.

  4. Run a statement to create a users table based on the user file from Log in With Credentials From a File.

    If you have not created the user file on your system, put the following content in /tmp/userfile:

    username,password,fullname,email
    george,costanza,George Costanza,george@example.com
    kramer,newman,Kramer,kramer@example.com
    bjensen,hifalutin,Babs Jensen,bjensen@example.com
    demo,changeit,Demo User,demo@example.com
    kvaughan,bribery,Kirsten Vaughan,kvaughan@example.com
    scarter,sprain,Sam Carter,scarter@example.com

    Then create the users table through the H2 console:

    DROP TABLE IF EXISTS USERS;
    CREATE TABLE USERS AS SELECT * FROM CSVREAD('/tmp/userfile');

    On success, the table should contain the same users as the file. You can check this by running SELECT * FROM users; in the H2 console.

Preparing Jetty’s Connection to the Database

Follow these steps to enable Jetty to connect to the database:

  1. Configure Jetty for JNDI.

    For the version of Jetty used in this sample, stop Jetty and add the following lines to /path/to/jetty/start.ini:

    # ===========================================================
    # Enable JNDI
    # -----------------------------------------------------------
    OPTIONS=jndi
    
    # ===========================================================
    # Enable additional webapp environment configurators
    # -----------------------------------------------------------
    OPTIONS=plus
    etc/jetty-plus.xml

    For more information, see the Jetty documentation on Configuring JNDI.

  2. Copy the H2 library to the classpath for Jetty:

    $ cp /path/to/h2/bin/h2-*.jar /path/to/jetty/lib/ext/
  3. Define a JNDI resource for H2 in /path/to/jetty/etc/jetty.xml:

    <New id="jdbc/forgerock" class="org.eclipse.jetty.plus.jndi.Resource">
      <Arg></Arg>
      <Arg>jdbc/forgerock</Arg>
      <Arg>
        <New class="org.h2.jdbcx.JdbcDataSource">
          <Set name="Url">jdbc:h2:tcp://localhost/~/test</Set>
          <Set name="User">sa</Set>
          <Set name="Password">password</Set>
        </New>
      </Arg>
    </New>
  4. Add a resource reference to the data source in /path/to/jetty/etc/webdefault.xml:

    <resource-ref>
        <res-ref-name>jdbc/forgerock</res-ref-name>
        <res-type>javax.sql.DataSource</res-type>
        <res-auth>Container</res-auth>
    </resource-ref>
  5. Restart Jetty to take the configuration changes into account.

Preparing the OpenIG Configuration

Add a new route to the OpenIG configuration to look up credentials in the database:

  1. To add the route, add the following route configuration file as $HOME/.openig/config/routes/03-sql.json:

    {
      "handler": {
        "type": "Chain",
        "config": {
          "filters": [
            {
              "type": "PasswordReplayFilter",
              "config": {
                "loginPage": "${true}",
                "credentials": {
                  "type": "SqlAttributesFilter",
                  "config": {
                    "dataSource": "java:comp/env/jdbc/forgerock",
                    "preparedStatement":
                    "SELECT username, password FROM users WHERE email = ?;",
                    "parameters": [
                      "george@example.com"
                    ],
                    "target": "${attributes.sql}"
                  }
                },
                "request": {
                  "method": "POST",
                  "uri": "http://app.example.com:8081",
                  "form": {
                    "username": [
                      "${attributes.sql.USERNAME}"
                    ],
                    "password": [
                      "${attributes.sql.PASSWORD}"
                    ]
                  }
                }
              }
            }
          ],
          "handler": "ClientHandler"
        }
      },
      "condition": "${matches(request.uri.path, '^/sql')}"
    }

    On Windows, the file name should be %appdata%\OpenIG\config\routes\03-sql.json.

  2. Notice the following features of the new route:

    • The SqlAttributesFilter specifies the data source to access, a prepared statement to look up the user’s record, a parameter to pass into the statement, and where to store the search results in the request context attributes map.

    • The `PasswordReplayFilter’s request retrieves the username and password from the attributes map and replaces your browser’s original HTTP GET request with an HTTP POST login request that contains the credentials to authenticate.

      Notice that the request is for username, password, and that H2 returns the fields as USERNAME and PASSWORD. The configuration reflects this difference.

    • The route matches requests to /sql.

To Try Logging in With Credentials From a Database

With H2, Jetty, and OpenIG correctly configured, you can try it out:

What’s happening behind the scenes?

login from sql

OpenIG intercepts your browser’s HTTP GET request. The request matches the new route configuration. The PasswordReplayFilter’s `SqlAttributesFilter looks up credentials in H2, and stores the credentials it finds in the request context attributes map. The `PasswordReplayFilter’s request pulls the credentials out of the attributes map, builds the login form, and performs the HTTP POST request to the HTTP server. The HTTP server validates the credentials, and responds with a profile page. OpenIG then passes the response from the HTTP server to your browser.