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:
- Digest Authentication: An HTTP authentication scheme where credentials are hashed using a nonce (server-provided random value) and other parameters, sent in the
Authorization
header. It’s more secure than Basic Authentication as it avoids sending plaintext credentials, even over HTTPS. - Form Authentication: A web-based authentication method where users submit credentials (username and password) via an HTML form, typically generating a session cookie upon successful login. REST Assured can simulate form submissions to test such endpoints.
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:
auth().digest("user", "passwd")
: Sets Digest Authentication with the usernameuser
and passwordpasswd
.statusCode(200)
: Verifies successful authentication.body("authenticated", equalTo(true))
: Confirms authentication in the response.log().all()
: Logs request and response for debugging.
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:
auth().digest("wronguser", "wrongpass")
: Uses incorrect credentials.statusCode(401)
: Expects an Unauthorized response.log().ifValidationFails()
: Logs details only if the test fails.
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:
formParam("username", "user")
: Sets form parameters for the login request.contentType("application/x-www-form-urlencoded")
: Specifies the form submission content type.cookie("session", ...)
: Simulates using a session cookie for subsequent requests (mocked here).- In a real scenario, extract the actual session cookie from the login response.
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:
formSuccessSpec
: Defines a specification for successful form submissions.spec(formSuccessSpec)
: Applies the specification to validate the response.
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:
Allure.addAttachment
: Attaches the response body to the Allure report for both tests.- Run
mvn clean test
andmvn allure:serve
to view the report.
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:
- Runs authentication tests with
mvn clean test
. - Publishes Allure reports to GitHub Pages for visibility.
Tips for Beginners
- Secure Credentials: Store credentials in environment variables or configuration files, not hardcoded in tests.
- Understand Digest Flow: Digest Authentication involves a server challenge (401) with a nonce, which REST Assured handles transparently.
- Handle Cookies for Form Auth: Extract and reuse session cookies to maintain authenticated sessions.
- Log Selectively: Use
log().ifValidationFails()
to debug authentication failures efficiently.
Troubleshooting Tip: If authentication fails, enablelog().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:
- OAuth 2.0 Authentication: Testing APIs with token-based authentication.
- API Key Authentication: Handling APIs that use keys in headers or query parameters.
- End-to-End Testing: Combining REST Assured with Selenium for UI and API testing.