Digest and Form Authentication

Introduction

In our REST Assured series, we’ve explored topics like Basic Authentication, GPath Expressions, and JSON Path Testing, building a robust foundation for API testing. Now, we’ll dive into Digest Authentication and Form Authentication, two essential mechanisms for securing APIs and web applications. This guide demonstrates how to implement these authentication types in REST Assured, with clear examples and best practices. It’s designed for beginners and experienced developers, ensuring you can confidently test secured endpoints.

Key Point: Digest Authentication provides a more secure alternative to Basic Authentication for APIs, while Form Authentication enables testing of web application login forms using REST Assured’s HTTP capabilities.

What are Digest and Form Authentication?

Let’s briefly define each authentication type:

REST Assured simplifies Digest Authentication with auth().digest() and supports Form Authentication by sending POST requests with form parameters. We’ll use https://httpbin.org/digest-auth/auth/user/passwd for Digest Authentication examples, which simulates authentication with the credentials user:passwd. For Form Authentication, we’ll simulate a login form submission to a mock endpoint, as public APIs rarely use form-based auth.

Setting Up for Authentication Testing

To test Digest and Form Authentication, we’ll set up a Maven project with REST Assured, JUnit, and Allure for reporting, consistent with previous posts. No additional dependencies are needed for Digest Authentication, but Form Authentication may require handling cookies, which REST Assured supports natively.

Here’s the pom.xml, styled with your preferred Blogger format for XML syntax highlighting:


<project xmlns="http://maven.apache.org/POM/4.0.0">
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>com.example</groupId>
    <artifactId>rest-assured-tests</artifactId>
    <version>1.0-SNAPSHOT</version>

    <properties>
        <java.version>11</java.version>
        <allure.version>2.27.0</allure.version>
        <aspectj.version>1.9.22</aspectj.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>io.rest-assured</groupId>
            <artifactId>rest-assured</artifactId>
            <version>5.4.0</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.junit.jupiter</groupId>
            <artifactId>junit-jupiter</artifactId>
            <version>5.10.2</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.hamcrest</groupId>
            <artifactId>hamcrest</artifactId>
            <version>2.2</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-databind</artifactId>
            <version>2.15.2</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>io.qameta.allure</groupId>
            <artifactId>allure-junit5</artifactId>
            <version>${allure.version}</version>
            <scope>test</scope>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-surefire-plugin</artifactId>
                <version>3.2.5</version>
                <configuration>
                    <argLine>
                        -javaagent:"${settings.localRepository}/org/aspectj/aspectjweaver/${aspectj.version}/aspectjweaver-${aspectj.version}.jar"</argLine>
                </configuration>
                <dependencies>
                    <dependency>
                        <groupId>org.aspectj</groupId>
                        <artifactId>aspectjweaver</artifactId>
                        <version>${aspectj.version}</version>
                    </dependency>
                </dependencies>
            </plugin>
            <plugin>
                <groupId>io.qameta.allure</groupId>
                <artifactId>allure-maven</artifactId>
                <version>2.12.0</version>
                <configuration>
                    <reportVersion>${allure.version}</reportVersion>
                </configuration>
            </plugin>
        </plugins>
    </build>
</project>

No additional setup is required for https://httpbin.org for Digest Authentication. For Form Authentication, we’ll simulate a login form submission to a mock endpoint, as real public APIs with form-based auth are uncommon.

Implementing Digest Authentication

Let’s explore how to implement and test Digest Authentication using REST Assured.

Example 1: Digest Authentication with Valid Credentials

Test an API endpoint using valid Digest Authentication credentials.


import io.qameta.allure.Description;
import io.qameta.allure.Feature;
import io.restassured.RestAssured;
import org.junit.jupiter.api.Test;
import static io.restassured.RestAssured.*;
import static org.hamcrest.Matchers.*;

@Feature("Digest Authentication Testing")
public class DigestAuthValidTest {

