REST & Security: More about the DominoStatelessTokenServlet

During the last days I have refined the DominoStatelessTokenServlet a little bit. It is now a pre-beta release, and I think it is time to explain some details about it. While it is still a proof-of-concept, it demonstrates how a stateless authentication can easily be implemented. A lot of testing is still required until it is ready for production use, but I think it provides really cool things for the domino environment.

First, it fixes the problematic 200er HTTP response code when an authentication was not successfull. Then it introduces a higher security level for web based applications, because the authentication token is only transferred in the HTTP headers: A CSRF attack as shown here is not possible anymore. The authentication works accross multiple servers / clusters, which can become interesting for example when you want to share the authentication securely between a Bluemix hosted application and your companies hosted infrastructure; the token is created from a server running in your company, and is then used to identify a user in the cloud-based application (It’s a real authentication, not a „misused authorization“ like OAuth).

The token can also be safely stored in an mobile app: When the device gets lost, the user credentials are not compromised. And it allows to create different tokens for different applications for the same user (currently not implemented).

As a short demonstration, I have added a Angular JS example (with a hardcoded token) to  show how it works in practise: An AJAX request is sent to the servlet, and the JSON response contains the name of the current Domino user.

The HTML page is not really complicated, it will just show the returned username:

<!doctype html>
<html ng-app>
   <head>
      <title>Hello AngularJS</title>
      <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.0.8/angular.min.js"></script>
      <script src="hello.js"></script>
   </head>
   <body>
      <div ng-controller="Hello">
         <p>Hello {{greeting.username}}!</p>
      </div>
   </body>
</html>

The „Hello“ controller which performs the AJAX request adds the „X-AUTH-TOKEN“ to the HTTP headers of the request:

function Hello($scope, $http) {

   // add a valid token to the headers
   $http.defaults.headers.common['X-AUTH-TOKEN'] = 
     'MTQyNDI2OTE0NDgxNCFUVGVzdFVzZXIwMQ==!HyC1mnvvdaneLaW0Wn48kZ1MaTrdowr1e4nWBRWRX8Y=';

   // load the data
   $http.get('http://localhost/token/validate/').
      success(function(data) {
         $scope.greeting = data;
      });

}

And this is the result:

StatelessToken 01 - Validate Token

The Token consist of two parts: The data part, and the Hmac hash of the data. Both are Base64 encoded, and when the data part is decoded, you can currently see the username and the timestamp of the token generation:

  • Encoded
MTQyNDI2OTE0NDgxNCFUVGVzdFVzZXIwMQ==
  • Decoded
1424269144814!TTestUser01

Because the data are hashed it is not possible to modify them. The timestamp is validated from the servlet; as soon it is too old, it is not longer valid.

To create a token, the servlet must be currently opened with the username and the password as URL parameters:

http://localhost/token/create/?username=TTestUser01&password=test01

In the response, the newly generated token is added to the HTTP headers:

StatelessToken 02 - Create Token

In the servlet configuration (web.xml), a backend user is defined on whose behalf a lookup to the NAB is made to verify the provided HTTP password.  The password for the hash is also stored there, and the maximum age of the token.

Dieser Beitrag wurde unter Allgemein, Java, REST, Security, Web abgelegt und mit , , , , , , , , verschlagwortet. Setze ein Lesezeichen auf den Permalink.

12 Antworten zu REST & Security: More about the DominoStatelessTokenServlet

  1. Mark Roden sagt:

    Fascinating – watching with great interest 🙂

    thanks !!

  2. I’m wondering why using this token approach is in your opinion better then relying for all requests on the server authentication mechanisms.

    • To be more specific (I saw that my previous post could be misunderstood):

      Do you say that you only rely on the token after the first authentication – or that server authentication will be always part of your approach?

    • Using session based authentication violates the principles of REST. It stores a state on the server. Basic authentication is a no go because it stores the credentials in the browser until it is closed, and the password is always sent over the wire.

      Maybe I move the whole authentication deeper in the webcontainer and create an own authengine.

      • I’m aware of the „issues“ of the several authentication mechanisms. And I know several implementations where token based authorization for REST services is used.

        But in most all of them the consuming client receives the token based on a previous authentication. So what – in your final target scenario – is the way to safely authenticate the user so that he’ll receive a token?

        • As described in the blog post, a way to create a token is already implemented: it currently uses the username and the password and validates it agains the HTTP password stored in Domino (via HTTP GET, should be POST).

          But you are free to change it to whatever you want: If you have a mobile app, you could send the token via SMS or send the token with APN / GCM.

          • Whoops. The credentials via SMS, not the token.

          • The GET solution means that username and password are submitted in clear text over the wire as part of the URI. So if I’m using that i. e. in a public wifi the credentials are more then easily „re-usable“ by the hotspot provider…

            As I understood the final plan is to use a SSL-enabled POST with the real user credential (minimum every hour) to the REST service. And not using the server’s HTTP authentication mechanisms. Right?

            One thing that should be taken into account is that a „bad admin“ can easily dump the POST data on the server side and get the user passwords.

          • Yes, the final plan is to not use the authentication mechanisms provided of the HTTP server on top of Domino. The complete XPages engine overrides this part (think about „sessionAsSigner“).

            Thanks for highlighting of the GET problem:
            While I thought this was clear enough, it can’t be repeated often enough, that HTTP GET is not secure. But for testing purposes it is a lot easier to work with GET requests, especially the load testing is less painfull.

            A „bad admin“ can do „bad things“ already today. He can run every code in the name of every user he wants, without any password. So why should he try to intercept logins? But if he wants to intercept them he can do this today on a running Domino in a few minutes.

          • Woops again:
            With SSL, your wifi hotspot provider wouldn’t see the URI of a HTTP GET.

            But he could see the unencrypted POST traffic.

  3. Excellent post Sven. I’m enjoying your REST security posts as it’s a topic I’m looking to learn more of.

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert