RESTful user authentication service

2019-03-19 11:54发布

问题:

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:

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.



回答2:

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



回答3:

Stormpath

Stormpath company dedicated to providing a user login management API and service for developers. They use a REST JSON approach.

There are some other companies that seem to dabble in this new area of authentication-as-a-service, but Stormpath is the only one I know of that is dedicated to it.



回答4:

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.



回答5:

Mozilla Persona

Since this question was posted, the Mozilla Foundation (the maker of the Firefox browser) has taken on the problem of simple user authentication. Their solution is Mozilla Persona, "a sign-in system for the Web". Designed to be easy for users and for developers. The user's identity is an email address. See Wikipedia article.

Update

Mozilla has basically given up work on Persona but not quite killed the project.