    @Test
    @Description("Test Digest Authentication with valid credentials")
    public void testValidDigestAuth() {
        RestAssured.baseURI = "https://httpbin.org";

        given()
            .auth().digest("user", "passwd")
            .log().all()
        .when()
            .get("/digest-auth/auth/user/passwd")
        .then()
            .statusCode(200)
            .body("authenticated", equalTo(true))
            .body("user", equalTo("user"));
    }
}

Explanation:

Important: Digest Authentication requires the server to send a nonce in a 401 challenge response, which REST Assured handles automatically.

Example 2: Digest Authentication with Invalid Credentials

Test an API endpoint with invalid credentials to verify error handling.


import io.qameta.allure.Description;
import io.qameta.allure.Feature;
import io.restassured.RestAssured;
import org.junit.jupiter.api.Test;
import static io.restassured.RestAssured.*;
import static org.hamcrest.Matchers.*;

@Feature("Digest Authentication Testing")
public class DigestAuthInvalidTest {

    @Test
    @Description("Test Digest Authentication with invalid credentials")
    public void testInvalidDigestAuth() {
        RestAssured.baseURI = "https://httpbin.org";

        given()
            .auth().digest("wronguser", "wrongpass")
            .log().ifValidationFails()
        .when()
            .get("/digest-auth/auth/user/passwd")
        .then()
            .statusCode(401);
    }
}

Explanation:

Implementing Form Authentication

Form Authentication involves submitting credentials via a POST request to a login endpoint, typically receiving a session cookie for subsequent requests. We’ll simulate a login form submission to a mock endpoint.

Assume a login form with the following HTML structure:

We’ll simulate submitting this form to a mock endpoint that expects username=user and password=pass as form parameters.

Example 3: Form Authentication with Valid Credentials

Test a form-based login and verify the session cookie for subsequent requests.


import io.qameta.allure.Description;
import io.qameta.allure.Feature;
import io.restassured.RestAssured;
import io.restassured.response.Response;
import org.junit.jupiter.api.Test;
import static io.restassured.RestAssured.*;
import static org.hamcrest.Matchers.*;

@Feature("Form Authentication Testing")
public class FormAuthValidTest {

    @Test
    @Description("Test Form Authentication with valid credentials")
    public void testValidFormAuth() {
        RestAssured.baseURI = "https://httpbin.org";

        // Simulate form submission
        Response loginResponse = given()
            .formParam("username", "user")
            .formParam("password", "pass")
            .contentType("application/x-www-form-urlencoded")
            .log().all()
        .when()
            .post("/post") // Using /post to echo form data
        .then()
            .statusCode(200)
            .body("form.username", equalTo("user"))
            .body("form.password", equalTo("pass"))
            .extract().response();

        // Simulate using session cookie (mock example)
        String sessionCookie = loginResponse.cookie("session"); // Mock cookie
        given()
            .cookie("session", sessionCookie != null ? sessionCookie : "mock-session")
            .log().all()
        .when()
            .get("/get")
        .then()
            .statusCode(200);
    }
}

Explanation:

Pro Tip: For Form Authentication, extract and reuse session cookies to maintain authenticated sessions across multiple requests.

Example 4: Form Authentication with Response Specification

Combine Form Authentication with a ResponseSpecification for reusable validation.


import io.qameta.allure.Description;
import io.qameta.allure.Feature;
import io.restassured.RestAssured;
import io.restassured.builder.ResponseSpecBuilder;
import io.restassured.specification.ResponseSpecification;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import static io.restassured.RestAssured.*;
import static org.hamcrest.Matchers.*;

@Feature("Form Authentication Testing")
public class FormAuthWithSpecTest {

    private ResponseSpecification formSuccessSpec;

    @BeforeEach
    public void setup() {
        formSuccessSpec = new ResponseSpecBuilder()
            .expectStatusCode(200)
            .expectContentType("application/json")
            .expectBody("form.username", equalTo("user"))
            .build();
    }

