Subject: [OAUTH-WG] Proposal: simplification of the end-user authorization endpoint

From: Eran Hammer-Lahav <[email-masked]>
Date: Wed, 16 Jun 2010 23:05:36 -0700

This is a joint proposal from David Recordon and me:

** Background:
 
The latest draft (-08) unified the  web-server and user-agent client types into a single authorization request format. This was done because once we added an optional authorization code to the user-agent response, it became almost identical to the web-server call. The two remaining differences:
 
- The web-server response must not return an access token, only an authorization code.
- The web-server response uses the URI query while the user-agent response uses the URI fragment.
 
The way in which the client indicates which response is requests is by using the 'type' parameter with either 'web_server' or 'user-agent'. This is all documented in:
 
http://tools.ietf.org/html/draft-ietf-oauth-v2-08#section-3
 
Many (if not most) services are likely to implement both the user-agent and web-server types (based on existing deployment and the requirements expressed by many of the participants).

The web-server flow requires client authentication (client secret) in order to obtain an access token. It also enables the registration of a redirection URI.

When using the user-agent flow, the client does not authenticate with the authorization server (at all) to obtain an access token. However, it does need to authenticate if it wants to exchange the optional authorization code for (another) access token.
 
The authorization server has a few options when managing the security and trust implications of each request type:
 
- Require that the client provide its type when registering with the service - if the authorization server knows the client type, it can limit that client to only make requests suitable for that client type, as well as only issue a client secret when the client is not a user-agent.
 
- Issue different access tokens based on the security context in which they are obtained - access tokens issued using the direct user-agent request will provide less access (shorter duration, read only, etc.) than an access token obtained using the web-server request type.
 
The first approach is problematic for complex clients requesting both an access token and authorization code using the user-agent request type. In this case, the authorization server is issuing two access tokens, each using a different level of security. It is means that one developer will need to obtain a different client identifier for the same application across different platforms.
 
The current separation between the two request types (user-agent and web-server) seems artificial. This is especially true when considering the use cases for native applications and the applicability of both options. At the end, the client type doesn't matter. What matters is whether the access token is issued with or without client authentication (and whether that authentication can be trusted, which goes beyond what the protocol can provide).
 
** Proposal:
 
Replace the 'type' parameter with a new parameter called 'request' (working title) which can take one of three values: 'token', 'code', or 'token_and_code'. This will allow the client (regardless of its type) to explicitly say what it wants.

The response is sent as follows:

- If the client requests an access token, all the response parameters (including errors) are included in the fragment (same as the user-agent flow today).
- If the client requests an authorization code, all the parameters are included in the query (same as the web server flow today).
- If the client requests both, the 'code', 'status', and 'error' are included in the query while everything else is included in the fragment (explained in the example below).

The authorization server issues the appropriate user warnings and access token based on the authentication level obtained. For example, when issuing an access token the server has to consider:
 
- Was the client authenticated using a secret or other means?
- Was the redirection URI registered?
- Is this a known client (white list) from a trusted third party (they are known not to leak their secrets)?
 
 The advantage of this approach is that it more clearly frames the security context of issuing tokens. It puts native applications at the same level as the web-server and user-agent clients (no one gets a special parameter value).

** Examples:

To help show the similarities, here are three example requests and responses:

- Token only (aka user-agent):

  https://server.example.com/oauth/authorize?
    client_id=...&
    redirect_uri=http://client.example.com/callback&
    request=token&
    state=foo

  http://client.example.com/callback#access_token=...&expires_in=...&state=foo

In this case all of the parameters are in relation to the token and thus consumed directly by the JavaScript, desktop app, etc.

- Code only (aka web-server):

  https://server.example.com/oauth/authorize?
    client_id=...&
    redirect_uri=http://client.example.com/callback&
    request=code&
    state=foo

  http://client.example.com/callback.php?code=...&state=foo

In this case there isn't an access token and all of the parameters are consumed by the client's server to be traded for an access token via a HTTPS request to the AS.

