OAuth For HTTP and REST API Authentication

Authentication is to verify users are really whom they claim they are. Since its inception, HTTP(s) has used different approaches like BASIC authentication, Form based authentication. Both require passing the user name and password from the client to the server. It’s definitely not good idea to use HTTP because the password is passed as it is or with very limited encoding like BASE64 – very easy to intercept the IP packets and extract out the password. When HTTPs is used, it’s much harder to get the password as all the traffic are encrypted. Still it’s subject to attacks like man-in-the-middle.

When it comes to REST APIs, the authentication is trickier than normal browser interactions. For one thing, once REST API is compromised the impact can be much larger than normal user manual interactions – automation scripts can read, or ever worse delete, all the information in a very short of time. So the stake is higher for REST APIs on authentication.

Bothered by SLOW Web UI to manage vSphere? Want to manage ALL your VMware vCenters, AWS, Azure, Openstack, container behind a SINGLE pane of glass? Want to search, analyze, report, visualize VMs, hosts, networks, datastores, events as easily as Google the Web? Find out more about vSearch 3.0: the search engine for all your private and public clouds.

The RFC 6749 is designed for this purpose. The VMware SSO is following the protocol. So reading the RFC will definitely help understand VMware SSO.

The standard can be used for single sign on, and it can also be used for client and server. For the latter case, Message Authentication Code (MAC) token is used.

In very simple words, it works like this. The server creates a pair of access token and secret key, which are sent to a client securely, maybe using a different media. In every request the client sent to the server, the secret key is used to sign a message consisting of current time in second since 1970-1-1, a random message, HTTP request method (all upper case), relative path, server hostname or IP address, port number, joined by “\n”. The following example shows a message from the draft of OAuth 2.0 Message Authentication Code (MAC) Tokens:

1336363200\n
dj83hs9s\n
GET\n
/resource/1?b=1&a=2\n
example.com\n
80\n
\n

The generated hash is then encoded with BASE64 so that it can be transported with HTTP protocol as other text.

The above string hashed by secret key 489dks293j39 is 6T3zZzy2Emppni6bzL7kdRxUWL4= after BASE64 encoding. The result in the draft (bhCQXTVyfj5cmA9uKkPFx1zeOXM=) is unfortunately incorrect. This is a very trick part of the protocol – even if you miss one space, the result will be totally different.

It’s a good idea to try a known set of input and check the result to see if your code is correct. If you try on a live system, the input data is always change at least the timestamp thus does the MAC string. Because the timestamp is part of the message, be sure to sync up the time of client and server. The easier thing to do is to sync them all to a NTP server.

The following is a complete Java code that shows how to generate the hash and then encode it:


package org.doublecloud.oauth2;

import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import javax.crypto.Mac;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
import javax.xml.bind.DatatypeConverter;

/**
 *
 * @author Steve Jin (http://www.doublecloud.org)
 */
public class MacDigestApp
{
  public static void main(String[] args) throws NoSuchAlgorithmException, InvalidKeyException 
  {
    String message = "1336363200\n"
            + "dj83hs9s\n"
            + "GET\n"
            + "/resource/1?b=1&a=2\n"
            + "example.com\n"
            + "80\n"
            + "\n";

    String token = "h480djs93hd8";
    String secret = "489dks293j39";
    String ALG = "HMACSHA1";

    SecretKey signKey = new SecretKeySpec(secret.getBytes(), ALG);

    Mac mac = Mac.getInstance(ALG);
    mac.init(signKey);

    byte[] digest = mac.doFinal(message.getBytes());
    System.out.println("Len of Digest: " + digest.length);
    String digestMsg = DatatypeConverter.printBase64Binary(digest);

    System.out.println(digestMsg);
  }
}

If you want to design a Web application or REST API, you have more work to do – get live information and repeat the process on the server side to validate the MAC string. In any case, do NOT pass secret key on the wire (probably except the first time for once). That is why OAuth2 MAC authentication is much securer than its predecessors.

This entry was posted in Software Development and tagged , , , . Bookmark the permalink. Post a comment or leave a trackback: Trackback URL.

Post a Comment

Your email is never published nor shared. Required fields are marked *

*
*

You may use these HTML tags and attributes <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>

  • NEED HELP?


    My company has created products like vSearch ("Super vCenter"), vijavaNG APIs, EAM APIs, ICE tool. We also help clients with virtualization and cloud computing on customized development, training. Should you, or someone you know, need these products and services, please feel free to contact me: steve __AT__ doublecloud.org.

    Me: Steve Jin, VMware vExpert who authored the VMware VI and vSphere SDK by Prentice Hall, and created the de factor open source vSphere Java API while working at VMware engineering. Companies like Cisco, EMC, NetApp, HP, Dell, VMware, are among the users of the API and other tools I developed for their products, internal IT orchestration, and test automation.