---
title: JMeter Basic Authentication Explained
url: https://blog.octoperf.com/jmeter-basic-authentication-explained/
date: '2018-04-24'
authors:
- jloisel
categories:
- JMeter
tags:
- JMeter
- Security
description: JMeter supports out of the box Basic Authentication through Http Authorization Manager. Learn how to configure JMeter to authenticate using a login and a password.
---

# JMeter Basic Authentication Explained

You're often confronted with web application which requires user to authenticate. [Basic Access Authentication](https://en.wikipedia.org/wiki/Basic_access_authentication) is one of the **most simple authentication method**:

1. [Client](https://en.wikipedia.org/wiki/User_agent) includes an HTTP Header like `Authorization: Basic dXNlcm5hbWU6cGFzc3dvcmQ=`, with [Base64 encoded](https://www.base64encode.org/) 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**:

- Using an [HTTP Authorization Manager](https://jmeter.apache.org/usermanual/component_reference.html#HTTP_Authorization_Manager),
- Using a [JSR223 PreProcessor](https://jmeter.apache.org/usermanual/component_reference.html#JSR223_Sampler) with a custom script,
- Or using the `base64Encode` function from [Custom Functions Plugin](https://jmeter-plugins.org/wiki/Functions/#base64Encodesupfont-color-gray-size-1-since-1-2-0-font-sup).

Let's see dive into [JMeter](https://jmeter.apache.org/) with examples you can use yourself!


## Example Application

![HTTPBin Endpoints](https://blog.octoperf.com/img/blog/jmeter-basic-authentication/http-bin-endpoints.png)

Let's use [HTTPBin.org](https://httpbin.io/) 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](https://blog.octoperf.com/img/blog/jmeter-basic-authentication/chrome-signin.png "Chrome Basic Authentication Prompt")

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

```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](https://developer.chrome.com/devtools). (hit `F12` in Chrome to open it, then select `Network` tab)

![Chrome Signin 401](https://blog.octoperf.com/img/blog/jmeter-basic-authentication/chrome-signin-unauthorized.png "Chrome Authentication Failure")

Shouldn't you provide the right username and password, the server rejects the access to the protected resource with an [HTTP 401: Unauthorized](https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#4xx_Client_errors) error. See? There is no `Authorization` header within the request.

![Chrome Signin Success](https://blog.octoperf.com/img/blog/jmeter-basic-authentication/chrome-signin-success.png "Chrome Authentication 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](https://blog.octoperf.com/img/blog/jmeter-basic-authentication/http-auth-manager.png "JMeter's HTTP Authorization Manager")

The key JMeter component to use is the [HTTP Authorization Manager](https://jmeter.apache.org/usermanual/component_reference.html#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](https://blog.octoperf.com/img/blog/jmeter-basic-authentication/jmeter-authorization-manager.png "Configuring HTTPBin demo authentication")

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.io/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](https://jmeter.apache.org/usermanual/component_reference.html#HTTP_Request)!

### HTTP Request

![JMeter HTTP Request](https://blog.octoperf.com/img/blog/jmeter-basic-authentication/jmeter-http-request.png "HTTP Request to the basic authenticated endpoint")

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](https://blog.octoperf.com/jmeter-result-analysis-the-ultimate-guide/#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](https://blog.octoperf.com/img/blog/jmeter-basic-authentication/jmeter-http-request-failure.png "Http Authorization manager is disabled")

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](https://blog.octoperf.com/img/blog/jmeter-basic-authentication/jmeter-http-request-success.png "Http Authorization manager is enabled")

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

```json
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](https://en.wikipedia.org/wiki/Digest_access_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](https://jmeter.apache.org/usermanual/component_reference.html#JSR223_Sampler) for that purpose. First, add the **JSR223 PreProcessor**.

![JSR223 PreProcessor](https://blog.octoperf.com/img/blog/jmeter-basic-authentication/add-jsr223-preprocessor.png "JSR223 PreProcessor Menu")

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

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

![JSR223 PreProcessor](https://blog.octoperf.com/img/blog/jmeter-basic-authentication/jsr223-script.png "JSR223 PreProcessor with the script")

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

![JSR223 Header Manager](https://blog.octoperf.com/img/blog/jmeter-basic-authentication/jsr223-header-manager.png "HTTP Header manager after the preprocessor")

The headers are configured as following:

- **Name**: `Authorization`,
- **Value**: `Basic $[auth}`.

### Results

Let's now run the test!

![JSR223 Result](https://blog.octoperf.com/img/blog/jmeter-basic-authentication/jsr223-result.png "Request authenticates successfully")

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](https://jmeter-plugins.org/wiki/Functions/#base64Encodesupfont-color-gray-size-1-since-1-2-0-font-sup). First, you need to install The JMeter **Custom Functions Plugin**: See our [JMeter Plugins Installation Guide](https://blog.octoperf.com/jmeter-plugins-installation-guide/) for more information.

![Custom Functions Plugin](https://blog.octoperf.com/img/blog/jmeter-basic-authentication/custom-functions-plugin.png "Installing 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](https://blog.octoperf.com/img/blog/jmeter-basic-authentication/base64encode-function-explained.png "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](https://blog.octoperf.com/img/blog/jmeter-basic-authentication/base64encode-function.png "base64Encode function using in Authorization 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:

```java
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.io/digest-auth/auth/user/passwd/MD5");

  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.io/digest-auth/auth/user/passwd/MD5`. 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 ](https://blog.octoperf.com/img/blog/jmeter-basic-authentication/jmeter-http-request-digest.png "Http Request forged with a script to support Digest Authentication")

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](https://blog.octoperf.com/img/blog/jmeter-basic-authentication/basic-authentication.png "Understanding Basic Authentication mechanism")

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](https://tools.ietf.org/html/rfc2617). It stated the *username* and *password* should be encoded with `ISO-8859-1` (also known as `ASCII`) [character encoding](https://en.wikipedia.org/wiki/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:

- You must use [HTML Entities](https://dev.w3.org/html5/html-author/charref) whenever the character is not included in the [189 chars supported](https://cs.stanford.edu/~miles/iso8859.html),
- And only handles [romance languages](https://en.wikipedia.org/wiki/Romance_languages) (mostly in Europe and America).

Wouldn't it be nice to use `UTF-8` encoding then? That's exactly what [RFC7617](https://tools.ietf.org/html/rfc7617) is about.

### New RFC7617

[RFC7617](https://tools.ietf.org/html/rfc7617) replaces [RFC 2617](https://tools.ietf.org/html/rfc2617) 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:

```json
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](https://fr.wikipedia.org/wiki/American_Standard_Code_for_Information_Interchange) (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](https://en.wikipedia.org/wiki/Web_browser) 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:

- [Google Chrome](https://www.google.com/chrome/index.html) seems to prefer `ÙTF-8`, 
- **Microsoft Edge** [doesn't support UTF-8](https://developer.microsoft.com/en-us/microsoft-edge/platform/issues/11879588/),
- [Firefox since version 57 supports UTF-8](https://bugzilla.mozilla.org/show_bug.cgi?id=1419658).

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](https://blog.octoperf.com/jmeter-tutorial-for-beginners/). Also consider putting [logins and passwords into CSV variables](https://blog.octoperf.com/mastering-jmeter-csv-data-set-config/).
