Thursday, August 15, 2013

Test automation framework for API testing :
The following post attempts to enumerate some of the salient features that make an automation easier to use for API testing. APIs such as those that are available over the web as RESTful APIs are great candidates for automations because there is a lot of repetitions and overlaps in the test matrix. The test matrix consists of variations in  protocol such as http or https and their versions, verbs such as GET, PUT, POST, DELETE, etc, endpoints and their ports for test, stage, production environments, endpoint versions, resource qualifiers and their query strings, their response types such xml or json and the request body in the case of post, the content-headers and their various options. A request and response sequence for each API alone constitutes a bulk of the test matrix.
Note that the testing largely relies on default values so that the test scripts are easier to write. Python requests library really help with making the scripts easier to write. One of the primary goals of automation framework is to make it easy to add tests. The lesser the code required to write the tests the lesser the chances of making mistakes, the lesser the frustrations, the easier it is to maintain and hence more popular. Python library enables succinct and terse test scripts. It's cool to write Python scripts.
Besides, UI based tools such as SOAPUI or TestRunner are nice to haves but consider that the primary input and output for REST API testing is all text. Variations in the text, their comparision, serialization and deserialization into objects for comparision with Data access layer are tedious and may need to be specified in the tests. While load testing, performance and call inspectors, capture and replay are undeniably UI features, the automation framework can separate out the UI tests from the scripts and in my case argue for script based framework.
The object model library should be comprehensive because such would be available in the corresponding development code. In fact test should refrain from from rewriting or redefining any or all objects that the requests and responses use. These objects should all be instanted via reflection and can live in properly namespaced development assemblies. Unifying the object model for development and test is not just for convenience, it enforces single maintenance policy and reuse. Code may be tweaked for different purposes in either test side or development side but object model has no reason to be different between test and dev code. To illustrate this point, in a well written development code, if you were to add strongly typed views in a model view controller framework, when you expand the drop down to choose the model for the view, you should be able to see all ( read dozens ) of objects to choose from. The same or similar should be available in test. The data and the object model mapping is also common. When the object model changes and the development code changes, the corresponding tests will break. The more they are tied, the more visible the regressions.
Testing often relies on interpreting data from the layers below the API implementation to compare the expected and actual results from the API. With default values for test scripts and a unified object model collection of assemblies, the test automation will be easier to use, more consistent and organized.
public static string ReverseWords(string s)
{
 var sb = new StringBuilder(s);
 Reverse(sb, 0, sb.Length - 1);
 int start = 0;
 int end = 0;
 for (int i = 1; i < sb.Length; i++)
 {
  if (sb[i - 1] != ' ')
  {
   end++;
   if (sb[i] != ' ')
   {
    continue;
   }
  }
  else
  {
    start = i;
    end = i;
  }
  Reverse(sb, start, end - 1);
  start = i;
  end = i;
 }
 Reverse(sb, start, end);
 return sb.ToString();
}

private static void Reverse(StringBuilder sb, int start, int end)
{
 while (start < end)
 {
  var c = sb[end];
  sb[end] = sb[start];
  sb[start] = c;
  end--;
  start++;
 }
}

Some sample test cases:
string s = "The quick brown fox jumped over the trot";Debug.Assert(s == ReverseWords(ReverseWords(s))) ;Debug.Assert("" == ReverseWords(ReverseWords("")));Debug.Assert("abc" == ReverseWords(ReverseWords("abc")));Debug.Assert("ab bc" == ReverseWords(ReverseWords("ab bc")));Debug.Assert(" ab " == ReverseWords(ReverseWords(" ab ")));Debug.Assert("ab " == ReverseWords(ReverseWords("ab ")));Debug.Assert(" ab" == ReverseWords(ReverseWords(" ab")));

Wednesday, August 14, 2013

testing oauth

Lessons learned today.
OAuth has two core concepts - user and client
user is the one who is identified by the user name and password on the registration site.
client is any application that wants to access users data.
user has to permit a client to do so.

Therefore OAuth is all about mapping users and clients. Testing OAuth is about testing this mapping.
Implementations  represent the users with their ID - usually a GUID.
Similarly clients are represented by their ID - also a GUID.

When user permits a client, the client gets a token. This token is the final result of OAuth authentication and authorization. It manifests the privilege granted by the user to the client. This privilege is quite detailed and scoped as we will see in a moment but it displays as a generated hash that has no meaning. It cannot be guessed or generated by third party.

