Visual Studio Web Tests and OAuth: Taming the elusive Access Token

Posted on Posted in Web Tests

Visual Studio Web Tests offer an excellent way to validate that your application’s endpoints (typically API calls) are performing the way you’d expect. They also offer a quick way to simulate “typical user” scenarios which can be integrated into Load Tests against your application. However, any application that requires a user to log in (usually with a test account for automated testing) will inevitably find that authentication is not handled by default in Web Tests.

The Problem

The most common issue faced is Web Test Recorder not capturing your Authorization header. While this seems like a flaw, there’s a very valid reason for it. Most OAuth access tokens are not intended to last indefinitely and will expire at some point (often in under an hour). When this happens, any requests attempting to use an Authorization: Bearer (token) header saved in the Web Test would be rejected as unauthorized, rendering them useless.

Another complication that can arise is the oauth/token false flag in your recorded test. Logging in and getting a new access token is one of the first steps that tends to happen during a Web Test Recording session. Seeing a call to oauth/token or its equivalent in the Web Test sure looks nice and may lead you to believe that you have authorization handled, but like most calls in a web test, nothing is done with the results. You might be successfully requesting a new access token from the server and getting back a response with a valid new token. However, by default, nothing is happening with that token. The access token is requested (often invalidating previous access tokens in the process) and then promptly discarded.

Extraction Rules To The Rescue

Searching around for how to solve this problem gives you back several painful or clumsy options. The most common one is to implement a WebTestPlugin with custom code to negotiate with the OAuth server, get the access token, and set it to a Context Parameter in your test run. If we’ve recorded the oauth/token request in our Web Test and it can be reliably repeated, the solution can be much simpler and requires nothing more than an Extraction Rule.

Extraction Rules allow you to parse information coming back in the response and save select bits into parameters. In our case, we’re making a call to the OAuth token endpoint already in the Web Test, we simply need to capture and use the access token that is returned. We’ll add a new Extraction Rule by right-clicking on the request and selecting Add Extraction Rule… menu item. There are numerous ways to extract data from the request, but since the response will always be in JSON, we’ll just use the Extract Regular Expression rule to parse out our access token from the response.

Our Regular Expression will be “access_token”:”(.*?)” and we need to make sure Use Groups is enabled so we get back just the access token and not the entire JSON key-value pair. We have specified that the value will be stored in the AccessToken context parameter which we set up in our web test beforehand. When this request executes now, it will parse out the access token from the OAuth response and save it into a parameter for us to use in future requests as needed. The parameter can be substituted in using the {{}}double curly braces anywhere that data-binding is supported.

As you can see in the screenshot above, an Extraction Rule’s usefulness extends beyond just OAuth tokens. In my Web Test, I mke a POST to api/sites to create a new site, which returns the new site’s ID. That ID must be used in future API calls I make, so I’ve used an Extraction Rule with a regex pattern to parse the SiteId parameter, stored the parsed value into a Context Parameter, and changed my API call’s URL from the previously hardcoded ID to api/sites/{{SiteId}}. More complex authentication schemes may require a WebTestPlugin, but for basic OAuth 2.0, Extraction Rules is usually all you need and they can go a long way in helping with other scenarios where you need to extract any data from responses for later use.

Leave a Reply

Your email address will not be published. Required fields are marked *