Subject: [OAUTH-WG] Facebook, OAuth, and WRAP

From: David Recordon <[email-masked]>
Date: Tue, 24 Nov 2009 10:57:33 -0800

Hey all,
This was originally a comment on Eran's post about WRAP (http://hueniverse.com/2009/11/wrap-and-the-demise-of-the-oauth-community/).  Beyond Luke and I talking at the Internet Identity Workshop a few weeks ago, I don't think we've actually articulated where Facebook is thinking in regards to OAuth.  In order to help get OAuth 2.0 done, I wanted to make sure we've shared where we see OAuth 1.0 falling short, why we're interested in WRAP, and the four main use cases our current proprietary authentication mechanism solves.  We've also signed Open Web Foundation agreements for OAuth Core 1.0a and the WRAP specs (http://developers.facebook.com/news.php?blog=1&story=335).

The largest issue in Facebook moving to OAuth 1.0 (and yes, Eran's new RFC is awesome) is the increase in the number of HTTP requests that developers will need to make in comparison to our current authentication mechanism.  We want to move to using OAuth, but for this reason and hearing strongly from other major implementors that OAuth has not been widely adopted by their developer communities because it is too difficult to correctly implement has us concerned.

The most interesting part of WRAP are the various profiles.  They currently map well to our existing authentication mechanisms and the username/password profile is an API we offer to whitelisted partners such as the XBox and Playstation 3.  It would be great if OAuth 2.0 had a similar profile mechanism where each profile is optimized in terms of the number of steps (HTTP requests) required versus being combined together like OAuth 1.0.

I'm not convinced that signatures are "too hard" for developers especially when libraries hide them away.  That said, OAuth 1.0 implementations still requires that developers understand the different types of tokens in addition to when and how they're generated.

WRAP is intriguing in terms of really simplifying what developers need to understand.  The first step being trading some set of credentials or asking the user to go somewhere results in an access token.  The second step then being including that access token via HTTP headers, a GET arg, or a POST arg over SSL without needing to calculate any sort of signatures.  The downside is that now all APIs need to be served over SSL, but that seems doable.

These are the four main use cases which were focused on.  While there is quite a bit of overlap between them, we think that it is important to have specifically optimized flows for each so that individually they are as simple as possible to implement.

1) "OAuth" web flow of redirecting a user to Facebook, them authorizing pre-registered application, and then being redirected back to the web app within their browser.
2) A mobile/desktop flow where the user is redirected back to Facebook, authorizes the app, and then is sent back to the application.  We both have a version of this use case where the application separately opens a browser and one where the application is able to embed a browser directly.
3) A mobile/desktop/device flow where the user enters their Facebook username/password which the application then trades for a token.  This is for whitelisted partners.
4) A fully JavaScript environment where the JavaScript sets a cookie containing the credentials needed for the web application to get API access while the user has an active session.

We think that WRAP currently solves #3, probably solves #2, and mostly solves #1.  #4 hasn't been tackled within WRAP yet, but we hope to develop a profile for it as well.

I'm happy to participate in the IETF to help develop OAuth 2.0 and to encourage others from Facebook to do the same, but also want to be really pragmatic around having something we can ship (either WRAP or 2.0) sooner rather than later.

Cheers,
--David

---

From: Mike Malone <[email-masked]>
Date: Tue, 24 Nov 2009 16:35:54 -0800