- Token and code:

https://server.example.com/oauth/authorize?
  client_id=...&
  redirect_uri=http://client.example.com/callback&
  request=token_and_code&
  state=foo

http://client.example.com/callback.php?code=...&state=foo#access_token=...&expires_in=...

In this case the parameters are consumer both by the JavaScript and the client's server. The parameters about the access token are in the fragment. The code is a query parameter so that the server can access it. state and error are useful to both and thus are query parameters which can be accessed by the JavaScript and the server.

---

From: David Recordon <[email-masked]>
Date: Wed, 16 Jun 2010 23:12:50 -0700

It took me a little while to shift my mind from thinking about how we
had drafted the flows previously, but given how similar the flows
already were it seems far more clear to have the client ask for a
token and/or code versus specifying types of web_server or user_agent.
Servers can still document the interactions separately, but it's also
become more clear around what servers need to implement given the
overlap.

--David

On Wed, Jun 16, 2010 at 11:05 PM, Eran Hammer-Lahav <[email-masked]> wrote:
> _______________________________________________
> OAuth mailing list
> [email-masked]
> https://www.ietf.org/mailman/listinfo/oauth
>

---

From: Nat Sakimura <[email-masked]>
Date: Thu, 17 Jun 2010 15:23:33 +0900

I like this, thought the name "request_type" or something seems more
appropriate title for the parameter.

-- 
Nat Sakimura (=nat)
http://www.sakimura.org/en/
http://twitter.com/_nat_en

---

From: Torsten Lodderstedt <[email-masked]>
Date: Thu, 17 Jun 2010 13:33:41 +0200

+1, although "request" sounds a bit wierd. Don't you like 
"response_type" or just "response"?

---

From: Marius Scurtescu <[email-masked]>
Date: Thu, 17 Jun 2010 10:48:21 -0700

Shifting from client type profile names to flow type profiles sounds good.

Not too sure about the combined case, token_and_code. I am not opposed
to it, but I think it would help us wrap our heads around it if a
detailed use case was presented.

Thanks,
Marius

---

From: David Recordon <[email-masked]>
Date: Thu, 17 Jun 2010 10:52:26 -0700

Hey Marius, take a look at
http://www.ietf.org/mail-archive/web/oauth/current/msg02657.html from
Twitter.

---

From: Justin Richer <[email-masked]>
Date: Thu, 17 Jun 2010 14:04:50 -0400

I think I'm missing something on the combined case here. How does the
server trust the javascript client code to pass it back valid data? Is
it assumed to just rely on an established browser session at that point
that the javascript client has access to?

 -- Justin

---

From: Marius Scurtescu <[email-masked]>
Date: Thu, 17 Jun 2010 11:08:22 -0700

Yes, I am aware of that thread. I did ask some questions there which
are unanswered.

Basically, why cannot be that problem solved by 2 different requests,
both done by the JavaScript layer?

If latency is a problem, it would be good to know exactly where. I
assume that authorization codes are issued very infrequently. Does
this new token_and_code mode eliminate a transaction every two weeks?
Does that make a difference?

Also,  when and authorization code is issued I guess it cannot be an
immediate request. If an approval page is shown to the user anyhow,
then a subsequent immediate request to also grab an access token makes
no difference at all.

Before we introduce a new complicated profile I think it would be good
to know in very good details what is this solving. For similar
requests the general response was: "write an extension" or "implement
it first". Doesn't that make sense in this case as well?

Marius

---

From: Eran Hammer-Lahav <[email-masked]>
Date: Thu, 17 Jun 2010 11:09:37 -0700

What do you mean by valid data?

In the user-agent case, the server returns an access token. We added an optional authorization code which can only be used after exchanging it for an access token with required client authentication (client secret).

EHL

-----Original Message-----
From: Justin Richer [mailto:[email-masked]] 
Sent: Thursday, June 17, 2010 11:05 AM
To: Marius Scurtescu
Cc: Eran Hammer-Lahav; OAuth WG ([email-masked])
Subject: Re: [OAUTH-WG] Proposal: simplification of the end-user authorization endpoint

