views:

240

answers:

3

Hey folks, this seems to have been discussion fairly often but I want to make a simple, watered down question around doing authentication with RESTful services. The scenario is as follows:

  • There is a system that houses registered users for an application. The system exposes a RESTful API for accessing these users.
  • There is a front-end application that has a login form. The application can either be internal, or external.
  • The front-end application needs to use the data in the User system to authenticate a user.

The question now is how to authenticate a user whose credentials (username/password) are entered in the client application against the data in the User system such that it is secure and performant? For the sake of this question, suppose the client application is internal to some sort of Intranet but the applications will not reside on the same machine and may only communicate through the service.

I understand the idea of having the application being "hypermedia driven" but we should be able to provide filtering/searching services. For example, consider the resources and API as below:

  • http://example.com/users
    • GET - retrieves all users (paged, hypermedia driven)
    • POST - creates new user
    • PUT/DELETE not supported
  • http://example.com/users/[id]
    • GET - returns a full representation of a user with id = {id}
    • PUT - updates user, takes in any predefined media type
    • DELETE - deletes the user (with appropriate authorization)
    • POST not supported

Based on the above, my idea would be have the client application GET on the user listing, filtering by username. The service will return the hashed password and salt to the client, the client will perform the authentication.

Thoughts?

+1  A: 

First, you don't want the client to perform the authentication, as it then would be trivial to write a client that breaks into your service.

Instead, just use an authentication mechanism like HTTP Basic or HTTP Digest.

Note that if you're using Java, the Restlet framework provides interceptors, called Guards, which support these and other mechanisms. I highly recommend Restlet.

Jim Ferrans
A: 

If I understand your question correctly, you are looking to implement a generic service that will handle authentication, so that you can re-use it for different applications.

I suggest you take a look at OAuth which has been built for precisely this problem domain.

Stefan Tilkov
A: 

Passing the username and the salt back is unnecessary and a real security risk.

Perhaps you could consider this approach:

Have the client pass the username and password to the server via Basic Authentication

The server fetches the encrypted password for the username along wiht the salt

The server encrypts the given password using some encryption method, using the salt to assist the algorithm (Ruby code follows):

def User.authenticate(login, password)
    ok = false

    user = User.find_by_login(login)

    if user
        #
        #   user contains the salt, it isn't passed from the client
        #  
        expected_password = hash_password(password, user.salt)

        ok = (user.password == expected_password)
    end

    return ok
end

There are multiple places to use this kind of approach but I like to do it in Rack.

Last point, do it all on a HTTPS connection

Chris McCauley