5

I'm in the process of developing a REST service that allows a user to claim their listing based on a couple of pieces of information that appear on their invoice (invoice number and billing zip).

I've read countless articles and Stack Overflow questions about when to use GET and when to use POST. Overall, the common consensus is that GET should be used for idempotent operations and POST should be used for operations that create something on the server side. However, this article:

http://blog.teamtreehouse.com/the-definitive-guide-to-get-vs-post

has caused me to question using GET for this particular scenario, simply because of the fact that I'm using these 2 pieces of information as a mechanism to validate the identity of the user. I'm not updating anything on the server using this particular method call, but I also don't necessarily want to expose the information in the URL.

This is an internal web service and only the front-end that calls the service is publicly exposed, so I don't have to worry about the URL showing up in a user's browser history. My only concern would be the unlikely event that someone gain server log access, in which case, I'd have bigger problems.

I'm leaning toward POST for security reasons; however, GET feels like the correct method due to the fact that the request is idempotent. What is the recommended method in this case?

Luke
  • 768
  • 2
  • 14
  • 33

3 Answers3

5

Independently of POST vs GET, I would recommend NOT basing your security as something as simple as a zip code and an invoice number. I would bet on the fact that invoice numbers are sequential (or close), and there aren't that many zip codes around - voila, I got full access to your listings.

If you're using another authentication method (typically in HTTP header), then you're good - it doesn't matter if you have an invoice number if the URL, so might as well use GET.

If you're not, then I guess POST isn't as bad as GET in term of exposing confidential content.

ptyx
  • 4,074
  • 1
  • 19
  • 21
  • Thanks for the reply. This confirms my thoughts on the topic, even though POST feels wrong for idempotent requests. While I agree that a more secure method of validation could be used, this is a business requirement, and I suppose would be the topic of a different discussion. – Luke Apr 17 '13 at 13:30
0

There isn't really any added security in a POST vs a GET. Sure, the request isn't in the URL, but it's REST we are talking about here, and the URL wouldn't be seen by a human anyway.

Lennart Regebro
  • 167,292
  • 41
  • 224
  • 251
  • Correct. I understand that there is no inherent security in either method, only that POST params wouldn't show up in a log file. Like you said, I guess it doesn't matter so much when it's a REST request. – Luke Apr 17 '13 at 13:12
  • Some people make the argument that POST is more secure because web servers can log URLs and leak data to a place is wasn't meant to be. I don't really think this is a practical concern but the theory is out there. – whitneyland Feb 19 '14 at 15:54
  • @LeeWhitney Good point. Well, in any case you definitely should not send passwords with a GET. :-) – Lennart Regebro Feb 19 '14 at 16:43
  • @LennartRegebro it's not `GET` that is the problem, it's unsecured HTTP requests. – thecoshman Aug 10 '15 at 14:07
0

You question starts with some bad presumptions. Firstly, GET is not just for any old idempotent operation, it is for GETting resources from the server; it just happens that doing so should be side effect free. Secondly, the URL is not the only way for a GET request to send data to the server, you can use a payload with a GET request (at least as far as HTTP is concerned, some implementations are bad and don't support this or make it hard). Third, as pointed out, you have chosen some terrible data fields to secure your access. Finally, you are using a plain text protocol any way, so what neither method really offers and better security.

You should use the the verb that best describes what you are doing, you are getting some information from the server, so use GET. Use some proper security, such as basic HTTPS encryption. If you want to avoid these fields 'clogging' up the URL, you can send data in the payload of the request, something like:

GET /listings HTTP/1.1
Content-Type = application/json

{ "zip"     : "IN0N0USZ1PC0D35",
  "invoice" : "54859081145" }
thecoshman
  • 8,394
  • 8
  • 55
  • 77