Nov. 11th, 2014

How to Run Performance Tests on OAuth Secured Apps with JMeter

First Off - What is OAuth & Why do You Need it?

 

OAuth (the Open Standard for Authorization) is an open protocol which provides token-based authentication and authorization - as opposed to the standard username and password requirements.  It allows third party services to use the end-user information without revealing their personal credentials.  

 

Here’s an example of how it works:

 

  1. The user goes to website A

  2. On website A, he’s given the option to sign in by using website B (Google, Facebook, LinkedIn, GitHub, etc.)

  3. The user confirms that information obtained from website B (i.e. first name and last name) can be used by website A

  4. The user is known on website A by the credentials (i.e. first name and last name) that he set up on website B.

 

This entire process is known as the flow. As you can see, the end user doesn’t need to enter his credentials at all on website A, which makes it far more secure.

 

Why and How Developers Started Using OAuth

 

OAuth version 1.0 was first released in 2007. Twitter was the first platform to start using OAuth to access its API.  By 2010, the platform had made the use of OAuth compulsory for all 3rd-party applications working with its API. In the  same year, IETF launched OAuth 2.0. Like its predecessors (Oauth 1.0 and OAuth 1.0.a),  OAuth 2.0 gives users the ability to grant third-party access to web resources without sharing their passwords. New features in OAuth 2.0 include new flows, simplified signatures and short-lived tokens with long-lived authorizations.

 

OAuth has a huge number of flows, different protocol versions - with opposing viewpoints on them (the creator of OAuth 1.0 withdrew his name and support from OAuth 2.0 due to suspected security flaws) - and various server/client sides implementations (OAuth 2.0 leaves a lot of things up to the implementor). It’s impossible to cover all of this in one article! In today’s post, my main aim is to show you how to run performance testing with JMeter on OAuth-secured applications - so I’m going to focus on the key areas of OAuth only.  Of course, you’re always welcome to post questions at the bottom if you’d like to find out more about another aspect of OAuth.


If you’re not so familiar with OAuth, you might want to check out these articles to help you understand some of the terms I’m using in this post:

 

 

Running Performance Tests on OAuth Secured Apps
Option 1: The End User

 

This first option is the closest one to a real-life user experience (logging into website A with your credentials from website B).

 

For this test scenario, I’m going to use BlazeMeter Sense - a free site which allows you to upload and analyse your JMeter load test results through a simple plugin. BlazeMeter Sense doesn’t give you the option to login with a username and password - it works only through OAuth.

 

If you look at sense.blazemeter.com, you’ll be able to see that the scenario can be split into three steps:

 

  1. HTTP Get Request - opens the BlazeMeter Sense login page

  2. WebDriver Sampler Request - opens the URL from step 1.1 and performs a sign in with Google

  3. HTTP Get Request - opens the BlazeMeter Sense GUI page

 

Here’s the JMeter test plan for the above scenario:

 

You can verify that the login was successful by checking the  View Results Tree Listener output.

 

For the very first request (open the BlazeMeter Sense login page), we can see that the login options are displayed in the response:

 

 

 

 

And if we look at the last request (open the BlazeMeter Sense GUI page) we can now see that we’re on the page for an authenticated user:

 

 

When you’re testing for multiple users, I recommend logging them in one by one and storing the cookies in the setUp Thread Group in JMeter Properties. You can then reuse these cookies in the thread groups where the real load is created.

 

Want to try this yourself?

 

Here’s how:

 

The JMeter .jmx file can be found in the Bitbucket repository at https://bitbucket.org/blazemeter/oauth-browser/ (it’s in the /bin folder). All the libraries you need are in the /lib folder.  So you need to:

  1. Download the whole repository from the downloads page

  2. Copy the resulting .zip file to your JMeter installation folder

  3. Unpack the .zip file

  4. Restart JMeter (if it’s already running)

  5. Set the “webdriver.firefox.bin” property to point to the Firefox binary (if it’s not in your system PATH) in the system.properties file.

  6. Change the “username” and “password” in the User Defined Variables to the details from your Google account.

 

You should be able to get the same results.

 

Running Performance Tests on OAuth Secured Apps
Option 2: On OAuth 1.0

 

OAuth 1.0 has a 3-step authorization flow to accessing protected resources. These are:

 

  1. Obtaining the Request Token and Token Secret using the Consumer Key and Consumer Secret

  2. Obtaining the Authorization Token using the Request Token and Secret

  3. Exchanging the Authorization Token to the Access Token -  which can be used to access protected resources.

 

Any of the above requests (and, in fact, any request for protected resources) must be signed using one of the following methods:

 

  • PLAINTEXT

  • HMAC-SHA1

  • RSA-SHA1

 

Put simply, the request parameters will look something like this:

 