I think I'm missing something on the combined case here. How does the server trust the javascript client code to pass it back valid data? Is it assumed to just rely on an established browser session at that point that the javascript client has access to?

 -- Justin

---

From: Marius Scurtescu <[email-masked]>
Date: Thu, 17 Jun 2010 11:17:27 -0700

On Thu, Jun 17, 2010 at 11:09 AM, Eran Hammer-Lahav <[email-masked]> wrote:
> We added an optional authorization code which can only be used after exchanging it for an access token with required client authentication (client secret).

Just to make sure I understand the new flow, the authorization code is
supposed to be exchanged for an access *and* a refresh token, right? I
don't see the point of swapping it only for an access token.

Marius

---

From: David Recordon <[email-masked]>
Date: Thu, 17 Jun 2010 11:27:19 -0700

Sure, a refresh token as well depending on the AS implementation.

---

From: Justin Richer <[email-masked]>
Date: Thu, 17 Jun 2010 14:28:35 -0400

OK, nevermind, I think I wasn't reading things correctly. I've re-read
both the current spec and the proposal below and I think I've answered
my own question. My question was essentially "how does the Javascript
client get the authorization code back to the server?", but now I see
that it doesn't have to. The callback URL has all the bits that it would
need in order to do that since, just as in the web-server flow, the
callback URL is on the web-server making the authorization request in
the first place. This wouldn't be an option for user-agent clients with
a provider-hosted callback URL, obviously.

 -- Justin

---

From: Eran Hammer-Lahav <[email-masked]>
Date: Thu, 17 Jun 2010 14:30:38 -0700

> From: Marius Scurtescu [mailto:[email-masked]]
> Sent: Thursday, June 17, 2010 11:08 AM
> To: David Recordon
> Yes, I am aware of that thread. I did ask some questions there which are
> unanswered.

Please repeat them so we can address them now.

> Basically, why cannot be that problem solved by 2 different requests, both
> done by the JavaScript layer?
> 
> If latency is a problem, it would be good to know exactly where. I assume
> that authorization codes are issued very infrequently. Does this new
> token_and_code mode eliminate a transaction every two weeks?

The advantage of the user-agent flow is that it address the lack of client authentication with the presence of the end-user. The server might not know who the client really is, but it does know that the right user is sitting in front of the client authorizing the request. It doesn't solve phishing but it provides some security.

In the case where a client (native application or user-agent) works in tandem with a server-based component, using just the web-server flow has two disadvantages I'm aware of: the client has to be more complex because it requires callbacks in order to obtain the access token from the server (multiple calls and more complex calls than just a simple server-hosted script), but it also lose the benefit of the user presence for security. The problem is now moved to the communication between the server component and the user-agent component of the client.

> immediate request. If an approval page is shown to the user anyhow, then a
> subsequent immediate request to also grab an access token makes no
> difference at all.

Why not? Both the web-server and user-agent flows were supposed to have immediate mode.

> Before we introduce a new complicated profile I think it would be good to
> know in very good details what is this solving. For similar requests the general
> response was: "write an extension" or "implement it first". Doesn't that
> make sense in this case as well?

It makes sense to have a detailed discussion. For similar requests the general response usually came after it was establish that there was enough interest in pursuing it but not enough consensus to put it in the core spec. Let's see where this discussion takes us. Also, this proposal isn't an extension but part of the overall spec flow and architecture.

EHL
 