When the user grants access to a data to a client, the token is generated by the authorizing endpoint which the client then uses to make calls to retrieve the data. The token has an expiry typically set to an hour so that the client can make more than one calls without having to repeat the handshake for every call. The expiry forces the client to request another so that it cannot be misused later and the issuer doesn't have to keep track of the granted privilege or require the client to revoke it.

The token is also granted for a certain scope of the user's data. Not all data may be accessible by the token. In fact the issuer of the token wants the user to scope down the privilege to only the minimum required so that the client can have access to just as much data and no more.  The scope is transparent to the client. This means that the string representing the scope is made up of parts that are understood by the client and defined by the issuer.

The token is responded with a certain state. The state is opaque to the issuer. It is mainly used by the client to keep track of the calls and the callbacks associated with the calls. Since the client sets the state, the client will know if there was a cross site request forgery when the state is tampered.

As we have seen the token issued for the client on behalf of the user, is associated with a privilege for a scope and with with an expiry period.  Testing focuses on this mapping and the result of the OAuth handshake.

Native applications in the OAuth RFC

This post I'm making so that I read up on what the spec says. Its easy to get confused in the labyrinth of terms and use cases so I will focus on select cases.
Implicit client credential grant
The RFC for OAuth calls implicit grant a simplified authorization flow because it issues a client token directly instead of an intermediate authorization code. The client is issued an access token directly because the resource owner is authenticated. When issuing an access token to the client, the client Id is not verfiied.  This is different from what I mentioned in the previous post. The redirect_uri in the token grant is intended to deliver the token to the client. The token may be exposed to the resource owner or other applications with access to the resource owner's user-agent. The access token security says that tokens can be generated or guessed by unauthorized parties and that its delivery should be over the TLS. Further the scope of the token should be as minimal as possible. The authorization server should though not a must verify the client identity.
there is no provisioning to verify that the token presented by a client was indeed issued by the server.
The RFC calls out a section for the native applications.
Native applications are clients installed and executed on the device used by the resource owner. The authorization endpoint requires interaction between the client and the resource owners' user agent. Native applications can invoke an external user-agent or embed a user-agent within the application.
If an external user agent is involved, the application can capture the response from the authorization server using a redirection URI and a callback for the JSON response from the server or manually copy and paste of the credentials or running a local web server or installing a user-agent extension to identify a server hosted resource which in turn makes the response available to the native application
If the user agent is embeded, the native application obtains the response with the redirect_uri and the token by directly communicating with the embedded user-agent such as resource load or cookies.
An external user-agent reassures the user to enter his password since this is going to the same site where he or she has been doing so and may even rely on features that come with the site.  It also offloads the session persistence and sign-on/sign-off from multiple devices for the user. Thi shsould be preferred.
An embedded user-agent removes the need to switch context or open new windows and the client can directly communicate with the user agent over the local device. But it leads to security vulnerabilities such as phising attacks.
When choosing between an implicit grant type and the authorization code grant type, native applications should request the code without the client credentials beacuse the native application cannot keep the client credentials confidential. This is why client id and client secret should not be hardcoded in the application and made avialable in the binary of the installation.
In the implicit grant type, there is no refresh token so on token expiry the authorization process is repated.

Tuesday, August 13, 2013

Password vs implicit grant on OAuth as I understand it

The OAuth implementations need not provide both password and implicit grant methods on the same endpoint. Hence there can be more than one endpoints available to the user agent. In this discussion we will use the following definitions:
User : this is the resource owner. She should have access to her profile via the APIs
User Agent : this is the browser. The mobile phone or an iPhone App can be a user agent as well.
Client : this is the application registered with Mashery. It can make service requests on behalf of the user.
Service: A service is the resource provider and holds all data.
Authorization server: this issues tokens
Note authentication and authorization are two separate parts of the login process. Authentication is assumed to be taken care of by web site using username and password such as in the case of starbucks.com with starbucks.com username and password. If the Starbucks application is official and branded, it has no problems taking the username and password from the user and together with its client id, retrieving a token from the authorization endpoint.
However implicit is required for unofficial developer applications because a user may not be comfortable providing his/her username or password to third party iPhone applications. Here the client inside the user agent will need to redirect the user to the login website along with the client id. The authentication website will redirect back to the user agent with the token so the user agent is only aware of the token and can make use of this token to make subsequent API calls.
We need this website that can accept requests from different clients and enables the user to grant access to these clients. Note that the website needs to be hosted by Starbucks.User Id may not be retrieved and certainly not passed to the client or user agent. The tokens last for 3600 seconds so they can be used across calls. However the token needs to be retrieved with the user context and the client context by the web site.
UserId translation is not required anywhere unless the implicit needs to be supported. In which case, they could be available off the request header. Note that Implicit is not a token provider because it would require userId or the alias me which is not supported by authorization endpoints because there is no way to tie the userId to the sender sending the userId even if the senders are all authenticated. This is the hurdle that needs to be overcome for implicit to work per the specification. The specification does not bar userId based token retrieval however implementations have to secure a lot more in order to fully implement implicit. This doesn't mean it cannot be done, just that there is a lot of difference between a password and a user Id. Besides a userId can be treated as internal to the system. In such cases implicit is never available to a mobile application. A mobile application has a well known route to send its client id over to the authentication website and expect a token back to facilitate further calls on behalf of the user.

