Extracting HTTP Basic Authentication from HttpServletRequest
Authentication is a fundamental aspect of securing web applications. One of the simplest and most widely used authentication mechanisms is HTTP Basic Authentication. When a client sends a request protected by Basic Authentication, the username and password are transmitted through the Authorization HTTP header in a Base64-encoded format. In Java servlet-based applications, developers often need to retrieve and process these credentials from the incoming HttpServletRequest. This can be useful for custom authentication logic, auditing, integration with legacy systems, or learning purposes. In this article, we will explore how HTTP Basic Authentication works, how to extract credentials from an HttpServletRequest, and how to test the implementation with a complete working example.
1. HTTP Basic Authentication
HTTP Basic Authentication (Wikipedia) is defined by the HTTP specification and uses the following header format: Authorization: Basic dXNlcm5hbWU6cGFzc3dvcmQ=. The value after the word Basic is a Base64-encoded string containing: username\:password. For example: admin\:secret123. After Base64 encoding: YWRtaW46c2VjcmV0MTIz Which results in: Authorization: Basic YWRtaW46c2VjcmV0MTIz. The server decodes the value, extracts the username and password, and validates them against a user store.
2. Code Example
2.1 Maven Dependency
The example relies only on the Servlet API and JUnit for testing.
<dependencies>
<dependency>
<groupId>jakarta.servlet</groupId>
<artifactId>jakarta.servlet-api</artifactId>
<version>use__latest__stable__jar__version</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter</artifactId>
<version>use__latest__stable__jar__version</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
<version>use__latest__stable__jar__version</version>
<scope>test</scope>
</dependency>
</dependencies>
This Maven configuration defines the project dependencies required for implementing and testing a Java Servlet-based application. The jakarta.servlet-api dependency provides the core Servlet API used to build and run servlet classes, and it is marked with provided scope because the servlet container (such as Tomcat or Jetty) supplies it at runtime. The junit-jupiter dependency is included under test scope to enable unit testing using JUnit 5, allowing developers to write and execute test cases for the application logic. Additionally, mockito-core, also under test scope, is used to mock dependencies like HttpServletRequest during testing, enabling isolated and controlled test scenarios without requiring an actual servlet container. Together, these dependencies ensure a clean separation between runtime requirements and testing utilities, making the application easier to develop, test, and maintain.
2.2 Retrieving Credentials from the Authorization Header
Let us create a utility class that extracts credentials from the Authorization header.
2.2.1 Credential Record
public record Credentials(String username, String password) {
}
This code defines a Credentials record in Java, which is a compact way of creating an immutable data carrier class. The record automatically generates the constructor, getter methods, equals(), hashCode(), and toString() methods for the two fields username and password. By using a record instead of a traditional class, the code becomes cleaner and reduces boilerplate while still providing a strongly typed structure to hold authentication-related data extracted from the HTTP request.
2.2.2 BasicAuthExtractor Implementation
import jakarta.servlet.http.HttpServletRequest;
import java.nio.charset.StandardCharsets;
import java.util.Base64;
import java.util.Optional;
public class BasicAuthExtractor {
public Optional<Credentials> extract(HttpServletRequest request) {
String header = request.getHeader("Authorization");
if (header == null || !header.startsWith("Basic ")) {
return Optional.empty();
}
String encodedCredentials = header.substring(6);
try {
byte[] decodedBytes =
Base64.getDecoder().decode(encodedCredentials);
String decoded =
new String(decodedBytes, StandardCharsets.UTF_8);
int separatorIndex = decoded.indexOf(':');
if (separatorIndex < 0) {
return Optional.empty();
}
String username =
decoded.substring(0, separatorIndex);
String password =
decoded.substring(separatorIndex + 1);
return Optional.of(
new Credentials(username, password)
);
} catch (IllegalArgumentException ex) {
return Optional.empty();
}
}
}
2.2.3 Example Servlet Usage
import jakarta.servlet.annotation.WebServlet;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import java.io.IOException;
@WebServlet("/login")
public class LoginServlet extends HttpServlet {
private final BasicAuthExtractor extractor =
new BasicAuthExtractor();
@Override
protected void doGet(
HttpServletRequest request,
HttpServletResponse response)
throws IOException {
extractor.extract(request)
.ifPresentOrElse(
credentials -> {
try {
response.getWriter().println(
"User: " +
credentials.username()
);
response.getWriter().println(
"Password: " +
credentials.password()
);
} catch (IOException e) {
throw new RuntimeException(e);
}
},
() -> {
try {
response.sendError(
HttpServletResponse.SC_UNAUTHORIZED
);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
);
}
}
This LoginServlet demonstrates how HTTP Basic Authentication credentials are processed in a Java Servlet. The servlet is mapped to the /login endpoint using the @WebServlet annotation and extends HttpServlet to handle HTTP requests. Inside the doGet method, it uses the BasicAuthExtractor utility to extract credentials from the incoming HttpServletRequest. If valid credentials are present, the ifPresentOrElse block prints the extracted username and password to the response output stream; otherwise, it sends an HTTP 401 Unauthorized error using HttpServletResponse.SC_UNAUTHORIZED. This approach cleanly separates authentication extraction logic from request handling and provides a simple mechanism for demonstrating or implementing Basic Authentication in servlet-based applications.
2.2.4 Code Run And Code Output
To test the implementation, we simulate an HTTP request containing a valid Basic Authentication header. In a real servlet container, this header is automatically sent by the client (browser, Postman, or API client). For testing purposes, we can mock the HttpServletRequest using Mockito and verify how the BasicAuthExtractor processes the input.
2.2.4.1 Test Case Example
import jakarta.servlet.http.HttpServletRequest;
import org.junit.jupiter.api.Test;
import java.util.Optional;
import static org.mockito.Mockito.*;
public class BasicAuthExtractorTest {
@Test
void shouldExtractCredentialsSuccessfully() {
HttpServletRequest request = mock(HttpServletRequest.class);
// username: admin, password: secret123
String encoded = "YWRtaW46c2VjcmV0MTIz";
when(request.getHeader("Authorization"))
.thenReturn("Basic " + encoded);
BasicAuthExtractor extractor = new BasicAuthExtractor();
Optional < Credentials > result = extractor.extract(request);
System.out.println(result);
}
}
2.2.4.2 Expected Output
When the above test runs successfully, the extracted credentials will be printed as:
Optional[Credentials[username=admin, password=secret123]]
If the Authorization header is missing or invalid, the output will be:
Optional.empty
3. Conclusion
Retrieving HTTP Basic Authentication credentials from an HttpServletRequest is a straightforward process that involves reading the Authorization header, decoding its Base64 value, and extracting the username and password pair. While modern applications often rely on OAuth2, JWT, or session-based authentication, understanding Basic Authentication remains important because it is still commonly used for internal services, legacy integrations, development environments, and API testing. By encapsulating the extraction logic in a dedicated utility such as BasicAuthExtractor, applications can keep authentication-related code clean, reusable, and easy to test. The approach demonstrated in this article provides a solid foundation for implementing custom authentication workflows in servlet-based Java applications.

