automation-1 automation-2 automation-3 automation-4 consultancy-1 consultancy-2 consultancy-3 consultancy-4 facebook google-plus outsourcing-1 outsourcing-2 outsourcing-3 outsourcing-4 power-engineering-1 power-engineering-2 power-engineering-3 power-engineering-4 twitter

Using RestAssured with Tomcat form authentication

Tomcat provides an easy to setup mechanism for authentication using forms. This is very useful for providing authentication for web applications, however, it is not very convenient for testing (or even using) REST interfaces programatically.

The main problem is in the specific handling of session IDs and form parameters, which does not allow easy automation. Form authentication process has the following steps:

  1. Some secured resource is requested from the server. Server returns response code 200 (OK) and sends authentication form and session id that will be used for POSTing to authentication form.

  2. User name and password are posted to the login form url. URL for the login form isj_security_check, while username and password are in the fieldsj_username andj_password. It is required to set session ID from the previous step, otherwise login will not work.On successful posting, server return response 302, redirected. Redirects is to the location originaly requested in step 1.

  3. The same request as in the step 1 is performed. Requested will be executed and proper response returned; however, it is important to note that a new session ID will be returned. This session ID is considered as an “authenticated” session and can be used in all subsequent requests, without need for another login.

In our test, server login is implemented in@BeforeClass method. It is a convenient place, as it will be executed before any other tests.

Request that is made in step 1 is intentionally made on a dummy resource (e.g. non existent one), but on the secured path on the server. That will force server to provide authentication form, but request itself will not need testing – it is expected to fail, which is easy to handle.

Final session ID is set in the RestAssures.sessionId field, which will force RestAssured to use it in all requests.

Below is a simplified code for@BeforeClass method:

@BeforeClass
    public static void setup() {
        String sessionId;

        // Step 1 - try to get non-existent resource within secured path.
        // Status code 200 is returned, with login form and new session id.
        sessionId =
        expect().
            statusCode(200).
            log().all().
        when().
            get("/secured_path/rest").sessionId();

        // Step 2 - post login parameters using session id from previous step.
        expect().
            statusCode(302).
            log().all().
        given().
            param("j_username", USERNAME).
            param("j_password", PASSWORD).
            cookie("JSESSIONID", sessionId).
        post("j_security_check");

        // Step 3 - repeat request from step one. It will return "authenticated" session id.
        // As we are using non-existent resource, server will return status code 404.
        sessionId =
        expect().
            statusCode(404).
            log().all().
        given().
            cookie("JSESSIONID", sessionId).
        when().
        get().sessionId();
        
        // Set this session id as the final one, all subsequent request will use it.
        RestAssured.sessionId = sessionId;
    }

Although RestAssured has .form() method for form authentication, it seems that it does not respect session id management the way tomcat is expecting. I haven’t managed it to work and according to data collected with WireShark, it seems that RestAssured tries first to post form data, then to access resource. This is not as Tomcat expects, I guess it is meant only for simple login forms, which do not exchange session ids.

However, there are some drawbacks for the method described above. What I wasn’t able to manage is to run tests in parallel - if all tests from the package are executed simultaneously (in Eclipse - right click on package name, run as JUnit test), most of the tests will fail. I guess this is because authenticated session id is kept as static field within RestAssured class - but I haven’t test it for real. Running tests file by file is ok - tests are executed correctly.

Share this article additional message.