On Tue, Nov 24, 2009 at 10:57 AM, David Recordon
<[email-masked]> wrote:
>
> The largest issue in Facebook moving to OAuth 1.0 (and yes, Eran's new RFC is awesome) is the increase in the number of HTTP requests that developers will need to make in comparison to our current authentication mechanism.

The OAuth _flow_ (in a browser) requires a couple additional requests
compared to Facebook Connect (in a browser). But Facebook Connect is
really a different beast since it relies on the Browser and Javascript
to magically set cookies cross domain and whatnot. I agree that it's
non-trivial to extend OAuth to cover this use case (we've sort of done
it at Six Apart and the flow is clunky and complicated). And even if
you figure out how to make the flow work you can't really make
requests purely on the client side without compromising your consumer
secret.

That said, as far as I can tell, using OAuth for delegated
communication via an intermediary (a web app or iPhone app, for
example) should be doable for Facebook. The only real differences I
see between OAuth and WRAP for this use case are:
  * WRAP requires SSL instead of signing URLs
  * WRAP renamed request token to refresh token and lets you use them
to exchange for temporary access tokens multiple times
  * WRAP has a defined flow for accepting username/password &
exchanging for an access token

I'm guessing that the big win you see is the third point, but the auth
flow is really a small part of OAuth. If the flow defined in OAuth 1.0
doesn't work for you why not create a new flow and keep the rest of
the spec?

> The most interesting part of WRAP are the various profiles.  They currently map well to our existing authentication mechanisms and the username/password profile is an API we offer to whitelisted pa…

Again, the flow is really just half of OAuth. Maybe it'd make sense to
split the OAuth flow and OAuth request signing into separate specs?

> I'm not convinced that signatures are "too hard" for developers especially when libraries hide them away.  That said, OAuth 1.0 implementations still requires that developers understand the differe…

WRAP seems to have a bunch of different tokens too, they just don't
call them all tokens (there's the refresh token, the client id &
secret, the access token, the verification code... everything seems to
be there).

Re: signatures, I think the SSL requirement would be a much larger
burden on developers. It's hard enough to debug OAuth problems when
you can sniff the flow using ngrep. Although I guess removing signing
would help here a bit.

> WRAP is intriguing in terms of really simplifying what developers need to understand.  The first step being trading some set of credentials or asking the user to go somewhere results in an access t…

I don't think you'd be able to use GET params with WRAP since stuff
isn't signed. Other than that, I guess the terminology is simpler..?
I'm used to the OAuth terminology by now so it's hard for me to say.
The flow doesn't seem all that different to me. Maybe it's a
communication problem?

> We think that WRAP currently solves #3, probably solves #2, and mostly solves #1.  #4 hasn't been tackled within WRAP yet, but we hope to develop a profile for it as well.

Again, I think the only use case that would be truly difficult to
solve with OAuth is #4. I think #4 is an interesting problem though,
and I'd be happy to see OAuth support for a pure Javascript
environment.

One final note - unless I'm missing something WRAP is vulnerable to
the same session fixation attack that OAuth 1.0 had... unless it's
requiring callback registration, which is a really lame solution to
that problem.

Mike

---

From: John Panzer <[email-masked]>
Date: Tue, 24 Nov 2009 22:15:30 -0800

On Tue, Nov 24, 2009 at 4:35 PM, Mike Malone <[email-masked]> wrote:

> > The largest issue in Facebook moving to OAuth 1.0 (and yes, Eran's new
> RFC is awesome) is the increase in the number of HTTP requests that
> developers will need to make in comparison to our current authentication
> mechanism.
>

Aside: If an SP specified OAuth PLAINTEXT signature mode, and used https:
URLs for its API, would there be any effective difference between OAuth and
WRAP for that SP?  (Best as I can tell the only difference would be a
mandated %26 character in the OAuth blob you pass in to get access, but I
may be missing something.)

---

From: Mike Malone <[email-masked]>
Date: Tue, 24 Nov 2009 22:40:17 -0800

> may be missing something.)

Yea, they're more or less the same. That's one use case for PLAINTEXT
OAuth. You still have a "signature" though, it's just the base64'd
signature base string.

---

From: Brent Goldman <[email-masked]>
Date: Wed, 25 Nov 2009 06:03:23 -0800

On Nov 24, 2009, at 4:35 PM, Mike Malone wrote:

On Tue, Nov 24, 2009 at 10:57 AM, David Recordon
<[email-masked]<mailto:[email-masked]>> wrote:

Facebook Connect can work without cookies (e.g., in a Safari iframe, or if the developer manually turns this off via a configuration option) -- the cookies are just used as a simple cache, and are not magic or a defining feature of Connect. Additionally, by default, Connect does not work across domains unless the developer configures a base domain with us. To top it all off, Connect also works in a non-JS environment, or in an environment where the developers don't want to use the Facebook JS.

Therefore, I think we can fairly compare OAuth and Facebook Connect apples to apples, and we should just consider cookies, multiple domains, and JS snazziness as extra features that would be nice to add to OAuth via extensions. As David stated, the largest issue with Facebook moving to OAuth truly is the number of requests.

The third point is pretty cool, but Facebook actually discourages exchanging usernames/passwords for access tokens. Only a handful of whitelisted partners have access to this.  In the vast majority of cases, usernames and passwords are given directly to Facebook.com<http://Facebook.com> instead of to the app.