oauth_consumer_keyOAuth 1.0 Consumer Key
oauth_tokenAccess token from step 3 above
oauth_signature_method

One of the above request signing methods

oauth_timestampCurrent timestamp (in seconds from 01.01.1970)
oauth_nonceAny random string (usually current timestamp in milliseconds from 01.01.1970)
any other request parameters 
oauth_signaturecalculated depending on signature type

 

The most tricky part is the oauth_signature. Here’s how you do it for each method.

 

  • PLAINTEXT: URL-encoded Consumer Secret + & + Token Secret

  • HMAC-SHA1: base64 of the sha1 of the Signature Base String - the HTTP Method followed by "&", then the URL of the resource (http or https), and then followed by the parameters which are sent to the endpoint and sorted alphabetically - hashed by the Consumer Secret

  • RSA-SHA1: PKCS#1 of Signature Base String hashed by Consumer’s private RSA key - and again Base64 and URL-encoded.

 

See OAuth 1.0 for detailed explanations, sample requests, etc.

 

Given the complexity of building this request, it’s best to use one of OAuth Java Client Libraries. In this demo, I’ll be using the:

 


 

As recommended in JMeter Performance and Tuning Tips and evidenced by Beanshell vs JSR223 vs Java JMeter Scripting: The Performance-Off You've Been Waiting For!, the right Test Element to be used when developing the OAuth 1.0 client side code is the JSR223 Sampler with Groovy.

 

Here’s the test flow:

 

  1. Download Groovy, find the groovy-all.jar and drop it into JMeter’s /lib folder

  2. Do the same for the latest version of the oauth-signpost jar for the /lib folder of your JMeter installation. As for signpost-core-1.2 and JMeter 2.11, the signpost-core.jar should be enough as other dependencies are already part of JMeter.  

  3. Restart JMeter (if it’s running)

  4. Add a Thread Group to the Test Plan

  5. Add User Defined Variables to the Thread Group or Test Plan. Provide the following variables:

    • consumerKey - key

    • consumerSecret - secret

    • requestUrl - http://oauthbin.com/v1/request-token

    • accessUrl - http://oauthbin.com/v1/access-token

    • protectedUrl - http://oauthbin.com/v1/echo

  6. Add the JSR223 Sampler to the Thread Group

  7. Type “groovy” into the “Language” input

  8. Provide the following script:

 

import oauth.signpost.OAuth;
import oauth.signpost.OAuthConsumer;
import oauth.signpost.OAuthProvider;
import oauth.signpost.basic.DefaultOAuthConsumer;
import oauth.signpost.basic.DefaultOAuthProvider;

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;


OAuthConsumer consumer = new DefaultOAuthConsumer(vars.get("consumerKey"),
     vars.get("consumerSecret"));
URL url = new URL(vars.get("requestUrl"));
HttpURLConnection request = (HttpURLConnection) url.openConnection();
consumer.sign(request);
request.connect();
BufferedReader reader = new BufferedReader(new InputStreamReader(
request.getInputStream()));
String inputLine;
log.info("========== OAuth token and token secret ==========");
while ((inputLine = reader.readLine()) != null)
   log.info(inputLine);
reader.close();
request.disconnect();

OAuthProvider provider = new DefaultOAuthProvider(
vars.get("requestUrl"), vars.get("accessUrl"),
vars.get("protectedUrl"));

log.info("========== OAuth Request Token ==========");

log.info(provider.retrieveRequestToken(consumer, OAuth.OUT_OF_BAND));

provider.retrieveAccessToken(consumer, OAuth.OUT_OF_BAND);

url = new URL(vars.get("protectedUrl") + "?jmeter=great");
request = (HttpURLConnection) url.openConnection();
consumer.sign(request);
request.connect();
reader = new BufferedReader(new InputStreamReader(
request.getInputStream()));
log.info("========== Authenticated Request Response ==========");

while ((inputLine = reader.readLine()) != null)
   log.info(inputLine);    
reader.close();
request.disconnect();

 

  1. Enable the Log Viewer from the “Options” menu

  2. Run the test and look into the log window. The output should look like the image below:

Looking for sources and libraries?

 

Check out the https://bitbucket.org/blazemeter/oauth1/ repository. It contains everything you need. You don’t need to change anything, just unpack, restart JMeter and launch.


 

Running Performance Tests on OAuth Secured Apps
Option 3: OAuth 2.0

 

The easy way...

 

OAuth 2.0 is considered simpler and easier than OAuth 1.0/1.0a. It doesn’t require any crazy signatures, timestamps or secrets - and for the simulation, all you have to do is add a HTTP Header Manager as a child of a single request, or at the same level as all requests (depending on the desired scope).

 

Only one header:

 

  • Name: Authorization

  • Value: Bearer ${OAuth2Token}

 

is enough to access protected resources.

 

