1

I have built simple auth for REST servers in academic projects. I always used the headers to pass the credentials. This is probably just because every tutorial I've ever seen did it this way. Initially, I'd have header fields for user and password, but I eventually switched to basic auth. Anyway, whatever it was, I always had it passed in the headers. My impression was that this was the single correct way.

I am told by the platform team at my work, that we are required to log all headers of each request received, no exceptions, and so, I should not be using headers to accept any sensitive information, such as a password. I was shown an example of a REST API built by another team. For POST and PUT methods, the auth string was accepted in the message body. For GET and DELETE methods, it was in the URL query. This seems wrong to me, but I can't exactly explain why.

I am trying to figure out if I should fight against this policy. I'd like to find out if my position is correct, and, if so, how to support it when I speak to leadership.

  • Am I correct in my thinking that HTTP headers is the single correct way to pass auth credentials in a stateless REST API?
  • Am I correct that using the URL query params is dangerously insecure, or otherwise inadvisable?
  • If I am correct, is there some authoritative source that I can reference when I make the case to my leadership? (other than RFC 7235, I've read it. It is too technical for the people I need to convince.)
  • 1
    This question might be more suited for Information Security. – Bart van Ingen Schenau Jan 20 '18 at 7:30
  • For most purposes, you should be using authorization scheme where the contents of your authorization information can be logged safely, e.g. bearer tokens. You'll need a mechanism to get a token, which would typically not be a part of your REST API itself but part of a more generic login mechanism, probably using credentials passed in the body of an HTTP POST request. This approach makes session hijacking less of a problem, so should be used wherever possible. – Jules Jan 21 '18 at 12:08
4
  • Am I correct in my thinking that HTTP headers is the single correct way to pass auth credentials in a stateless REST API?

No. REST doesn't really address authentication and OAuth uses the query string and POST bodies to get credentials. A header is used for the access token, but this doesn't contain any passwords.

  • Am I correct that using the URL query params is dangerously insecure, or otherwise inadvisable?

Hmmmmm. HTTPS encrypts the query string. Although obviously if someone is standing behind you they can see stuff in the address bar

  • If I am correct, is there some authoritative source that I can reference when I make the case to my leadership? (other than RFC 7235, I've read it. It is too technical for the people I need to convince.)

You shouldn't really be sending usernames and passwords to individual services. Have your client get an access token from the authentication server using POST Body requests.

Then you can pass it around to various services which can check its signature against the public key.

Its fine to log these tokens, as they expire in a few seconds, so you can keep them in the headers as is usual.

  • Ewan, I found this, which seems to contradict. It seems to be an OWASP standard not to use the query string, because it gets logged by the server. (we don't use OAuth) owasp.org/index.php/REST_Security_Cheat_Sheet. – ds390s Jan 22 '18 at 18:08
  • are you referring to "Passwords, security tokens, and API keys should not appear in the URL"? its good advice, but I don't think its contradicting me. – Ewan Jan 22 '18 at 18:29
  • I agree its weird to log the headers, but technically they could be logging anything and everything. Using a token with a expiry mitigates the risk as you need to access the logs in real time to make use of it. – Ewan Jan 22 '18 at 18:32
1

I am trying to figure out if I should fight against this policy.

Change your organization, or change your organization.

The policy sounds very wrong, in a general context. It may make sense under the circumstances. I would never advocate those practices in a system being built from scratch, but it might be a practical solution given the local constraints.

Fielding wrote in 2008

REST is intended for long-lived network-based applications that span multiple organizations. If you don’t see a need for the constraints, then don’t use them.

REST was designed for building web-scale applications; for example, the world wide web. An important part of that design was paying attention to generic components, and what they could know about the messages being passed. The HTTP Headers are effectively meta data so that generic components know what is going on. This in turn affords various optimizations like caching.

Which is to say, if you don't put the authentication information into message where the generic components expect, then they aren't going to see that information, and they aren't going to react appropriately.

See RFC 7234, Storing Responses to Authenticated Requests.

Now, that argument in particular is somewhat weaker than it was twenty years ago, because we're likely to be using an encrypted connection to exchange the messages. Under those circumstances, the capabilities of the intermediaries are less of a concern, because they shouldn't be able to read the messages anyway.

For POST and PUT methods, the auth string was accepted in the message body. For GET and DELETE methods, it was in the URL query. This seems wrong to me, but I can't exactly explain why.

Strictly speaking, embedding authentication data in the payload of a PUT request is semantically incorrect

The PUT method requests that the state of the target resource be created or replaced with the state defined by the representation enclosed in the request message payload.

Unless the goal is to include the authentication information in the updated representation of the resource, it doesn't belong there.

Putting authentication credentials into the query part of the URI in the request is "wrong" because the URI is an identifier - /foo/bar?user=alice is a different resource than /foo/bar?user=bob. The fact that these two resources always have the same representation, and that deleting one necessarily deletes the other, is an implementation detail that isn't visible outside of the server.

What it sounds like to me is that your team is not trying to do REST, but are instead implementing an RPC protocol using HTTP as transport for messages. Which is fine if they don't need the scaling properties protected by the REST architectural style.

Is there a valid alternative to HTTP headers for sending auth credentials

Client certificates would be another approach; which is to say, the client and server negotiate an encrypted connection, and the server knows who the client is because the responses provided by the client are consistent with the client's known public key (which implies that the client has access to the private key).

(There's not really anything wrong with putting authentication credentials into the POST body. POST is so generic it really doesn't matter; intermediary components aren't allowed to draw many conclusions when the semantics are so loosely specified. It's kind of clumsy, though -- imagine a web page where every link was replaced with a form.)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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