Saturday 5 November 2011

Authentication and Authorization

When securing your web service there are two main things you need to worry about. Authentication and Authorization. 

I am sure everyone is familiar with authentication, since every time we log into Facebook  or our banks website we need to enter our user name and passwords. This is then verified against the user name and password set when you created your account for authentication. 

Once you are authenticated you are restricted to only viewing and editing content that you are authorized to view. In Facebook, you are not authorized to edit strangers profiles and you are not authorized to access the administrators endpoints.  

For each endpoint you visit on the web service you need to be both authorized and authenticated. Typically with web pages you would use http authentication schemes such as basic access authentication or  digest access authentication. Then depending on how secure your service needs to be, you can use TSL  to encrypt all communication. Once a user is authenticated they stay logged in for the session and don't need to authenticate again. However, one of the principles of REST is that it is stateless, so we shouldn't be saving session data between calls to the server. For each call to an endpoint we should be sending enough data to the sever to authenticate the user. 

For this project I decided to use 2 legged oAuth, since the client will be written in actionscript and not an http web browser. Well truth be told, there is no actual 2 legged oAuth 1.0. So I am using a cut down version, where we use the consumer key and consumer secret to authenticate the client and use the oAuth signature methods to validate them. Since REST is stateless we need to send enough information to authenticate the user with each call to the endpoint. We could send an oAuth signature with each call but instead I:
-  Have the user log in which uses oAuth to authenticate the users.
- We then create a session key to save into our DB and return it to the user.
- Each subsequent call I include the session key with the call and use that to identify the user. 

Unless you secure the connection with TLS there are some obvious security issues,  such as someone packet sniffing can getting your session key. Or someone could guess your session key, so we make sure that they expire within a short time of not hearing from the users. The more I think about it the less I like creating a session key and the more I like the idea of using oAuth to authenticate each call. It would be more secure since we don't have a session key to hijack.

Where authentication is checked once up front, authorization is something that has to be integrated all over your code. First off you can restrict the access to endpoints by using the jersey annotation @RolesAllowed, such as:
       @PUT
       @Consumes(MediaType.APPLICATION_XML)
       @RolesAllowed({Role.ADMIN_STRING, Role.CS_STRING, Role.USER_STRING})
       public DetailedCustomerTrans updateCustomer(DetailedCustomerTrans custTrans)

But that doesn't help when you have an endpoint that allows a user to update their details. All customers have access to that endpoint, but you don't want to authorize Customer A to edit Customer B's data. So you need to specifically code those business rules into your program.

No comments:

Post a Comment