What is the delimiter for WWW-Authenticate for multiple schemes? - http-authentication

I've read through RFC 2617 and can't find there or anywhere else what the delimiter is if multiple schemes are supported. For example, suppose both Basic and Digest are supported. I understand that it may appear this way:
HTTP/1.1 401 Unauthorized
WWW-Authenticate: Basic
WWW-Authenticate: Digest
But I've also read that both can be listed as one line, but no one ever shows an example or describes what delimiter to use. I've seen cautions that commas can be used within a single scheme:
HTTP/1.1 401 Unauthorized
WWW-Authenticate: Digest param1="foo", param2="bar"
I've also read that if commas are used within a scheme, that other schemes must be placed on separate lines. So I imagine in the above case if we added Basic it would appear like this:
HTTP/1.1 401 Unauthorized
WWW-Authenticate: Digest param1="foo", param2="bar"
WWW-Authenticate: Basic
That's simple enough. But now suppose you just have one line
HTTP/1.1 401 Unauthorized
WWW-Authenticate: Scheme stuff, morestuff, more stuff
Which is that? Is that a comma-delimited list of schemes, or is that one scheme, with a few parameters?

As far as I can tell, the spec punts on the issue. Section 1.2 states:
Note: User agents will need to take special care in parsing the WWW-
Authenticate or Proxy-Authenticate header field value if it contains
more than one challenge, or if more than one WWW-Authenticate header
field is provided, since the contents of a challenge may itself
contain a comma-separated list of authentication parameters.
I think we can translate special care to best of luck chap.
Pragmatism
As a practical matter, I suspect multiple schemes means one should use multiple wwww-authenticate headers. Schemes are extensible; e.g., I can come up with a scheme called "strawberry" or "opaque" if I want to be sinister. Given this, there isn't really a good way to parse a one liner without some sort of 'scheme termination' delimiter.
W3C Discussion
You aren't the first person with this question. There was a discussion on the W3C mailing list. The poster stated :
I wasn't questioning the need to provide multiple challenges in a
single response. I was only questioning the wisdom in allowing
multiple challenges in a single header field, given the odd
combination of separators it creates.
Some other threads discussing current issues & future action that may be of interest:
root of above thread
Backwards definition of authentication header
#342 WWW-Authenticate ABNF slightly ambiguous
WWW-Authenticate ABNF is ambiguous
future http 2 - Multi-legged Authentication for HTTP Multiplexing
If only ...
Not that I have the stomach for it, but one could dig through the chromimum, firefox & webkit code to see how those communities have handled the issue.

Related

REST API Design: Respond with 406 or 404 if a resource is not available in a requested representation

