Skip to content
JMeter Basic Authentication Explained

JMeter Basic Authentication Explained

You're often confronted with web application which requires user to authenticate. Basic Access Authentication is one of the most simple authentication method:

  1. Client includes an HTTP Header like Authorization: Basic dXNlcm5hbWU6cGFzc3dvcmQ=, with Base64 encoded username and password (username:password equals dXNlcm5hbWU6cGFzc3dvcmQ= in Base64) in each request,
  2. Server grants access whenever the provided username and password are correct.

This guide will teach you 3 different ways to handle basic authentication:

Let's see dive into JMeter with examples you can use yourself!

OctoPerf is JMeter on steroids!
Schedule a Demo

Example Application

HTTPBin Endpoints

Let's use HTTPBin.org as example application. We're interested in the following endpoints:

  • /basic-auth/:user/:passwd Challenges HTTPBasic Auth.
  • /hidden-basic-auth/:user/:passwd 404'd BasicAuth.
  • /digest-auth/:qop/:user/:passwd/:algorithm Challenges HTTP Digest Auth.
  • /digest-auth/:qop/:user/:passwd Challenges HTTP Digest Auth.

HTTPBin is a demo application of great use: it provides sample endpoints to call with configurable parameters.

For example, when clicking on the /basic-auth/:user/:passwd link, your browser (here I use Google Chrome) should prompt you to enter a username and password.

Chrome Signin

The default username is user and the default password is passwd. The server should respond with the following json:

{
  "authenticated": true, 
  "user": "user"
}

What happens if we don't provide any credentials, or provide wrong credentials? Let's find out using Chrome Developer Tools. (hit F12 in Chrome to open it, then select Network tab)

Chrome Signin 401

Shouldn't you provide the right username and password, the server rejects the access to the protected resource with an HTTP 401: Unauthorized error. See? There is no Authorization header within the request.

Chrome Signin Success

When providing the right login and password, the server responds right away with an HTTP 200: OK. And we can clearly see the browser sending the Authorization: Basic dXNlcjpwYXNzd2Q= http header within the request.

Let's see how we can do this with JMeter!

Http Authorization Manager

Configuration

HTTP Authorization Manager

The key JMeter component to use is the HTTP Authorization Manager:

The Authorization Manager lets you specify one or more user logins for web pages that are restricted using server authentication.

It provides the ability to automatically add the relevant Authorization http header to subsequent http requests.

HTTP Authorization Manager

Let's configure it to authenticate on HTTPBin.org https://httpbin.org//basic-auth/user/passwd. Add the following line to the table:

  • Clear Auth on each Iteration: can be left as is.
  • Base URL: https://httpbin.org/basic-auth/user/passwd,
  • User: user,
  • Password: passwd,
  • Leave Domain and Realm empty,
  • Mechanism: BASIC_DIGEST.

The HTTP Authorization Manager must be placed at the beginning of the thread group, right under it. The screen above shows the final configuration once done properly. Let's now create an HTTP Request!

HTTP Request

JMeter HTTP Request

The HTTP Request is configured with the following settings:

  • Protocol: https (http is fine too, but must also be set in Authorization Manager accordingly),
  • Server name: httpbin.org,
  • Method: it's a simple GET request,
  • Path: /basic-auth/user/passwd.

All other settings can be left as is. Finally, we use the View Results Tree UI Listener to view the results.

We're now ready to execute the sample script!

Running The Test

JMeter HTTP Request Failure

First, I've ran the test with the HTTP Authorization Manager disabled. The server returned an HTTP 401 Unauthorized as expected. Now let's enable it and compare the test runs.

JMeter HTTP Request Success

Now the server grants the access and returns an HTTP 200 OK response. That's great! A closer inspection of the request headers shows:

Request Headers:
Connection: keep-alive
Host: httpbin.org
User-Agent: Apache-HttpClient/4.5.5 (Java/1.8.0_161)
Authorization: Basic dXNlcjpwYXNzd2Q=

What about Digest Authentication? Unfortunately, JMeter doesn't support Digest Authentication yet. The authorization manager works great for Basic and Kerberos authentication thought.

The Www-Authenticate header must therefore be generated manually using a script.

JSR223 PreProcessor

Configuration

You need to add the Authorization header with the value Basic base64Encode(username:password). The problem is that JMeter has no base64 function. We're going to use the JSR223 Pre-Processor for that purpose. First, add the JSR223 PreProcessor.

JSR223 PreProcessor

Then, we're going to use the following script to encode the user:passwd:

import org.apache.commons.codec.binary.Base64;
byte[] encodedUsernamePassword = Base64.encodeBase64("user:passwd".getBytes());
vars.put("auth",new String(encodedUsernamePassword));

JSR223 PreProcessor

Finally, we add an HTTP Header Manager right after the script.

JSR223 Header Manager

The headers are configured as following:

  • Name: Authorization,
  • Value: Basic $[auth}.

Results

Let's now run the test!

JSR223 Result

The script encoded the username and password combinations into a Base64 string, then put it in a variable. Finally, we reuse that variable within the header manager.

Custom Functions Plugin

Configuration

This is the third and last method to configure Basic Authentication: using the base64Encode function from Custom Functions Plugin. First, you need to install The JMeter Custom Functions Plugin: See our JMeter Plugins Installation Guide for more information.

Custom Functions Plugin

Open the Plugins Manager, then select Available Plugins and type function. The Custom JMeter Functions plugin should show up. Click on Apply changes and restart JMeter to install it.

Base64Encode Function