This is a really interesting idea that I think makes a lot of sense. I don't see why the various WRAP profiles couldn't work almost identically in OAuth 2.0, with the main differences being that OAuth 2.0 would have an extra step to exchange a secret (or perhaps even reuse a step if it makes sense, and then API calls would have a signature instead of being called over SSL.

Good point about the tokens. One of us should make a list of all the terms in each spec, and then set up a mapping between the sets, to see if the number of concepts is really all that different.

Why does the lack of signatures mean we can't use GET params? We can still trust everything because it's happening over SSL.

Mike

---

From: Brent Goldman <[email-masked]>
Date: Wed, 25 Nov 2009 06:10:07 -0800

> OAuth. You still have a "signature" though, it's just the base64'd

If they're more or less the same (besides the difference you  
mentioned), then why not also create an SSL signature mode which  
leaves out the oauth_signature param? If SSL mode is this essentially  
the same as WRAP, why not actually make this the bridge between the  
two specs?

---

From: Leah Culver <[email-masked]>
Date: Wed, 25 Nov 2009 08:15:28 -0800

> the same as WRAP, why not actually make this the bridge between the
+1 since this is easy enough to add to most OAuth libraries. I know (at
least) the PHP and Python ones break out the signature step into separate
methods so we could just add another one for SSL with no oauth_signature.
Hmm... the only thing that might have to change is some of the error
messages.

Leah

---

From: Mike Malone <[email-masked]>
Date: Mon, 30 Nov 2009 11:44:01 -0800

On Wed, Nov 25, 2009 at 6:03 AM, Brent Goldman <[email-masked]> wrote:
> This is a really interesting idea that I think makes a lot of sense. I don't
> see why the various WRAP profiles couldn't work almost identically in OAuth
> 2.0, with the main differences being that OAuth 2.0 would have an extra step
> to exchange a secret (or perhaps even reuse a step if it makes sense, and
> then API calls would have a signature instead of being called over SSL.

Yes.

> Good point about the tokens. One of us should make a list of all the terms
> in each spec, and then set up a mapping between the sets, to see if the
> number of concepts is really all that different.

My informal list (from a cursory read of the spec):
  OAuth / WRAP
  Consumer / Client
  Request Token / Refresh Token
  Access Token / Access Token
  Consumer Token / Client identifier & secret
  OAuth Verifier / Verification Code

There are probably others that I'm missing.

> Why does the lack of signatures mean we can't use GET params? We can still
> trust everything because it's happening over SSL.

I guess technically GET params are secure with HTTPS, it just _feels_
kinda dirty since the URL (including params) is often bandied about
without a lot of thought. It may show up in logs, web server
scoreboards (Twitter's recent Apache scoreboard snafu comes to mind),
error messages, etc. Since a request doesn't have a nonce or timestamp
they can be replayed until the access token expires. Then again, maybe
I'm just being paranoid / playing devil's advocate here.

Mike

---

From: Brian Eaton <[email-masked]>
Date: Mon, 30 Nov 2009 13:49:47 -0800

>  Request Token / Refresh Token

WRAP has no equivalent of the request token.  The closest thing is the
verification code.

>  OAuth Verifier / Verification Code

WRAP has a refresh token.  The closest OAuth analog is the session
handle used in the scalable OAuth extension.

Cheers,
Brian

---

From: Mike Malone <[email-masked]>
Date: Mon, 30 Nov 2009 14:52:27 -0800

> handle used in the scalable OAuth extension.

As far as I can tell, if we're treating everything as opaque strings,
the only real difference between a WRAP "refresh token" and an OAuth
"request token" is that a "refresh token" can be exchanged for an
"access token" multiple times in WRAP (since the access tokens
expire). Is there some other non-trivial difference that I'm missing?

Again, maybe I'm mistaken, but the verification code seems to be
included in WRAP to protect against the sort of session fixation
attack that OAuth 1.0 was susceptible to. In OAuth 1.0a the OAuth
Verifier was added to fix that vulnerability, which is why I said the
OAuth Verifier and WRAP Verification Code were essentially equivalent.

Mike

---

From: Brian Eaton <[email-masked]>
Date: Mon, 30 Nov 2009 16:20:26 -0800

> expire). Is there some other non-trivial difference that I'm missing?

The main difference between the OAuth request token and the WRAP
refresh token is when they are generated and how they are used.

> OAuth Verifier and WRAP Verification Code were essentially equivalent.

In WRAP we combined the OAuth request token and the OAuth verification
code into a single value.  It saves a round trip in the protocol.  The
verification code serves both as a form of user identifier and as an
unguessable value used to prevent session fixation.

Cheers,
Brian