Ian Hickson wrote:
On Wed, 13 Feb 2008, John Panzer wrote:
An API needs to do an authorization check on a CSR request, not an
authentication check. For CSR especially, just doing an authn check
doesn't give you valid evidence of authorization.
Agreed.
Some of today's APIs like Flickr put authorization evidence into URL
query parameters for CSR. It's mildly bad to do this because such
things are more likely to get logged and sniffed than headers, and you
can't separate the resource URL from the authorization proof being
presented to use it, which would be useful in caching.
Also agreed. That's one of the reasons that XMLHttpRequest + Access
Control together let you set arbitrary extension headers.
The OAuth spec uses
Authorization: OAuth ...
by preference for these reasons, where the ... represents an
authorization proof provided by the party A script. It looks like this
is disallowed by the AC4CSR specification.
Right, you'd have to use X-OAuth or something like that. "Authorization"
headers are reserved for user and client authentication [sic], as
described in HTTP 1.1 section 14.8.
Relevant text, just for reference:
14.8 Authorization
A user agent that wishes to authenticate itself with a server--
usually, but not necessarily, after receiving a 401 response--does
so by including an Authorization request-header field with the
request. The Authorization field value consists of credentials
containing the authentication information of the user agent for
the realm of the resource being requested.
Authorization = "Authorization" ":" credential
1. Should OAuth invent a new header for authorization? That is, should
we not be using Authorization: for authorization?
When it's direct A-B communication, and A is authenticating to B, then
Authorization: is appropriate. When there are three parties, and the
communication is from C to B on behalf of A, the Authorization: header is
authenticating C, not A. A needs to use different headers in this case.
I'm not sure I understand the distinction being made here, possibly
because OAuth doesn't really follow this model? Let me try to work this
out...
Take the delegated server case first. I, the user, talk to server B and
tell it that it's okay for server C to do certain operations on my
behalf (read my address book for example). I believe I'm A in this
case. So later on, C can talk to B on my (A's) behalf in order to
retrieve my address book data. In the case of OAuth, there are actually
two components to this:
1. C proves that it's C to B (typically by signing with a long-lived
shared secret)
2. C asserts that it has permission from A to do the operation (by
signing with a second, shorter lived shared secret generated when A
granted permission)
However, (1) and (2) aren't physically separated -- the secrets are
combined and both are used to sign the request. There is no separate
authentication/authorization step, just a single auth[nz] step. So it
appears that we're authenticating C in this case (and also authorizing
the specific request).
Now in the case of CSR, I'll assert that C is a distributed system
consisting of a server component plus Javascript extensions that run on
my desktop in a sandbox. From my P.O.V. as a user, I'm still dealing
with C. I talk to B and tell it it's okay for C to read my address
book; C's Javascript then executes (1) and (2) and makes the CSR call to
B. Is the situation different than in the delegated server case?
Aside #1: The security is definitely different if we leak secrets to end
user machines, but there are ways to deal with that that don't affect
this discussion I think.
Aside #2: To make things more complicated, in some cases you can skip
(2); for operations that don't require user permissions, for example, or
where the user permissions are asserted some other way. In this case
you have the same mechanism but simply use an empty string for step 2,
so effectively you are only proving that you're C.
Aside #3: To make things even more complicated, OAuth also allows for
semi-trusted assertions for #1, for example if you have a desktop
application where the 'secret' ends up stored on an end user's
computer. You have to assume that this secret can be found and copied.
This is also similar to the case where you download Javascript to an end
user's computer and perform signing there, so it's probably the relevant
case for CSR. However, it would be possible to generate a unique secret
per end user computer too, so you can still do both #1 and #2 together
even with CSR.
Aside #4: Both Google AuthSub and Amazon's auth use Authorization: for
this purpose :).
-John