Subject: [OAUTH-WG] Proposal: make it possible to get a verification code in the user-agent flow

From: Brian Ellin <[email-masked]>
Date: Fri, 21 May 2010 10:39:55 -0700

We're using the OAuth 2.0 User-Agent flow in @anywhere at Twitter.
 @anywhere is a pure javascript layer that developers can drop in to add
Twitter features to their website.  With the User-Agent flow, we issue short
lived access tokens that refresh as they expire.  It works great for in-page
stuff, but many developers are also building server-side integrations and
would love to have different longer lived access tokens on their server.
 This is a common pattern that other connect-like services built on top of
OAuth 2.0 will also find necessary.

So, why not just use the access token issued by the User-Agent flow on the
client server?  Overloading the use of that token is not desirable for a
couple of reasons:

1) The client server may not be using ssl, and as such the browser cannot
securely transfer the access token to the server.

2) The access token lifetime policy for the User-Agent flow may not
be desirable on the server.  Specifically, the server may need a token that
lasts for, say, two weeks instead of 15 minutes.  Additionally, the token on
the server may have access to different resources that are not desirable to
transmit to or through the browser.

In short, it is desirable to get two different access tokens from a single
user authorization triggered by the User-Agent flow.

Proposal:

Make it possible to get a Web Server flow verification code from the
User-Agent client authorization request [1]. Specifically, add a new
optional parameter named "web_server_code" which when set to "true" returns
a Web Server flow verification "code" field in the User-Agent authorization
response.  The verification code can then be sent by the javascript layer to
the client server, where it is then used to request an access token [2].

Love to hear your feedback.

1: http://tools.ietf.org/html/draft-ietf-oauth-v2-05#section-3.5.1
2: http://tools.ietf.org/html/draft-ietf-oauth-v2-05#section-3.6.2

-- 
Brian Ellin
Product Manager, Twitter Platform
http://twitter.com/brianellin

---

From: Brian Ellin <[email-masked]>
Date: Fri, 21 May 2010 13:46:21 -0700

Marius,

I don't understand.  Will you elaborate on how specifically that would work?

Brian

On Fri, May 21, 2010 at 12:35 PM, Marius Scurtescu <[email-masked]>wrote:

> Why not use the web server flow in this case?
>
> I think it should work with un-registered clients as well (no client
> secret).
>
> Marius
>
>
>
> On Fri, May 21, 2010 at 10:39 AM, Brian Ellin <[email-masked]> wrote:
> > _______________________________________________
> > OAuth mailing list
> > [email-masked]
> > https://www.ietf.org/mailman/listinfo/oauth
> >
> >
>

-- 
Brian Ellin
Twitter Platform Team

---

From: Marius Scurtescu <[email-masked]>
Date: Fri, 21 May 2010 12:35:04 -0700

I think it should work with un-registered clients as well (no client secret).

Marius

---

From: Brian Eaton <[email-masked]>
Date: Fri, 21 May 2010 15:30:01 -0700

> transmit to or through the browser.

I think I like this.

At the OAuth 2 interim meeting yesterday, I mentioned that the
security characteristics of the user-agent flow could be improved.  In
particular, refresh tokens issued through the user-agent flow are a
problem.  Imagine this scenario:

- RP receives refresh tokens from many users.
- RP is compromised.   The refresh token database leaks.

The only way to recover from this scenario is to revoke all of the
refresh tokens and ask users to reapprove.

The web server flow doesn't have the same weakness.  For the web
server flow, you can change the client secret of the RP web site
instead.  The stolen refresh tokens are then useless.

To understand why rotating client secrets doesn't work for the
user-agent flow, consider this attack:
- attacker steals refresh token
- client secret is changed
- attacker starts the user-agent flow
- attacker replays the stolen refresh token
- RP accepts the stolen refresh token and uses it on the attacker's behalf

So maybe the user-agent flow should *never* return a refresh token on
the URL.  Instead, it should return an access token, plus an optional
verification code.

Cheers,
Brian

---

From: Chuck Mortimore <[email-masked]>
Date: Fri, 21 May 2010 17:27:48 -0700

+1

