views:

121

answers:

4

Overview

I'm looking to create a (REST) API for my application. The initial/primary purpose will be for consumption by mobile apps (iPhone, Android, Symbian, etc). I've been looking into different mechanisms for authentication and authorization for web-based APIs (by studying other implementations). I've got my head wrapped around most of the fundamental concepts but am still looking for guidance in a few areas. The last thing I want to do is reinvent the wheel, but I'm not finding any standard solutions that fits my criteria (however my criteria my be misguided so feel free to critique that as well). Additionally, I want the API to be the same for all platforms/applications consuming it.

oAuth

I'll go ahead and throw out my objection to oAuth since I know that will likely be the first solution offered. For mobile applications (or more specifically non-web applications), it just seems wrong to leave the application (to go to a web-browser) for the authentication. Additionally, there is no way (I am aware of) for the browser to return the callback to the application (especially cross-platform). I know a couple of apps that do that, but it just feels wrong and gives a break in the application UX.

Requirements

  1. User enters username/password into application.
  2. Every API call is identified by the calling application.
  3. Overhead is kept to a minimum and the auth aspect is intuitive for developers.
  4. The mechanism is secure for both the end user (their login credentials are not exposed) as well as the developer (their application credentials are not exposed).
  5. If possible, not require https (by no means a hard requirement).

My Current Thoughts on Implementation

An external developer will request an API account. They will receive an apikey and apisecret. Every request will require at minimum three parameters.

  • apikey - given to developer at regisration
  • timestamp - doubles as a unique identifier for each message for a given apikey
  • hash - a hash of the timestamp + the apisecret

The apikey is required to identify the application issuing the request. The timestamp acts similarly to the oauth_nonce and avoids/mitigates replay attacks. The hash ensures that request was actually issued from the owner of the given apikey.

For authenticated requests (ones done on the behalf of a user), I'm still undecided between going with an access_token route or a username and password hash combo. Either way, at some point a username/password combo will be required. So when it does, a hash of several pieces of information (apikey, apisecret, timestamp) + the password would be used. I'd love feedback on this aspect. FYI, they would have to hash the password first, since I don't store the passwords in my system without hashing.

Conclusion

FYI, this isn't a request for how to build/structure the API in general only how to handle the authentication and authorization from solely within an application.

Random Thoughts/Bonus Questions

For APIs that only require an apikey as part of the request, how do you prevent someone other than the apikey owner from being able to see the apikey (since sent in the clear) and make excessive requests to push them over usage limits? Maybe I'm just over thinking this, but shouldn't there be something to authenticate that a request was verified to the apikey owner? In my case, that was the purpose of the apisecret, it is never shown/transmitted without being hashed.

Speaking of hashes, what about md5 vs hmac-sha1? Does it really matter when all of the values are hashed with with sufficiently long data (ie. apisecret)?

I had been previously considering adding a per user/row salt to my users password hash. If I were to do that, how could the application be able to create a matching hash without knowing the salt used?

+5  A: 

The way I'm thinking about doing the login part of this in my projects is:

  1. before login the user requests a login_token from the server. These are generated and stored on the server on request, and probably have a limited lifetime.

  2. to login the application calculates the hash of the users password, then hashes the password with the login_token to get a value, they then return both the login_token and the combined hash.

  3. The server checks the login_token is one that it has generated, removing it from its list of valid login_tokens. The server then combines its stored hash of the users password with the login_token and check that that matches the submitted combined token. If it matches you have authenticated your user.

Advantages of this are that you never store the users password on the server, the password is never passed in the clear, the password hash is only passed in the clear on account creation ( though there may be ways around this), and it should be safe from replay attacks as the login_token is removed from the DB on use.

Michael Anderson
Thanks, I forgot to add the part about hashing the password on the application side. I don't store my users passwords in the clear (I hash before storing).
jsuggs
+2  A: 

So what you're after is some kind of server side authentication mechanism that will handle the authentication and authorisation aspects of a mobile application?

