You’re often confronted with web application which requires user to authenticate. Basic Access Authentication is one of the most simple authentication method:
- Client includes an HTTP Header like
Authorization: Basic dXNlcm5hbWU6cGFzc3dvcmQ=
, with Base64 encoded username and password (username:password
equals dXNlcm5hbWU6cGFzc3dvcmQ=
in Base64
) in each request,
- 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!
Example Application
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 Basic Authentication Prompt
The default username is user
and the default password is passwd
. The server should respond with the following json:
1
2
3
4
|
{
"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 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 error. See? There is no Authorization
header within the request.
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
JMeter’s 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.
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.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
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 UI Listener to view the results.
We’re now ready to execute the sample script!
Running The Test
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.
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:
1
2
3
4
5
|
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 Menu
Then, we’re going to use the following script to encode the user:passwd
:
1
2
3
|
import org.apache.commons.codec.binary.Base64;
byte[] encodedUsernamePassword = Base64.encodeBase64("user:passwd".getBytes());
vars.put("auth",new String(encodedUsernamePassword));
|
JSR223 PreProcessor with the script
Finally, we add an HTTP Header Manager right after the script.
HTTP Header manager after the preprocessor
The headers are configured as following:
- Name:
Authorization
,
- Value:
Basic $[auth}
.
Results
Let’s now run the test!
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. First, you need to install The JMeter Custom Functions Plugin: See our JMeter Plugins Installation Guide for more information.
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
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 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:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
|
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:
1
|
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"
|
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:
1
2
3
4
5
6
7
|
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
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. 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:
1
|
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.
Great example about authenticating against HTTPBin.org. It worked for me using digest authentication in jmeter4.
Thanks Again!
In one of my application i face the issue authorization token and basic authentication and below error. error: ““message”:“Format is Authorization: Bearer [token]”,“name”:“credentials_bad_scheme”,“code”:“credentials_bad_scheme”,“status”:401” I fallow the procedure which you explained above for basic authentication method still I am facing the same error. can you on this.
In reply to phaneendra
Hi Phaneendra, You have the answer in your own question:
Format is Authorization: Bearer [token]
.My password is encrypted in Client side using Jquery.jcryption library. I get my secret key from server side and in client side using the key used to encrypt username and password. Then encrypted User Name and password is decrypted on server side based on same key. How do i encrypt my data in jmeter at each thread run using jquery.jcryption.js? Is there any way to run Jquery Files in Jmeter? I am stuck and not able to resolve this.
In reply to Abhinesh Kumar
Hi Abhinesh, I would setup a small nodeJS (as it’s Javascript, you can embed
jcryption
easily) with all the logic encapsulates in a tiny rest endpoint. That way, you can make an http request from JMeter to this server, then use a regexp extractor to extract the encrypted username and password.Ask the application developers if you need help, they may expose you a REST endpoint to do this.
Hi, There might be some code at browser which would be decrypting the password before sending it. You need to get that code.Capture the value and pass it in that code before sending it.
It might be written in javascript, else check what it is doing and replicate same in BeanShell.
Read more :- https://softwaretestingboard.com/q2a/3381/
Very well explained the Auth handling in Jmeter. I am new to JMeter, this helped me greatly in handling website authentication in Jmeter. Thanks again :)