    @Test
    @Description("Test Form Authentication with Response Specification")
    public void testFormAuthWithSpec() {
        RestAssured.baseURI = "https://httpbin.org";

        given()
            .formParam("username", "user")
            .formParam("password", "pass")
            .contentType("application/x-www-form-urlencoded")
            .log().all()
        .when()
            .post("/post")
        .then()
            .spec(formSuccessSpec)
            .body("form.password", equalTo("pass"));
    }
}

Explanation:

Integrating with Allure Reporting

Document Digest and Form Authentication tests with Allure, attaching request and response details.


import io.qameta.allure.Allure;
import io.qameta.allure.Description;
import io.qameta.allure.Feature;
import io.restassured.RestAssured;
import io.restassured.response.Response;
import org.junit.jupiter.api.Test;
import static io.restassured.RestAssured.*;
import static org.hamcrest.Matchers.*;

@Feature("Digest and Form Authentication Testing")
public class AllureAuthTest {

    @Test
    @Description("Test Digest Authentication with Allure reporting")
    public void testDigestAuthWithAllure() {
        RestAssured.baseURI = "https://httpbin.org";

        Response response = given()
            .auth().digest("user", "passwd")
            .log().all()
        .when()
            .get("/digest-auth/auth/user/passwd")
        .then()
            .statusCode(200)
            .body("authenticated", equalTo(true))
            .extract().response();

        Allure.addAttachment("Response Body", "application/json", response.asString(), ".json");
    }

    @Test
    @Description("Test Form Authentication with Allure reporting")
    public void testFormAuthWithAllure() {
        RestAssured.baseURI = "https://httpbin.org";

        Response response = given()
            .formParam("username", "user")
            .formParam("password", "pass")
            .contentType("application/x-www-form-urlencoded")
            .log().all()
        .when()
            .post("/post")
        .then()
            .statusCode(200)
            .body("form.username", equalTo("user"))
            .extract().response();

        Allure.addAttachment("Response Body", "application/json", response.asString(), ".json");
    }
}

Explanation:

Integrating with CI/CD

Add Digest and Form Authentication tests to a GitHub Actions pipeline for automation.

Create or update .github/workflows/ci.yml:


name: REST Assured CI Pipeline

on:
  push:
    branches:
      - main
  pull_request:
    branches:
      - main

jobs:
  build-and-test:
    runs-on: ubuntu-latest

    steps:
      - name: Checkout code
        uses: actions/checkout@v4

      - name: Set up JDK 11
        uses: actions/setup-java@v4
        with:
          java-version: '11'
          distribution: 'temurin'

      - name: Cache Maven dependencies
        uses: actions/cache@v4
        with:
          path: ~/.m2/repository
          key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }}
          restore-keys: ${{ runner.os }}-maven-

      - name: Run tests
        run: mvn clean test

      - name: Generate Allure report
        run: mvn allure:report

      - name: Upload Allure results
        if: always()
        uses: actions/upload-artifact@v4
        with:
          name: allure-results
          path: target/allure-results

      - name: Publish Allure report
        if: always()
        uses: simple-elf/allure-report-action@v1.7
        with:
          allure_results: target/allure-results
          gh_pages: gh-pages
          allure_report: allure-report

      - name: Deploy report to GitHub Pages
        if: always()
        uses: peaceiris/actions-gh-pages@v4
        with:
          github_token: ${{ secrets.GITHUB_TOKEN }}
          publish_dir: allure-report

Explanation:

Tips for Beginners

Troubleshooting Tip: If authentication fails, enable log().all() to inspect headers (e.g., Authorization for Digest, cookies for Form) and verify credentials against the API or form requirements.

What’s Next?

This post enhances our REST Assured series by covering Digest and Form Authentication, key skills for testing secured APIs and web applications. To continue your learning, consider exploring:

Stay tuned for more testing tutorials!

🤖
PrepCampusPlus AI Tutor
Scroll to Top