REST API callback

A callback is something that you wrap the response of an API call with such as a javascript function. This is typically supported by GET API calls only.
To make a REST call from a web browser across domains, we can use JSONP.
JSONP or JSON with padding provides a method to request data from a server in a different domain. This was previously prohibhited to ensure same origin policy but has since been addressed with Cross-Origin resource sharing (CORS). The same origin policy was overridable with the script tag in HTML5. Some pages use the script tag to retrieve Javascript code that operates on dynamically generated JSON from different origin.
So you can have a script like so:
<script src="your_api_call?callback=printResponse" /> This is the cross domain access supported by JSONP.
Each new JSONP request comes with its own script element or reuses an existing one. In the former case, when the script element is newly added to the document object model, it is referred to as the script element injection.  The current mime type supported by JSONP is "application/javascript". There has been discussion to make it more strict with "application/JSON-P"
Cross site request forgery or xsrf attack is often considered a vulnerability in making cross domain calls, however this is avoided by not using callbacks for sensitive data or using callbacks only with same origin for such data. This enforces that the sensitive data is not in the open unless the request is proper. When programmers rely on cookies alone to determine if the request is valid, it is often vulnerable to cross site request forgery.
In cross origin resource sharing , the website accepting cross domain requests sends an Access-Control-Allow-Origin in its response. The values of the headers indicate which sites are allowed.  To allow access from all site a Access-Control-Allow-Origin : * can be specified. However, this is not advisable unless the API is public with non-sensitive data.
The difference between CORS and JSONP is that JSONP only supports GET methods where as CORS supports other methods. Another difference is that JSONP causes XSS issues when external site is compromised. However, CORS allows websites to manually parse responses to further improve security.
Web messaging or cross domain messaging is used when documents communicate with one another across domains. Here the postMessage method in the messaging API and retrieving the window object of the receiving document, plain text data can directly be posted in an iFrame. The message usually carries the following three attributes : data or the actual content, the origin of the sender and lastly the source or the WindowProxy where the document came from. Window has addEventListener method to receive messages.
Courtesy : Wikipedia.

Monday, August 12, 2013

Javascript & OAuth API calls

Javascript is convenient to make OAuth API calls. User places a simple button to retrieve an OAuth token by way of an API call. The type of OAuth flow required for this could be based on password since it is convenient to ask the user what the password is. This could appear with rich Ajax soft sliding appearance of a text input for password on the click of the token retrieval button. The password entry can then directly be used to make the API calls. Helper libraries from the site hosting this page such as scripts at the root level or framework can be used to simplify the code. Here is an example:
<!DOCTYPE html>
<html>
<head>
<script>
function parseJSON(data) {
    return window.JSON && window.JSON.parse ? window.JSON.parse( data ) : (new Function("return " + data))();
}
function GetAccessToken()
{
if (document.getElementById("password").value == "")
{
alert("Enter your password to retrieve an access token");
return;
}

        var xdr= new XDomainRequest();
        xdr.timeout = 10000;
xdr.onreadystatechange=function()
  {
  if (xdr.readyState==4 && xdr.status==200)
    {
  var resp = parseJSON(xdr.responseText);
  document.getElementById(params[access_token]).innerHTML=resp.access_token;
    }
        }
  xdr.open("POST","https://testhost.openapi.starbucks.com/v1/token/",true);
  xdr.setRequestHeader("Content-type","application/json");
  xdr.send("api_Key="+ document.getElementById("apiKey").value +"&grant_type=password&client_id=" + document.getElementById("apiKey").value + "&username=" + mashery_info.username + "&password=" + document.getElementById("password").value + "&scope=test_scope&client_secret=" + document.getElementById("apiSecret").value);
}
</script>
</head>
<body>

<h2>AJAX</h2>
<button type="button" onclick="GetAccessToken()">Get Access Token</button>
<input type="password" id="password" name="password"  />
<input type="text" name="params[access_token]" value="" placeholder="required" />
</body>
</html>