> >> Not too sure about the combined case, token_and_code. I am not
> >> opposed to it, but I think it would help us wrap our heads around it
> >> if a detailed use case was presented.
> >>
> >> Thanks,
> >> Marius
> >>
> >>
> >>
> >>> The latest draft (-08) unified the  web-server and user-agent client types
> into a single authorization request format. This was done because once we
> added an optional authorization code to the user-agent response, it became
> almost identical to the web-server call. The two remaining differences:
> >>>
> >>> The way in which the client indicates which response is requests is by
> using the 'type' parameter with either 'web_server' or 'user-agent'. This is all
> documented in:
> >>>
> >>> Many (if not most) services are likely to implement both the user-agent
> and web-server types (based on existing deployment and the requirements
> expressed by many of the participants).
> >>>
> >>> The web-server flow requires client authentication (client secret) in
> order to obtain an access token. It also enables the registration of a
> redirection URI.
> >>>
> >>> When using the user-agent flow, the client does not authenticate with
> the authorization server (at all) to obtain an access token. However, it does
> need to authenticate if it wants to exchange the optional authorization code
> for (another) access token.
> >>>
> >>> The authorization server has a few options when managing the security
> and trust implications of each request type:
> >>>
> >>> - Require that the client provide its type when registering with the
> service - if the authorization server knows the client type, it can limit that
> client to only make requests suitable for that client type, as well as only issue
> a client secret when the client is not a user-agent.
> >>>
> >>> - Issue different access tokens based on the security context in which
> they are obtained - access tokens issued using the direct user-agent request
> will provide less access (shorter duration, read only, etc.) than an access
> token obtained using the web-server request type.
> >>>
> >>> The first approach is problematic for complex clients requesting both an
> access token and authorization code using the user-agent request type. In
> this case, the authorization server is issuing two access tokens, each using a
> different level of security. It is means that one developer will need to obtain
> a different client identifier for the same application across different
> platforms.
> >>>
> >>> The current separation between the two request types (user-agent and
> web-server) seems artificial. This is especially true when considering the use
> cases for native applications and the applicability of both options. At the end,
> the client type doesn't matter. What matters is whether the access token is
> issued with or without client authentication (and whether that
> authentication can be trusted, which goes beyond what the protocol can
> provide).
> >>>
> >>> ** Proposal:
> >>>
> >>> Replace the 'type' parameter with a new parameter called 'request'
> (working title) which can take one of three values: 'token', 'code', or
> 'token_and_code'. This will allow the client (regardless of its type) to
> explicitly say what it wants.
> >>>
> >>> - If the client requests an access token, all the response parameters
> (including errors) are included in the fragment (same as the user-agent flow
> today).
> >>> - If the client requests an authorization code, all the parameters are
> included in the query (same as the web server flow today).
> >>> - If the client requests both, the 'code', 'status', and 'error' are included
> in the query while everything else is included in the fragment (explained in
> the example below).
> >>>
> >>> The authorization server issues the appropriate user warnings and
> access token based on the authentication level obtained. For example, when
> issuing an access token the server has to consider:
> >>>
> >>>  The advantage of this approach is that it more clearly frames the
> security context of issuing tokens. It puts native applications at the same
> level as the web-server and user-agent clients (no one gets a special
> parameter value).
> >>>
> >>> ** Examples:
> >>>
> >>> In this case all of the parameters are in relation to the token and thus
> consumed directly by the JavaScript, desktop app, etc.
> >>>
> >>> In this case there isn't an access token and all of the parameters are
> consumed by the client's server to be traded for an access token via a HTTPS
> request to the AS.
> >>>
> >>> - Token and code:
> >>>
> >>> In this case the parameters are consumer both by the JavaScript and the
> client's server. The parameters about the access token are in the fragment.
> The code is a query parameter so that the server can access it. state and
> error are useful to both and thus are query parameters which can be
> accessed by the JavaScript and the server.
> >>>
> >>>

---

From: Marius Scurtescu <[email-masked]>
Date: Thu, 17 Jun 2010 14:55:37 -0700

> Please repeat them so we can address them now.

That's what I did below.

> The advantage of the user-agent flow is that it address the lack of client authentication with the presence of the end-user. The server might not know who the client really is, but it does know tha…