Don’t have OAuth2Token?  You’ll need to either:

 

  • get one somehow (sniffer, asking around)

  • implement the end-user-scenario (see ‘Option 1’)

  • go the hard way (see the section below)

 

The hard way...

 

Just like for OAuth 1.0, you’ll need the following libraries to be in the  /lib folder of your JMeter installation:

 

  • groovy-all-x.jar (downloadable from http://groovy.codehaus.org/Download

  • google-api-client-1.19.0.jar

  • google-api-services-plus-v1-rev137-1.19.0.jar

  • google-http-client-1.19.0.jar

  • google-http-client-jackson2-1.19.0.jar

  • google-oauth-client-1.19.0.jar

  • guava-14.0.jar

  • guava-jdk5-13.0.jar

  • jackson-core-2.1.3.jar

  • jsr305-1.3.9.jar

 

The Google Plus OAuth2 authentication script looks like this (add the code below to the JSR223 Sampler)

 

import com.google.api.client.googleapis.auth.oauth2.GoogleCredential;
import com.google.api.client.googleapis.javanet.GoogleNetHttpTransport;
import com.google.api.client.http.HttpTransport;
import com.google.api.client.json.JsonFactory;
import com.google.api.client.json.jackson2.JacksonFactory;
import com.google.api.services.plus.Plus;
import com.google.api.services.plus.PlusScopes;
import com.google.api.services.plus.model.Activity;


String APPLICATION_NAME = vars.get("applicationName");
String SERVICE_ACCOUNT_EMAIL = vars.get("serviceAccountEmail");
JsonFactory JSON_FACTORY = JacksonFactory.getDefaultInstance();


HttpTransport httpTransport = GoogleNetHttpTransport.newTrustedTransport();
GoogleCredential credential = new GoogleCredential.Builder().setTransport(httpTransport)
.setJsonFactory(JSON_FACTORY)
.setServiceAccountId(SERVICE_ACCOUNT_EMAIL)
.setServiceAccountScopes(Collections.singleton(PlusScopes.PLUS_ME))
.setServiceAccountPrivateKeyFromP12File(new File(vars.get("p12FilePath")))
.build();

Plus plus = new Plus.Builder(httpTransport, JSON_FACTORY, credential)
.setApplicationName(APPLICATION_NAME).build();


String activityId = vars.get("activityId");
Activity activity = plus.activities().get(activityId).execute();
log.info("id: " + activity.getId());
log.info("url: " + activity.getUrl());
log.info("content: " + activity.getObject().getContent());


 

Now, let’s take a look at the User Defined Variables that need to be set and see where to get the appropriate values.

 

We’ll need the following:

 

  1. applicationName - the name of the product which will perform the OAuth authentication and authorization

  2. serviceAccountEmail - Google Service Account Email Address

  3. p12FilePath - location of .p12 file containing Google Service Account credentials

  4. activityId - Google+ activity ID  - protected resource, can be left default - z12gtjhq3qn2xxl2o224exwiqruvtda0i

 

You need to have a Google Account to get the relevant values for points 1-3:

 

  1. Go to the Google Developer Console at: https://console.developers.google.com/project

  2. Click the “Create Project” button and provide a Name and ID

  3. Expand “API and Auth” and go to “Consent Screen”

  4. Fill out the “Email Address” and “Product Name” fields

  5. Go to “APIs”

  6. Turn on “Google+ API”

  7. Go to “Credentials” and click “Create new Client ID”

  8. Choose “Service Account” (elsewise you’ll need to provide a redirect URL and use the browser for Google Authentication). See the first section for more information on this.

  9. After clicking the “Create” button, you’ll receive a .p12 key file and password. Save it somewhere so JMeter can access it (i.e. in the /bin folder of your JMeter installation)

  10. You’ll be able to see your Service Email Address and Client ID in the “Credentials” screen

 

 


 

Populate the User Defined Variables with the values from your Google Developer Console and run your test. Now look at the Log Viewer window:

 

 

 

 

Again, if you want to run it yourself or for any other reason, the JMeter .jmx file and 3rd-party dependency jars are available here: https://bitbucket.org/blazemeter/oauth2/

 

I think that pretty much covers the key ways you can access OAuth-protected resources. If you’re already using BlazeMeter (or considering using it), it’s probably worth mentioning that it supports all of the approaches mentioned above.

 

Have any questions or comments? Please post them below and I’ll do my best to answer as quickly as possible. :)



LEARN MORE



If you are new to JMeter, and you’d like to learn more, please sign up for our free online JMeter training course.
 

For more experienced JMeter users, you'll want to view the on-demand webcast, How to Create Advanced Load Testing Scenarios with JMeter.
 

Be sure to read through all our JMeter list of resources




 

Interested in writing for our Blog? Send us a pitch!