Assuming this is the case, then I would approach it as follows (but only 'cos I'm a Java developer so a C# guy would do it differently):

The RESTful authentication and authorisation service

  1. This will work only over HTTPS to prevent eavesdropping.
  2. It will be based on a combination of RESTEasy, Spring Security and CAS (for single sign on across multiple applications).
  3. It will work with both browsers and web-enabled client applications
  4. There will be a web-based account management interface to allow users to edit their details, and admins (for particular applications) to change authorisation levels

The client side security library/application

  1. For each supported platform (e.g. Symbian, Android, iOS etc) create a suitable implementation of the security library in the native language of the platform (e.g. Java, ObjectiveC, C etc)
  2. The library should manage the HTTPS request formation using the available APIs for the given platform (e.g. Java uses URLConnection etc)
  3. Consumers of the general authentication and authorisation library ('cos that's all it is) will code to a specific interface and won't be happy if it ever changes so make sure it's very flexible. Follow existing design choices such as Spring Security.

So now that the view from 30,000ft is complete how do you go about doing it? Well, it's not that hard to create an authentication and authorisation system based on the listed technologies on the server side with a browser client. In combination with HTTPS, the frameworks will provide a secure process based on a shared token (usually presented as a cookie) generated by the authentication process and used whenever the user wishes to do something. This token is presented by the client to the server whenever any request takes place.

In the case of the local mobile application, it seems that you're after a solution that does the following:

  1. Client application has a defined Access Control List (ACL) controlling runtime access to method calls. For example, a given user can read a collection from a method, but their ACL only permits access to objects that have a Q in their name so some data in the collection is quiety pulled by the security interceptor. In Java this is straightforward, you just use the Spring Security annotations on the calling code and implement a suitable ACL response process. In other languages, you're on your own and will probably need to provide boilerplate security code that calls into your security library. If the language supports AOP (Aspect Oriented Programming) then use it to the fullest for this situation.
  2. The security library caches the complete list of authorisations into it's private memory for the current application so that it doesn't have to remain connected. Depending on the length of the login session, this could be a one-off operation that never gets repeated.

Whatever you do, don't try to invent your own security protocol, or use security by obscurity. You'll never be able to write a better algorithm for this than those that are currently available and free. Also, people trust well known algorithms. So if you say that your security library provides authorisation and authentication for local mobile applications using a combination of SSL, HTTPS, SpringSecurity and AES encrypted tokens then you'll immediately have creditibility in the marketplace.

Hope this helps, and good luck with your venture. If you would like more info, let me know - I've written quite a few web applications based on Spring Security, ACLs and the like.

Gary Rowe
Thanks, good info. Couple of questions. First, if eavesdropping is acceptable (not sure whether it is/isn't, my application in mind doesn't have any real personal/valuable information, but if it did my rationale would change) then is HTTPS actually required?
jsuggs
You can operate the overall system outside of HTTPS if you like. HTTPS is only to protect secret information, so I'd assume that during the authentication phase you'd do that through HTTPS to provide some guarantee that your username/password/secret is kept secret. After the token is handed over in the response then further requests can be made in the clear if the information contained in the stream (that required authentication to obtain) does not need protection from eavesdroppers.
Gary Rowe
Also, this description of the CAS authentication protocol may be useful: http://www.jasig.org/cas/protocol
Gary Rowe
+2  A: 

That's a whole lot of questions in one, I guess quite a few people didn't manage to read all the way to the end :)

My experience of web service authentication is that people usually overengineer it, and the problems are only the same as you would encounter on a web page. Possible very simple options would include https for the login step, return a token, require it to be included with future requests. You could also use http basic authentication, and just pass stuff in the header. For added security, rotate/expire the tokens frequently, check the requests are coming from the same IP block (this could get messy though as mobile users move between cells), combine with API key or similar. Alternatively, do the "request key" step of oauth (someone suggested this in a previous answer already and it's a good idea) before authenticating the user, and use that as a required key to generate the access token.

An alternative which I haven't used yet but I've heard a lot about as a device-friendly alternative to oAuth is xAuth. Have a look at it and if you use it then I'd be really interested to hear what your impressions are.

For hashing, sha1 is a bit better but don't get hung up about it - whatever the devices can easily (and quickly in a performance sense) implement is probably fine.

Hope that helps, good luck :)

Lorna Mitchell
Thanks for the response. I have been looking into xAuth and that could be the route I go so that I can end up with an oAuth installation, which makes for a more standardized process for interacting with the API.
jsuggs
+2  A: 

Twitter addressed the external application issue in oAuth by supporting a variant they call xAuth. Unfortunately there's already a plethora of other schemes with this name so it can be confusing to sort out.

The protocol is oAuth, except it skips the request token phase and simply immediately issues an access token pair upon receipt of a username and password. (Starting at step E here.) This initial request and response must be secured - it's sending the username and password in plaintext and receiving back the access token and secret token. Once the access token pair has been configured, whether the initial token exchange was via the oAuth model or the xAuth model is irrelevant to both the client and server for the rest of the session. This has the advantage that you can leverage existing oAuth infrastructure and have very nearly the same implementation for mobile/web/desktop applications. The main disadvantage is that the application is granted access to the client's user name and password, but it appears like your requirements mandate this approach.

In any case, I'd like to agree with your intuition and that of several other answerers here: don't try to build something new from scratch. Security protocols can be easy to start but are always hard to do well, and the more convoluted they become the less likely your third-party developers are to be able to implement against them. Your hypothetical protocol is very similar to o(x)Auth - api_key/api_secret, nonce, sha1 hashing - but instead of being able to use one of the many existing libraries your developers are going to need to roll their own.

lantius
I should also point out that it looks like the 'skip request token' endpoint is going to be in oAuth 2, it's listed in the current draft as the "password" access grant type. See section 4.1.2: http://tools.ietf.org/html/draft-ietf-oauth-v2-10#section-4.1.2
lantius
Like I mentioned to Lonra, I am looking more into xAuth and specifically for the reasons you mentioned at the end...developers can you "off the shelf" oAuth tools/libs to interact with my API, which is "a good thing".
jsuggs