General pattern of protocol flow in OAuth and CX Artifact Binding is almost identical.
Just to assist the OAuth people to understand CX easily, here are the glossary of the terms.
|Consumer Secret (shared between Consumer and Service Provider)
||Consumer Certificate. (Only public certs/key is shared and no secret is being shared.)
|Request Token Request
|Unauthorized Request Token
|Request Token Secret
|Authorized Request Token
|Access Token Secret
||Transaction ID (cx.id)
Here after, I will write this article in OAuth terminology and express CX terminology like cx:Offer.
Message Flow Comparison
From the message flow point of view, it is completely identical.
The difference is that CX’s version has much richer structure.
For example, cx:Offer (Request Token Request) has “Consumer” identity, its public key, term and conditions, “Consumer” pub-key based signature etc. in it, and cx:Contract (Access Token) has User’s identity, Service Providers Public Key, Service Provider Signature, etc.
Now, let us dive into protocol difference.
(Source: OAuth Core Final 1.0. Click to Magnify)
There are some differences in the details.
In B above, OAuth returns Unauthorized Request Token and Request Token Secret which is used as a part of signature key (consumer secret + token secret) . Unauthorized Request Token is bound to the Local ID of the “Original” User. In CX, it is either not bound to anybody at this stage, or if it is, the Users global identifier (e.g., OpenID) is explicitly written in the Request Token Request (cx:Offer).
In C, to obtain Authorized Request Token (cx:ContractID), the Token is sent (or input) to the Service Provider.
At this point the (hopefully the original) User identifies himself (by something like username and password.) Note that there is no guarantee that the User here is the same User that started off the Request Token Request. This is one source of OAuth Fixation Vulnerability. If the User is the victim of this attack, his local identity at the Service Provider is effectively linked to the attacker’s (Original User’s) identity at the Consumer.
In CX, if the user was not identified at the Consumer, then his global identifier is verified at the Service Provider and written into the Access Token (cx:Contract). If the user was identified at the Consumer, then its global identity is already written in the Request Token Request (cx:Offer), and thus in the Access Token (cx:Contract). Thus, OAuth Fixation vulnerability does not exist here. It is simply not possible to link a user at the Consumer to another user at the Service Provider.
Once the user was identified, and an appropriate authorization/permissioning happens, Authorized Request Token (cx:ContractID) is generated. At this point, the Authorized Request Token is bound to the User at the Service Provider in OAuth. In CX, Access Token (cx:Contract) is generated here as well, and User’s Identifier is written into the Access Token (cx:Contract). Of course, if the identifier in the offer (if not identifier_select) and the identifier of the User at the Service Provider does not match, it fails.
In step D, this Authorized Request Token (cx:ContractID) is returned to the Consumer via browser redirect.
Then, in step E, Consumer requests Access Token (cx:Contract) using Authorized Request Token (cx:ContractID) and Consumer Secret + Request Token Secret as the Key of the signature. In case of CX, we just use Consumer’s secret key to sign the request.
In OAuth, at this point Access Token (cx:Contract) is generated. Note that in CX, it was generated before step D.
In F, Access Token (cx:Contract) and Access Token Secret (cx: no such thing) is returned, which is subsequently used to access resources. In CX, this is optionally encrypted by the Consumer’s Public Key obtained through Request Token Request (cx:Offer), so that nobody but only the Consumer can read it.
So, to summarize:
- OAuth and CX is almost identical in the protocol flow.
- OAuth requires manual step to establish the Consumer’s identifier called Consumer Key, while CX leverages on metadata including its identifier in XRD.
- OAuth does not require an identity framework such as OpenID while CX does.
- OAuth uses Token Secrets. In CX, there is no need of them.
- CX leverages on public key cryptography for security while OAuth depends on shared secret. In another words, in CX, there is no shared secret.
- Authorized Request Token (cx:ContractID) and Access Token (cx:Contract) is generated at different point in the sequence in OAuth, while it is generated simultaneously in CX.
- OAuth implicitly assumes that the User at the Consumer and the Service is the same guy and binds a local user at the Consumer to another local user at the Service Provider by Request Token, while CX does not and leverages on the User’s global Identifier to distinguish them.
- OAuth implicitly assumes that the User in the different point in the sequence is the same guy, while CX does not and leverages on the User’s global Identifier to distinguish them.
- In CX, the authorization fails if the identifier in the cx:Offer/cx:Contract does not match with the User’s Identifier
- CX is not vulnerable to the OAuth Fixation Attack, though on the surface, the protocol flow seems almost identical.
Comments on OAuth Vulnerability Fix Proposals
It seems there are two proposals on the table .
- Signed Callback URLs
- Signed Approval URLs
IMHO, they are not dealing with the core of the problem. The core of the problem is the identification of the users at each site and the conflation of the potentially different identity over time and location. The above may work for this vulnerability, but it is just patching a hole and not coping with the real problem. I am very sleepy (I have slept only two hours each for last couple of days…) so I might be wrong, but sending the Local ID of the requesting party (the Original User) with the Request Token Request (cx:Offer) and Service Provider prominently showing this to the User might be a better idea.