4

I have an HTTP serving an API which works either anonymously or with a secret key in a header, like so:

GET /profile?authenticationKey
Authorization: 1234567890

I want to reject any request coming in over HTTP that uses an Authorization header, since those headers would come across in plain text. But I'm not sure what the appropriate response is.

I've considered 400 Bad Request with a note explaining why what they did was stupid and suggesting that they immediately invalidate their key.

But I'm wondering whether 426 Upgrade Required might be better or worse. It's a code specific to the idea that an HTTP request needs to be an HTTPS request, but reading RFC 2817 makes me think that it is designed to help switch to HTTPS from the same port. Can I use it in this case as well? If so, do I need to include an Upgrade: TLS/1.0 header as well?

2
  • 1
    No, this is not a protocol upgrade. Oct 27, 2015 at 19:37
  • Does 426 need to be used only for protocol upgrades? Alternately, if I respond as described above, are there some clients that might attempt to automatically the protocol if I did this? Oct 27, 2015 at 19:42

1 Answer 1

8

The situation you are trying to avoid here is that of API users sending their credentials over the wire in a form easily sniffed by third parties.

If you either redirect to HTTPS or serve any HTTP error, you don't avoid this situation; the credentials are already sent before you have a chance to respond.

The only really proper thing to do is to not serve the API on HTTP at all, not even for anonymous requests. For your API server, ideally there should not be a server listening on port 80 at all. If you must have that IP address listening on port 80 (e.g. because you don't have any spare IP addresses), then you should return 403 Forbidden or 404 Not Found for API requests. Optionally you could capture and invalidate such credentials as were sent mistakenly over HTTP, but it's best to simply not listen on HTTP at all.

5
  • I'll give you a real world example of this sort of problem. Amazon S3 is a RESTful API that works on HTTP and HTTPS. It supports optional customer-provided encryption keys, which are transmitted in a header. Most users do not use that feature, but if they do want to use it, they must use HTTPS. Are you saying that the only really proper thing for S3 to do is not support HTTP at all? Oct 27, 2015 at 20:47
  • The users don't have to use HTTPS in that scenario, but then their credentials go out over the wire exposed. If you want to completely eliminate this possibility, you can't offer your API via HTTP at all. Oct 27, 2015 at 20:49
  • Well, in any case, S3's actual decision, to simply allow the request to succeed while ignoring the headers completely, therefore storing the objects in plaintext, appears to be completely insane. So I will allow that your option is better, although I still think a 400 is a perfectly valid response. Oct 27, 2015 at 22:06
  • 1
    @Bob From the RFC: "The 400 (Bad Request) status code indicates that the server cannot or will not process the request due to something that is perceived to be a client error (e.g., malformed request syntax, invalid request message framing, or deceptive request routing)." I guess that sort of fits, but it's hardly ideal. Oct 27, 2015 at 22:10
  • I'm unsure of how "not listening on port 80" prevents the request from being intercepted by a third party? I agree the client is making a mistake... but even if there's no listener on port 80, I assume the request will still be visible to anyone sniffing traffic. So if that is true, it seems valid to return something useful, rather than the client wondering why it isn't working. Feb 7, 2022 at 22:45

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.