MarkUs Blog

MarkUs Developers Blog About Their Project

MarkUs API Authentication Scheme

with 4 comments

The last couple of days I’ve been thinking of a way to do user authentication for MarkUs’ Web API. This is what I’ve come up so far. Feedback and suggestions are very welcome.

  1. Instructors and TAs will be able to get a “key” via MarkUs. When an instructor logs in the API key (a SHA2 512 bits in length) is displayed to him on the dashboard. TAs will see the key below the list of the assignments when they log in.
  2. The goal is that the private key never shows up in a script.
  3. In order to use this key for authentication from within a script the following steps are required:
    1. A MD5 hash of the private key has to be generated.
    2. This MD5 hash will be then encoded using Base 64 and the result will be used as a token and travels over the wire for each request.
    3. The token, generated as described above, will be sent to the MarkUs server by facilitating the HTTP header “Authorization”. I.e. each request sent to the MarkUs API has to include this header with the appropriate token.
    4. Since MarkUs knows about the private key and that the token is a Base 64 encoded MD5 digest of the key a matching user can be easily determined and the private key never has to be included in scripts on semi-private servers, where the scripts are run.

I was thinking that the Authorization HTTP header (which is otherwise used for Basic or Digest schemes) could have the following form:

Authorization: MarkusCustom MDk4ZjZiY2Q0NjIxZDM3M2NhZGU0ZTgzMjYyN2I0ZjYK

So far my thoughts. What do you think? Concerns? Am I on the wrong track? Thanks!

Written by Severin

December 30th, 2009 at 6:41 am

Posted in Uncategorized

4 Responses to 'MarkUs API Authentication Scheme'

Subscribe to comments with RSS or TrackBack to 'MarkUs API Authentication Scheme'.

  1. There are lots of things to worry about in authentication/authorization schemes, depending on what threats you’re trying to defend against.

    The main issue with this scheme is that the so-called private key is irrelevant – anyone who can send you the hash value will authenticate successfully, and that hash value is included in the script. That means anyone who can get their hands on a script can impersonate that script’s owner.

    Turns out that the general problem of having a script authenticate to a server on behalf of a user is pretty much impossible to solve, so you’re always going to have to compromise somehow. Using a token like in your scheme is a step up from putting the owner’s username/password in the script.

    Irving Reid

    30 Dec 09 at 1:33 pm

  2. Severin:

    It sounds good to me – but it might be worth trying to leverage some previous experience on this. Reading the Basie Blog, it looks like Bill Konrad has really been heading up the REST API over there. It might be worth firing off an email to him and seeing how he recommends performing authentication.

    -Mike

    Mike C

    30 Dec 09 at 1:35 pm

  3. Many thanks for the feedback. Two reasons why I think HTTP’s basic and digest authentication won’t work easily for us. Hence the slightly non-standard Authorization HTTP header.

    1.) Both schemes use the username/password as a basis for the digest. In ‘basic’ the password is hashed; in ‘digest’ the username and the password. When using this ‘key’ we decouple it more from the username/password combination of the user.

    2.) How would we find out if the username/password combination is correct? When we would use ‘basic’ we would have to pass the hashed password to our third party authentication script. I.e. our sysadmin would have to change it (I believe).

    Another reason why I prefer the proposed mechanism is that the user has to log in to MarkUs in order to get the key. But this has to be done only once (i.e. the third party program for authentication is used only once instead of each time when an API request comes in). Also, the key is decoupled from username/password combinations of our users. That means if some token is lost or stolen, we could easily implement a control to let users/admins reset the “private” keys. Alternatively, we could automatically expire the tokens each week (or day or hour). I’m not sure if we want that, though.

    @Irving: I agree with you that the “private” key seems to be irrelevant when the Base64 encoded MD5 hash of the key is in the script. However, as noted above, we can reset the keys – hence, also the MD5 hash on the server.

    Overall, I think this is flexible, simple and secure enough for our purposes. The neat thing is – as I find – that we don’t need to query the third party authentication program for API requests. Although that might not even be a concern.

    Thanks again, and let me know if I’m missing something.

    Severin

    30 Dec 09 at 4:32 pm

  4. This is basic “shared secret” authentication – the client sends a secret, the server verifies that secret against a stored reference value. The fact that that secret is generated by hashing something else doesn’t add value beyond any other way of making that secret hard to guess.

    Other things to consider: Have the client send the randomly generated key as “plaintext” and the server to hash that and compare it to a stored hash (like Unix passwords). That way access to the server-side database doesn’t yield usable secrets. The server would create the key, display it to the user, then hash it and only store the hash. In your case probably not necessary, since anyone who can get at the server-side database already has more power than the user.

    Time limiting the keys helps, as does giving the user ability to revoke them manually. Another option would be delegate a limited subset of user privileges to the key so that stolen keys can’t do everything the user could; this might be overkill for your use case.

    Irving Reid

    30 Dec 09 at 5:33 pm

Leave a Reply