6

There are many excellent questions (and answers) on S.O. around the subject of REST and security. Many say "purists won't like this, but blah blah"... and then others says "you should never do that, because blah blah".

But I have not seen the solution that the "purists" are suggesting for the following scenario. So my question is - what are the "pure RESTful solutions" to the following scenario?

The simple scenario...

Imagine building a database/website that lets a user manage their favorite recipes. The website exposes a RESTful API so that users can query and manipulate their list from a custom program that they want to write (that utilizes this API).

So, user "A" has 3 favorite recipes with the ID's "1", "2" and "3".

User "B" has 2 favorite recipes with the ID's "4" and "5".

We need to make sure that if user A sends a DELETE command to /Recipes/4 that he will get a Forbidden (403) response.

What I would normally do...

What I would normally do is make them first call an authentication method, and send them some sort of auth-token that is valid for 30 minutes or so. Typically this token would be passed via a cookie.

What is the pure solution?

Is the pure REST solution to have them pass it as a variable in the query string? Are cookies the devil? Should the token be used as a segment of the URL (as opposed to a query string parameter)? Is there something else that answers this question clearly?

Timothy Khouri
  • 31,315
  • 21
  • 88
  • 128
  • 1
    A little pedantic here: I think in your case you would want to give a 403, not a 401. Authentication is with a service, but in your case user A is _forbidden_ to get recipe 4. I know it doesn't answer the question exactly, but worth pointing out. http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html shows the difference. (Reauthentication will not help user A see recipe 4, hence the 403.) – Ray Toal Jun 02 '12 at 02:54
  • Right - actually either one is an issue... first 401 - as in, are you authorized and then secondly 403 - as in, what are your "permissions" - which gets into state/session/usercontext debates... either way, the question remains. Thanks for the clarification! – Timothy Khouri Jun 02 '12 at 02:57
  • 2
    Yes, both are important. The simplest solution is of course basic auth over https. I think that is "pure". Are you looking for alternatives? – Ray Toal Jun 02 '12 at 02:59
  • @RayToal - Basic doesn't give the ability to have the authentication expire after 'n' minutes... and it's awful :) The most-likely consumer of a REST API is a website using JavaScript (probably jQuery). Requiring them to construct the nasty header is ... well, nasty. But that is a "solution", so thank you. – Timothy Khouri Jun 02 '12 at 10:22

3 Answers3

4

Pass the token in the authorization header. That's what it is designed for. See http://greenbytes.de/tech/webdav/draft-ietf-httpbis-p7-auth-12.html

Darrel Miller
  • 139,164
  • 32
  • 194
  • 243
  • I like the idea, but it looks like I would be improperly using the Authentication header possibly... I'll keep looking to see if this is "proper" :) – Timothy Khouri Jun 03 '12 at 20:02
  • @TimothyKhouri What are you seeing that makes you think you would be misusing the auth header? – Darrel Miller Jun 03 '12 at 22:32
  • That header seems to be specific for Basic and Digest Access Authentication: http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.8 – Timothy Khouri Jun 04 '12 at 10:22
  • @TimothyKhouri No, those are just the original implementations. The auth-scheme is intended to be extensible They are in the process of setting up a registry at IANA for people to publish schemes. – Darrel Miller Jun 04 '12 at 11:02
  • @TimothyKhouri Check out the Bearer Token spec and how it uses the authentication header http://self-issued.info/docs/draft-ietf-oauth-v2-bearer.html – Darrel Miller Jun 04 '12 at 11:04
1

Treat the auth token as a resource.

You authenticate by GETting an auth token with parameters being credentials (basic auth over https for example).

Logout by DELETE'ing the auth token resource you got when logging in.

matb33
  • 2,820
  • 1
  • 19
  • 28
  • Right, but how do they pass the token is the same question. Is it via the query string, header, etc, etc. I feel like I've repeated this comment 4 times now - clearly this is a question that has not been (clearly) answered. Also, is that valid/pure to have them pass the token via a header or cookie? – Timothy Khouri Jun 02 '12 at 10:24
  • Via header. This should be helpful: http://stackoverflow.com/questions/549/the-definitive-guide-to-forms-based-website-authentication. That applies to any approach, RESTful or not. With a pure RESTful approach, the auth token is treated as a resource so that it's not an oddball RPC – matb33 Jun 02 '12 at 12:45
0

A simple stateless and cookie free solution would be giving each of your users an identical token.

There are ways to generate those tokens so that they are sparse enough for security concerns.

e.g. https://www.grc.com/passwords.htm

Suppose you have user A and user B. You generate a token X for user A and a token Y for user B.

So the user A will use something like /X/Recipes/1

and user B will use something like /Y/Recipes/4

It's safe because user A is the only one knows his token and as I mentioned before, the way you generate tokens can make sure it's "impossible" for others to guess that token.

So if someone else, like user B uses some other token in the url, say /Z/Recipes/1, you should be able to recognize and return a corresponding error message.

You can let user deliver the token in url, like I showed above, or embed it in HTTP request as Autherticantion message.

xvatar
  • 3,229
  • 17
  • 20
  • You mean a unique token right? If they all have identical tokens then anyone can delete anything... – evanmcdonnal Jun 02 '12 at 02:50
  • 1
    I don't quite follow... I think the question still remains - how are they delivering that "password" - is it with every request in the query string, post, cookie, etc. - This solution has the same questions. – Timothy Khouri Jun 02 '12 at 02:54
  • @xvatar - While it's true that this is a solution (similar to issuing a certificate for every person), it's highly impractical (if I am Facebook with 800 million users). Also, it's highly insecure as the user would basically be forced to hard-code his giant password in his own website or program. Nonetheless, this is a solution, so I thank you and give a hearty +1 :) – Timothy Khouri Jun 02 '12 at 10:16
  • @TimothyKhouri thank you for your +1 :) For your first concern, say FB has 2^30 users, however the total amount of tokens you can generate using that method is 2^512, so I think it's still sparse enough. For your second concern, as long as your user need to provide something, they need to hard-code something somewhere. If you are still concerned, see how [AmazonS3](http://docs.amazonwebservices.com/AmazonS3/latest/dev/RESTAuthentication.html#ConstructingTheAuthenticationHeader) does it. Basically they encrypt the token in the http request – xvatar Jun 02 '12 at 17:09
  • @xvatar - I see what you're saying, but In most cases, people want to invalidate the user after 30 minutes so they have to "log-in" again. So one long-term-hard-coded-token isn't practical for that very common scenario. – Timothy Khouri Jun 03 '12 at 19:57
  • @TimothyKhouri ok.. then i guess you need to maintain a sort of session.. you could use the token to issue a temporary session ID and expire that in 30min though.. anyway, good luck! – xvatar Jun 03 '12 at 20:42