How do I implement login in a RESTful web service?

As S.Lott pointed out already, we have a two folded things here: Login and authentication

Authentication is out-of-scope here, as this is widely discussed and there is common agreement. However, what do we actually need for a client successfully authenticate itself against a RESTful web service? Right, some kind of token, let's call it access-token.

Client) So, all I need is an access-token, but how to get such RESTfully?
Server) Why not simply creating it?
Client) How comes?
Server) For me an access-token is nothing else than a resource. Thus, I'll create one for you in exchange for your username and password.

Thus, the server could offer the resource URL "/accesstokens", for POSTing the username and password to, returning the link to the newly created resource "/accesstokens/{accesstoken}". Alternatively, you return a document containing the access-token and a href with the resource's link:

<access-token
  id="{access token id goes here; e.g. GUID}"
  href="/accesstokens/{id}"
/>

Most probably, you don't actually create the access-token as a subresource and thus, won't include its href in the response.
However, if you do so, the client could generate the link on its behalf or not? No!
Remember, truly RESTful web services link resources together in a way that the client can navigate itself without the need for generating any resource links.

The final question you probably have is if you should POST the username and password as a HTML form or as a document, e.g. XML or JSON - it depends... :-)


You don't "login". You "authenticate". World of difference.

You have lots of authentication alternatives.

HTTP Basic, Digest, NTLM and AWS S3 Authentication

  • HTTP Basic and Digest authentication. This uses the HTTP_AUTHORIZATION header. This is very nice, very simple. But can lead to a lot of traffic.

  • Username/Signature authentication. Sometimes called "ID and KEY" authentication. This can use a query string.

    ?username=this&signature=some-big-hex-digest

    This is what places like Amazon use. The username is the "id". The "key" is a digest, similar to the one used for HTTP Digest authentication. Both sides have to agree on the digest to proceed.

  • Some kind of cookie-based authentication. OpenAM, for example, can be configured as an agent to authenticate and provide a cookie that your RESTful web server can then use. The client would authenticate first, and then provide the cookie with each RESTful request.


Great question, well posed. I really like Patrick's answer. I use something like

-/users/{username}/loginsession

With POST and GET being handled. So I post a new login session with credentials and I can then view the current session as a resource via the GET.

The resource is a login session, and that may have an access token or auth code, expiry, etc.

Oddly enough, my MVC caller must itself present a key/bearer token via a header to prove that it has the right to try and create new login sessions since the MVC site is a client of the API.

Edit

I think some other answers and comments here are solving the issue with an out-of-band shared secret and just authenticating with a header. That's fine in many situations or for service-to-service calls.

The other solution is to flow a token, OAuth or JWT or otherwise, which means the "login" has already taken place by another process, probably a normal login UI in a browser which is based around a form POST.

My answer is for the service that sits behind that UI, assuming you want login and auth and user management placed in a REST service and not in the site MVC code. It IS the user login service.

It also allows other services to "login" and get an expiring token, instead of using a pre-shared key, as well as test scripts in a CLI or Postman.