We have a REST API to fetch binary files from the server.
The requests look like
GET /documents/e62dd3f6-18b0-4661-92c6-51c7258f9550 HTTP/1.1
Accept: application/octet-stream
For every response indicating an error, we'd like to give a reason in JSON.
The problem is now, that as the response is not of the same content type as the client requested.
But what kind of response should the server produce?
Currently, it responds with a
HTTP / 1.1 406 Not Acceptable
Content-Type: application/json
{
reason: "blabla"
...
}
Which seems wrong to me, as the underlying issue is, that the resource is not existing and not the client requesting the wrong content type.
But the question is, what would be the right way to deal with such situations?
Is it ok, to respond with 404 + application/json although application/octet-stream was requested
Is it ok, to respond with 406 + application/json, as the client did not specify an application/json as an acceptable type
Should spec been extended so that the client should use the q-param - for example, application/octet-stream, application/json;q=0.1
Other options?
If no representation can be found for the requested resource (because it doesn't exist or because the server wishes to "hide" its existence), the server should return 404.
If the client requests a particular representation in the Accept header and the server is not available to provide such representation, the server could either:
Return 406 along with a list of the available representations. (see note** below)
Simply ignore the Accept header and return a default representation of the resource.
See the following quote from the RFC 7231, the document the defines the content and semantics of the HTTP/1.1 protocol:
A request without any Accept header field implies that the user agent will accept any media type in response. If the header field is present in a request and none of the available representations for the response have a media type that is listed as acceptable, the origin server can either honor the header field by sending a 406 (Not Acceptable) response or disregard the header field by treating the response as if it is not subject to content negotiation.
Mozilla also recommends the following regarding 406:
In practice, this error is very rarely used. Instead of responding using this error code, which would be cryptic for the end user and difficult to fix, servers ignore the relevant header and serve an actual page to the user. It is assumed that even if the user won't be completely happy, they will prefer this to an error code.
** Regarding the list of available representations, see this answer.

Is it OK to put semantic information in the HTTP reason-phrase in a REST API?

For example, I might want to return the current sequence number of the resource with a 409 response to a HEAD request to a versioned resource, but I may not supply it in the response entity because HEAD doesn't allow any. Another example: suppose a POST request to a commit endpoint fails due to version conflict. I can respond with 409, but sometimes I may want to additionally inform the client that the transaction it was committing has exceeded the maximum retry count and further attempts will not be successful. I might return e.g. HTTP/1.1 409 Conflict/final instead of just HTTP/1.1 409 Conflict in this case. My question is, is this acceptable practice? HTTP 1.1 RFC does not supply a clear-cut answer to this question.
I know I can put such information in a X-... HTTP header, or include this information in the response entity in some manner (additional XML tag or JSON property etc.) Assume I can't or don't want to do so if I can help it.
The reason phrase is cute for debugging; but that's it. It's gone in HTTP/2, and may be lost by intermediaries and/or software libraries; don't rely on it being preserved.
The format of the HTTP response is
Status-Line = HTTP-Version SP Status-Code SP Reason-Phrase CRLF
As per the spec,Here Reason Phrase can be custom. You can add your version of the error message.Please check here http://www.w3.org/Protocols/rfc2616/rfc2616-sec6.html. It mentions that
The reason phrases listed here are only recommendations -- they MAY be replaced by local equivalents without affecting the protocol.

values of SIP Accept and SIP Accept-Contact

I am trying to find out the range of possible values of Accept and Accept-Contact header fields, but I can't find a complete list in the RFCs. Does anyone know where they are? I often see
Accept: application/sdp;level=1, application/x-private, text/html
but don't know all possible values. More generally, where can I find all possible values of SIP headers?
Thanks,
A lot of sections in the [SIP RFC]1 are based on the [HTTP 1.1 RFC]2 in acknowledgement that the semantics of SIP and HTTP are very similar. The SIP Accept header is a good case in point. The SIP RFC section that deals with the Accept header refers to [H14.1] which translates to section 14.1 in the HTTP 1.1 RFC and which goes into detail about how the Accept header can be used to specify the different types of media that are acceptable in the response.
That all being said in the real World 90% of the time the SIP response media is going to be application/sdp. There will be SIP requests that accept other types of response media but they are not that common.
Bob what you are looking is MIME types.
You find some common MIME type here
http://en.wikipedia.org/wiki/Internet_media_type
A text formation of SIP is derive from HTTP so you can refer HTTP headers also to fine possible values of other headers.
Most headers and parameter with their corresponding RFC are listed: http://www.iana.org/assignments/sip-parameters

Message Integrity Check with HTTP headers since Content-MD5 was deprecated?

Making a REST web server mainly based on large files uploads / downloads, I want to be able to check the file integrity. I believed that the proper way to do it was using Content-MD5 HTTP header [0] as proved useful by aws experience [1].
However, much to my dismay, I recently learned that it was (to be ?) deprecated [2].
The deprecation discussion did not give any workaround hint, so I am asking you :
Should I still decide to use a Content-MD5 HTTP header ?
Should I use an ETag with the same meaning (base64 encoding of the md5sum) ?
Should I use an ?md5sum=XXX parameter ?
Is there a better solution altogether ?
Thanks for your insights.
Best Regards,
B.
[0] https://webmasters.stackexchange.com/questions/2924/
[1] http://developer.amazonwebservices.com/connect/thread.jspa?threadID=22709
[2] http://trac.tools.ietf.org/wg/httpbis/trac/ticket/178
Add a custom header, called say X-YourService-Integrity. That makes it explicit that it's a system specific to your service, and allows you to use integrity check mechanisms other than MD5 in the future (for example, SHA1). It also avoids you having to "overload" existing mechanisms that are similar but not quite what you want.
https://www.ietf.org/rfc/rfc3230.txt
4.3.2 Digest
The Digest message header field provides a message digest of the
instance described by the message.
Digest = "Digest" ":" #(instance-digest)
The instance described by a message might be fully contained in the
message-body, partially-contained in the message-body, or not at all
contained in the message-body. The instance is specified by the
Request-URI and any cache-validator contained in the message.
A Digest header field MAY contain multiple instance-digest values.
This could be useful for responses expected to reside in caches
shared by users with different browsers, for example.
A recipient MAY ignore any or all of the instance-digests in a Digest
header field.
A sender MAY send an instance-digest using a digest-algorithm without
knowing whether the recipient supports the digest-algorithm, or even
knowing that the recipient will ignore it.
Examples:
Digest: md5=HUXZLQLMuI/KZ5KDcJPcOA==
Digest: SHA=thvDyvhfIqlvFe+A9MYgxAfm1q5=,unixsum=30637
Do not use Content-MD5: it has been deprecated because it leads to inconsistencies.
Use Digest with sha-256 or sha-512. We are updating RFC3230 to the latest HTTP specification (RFC7231) and added a lot of useful examples https://datatracker.ietf.org/doc/html/draft-ietf-httpbis-digest-headers-02
Digest: sha-256=4REjxQ4yrqUVicfSKYNO/cF9zNj5ANbzgDZt3/h3Qxo=
There Want-Digest allows requesting a specific Digest header.
Eg. The client requests a digest, supporting sha-256 and sha-512. The server replies with sha-256
Request:
GET /items/123 HTTP/1.1
Want-Digest: sha-256, sha-512
Response:
HTTP/1.1 200 OK
Content-Type: application/json
Digest: sha-256=X48E9qOokqqrvdts8nOJRJN3OWDUoyWxBf7kbu9DBPE=
{"hello": "world"}

Problem with OAuth, POST with parameters

I'm using Jon Crosby's open source Objective-C OAuth library http://code.google.com/p/oauthconsumer/ for some basic http authentication that does not deal with tokens, only consumer key and consumer secret. My code works great for GET, GET with parameters in the URL, and POST. When I issue a POST request that has parameters in the URL, though, the request fails authorization. I'm trying to figure out why.
The server is using Apache Commons OAuth, so I'd like to compare my base string with that library. Here's a contrived example and the base string and signature produced by my library. Can anyone see what the problem is?
consumer key: abcdef
consumer secret: ghijkl
POST request: http://emptyrandomhost.com/a/uriwith/params?interesting=foo&prolific=bar
my base string: POST&http%3A%2F%2Femptyrandomhost.com%2Fa%2Furiwith%2Fparams&interesting%3Dfoo%26oauth_consumer_key%3Dabcdef%26oauth_nonce%3D1%26oauth_signature_method%3DHMAC-SHA1%26oauth_timestamp%3D2%26oauth_version%3D1.0%26prolific%3Dbar
This data produces the following OAuth header authorization:
Authorization: OAuth oauth_consumer_key="abcdef",
oauth_version="1.0",
oauth_signature_method="HMAC-SHA1",
oauth_timestamp="2",
oauth_nonce="1",
oauth_signature="Z0PVIz5Lo4eB7aZFT8FE3%2FFlbz0%3D"
And apparently my signature is wrong. The problem has to either be in the construction of the base string, in the way that the HMAC-SHA1 function is implemented (using Apple's CCHmac from CommonHMAC.h, so hopefully this isn't it), or with my Base64Transcoder, which is open source c. 2003 by Jonathan Wight/Toxic Software. I primarily suspect the base string, since the requests work for GET and POST and only fail with POST with URL parameters as above.
Can someone with lots of OAuth experience spot the problem above? Something else that would be very useful is the base string that is produced by Apache Commons OAuth in their authentication. Thanks.
As per RFC 5849 section 3.4.1.2, the OAuth base string URI does not include the query string or fragment. If either the client or the server does not remove the query parameters from the base string URI and add them to the normalized OAuth parameter list, the signatures won't match. Unfortunately, it's hard to tell which side is making this mistake. But it's easy to determine this is the problem: If it always works without query parameters but always fails with query parameters, you can be pretty sure that one side or the other is generating the wrong base string. (Be sure that it always happens though... intermittent errors would be something else. Similarly, if it never works with or without a query string, that would also be something else.) The other possibility is that normalization was done incorrectly — the parameter list must be sorted and percent encoded sequences must be upper-cased. If it's not normalized correctly on both sides, that will also cause a base string mismatch, and thus a signature mismatch.
you can build and check visually your request at this URL:
http://hueniverse.com/2008/10/beginners-guide-to-oauth-part-iv-signing-requests/
Open the boxes denoted by [+] signs and fill in your values, that way you may be able to see if the problem is at your code, or at the provider side.