The ${__base64Encode(string)} function is clearly what we need. This is why we installed the plugin: as seen previously, JMeter has no base64 function by default. Let's use it within the Authorization header.

Base64Encode Function Header

The headers are configured as following:

  • Name: Authorization,
  • Value: Basic ${__base64Encode(user:passwd)}.

It's even easier to use than the JSR223 PreProcessor since you don't need an additional element!

JMeter Digest Auth

In order to execute an HTTP request against an endpoint which is protected by Digest Authentication, we need to use a JSR223 Sampler. Http Auth Manager doesn't support generating digest authentication headers by default. The server answered with an HTTP/1.1 200 OK as expected!

The script is the following:

import org.apache.http.HttpHost;
import org.apache.http.auth.AuthScope;
import org.apache.http.auth.UsernamePasswordCredentials;
import org.apache.http.client.AuthCache;
import org.apache.http.client.CredentialsProvider;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.protocol.HttpClientContext;
import org.apache.http.impl.auth.DigestScheme;
import org.apache.http.impl.client.BasicAuthCache;
import org.apache.http.impl.client.BasicCredentialsProvider;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;

HttpHost target = new HttpHost("httpbin.org", 80, "http");
CredentialsProvider credsProvider = new BasicCredentialsProvider();
credsProvider.setCredentials(
      new AuthScope(target.getHostName(), target.getPort()),
      new UsernamePasswordCredentials("user", "passwd"));
CloseableHttpClient httpclient = HttpClients.custom()
      .setDefaultCredentialsProvider(credsProvider)
      .build();
try {

  // Create AuthCache instance
  AuthCache authCache = new BasicAuthCache();
  // Generate DIGEST scheme object, initialize it and add it to the local
  // auth cache
  DigestScheme digestAuth = new DigestScheme();
  // Suppose we already know the realm name
  digestAuth.overrideParamter("realm", "some realm");
  // Suppose we already know the expected nonce value
  digestAuth.overrideParamter("nonce", "whatever");
  authCache.put(target, digestAuth);

  // Add AuthCache to the execution context
  HttpClientContext localContext = HttpClientContext.create();
  localContext.setAuthCache(authCache);

  HttpGet httpget = new HttpGet("https://httpbin.org/digest-auth/auth/user/passwd");

  log.info("Executing request " + httpget.getRequestLine() + " to target " + target);

  CloseableHttpResponse response = httpclient.execute(target, httpget, localContext);
  try {
    log.info("----------------------------------------");
    log.info(String.valueOf(response.getStatusLine()));
    log.info(EntityUtils.toString(response.getEntity()));
  } finally {
    response.close();
  }

} finally {
  httpclient.close();
}

It's an example script to HTTPBin https://httpbin.org/digest-auth/auth/user/passwd. It creates a new HTTPClient and configures it properly to include the digest authentication header which should look like:

Authorization: Digest username="user", realm="me@kennethreitz.com", nonce="b8856184521cd0e23a3a8a8e04370158", uri="/digest-auth/auth/user/passwd/MD5/never", algorithm=MD5, response="1307ef4053cda82c0259f87656684d74", opaque="a5f3d832389217038bcadb09ef460895", qop=auth, nc=0000000a, cnonce="dc8bbb91c13c392d"

JMeter HTTP Request

Once run, some of the information are logged within the JMeter Logs Panel. You should see something similar to:

2018-04-24 16:00:33,682 INFO o.a.j.p.j.s.JSR223Sampler: Executing request GET http://httpbin.org/digest-auth/auth/user/passwd HTTP/1.1 to target http://httpbin.org:80
2018-04-24 16:00:33,919 INFO o.a.j.p.j.s.JSR223Sampler: ----------------------------------------
2018-04-24 16:00:33,921 INFO o.a.j.p.j.s.JSR223Sampler: HTTP/1.1 200 OK
2018-04-24 16:00:33,922 INFO o.a.j.p.j.s.JSR223Sampler: {
  "authenticated": true, 
  "user": "user"
}

That way you can even load test Digest Authentication protected web application. JMeter probably doesn't support it because it's not a common way to authenticate. You can now strut around the beach and impress the girls with your new JMeter skills!

Basic Authentication

Basic Authentication

Before diving into JMeter configuration, let's first understand how Basic Authentication works.

Don't fall asleep there, the nice things come after!

Old RFC2617

Basic authentication was initially based on RFC 2617. It stated the username and password should be encoded with ISO-8859-1 (also known as ASCII) character encoding. Most servers understand it that way and fail to login when the charset is not appropriate.

Sadly, ISO-8859-1 character encoding, while being easy to use, has several flaws:

Wouldn't it be nice to use UTF-8 encoding then? That's exactly what RFC7617 is about.

New RFC7617

RFC7617 replaces RFC 2617 since 2015. The new RFC provides the ability to define the character encoding explicitely for the username and password.

Typically, the Authorization header would look like:

Authorization: Basic BASE64, realm="octoperf.com", charset="utf-8"

In addition to this:

  • Default Encoding is still undefined. It must be compatible with US-ASCII (which maps ASCII bytes to US-ASCII bytes, like UTF-8),
  • Only UTF-8 alternative is allowed. Servers will accept  UTF-8 encoded username and password if the charset is specified.

What about the web browsers supporting this change?

Browser Support

As of now (presently 2018), most web browser (like Chrome, Firefox) all support the new RFC7617 with the following empirical results:

That being said, the most commonly used web browser are all supporting the new specifications. We're done with the boring stuff!

Feel free to wander around and read our other JMeter tutorials. Also consider putting logins and passwords into CSV variables.

Want to become a super load tester?
Request a Demo