Sure, but how is this affected by token_and_code? The authz server
knows who the user is when it issues the access token and the
authorization code. The authorization code is passed down to the
client server and now the client server asks for access/refresh
tokens. No user this time but potentially there is a client secret.

> In the case where a client (native application or user-agent) works in tandem with a server-based component, using just the web-server flow has two disadvantages I'm aware of: the client has to be more complex because it requires callbacks in order to obtain the access token from the server (multiple calls and more complex calls than just a simple server-hosted script),

The JavaScript client can either use the authorization code with a
direct call (as you probably suggest), but then it cannot pass the
authorization code down to the client server anymore. The JavaScript
client can do a separate User-Agent call in immediate mode to get an
access token directly. This is what it would normally do. No point in
swapping the authorization code since it can be exchanged only once.

> but it also lose the benefit of the user presence for security.

With the User-Agent immediate call this is not lost.

> The problem is now moved to the communication between the server component and the user-agent component of the client.
>

I was saying that it makes no difference from a latency perspective,
The end user just clicked an "Approve" button and was redirected, and
extra call (direct or immediate) will probably not be felt at all.

Thanks,
Marius

---

From: Eran Hammer-Lahav <[email-masked]>
Date: Fri, 25 Jun 2010 12:07:13 -0700

> Sent: Thursday, June 17, 2010 2:56 PM

> > The advantage of the user-agent flow is that it address the lack of client
> authentication with the presence of the end-user. The server might not
> know who the client really is, but it does know that the right user is sitting in
> front of the client authorizing the request. It doesn't solve phishing but it
> provides some security.
> 
> Sure, but how is this affected by token_and_code? The authz server knows
> who the user is when it issues the access token and the authorization code.
> The authorization code is passed down to the client server and now the client
> server asks for access/refresh tokens. No user this time but potentially there
> is a client secret.

But those are two different parts of the client. Returning a direct access token uses the fact that the end-user it present which provides a measure of security because a good UI can help explain to the end-user what is going on and put context into the transaction. If we force clients who need the access token both in the client and on the server to use only the code mode, then they need to find a way to share that access token. However, an access token issued using a code and client secret will potentially have more power than an access token issued using the user-agent direct communication.

The alternative of using both flows means annoying the end-user.

> > In the case where a client (native application or user-agent) works in
> > tandem with a server-based component, using just the web-server flow
> > has two disadvantages I'm aware of: the client has to be more complex
> > because it requires callbacks in order to obtain the access token from
> > the server (multiple calls and more complex calls than just a simple
> > server-hosted script),
> 
> The JavaScript client can either use the authorization code with a direct call
> (as you probably suggest), but then it cannot pass the authorization code
> down to the client server anymore. The JavaScript client can do a separate
> User-Agent call in immediate mode to get an access token directly. This is
> what it would normally do. No point in swapping the authorization code since
> it can be exchanged only once.

I think relying on immediate mode is a possible but more complex solution which can break depending on the state of cookies and sessions.
 
EHL

---

From: Marius Scurtescu <[email-masked]>
Date: Mon, 28 Jun 2010 13:27:20 -0700

> The alternative of using both flows means annoying the end-user.

Not if the second flow is done in immediate mode.

> I think relying on immediate mode is a possible but more complex solution which can break depending on the state of cookies and sessions.

Not sure if a JavaScript client can reliably work without an immediate
mode. Access tokens are short lived, the user would have to approve
every single renewal (which could be every hour).

Again, all I am saying is that it would help to have a very detailed
use case for this token_and_code mode, to see if it is really needed.
Or, an actual implementation.

Marius

---

From: Eran Hammer-Lahav <[email-masked]>
Date: Mon, 28 Jun 2010 13:37:51 -0700

> Or, an actual implementation.

I have no objections. I will include it in -09 but will mark it as
conditional pending more discussions. I hope -09 will become stable and
allow most vendors to start implementing it and gather experience. We will
decide what to do with this option once we get more insight.

It would be useful if someone from Twitter who initially proposed this would
come to defend their use case.

EHL