At the moment we don't intend to issue refresh tokens on the user-agent flow.    This would likely change our mind.

-cmort

On 5/21/10 3:30 PM, "Brian Eaton" <[email-masked]> wrote:

I think I like this.

Cheers,
Brian

---

From: Marius Scurtescu <[email-masked]>
Date: Fri, 21 May 2010 17:50:27 -0700

> I don't understand.  Will you elaborate on how specifically that would work?

Maybe I am missing something, but I was suggesting that the JavaScript
code starts a web server flow at the end of which it has a
verification code. It passes this verification code down to the client
server, the client server swaps it for an access token and a refresh
token and passes the access token to the JavaScript client. When the
access token expires the client JavaScript has two options, ask the
client server for a refresh or do an immediate request to that authz
server.

If you want that the client server and client JavaScript have tokens
with totally different scopes, then you probably want to send the user
for approval twice. If you just want the client JavaScript to have a
token with a lesser scope (and avoid a second approval), then we
should probably look into down-scoping, which currently is not
supported.

Would that work?

Marius

---

From: Marius Scurtescu <[email-masked]>
Date: Sat, 22 May 2010 11:34:13 -0700

> the URL.  Instead, it should return an access token, plus an optional

How is this verification code used after that? I assume it is passed
down from the client JavaScript to the client web server, right? The
client JavaScript still cannot get fresh access tokens without an
immediate call, so the verification code is no help there.

Is the only optimization the fact that the client web server does not
have to send the user for a separate approval? If so, aren't immediate
calls solving this already?

Marius

---

From: Luke Shepard <[email-masked]>
Date: Sun, 23 May 2010 19:13:29 -0700

Brian - I like your proposal. It solves the refresh token problem and the server-side auth in one go.

Marius - your proposal would work great in a circumstance where you have strong integration between JavaScript and the server, and they are both controlled by the same developer. In that case, sure, the developer could pass the access token back to the front-end (although you would have a perf hit).

However, the case that I'd like to solve (and what I read, Brian wants to as well) is like this:

- Client includes some Javascript from the relevant service (either Facebook or Twitter @anywhere)
- The JS handles the auth flow and does some client-side API calls - for example, Twitter displays hovercards on each username on the site, or Facebook renders some profile pics
- The JS also passes a token down to the server - either in the cookies, or perhaps directly via an Ajax call
- The server can now independently make its own API calls if it wants, and gets a refresh token or whatever else it wants

This allows for a single, general purpose JS library that handles auth for both client and server applications - which is something that the web server flow by itself does not allow.

---

From: Eran Hammer-Lahav <[email-masked]>
Date: Mon, 24 May 2010 14:22:47 -0700

Anyone wants to turn this into an actual proposal with list of changes to the current flow?

EHL

On 5/23/10 7:13 PM, "Luke Shepard" <[email-masked]> wrote:

---

From: Marius Scurtescu <[email-masked]>
Date: Tue, 25 May 2010 10:46:13 -0700

> - The JS also passes a token down to the server - either in the cookies, or perhaps directly via an Ajax call

Isn't this suggesting a strong integration as well?

> This allows for a single, general purpose JS library that handles auth for both client and server applications - which is something that the web server flow by itself does not allow.

I think that "Web Server" is a bit of misnomer. This flow can be used
by native apps and also by JavaScript clients. The main difference
between Web Server and User-Agent flows is that the former requires an
extra direct call to swap the verification code.

I could be missing something, but here is how I see how "User-Agent
with optional verification code" can be implemented with the current
spec:
1. JavaScript client starts Web Server flow with immediate off
2. user approves scopes
3. JavaScript receives verification code
4. JavaScript passes verification code down to client server
5. JavaScript does User-Agent flow with immediate on
6. JavaScript receives access token
7. JavaScript uses access token
8. When access token expires, go to 5.

One problem, how does the JavaScript code know when to request a
verification code, but this applies to the proposed enhanced
User-Agent flow as well.

Also, the proposed flow saves on one immediate call, that can be
optimized by the client server returning an access token on the
request that passes the verification code down. Not sure it is worth
it.

Does the above work?

Marius

-