Subject: [OAUTH-WG] User-agent flow and pre-registered redirect_uri

From: Andrew Arnott <[email-masked]>
Date: Fri, 4 Jun 2010 21:49:55 -0700

The user agent flow indicates that the redirect_uri SHOULD be preregistered
with the auth server for a given client.  I would like to suggest that the
SHOULD here be changed to *MUST*.  Unless I'm missing something, without a
preregistered redirect_uri any arbitrary client can obtain an access token
under the pretense of being another client, and thereby perhaps altogether
skip a user authorization prompt.

As there will likely be a few popular client_id's in use, it will actually
make it trivially easy to obtain elevated access to private user data as a
rogue application.  This danger is unique to the user-agent flow because in
this flow the client_secret is not required to obtain the access token,
whereas it is for other flows.

Thoughts?
--
Andrew Arnott
"I [may] not agree with what you have to say, but I'll defend to the death
your right to say it." - S. G. Tallentyre

---

From: Andrew Arnott <[email-masked]>
Date: Mon, 7 Jun 2010 08:43:23 -0700

Rick, ...

On Sat, Jun 5, 2010 at 12:45 PM, Rick Olson <[email-masked]> wrote:

> How else are you preregistered with the auth server?

I don't understand the question, sorry.

>  Why can't you
> just return the temporary code and rely on the JS or Desktop app to
> make another call to get the access token?  JSONP would work well for
> the response to JS apps.
>
Besides being less convenient for the clients, what would that accomplish?
I don't think it would improve security, if that's the objective, since the
clients still can't keep their own secrets and it's the secret that
accompany the follow-up request for an access token that prevent the
security problem in the other flows.

>
> On Sat, Jun 5, 2010 at 12:49 AM, Andrew Arnott <[email-masked]>
> wrote:
> > SHOULD here be changed to MUST.  Unless I'm missing something, without a
> > _______________________________________________
> > OAuth mailing list
> > [email-masked]
> > https://www.ietf.org/mailman/listinfo/oauth
> >
> >
>
>
>
> --
> Rick Olson
>

---

From: Marius Scurtescu <[email-masked]>
Date: Mon, 7 Jun 2010 16:36:29 -0700

> whereas it is for other flows.

Not sure registration buys you too much.

An arbitrary client cannot pretend being another client, client in
this case is the redirect_uri. It is up to the end user to trust this
redirect_uri.

For example, bad.example.com/back cannot pretend it is
good.example.com/back because the redirect with the access token will
go to good.example.com/back and not to bad.example.com/back.

What can happen is that exmple.com/back can pretend to be
example.com/back, but registration does not help in this case.

The only case where registration really helps is if example.com allows
people to create their own pages and as a result someone could create
a JavaScript client at example.com/pages/bad. Since you can have
several clients under the same domain, the user will be confused. In
this case if example.com registers its own redirect_uri no one else
under the same domain could potentially use one. But this is a
particular case, and up to example.com to enforce. Also, if
example.com wants to allow clients installed at different paths, then
again, registration does not help.

Marius

---

From: Chuck Mortimore <[email-masked]>
Date: Mon, 7 Jun 2010 17:31:13 -0700

Note sure I follow this Marius:

"What can happen is that exmple.com/back can pretend to be
example.com/back, but registration does not help in this case."

I believe it does help in this case, as the Authorization server can validate the registered redirect_uri vs. the requested redirect_uri.   Hence the server would not issue a token to exmple.com in this case.   Am I missing something?

-cmort

On 6/7/10 4:36 PM, "Marius Scurtescu" <[email-masked]> wrote:

Marius

---

From: Dick Hardt <[email-masked]>
Date: Mon, 7 Jun 2010 18:19:58 -0700

You are pointing out Marius point -- he wants to require registration. If the redirect_uri is not registered, the only party that can detect that it is the right URI is the user. The AS can only show the user the redirect_uri passed over.

-- Dick

On 2010-06-07, at 5:31 PM, Chuck Mortimore wrote:

> “What can happen is that exmple.com/back can pretend to be
> example.com/back, but registration does not help in this case.”
>

---

From: Marius Scurtescu <[email-masked]>
Date: Mon, 7 Jun 2010 18:23:09 -0700

On Mon, Jun 7, 2010 at 5:31 PM, Chuck Mortimore
<[email-masked]> wrote:
> I believe it does help in this case, as the Authorization server can
> validate the registered redirect_uri vs. the requested redirect_uri.   Hence
> the server would not issue a token to exmple.com in this case.   Am I
> missing something?

What stops exmple.com from registering? Unless the authz wants to
operate only with a short list of human verified clients. The current
spec allows that. But if registration cannot be controlled like that,
and all it does it proves that the client owns a domain, then it does
not help.

I don't think registration should/can be enforced.

Marius

---

From: Chuck Mortimore <[email-masked]>
Date: Tue, 8 Jun 2010 10:40:52 -0700

Thanks - I get your line of reasoning now.   I believe it would still help in preventing certain types of attack.   These are especially apparent around immediate.

1) User initially grants access to example.com
2) User goes to an evil site
3) Without the user's knowledge, the malicious site issues an immediate user_agent flow

https://authzserver.com/authorize?type=user_agent&immediate=true&client_id=<Example.com's Client ID>&redirect_uri=<Evil URL>

4) Evil site is handed an access token based upon the previous grant to example.com

This would be prevented with a redirect_url whitelist.

-cmort

On 6/7/10 6:23 PM, "Marius Scurtescu" <[email-masked]> wrote:

Marius

---

From: Marius Scurtescu <[email-masked]>
Date: Tue, 8 Jun 2010 11:04:15 -0700

On Tue, Jun 8, 2010 at 10:40 AM, Chuck Mortimore
<[email-masked]> wrote:
> Thanks – I get your line of reasoning now.   I believe it would still help
> in preventing certain types of attack.   These are especially apparent
> around immediate.

I do agree that requiring registration may be a good idea in many
cases, all I am saying is that this should not be enforced. Some authz
servers may want to allow unregistered clients, and that's fine. I
think the current SHOULD is good enough and changing it to MUST would
be going too far.

> 3) Without the user’s knowledge, the malicious site issues an immediate
> user_agent flow
>
> https://authzserver.com/authorize?type=user_agent&immediate=true&client_id=<Example.com’s
> Client ID>&redirect_uri=<Evil URL>
>

I don't think this attack will work. If exmple.com was not registered,
then it has not client_id, so the previous approval should be
remembered for example.com's redirect_uri. Evil site needs to use its
own redirect_uri, so immediate will not work.

Marius

---

From: Andrew Arnott <[email-masked]>
Date: Tue, 8 Jun 2010 23:20:53 -0700

Marius,

You seem to be coming from the perspective that the auth server stores
authorizations (that would eliminate the need for the user to interactively
approve an authorization) based on redirect_url rather than client_id.  Is
that right?

I've always considered an authorization as a tuple of
client_id,user,scope,issue_date.  If an authorization has been approved, and
another request for authorization for a subset of the scope previously
issued comes in, the auth server can skip the interactive user authorization
and just approve the request since nothing new is being issued.

If my tuple is correct, then the user agent flow allows any random client to
submit a trusted client_id as if it was them, but with an evil redirect_url
so they can obtain user authorization without the user noticing at all (if
an authorization already existed).  But if redirect_url belongs in that
tuple, then that would be the mitigation I guess.  But we could avoid extra
user prompts if we just forced clients to register their redirect_url's in
order to be enabled for user agent flows, thus protecting the user from bad
clients sending in evil redirect_urls in order to steal access tokens.

---

From: Marius Scurtescu <[email-masked]>
Date: Wed, 9 Jun 2010 09:35:46 -0700

> approve an authorization) based on redirect_url rather than client_id.  Is

Only for the unregistered case. If the client did register with the
authz server then you can use the client_id, but then you also have to
match the registered redirect_uri with the actual one (and how
matching is done is still not defined).

> and just approve the request since nothing new is being issued.

The tuple seems right, except for the issue date, why would you add that?

> clients sending in evil redirect_urls in order to steal access tokens.

I think you are saying the same thing. Basically, registered and
unregistered behave differently, and the spec should allow for both I
think.

Marius

---

From: Andrew Arnott <[email-masked]>
Date: Thu, 10 Jun 2010 08:35:32 -0700

Thanks Marius.

I've answered your question below.

> The tuple seems right, except for the issue date, why would you add that?

The issue_date enables to scenarios: expiring tokens and token revocation.
Here's how, for each scenario:

Obviously to know if a token has expired you need to know when it was
issued.  Or, you can forget the issue date and just store the expiration
date in the token. I choose to go with an issue date (plus an optional
expected lifetime) because it gives more ability in the future to say "oops,
we had a security weakness in all tokens issued prior to [date], so let's
consider all earlier tokens invalid."  It's harder to say that when all you
have are expiration dates because you don't know how old the token is.  This
is just the way I chose to do it, but I know there are other ways.

Now let's look at how you revoke issued tokens.  One of the nice things
enabled by OAuth 2.0 is that the authorization server and resource server
never have to store tokens if they are appropriate signed by the auth
server.  This is great because (among other things) clients with
little-to-no ability to persistently store tokens may ask for tokens
frequently, and that could bog down an auth server with storing all those
issued tokens.  But how can a user revoke a previously authorized token if
no one but the client knows what the tokens are? (thought question)  My
solution to this is that instead of thinking about revoking *tokens*, the
user revokes *authorizations*.  The user goes through his account on the
authorization server and sees a list of clients and what they are authorized
to do.  Note that this only requires the auth server to store this
authorization tuple -- not the actual issued tokens.  If the user clicks
"revoke" on one of these authorizations, that row is deleted in the
database.  Issued tokens (both refresh and access tokens) have this same
tuple encoded in them.
Now, when a refresh token is used to obtain a new short-lived access token
(and you could do this on every access token use as well if you wanted) the
token is of course signature-validated, but it is also checked that the
authorization tuple has a matching tuple in the auth server's database.  If
it's missing, then that authorization has been revoked and the token is
thereby invalidated.
So why the issue date?  Because suppose the user has authorized a client and
then that client's tokens are compromised (stolen computer perhaps).  The
user will of course revoke authorization for that client.  The user then
gets a new copy of that client (perhaps a new computer) and authorizes it.
Whoops.  Now all those invalidated tokens are valid again because the
authorization tuple exists.  *Except now the issue date on the authorization
on the auth server is newer than in the refresh token on the invalidated
client*.  That's why issue date is such a critical part of an authorization
tuple.  Any token issued prior to the earliest authorization on record at
the auth server represents a revoked authorization, and without an issue
date in the tuple there's no way to recognize that.

At least that's the way I'm seeing it.  I hope that makes sense.

---

From: Marius Scurtescu <[email-masked]>
Date: Thu, 10 Jun 2010 10:34:40 -0700

On Thu, Jun 10, 2010 at 8:35 AM, Andrew Arnott <[email-masked]> wrote:
> solution to this is that instead of thinking about revoking tokens, the user
> revokes authorizations.  The user goes through his account on the
> authorization tuple exists.  Except now the issue date on the authorization
> client.  That's why issue date is such a critical part of an authorization

I see where are you coming from. I assumed that access tokens are
saved and issue/expiry times are associated with the tokens, not with
the authorization decisions.

Marius

---

From: Thomas Hardjono <[email-masked]>
Date: Thu, 10 Jun 2010 16:27:10 -0400

Andrew, Marius,

Comments in-line.

> -----Original Message-----
> From: [email-masked] [mailto:[email-masked]] On Behalf Of
> Marius Scurtescu
> Sent: Thursday, June 10, 2010 1:35 PM
> To: Andrew Arnott
> Cc: [email-masked]
> Subject: Re: [OAUTH-WG] User-agent flow and pre-registered redirect_uri
> 
> >> > client_id,user,scope,issue_date.  If an authorization has been
approved,
> >> > and

I noticed that there is no nonce used in the token request portion
and the response from authorization server.
Did I miss it (ie. is it embedded somewhere?)

> > server.  

Yes and no.  It depends on (a) what is meant by "signing" the tokens and
(b) whether the Autz Server needs to log all actions for legal purposes
(eg. non-repudiation) Some service providers might want to archive all
tokens it accepted/validated together with the info on resources/objects
accessed by the clients.

> > This is great because (among other things) clients with

OK, so this is not live "revocation" with an immediate effect. Like
Kerberos, there is a gap of time between the client revoking the token
(service ticket) to the time when the refresh token (TGT) is exercised next.
During this gap of time the token is still live and valid.

The only way to get around this is to have the resource server contact the
authorization server every time (but that would defeat the purpose of
tokens/tickets). Even in X509, cert validation means the service provider or
RP performs a live check against the OCSP servers.

> > authorization tuple exists.  

If the tokens (tickets) were issued to the client entity (principal) versus
to the human-user principal, then this will not be a problem. If the user
loses her client/laptop, then she need only revoke the tokens associated to
the client/laptop.

I think this is where there is room for OAuth 2.0 to innovate, such as to
introduce a special kind of token (human-token) that is independent from
client/laptop tokens.  The human-token could even be stored in a secure
cloud service and be used for client-initiation or emergency purposes only.
Thus, whenever the human-user wants to move to a new laptop/client, the
human-token is pulled down from the cloud, used to authenticate to the auth
server, and then deleted (from the client) once the new client/laptop
becomes a known entity/principal in the ecosystem and has its own tokens.
Just a thought.

> >
> > Except now the issue date on the authorization

/thomas/

---

From: Andrew Arnott <[email-masked]>
Date: Thu, 10 Jun 2010 20:19:56 -0700

Hi Thomas,

Some responses inline...

On Thu, Jun 10, 2010 at 1:27 PM, Thomas Hardjono <[email-masked]> wrote:

> I actually asked a similar question on another thread.  The spec doesn't
mention nonces at all.  The only place they seem to make sense to me would
be as an embedded part of the verification code, and that's only if the
authz server wants to make sure they can only be exchanged for a refresh
token once.  In my implementation that's exactly what I did: there's a nonce
embedded in the verification code.

> tokens it accepted/validated together with the info on resources/objects

Of course there are different requirements for different companies and
governments, absolutely.  I'm just speaking of technological requirements
here.  However, I suggest we choose our terms a bit more carefully here
because what you're saying doesn't seem to strictly fit.  An authorization
server doesn't need non-repudiation because it never receives signed
messages from anyone other than itself.  An authz server may want to log
that authorizations took place, and perhaps even what tokens were issued,
but they can be in a log file perhaps without being in the database for
programmatic lookup later as a normal course of business.  I suspect when
you said "service provider" you meant what the spec refers to as a "resource
server", and certainly they can log whatever they want as well.  But
technologically speaking, the only member that has to actually store tokens
for the flow to work is the client, and even that can be a very short-lived
persistence depending on the user scenario.

> > > authorization tuple has a matching tuple in the auth server's
> database.
> If

I agree.  And where that time window between a token's revocation and its
actual loss of usefulness is something that has to be weighed by each
application and it might mean checking each token as it comes in on each
request.  Although the spec separates the authz server and resource server
roles, they commonly will be the same server, so this token check will
simply be a database lookup. If the two roles are indeed on different
servers a token validity check on every single request to the resource
server *may* be too costly in bandwidth and performance, in which case there
is actually a variety of ways to mitigate the problems, but that's beyond
the scope of this thread by quite a bit (start a new one if you'd like).

>
>
> > > So why the issue date?  Because suppose the user has authorized a
> client
> > and

Sure, but that requires either that you store all issued tokens so you can
revoke individual ones, or that you revoke all tokens issued to a
client_id.  But client apps can't keep secrets, so an installed app on a
laptop will likely just have a client_id that is preset for the app (it
doesn't have to be this way, but it may).  That means that all installations
of that app on all laptops will have the same client_id (and no secret), and
therefore you can't revoke all tokens issued to an individual laptop because
there's no distinction for it.

Yes, I know this isn't the way all applications will be, but again it MAY be
this way, so I'm planning for it.

> becomes a known entity/principal in the ecosystem and has its own tokens.

Bring on the innovation. :)

---

From: George Fletcher <[email-masked]>
Date: Fri, 11 Jun 2010 10:38:40 -0400

Makes perfect sense as we have the same model for our clients & tokens:)

The one use case we've encountered is that this model revokes the tokens 
for all clients with the same client_id. So if I've got three of the 
same client installed (on three computers) and they likely all have the 
same client_id, then revoking that client_id affects all three clients. 
I think this is a reasonable trade-off. Especially since revoking 
authorizations will be an infrequent event.

Thanks,
George

On 6/10/10 11:35 AM, Andrew Arnott wrote:
> On Wed, Jun 9, 2010 at 9:35 AM, Marius Scurtescu 
> <[email-masked] <mailto:[email-masked]>> wrote:
>
>     approved, and
> The issue_date enables to scenarios: expiring tokens and token 
> revocation.  Here's how, for each scenario:
>
> issued.  Or, you can forget the issue date and just store the 
> expiration date in the token. I choose to go with an issue date (plus 
> an optional expected lifetime) because it gives more ability in the 
> future to say "oops, we had a security weakness in all tokens issued 
> prior to [date], so let's consider all earlier tokens invalid."  It's 
> harder to say that when all you have are expiration dates because you 
> don't know how old the token is.  This is just the way I chose to do 
> it, but I know there are other ways.
>
> Now let's look at how you revoke issued tokens.  One of the nice 
> things enabled by OAuth 2.0 is that the authorization server and 
> resource server never have to store tokens if they are appropriate 
> signed by the auth server.  This is great because (among other things) 
> clients with little-to-no ability to persistently store tokens may ask 
> for tokens frequently, and that could bog down an auth server with 
> storing all those issued tokens.  But how can a user revoke a 
> previously authorized token if no one but the client knows what the 
> tokens are? (thought question)  My solution to this is that instead of 
> thinking about revoking /tokens/, the user revokes /authorizations/.  
> The user goes through his account on the authorization server and sees 
> a list of clients and what they are authorized to do.  Note that this 
> only requires the auth server to store this authorization tuple -- not 
> the actual issued tokens.  If the user clicks "revoke" on one of these 
> authorizations, that row is deleted in the database.  Issued tokens 
> (both refresh and access tokens) have this same tuple encoded in them.
> Now, when a refresh token is used to obtain a new short-lived access 
> token (and you could do this on every access token use as well if you 
> wanted) the token is of course signature-validated, but it is also 
> checked that the authorization tuple has a matching tuple in the auth 
> server's database.  If it's missing, then that authorization has been 
> revoked and the token is thereby invalidated.
> client and then that client's tokens are compromised (stolen computer 
> perhaps).  The user will of course revoke authorization for that 
> client.  The user then gets a new copy of that client (perhaps a new 
> computer) and authorizes it.  Whoops.  Now all those invalidated 
> tokens are valid again because the authorization tuple exists. /Except 
> now the issue date on the authorization on the auth server is newer 
> than in the refresh token on the invalidated client/.  That's why 
> issue date is such a critical part of an authorization tuple.  Any 
> token issued prior to the earliest authorization on record at the auth 
> server represents a revoked authorization, and without an issue date 
> in the tuple there's no way to recognize that.
>

---

From: Torsten Lodderstedt <[email-masked]>
Date: Fri, 11 Jun 2010 16:50:05 +0200

Am 11.06.2010 16:38, schrieb George Fletcher:
> The one use case we've encountered is that this model revokes the 
> tokens for all clients with the same client_id. So if I've got three 
> of the same client installed (on three computers) and they likely all 
> have the same client_id, then revoking that client_id affects all 
> three clients. I think this is a reasonable trade-off. Especially 
> since revoking authorizations will be an infrequent event.

Alternatively, a device_id (hostname, IMEI, ...) could be incorporated 
into the authorization tuple. This would allow to a) visualize to the 
end-user the devices were clients w/ tokens reside and b) revoke tokens 
by device_id.

regards,
Torsten.
>> signed by the auth server.  This is great because (among other 
>> things) clients with little-to-no ability to persistently store 
>> tokens may ask for tokens frequently, and that could bog down an auth 
>> server with storing all those issued tokens.  But how can a user 
>> revoke a previously authorized token if no one but the client knows 
>> what the tokens are? (thought question)  My solution to this is that 
>> instead of thinking about revoking /tokens/, the user revokes 
>> /authorizations/.  The user goes through his account on the 
>> authorization server and sees a list of clients and what they are 
>> authorized to do.  Note that this only requires the auth server to 
>> store this authorization tuple -- not the actual issued tokens.  If 
>> the user clicks "revoke" on one of these authorizations, that row is 
>> deleted in the database.  Issued tokens (both refresh and access 
>> tokens) have this same tuple encoded in them.
>> tokens are valid again because the authorization tuple exists. 
>> /Except now the issue date on the authorization on the auth server is 
>> newer than in the refresh token on the invalidated client/.  That's 
>> why issue date is such a critical part of an authorization tuple.  
>> Any token issued prior to the earliest authorization on record at the 
>> auth server represents a revoked authorization, and without an issue

---

From: Justin Richer <[email-masked]>
Date: Fri, 11 Jun 2010 11:05:53 -0400

Along these lines, I'd like to propose an extension for per-client
instance information to be passed from a client to the server. Things
like a human-readable client name/description, instance name/description
(could be tied to host name, ip, label like "home" or "Work"), and even
something like a display icon. This is especially useful for things like
device clients (where I might have a bunch of devices with the same
client ID) or unregistered clients, where the client id string ends up
being closer to a user-agent string from a browser than a trusted
identifier, especially since it can't have a reliable secret. 

Speaking of which, the spec is relatively quiet on registered vs.
unregistered clients. I'd like to see the WG maybe pull together some
guidance on this topic? I'm not sure what form that would take though,
an information note that sits along with the RFC? A page on the oauth
wiki? Basically, I think we can get away from the anonymous/anonymous
hack that Google used with OAuth1 since we're not requiring the client
secret for signing anymore. Thoughts?

 -- Justin

On Fri, 2010-06-11 at 10:38 -0400, George Fletcher wrote:
> > <[email-masked]> wrote:
> > Obviously to know if a token has expired you need to know when it
> > was issued.  Or, you can forget the issue date and just store the
> > expiration date in the token. I choose to go with an issue date
> > (plus an optional expected lifetime) because it gives more ability
> > in the future to say "oops, we had a security weakness in all tokens
> > issued prior to [date], so let's consider all earlier tokens
> > invalid."  It's harder to say that when all you have are expiration
> > dates because you don't know how old the token is.  This is just the
> > way I chose to do it, but I know there are other ways.
> > 
> > tokens may ask for tokens frequently, and that could bog down an
> > auth server with storing all those issued tokens.  But how can a
> > user revoke a previously authorized token if no one but the client
> > knows what the tokens are? (thought question)  My solution to this
> > is that instead of thinking about revoking tokens, the user revokes
> > authorizations.  The user goes through his account on the
> > token (and you could do this on every access token use as well if
> > you wanted) the token is of course signature-validated, but it is
> > also checked that the authorization tuple has a matching tuple in
> > the auth server's database.  If it's missing, then that
> > authorization has been revoked and the token is thereby invalidated.
> > client and then that client's tokens are compromised (stolen
> > computer perhaps).  The user will of course revoke authorization for
> > that client.  The user then gets a new copy of that client (perhaps
> > a new computer) and authorizes it.  Whoops.  Now all those
> > invalidated tokens are valid again because the authorization tuple
> > exists.  Except now the issue date on the authorization on the auth
> > server is newer than in the refresh token on the invalidated client.
> > That's why issue date is such a critical part of an authorization
> > tuple.  Any token issued prior to the earliest authorization on
> > record at the auth server represents a revoked authorization, and
> > without an issue date in the tuple there's no way to recognize that.
> >

---

From: Christian Scholz <[email-masked]>
Date: Fri, 11 Jun 2010 17:35:17 +0200

Hi!

> identifier, especially since it can't have a reliable secret. 

We have the need for dynamic binding of clients in the User Managed
Access group (UMA) as well. I did look into OpenID Connect but felt that
reusing an OAuth flow based on a different type is maybe mixing things a
bit too much. To me using a flow means that in the end usually
you end up with an access token which here is not the case. Especially I
don't like the reuse of the token URI as IMHO it's better to use
separate endpoints for different APIs.

I thus went along and crafted some simple handshake in the UMA
specification which I also wanted to move out into a single
specification over the next days.

You can find it here:

http://kantarainitiative.org/confluence/display/~christianscholz/Step+1+experimental+version+v1

under "Dynamic binding of OAuth clients".

It is a simple handshake where you provide a JSON formatted client
descriptor containing the information you describe above and the results
is a set of client credentials plus optionally additional information
(in UMA we eventually need to pass back more information like additional
endpoints).

We also discussed it yesterday on the UMA conference call and the
consensus was that it's better to let the server assign a client id so
you have a more unique identifier.

Moreover it is probably easier to send the client id as intended and not
all the relevant client information on every request.

Other options would be to use some URL as client id and providing an XRD
document describing the client via hostmeta.

Any feedback on what people's requirements and thoughts on the issue are
welcome!

-- Cristian

-- 
Christian Scholz                          Homepage: http://comlounge.net
COM.lounge GmbH                              blog: http://mrtopf.de/blog
Hanbrucher Str. 33                                       Skype: HerrTopf
52064 Aachen                             Video Blog: http://comlounge.tv
Tel: +49 241 400 730 0                           E-Mail [email-masked]
Fax: +49 241 979 00 850                               IRC: MrTopf, Tao_T

Podcasts:
Der OpenWeb-Podcast (http://openwebpodcast.de)
Data Without Borders (http://datawithoutborders.net)
Politisches: http://politfunk.de/
Technical: http://comlounge.tv/

---

From: George Fletcher <[email-masked]>
Date: Fri, 11 Jun 2010 11:52:05 -0400

+1 for "dynamic registration"

On 6/11/10 11:35 AM, Christian Scholz wrote:
>>> Makes perfect sense as we have the same model for our clients&
>>> tokens:)
>>>

---

From: Justin Richer <[email-masked]>
Date: Fri, 11 Jun 2010 11:52:35 -0400

One missing point from this is that the same client ID could be used for
different instances for the same user. That's how google's
xoauth_display_name was used, and that's what I'm proposing as an
extension to the capability below. Unregistered clients are a separate,
but slightly related, issue, and the handshake proposal outlined here
might help that (or the dynamic binding proposed as part of OpenID
Connect). But I think that we might be better served to have a means
that doesn't require registration at all. I think we can get the
functionality of just using "anonymous" as the client id without
requiring all clients to do so, again like a browser user agent string
can do today. It can't be trusted as authoritative, but can be used as a
hint. And of course, any particular AS may choose to require
registration still.

Maybe we need to drill in to the pros/cons of requiring registration,
allowing ad-hoc registration, and allowing unknown client ids before we
can answer this question.

 -- Justin

---

From: Marius Scurtescu <[email-masked]>
Date: Fri, 11 Jun 2010 08:54:10 -0700

> (in UMA we eventually need to pass back more information like additional

In general during registration an authz server will verify that the
client really owns the domain it claims it does. Does any validation
like that happen in the suggested "Dynamic binding of OAuth clients"?

Marius

---

From: David Recordon <[email-masked]>
Date: Fri, 11 Jun 2010 08:59:06 -0700

That sounds like a security consideration to me! :)

I imagine that authorization servers will verify ownership in
different manners depending on their tolerance of risk.

---

From: Marius Scurtescu <[email-masked]>
Date: Fri, 11 Jun 2010 09:07:38 -0700

> different manners depending on their tolerance of risk.

Instead of POSTing a JSON with all the details, dynamic binding could
send only a host name. The authz server would then do discovery on
this host and get a pointer to this JSON from host-meta.

Marius

---

From: George Fletcher <[email-masked]>
Date: Fri, 11 Jun 2010 12:25:11 -0400

On 6/11/10 12:07 PM, Marius Scurtescu wrote:
> On Fri, Jun 11, 2010 at 8:59 AM, David Recordon<[email-masked]>  wrote:
>    
I think most all of this could be described in the host-meta XRD 
directly to save yet another round trip. And I believe there are some 
security advantages to using this approach, but it does require the 
"client" to be a web-server. This might not always be the case (rich 
desktop app). For native/desktop apps, it seems that posting some set of 
parameters (equivalent security-wise to a browser user-agent) makes 
sense and keeps the protocol simple.

Thanks,
George
>>
>> On Fri, Jun 11, 2010 at 8:54 AM, Marius Scurtescu<[email-masked]>  wrote:
>>      
>>> On Fri, Jun 11, 2010 at 8:35 AM, Christian Scholz<[email-masked]>  wrote:
>>>        
>>>> Hi!
>>>>

---

From: Marius Scurtescu <[email-masked]>
Date: Fri, 11 Jun 2010 09:34:34 -0700

On Fri, Jun 11, 2010 at 9:25 AM, George Fletcher <[email-masked]> wrote:
> I think most all of this could be described in the host-meta XRD directly to
> save yet another round trip. And I believe there are some security
> advantages to using this approach, but it does require the "client" to be a
> web-server. This might not always be the case (rich desktop app). For
> native/desktop apps, it seems that posting some set of parameters
> (equivalent security-wise to a browser user-agent) makes sense and keeps the
> protocol simple.

Yes, but in this case (desktop app) the "url" and "icon" parameters
don't work and what is left is "name" and "description". I think that
the suggested "client_name" parameter does exactly the same thing,
much simpler. Is there any value in this case in a client_secret?

Marius

---

From: George Fletcher <[email-masked]>
Date: Fri, 11 Jun 2010 13:07:47 -0400

On 6/11/10 12:34 PM, Marius Scurtescu wrote:
> On Fri, Jun 11, 2010 at 9:25 AM, George Fletcher<[email-masked]>  wrote:
>    
Well... given this is a POST and structured data... it would be possible 
for the desktop app to post the raw icon data (though I suppose it could 
also POST a URL to the web server of the company the produces the app). 
In which case your previous suggestion would work (parameters discovered 
via the URL).

I do believe the client_secret is valuable in this case because the AS 
is returning both the client_id and the client_secret. This then becomes 
a way for provisioning a unique client_id and client_secret to every 
instance of the app. A lot more for the AS to keep track of, but also 
makes it more difficult for an attacker to compromise a client. The 
attacker could impersonate the POST'd client description data (just like 
user-agent strings can be impersonated), but then the attacker just has 
a client_id and client_secret for it's instance.

This should force the attacker to get explicit user consent from the 
user to authorize that unique client_id. I wouldn't recommend for the AS 
to track authorization against the POST'd client description but rather 
the client_id.

Thanks,
George

---

From: Eran Hammer-Lahav <[email-masked]>
Date: Fri, 11 Jun 2010 10:25:00 -0700

Client doesn't need to *be* a web server, just *have* a web server available.

EHL

> From: [email-masked] [mailto:[email-masked]] On Behalf
> Of George Fletcher
> Sent: Friday, June 11, 2010 9:25 AM
> To: [email-masked]
> (equivalent security-wise to a browser user-agent) makes sense and keeps
> the protocol simple.
> 
> Thanks,
> George
> >>
> >>>>> instance information to be passed from a client to the server.
> >>>>> Things like a human-readable client name/description, instance
> >>>>> name/description (could be tied to host name, ip, label like
> >>>>> "home" or "Work"), and even something like a display icon. This is
> >>>>> especially useful for things like device clients (where I might
> >>>>> have a bunch of devices with the same client ID) or unregistered
> >>>>> clients, where the client id string ends up being closer to a
> >>>>> user-agent string from a browser than a trusted identifier, especially
> since it can't have a reliable secret.
> >>>>>
> >>>> Access group (UMA) as well. I did look into OpenID Connect but felt
> >>>> that reusing an OAuth flow based on a different type is maybe
> >>>> mixing things a bit too much. To me using a flow means that in the
> >>>> end usually you end up with an access token which here is not the
> >>>> case. Especially I don't like the reuse of the token URI as IMHO
> >>>> it's better to use separate endpoints for different APIs.
> >>>>
> >>>> descriptor containing the information you describe above and the
> >>>> results is a set of client credentials plus optionally additional
> >>>> information (in UMA we eventually need to pass back more
> >>>> information like additional endpoints).
> >>>>

---

From: Marius Scurtescu <[email-masked]>
Date: Fri, 11 Jun 2010 11:09:28 -0700

On Fri, Jun 11, 2010 at 10:07 AM, George Fletcher <[email-masked]> wrote:
>>> the
> Well... given this is a POST and structured data... it would be possible for
> the desktop app to post the raw icon data (though I suppose it could also
> POST a URL to the web server of the company the produces the app). In which
> case your previous suggestion would work (parameters discovered via the
> URL).
>
> I do believe the client_secret is valuable in this case because the AS is
> returning both the client_id and the client_secret. This then becomes a way
> for provisioning a unique client_id and client_secret to every instance of
> the app. A lot more for the AS to keep track of, but also makes it more
> difficult for an attacker to compromise a client. The attacker could
> impersonate the POST'd client description data (just like user-agent strings
> can be impersonated), but then the attacker just has a client_id and
> client_secret for it's instance.
>
> This should force the attacker to get explicit user consent from the user to
> authorize that unique client_id. I wouldn't recommend for the AS to track
> authorization against the POST'd client description but rather the
> client_id.

An attacker can also dynamically register a very similar client
name/description and trick the user.

The authz server is issuing a unique refresh token for each client,
and I still don't see how an extra client_secret helps in this case.

For a web client the client secret helps if the refresh token is
compromised. The web client most likely will store many refresh
tokens, one for each user, in the database, with SQL injection all of
these can be compromised, but the client secret (if it was not in the
same database) makes them useless. This could be a reason why dynamic
registration for web clients is a bad idea, the client secret will end
up in the database, instead of a config file.

For a desktop client, this is not the case.

Marius

---

From: George Fletcher <[email-masked]>
Date: Fri, 11 Jun 2010 14:46:38 -0400

On 6/11/10 2:09 PM, Marius Scurtescu wrote:
> On Fri, Jun 11, 2010 at 10:07 AM, George Fletcher<[email-masked]>  wrote:
>    
True... but the user will see another consent form. This might be a 
minor hurdle but at least it's not totally seamless. I think that is an 
advantage.
> and I still don't see how an extra client_secret helps in this case.
Good point. With SSL and bearer tokens the client_secret doesn't do much 
good. Now if we signed the requests with the unique client_secret from 
the desktop app... :)
> up in the database, instead of a config file.
The web site could store client_secrets in a different database that is 
not exposed to the same SQL Injection attacks. Where the data is stored 
doesn't seem like it affects it's ability to be compromised or 
protected. If the web server is not well protected, getting the config 
file with the client_secret might be easier than getting data out of the 
database. I think the security of where the web app stores the data is 
orthogonal to the security of the protocol.
> For a desktop client, this is not the case.
I suppose this also depends on which flow the desktop app is following. 
If using the web-user flow (by launching the default browser, then the 
client_secret (v2-06) is required. If following the device flow... then 
it's not (though it seems this flow is still being defined).

So maybe the solution is that if the authorization server doesn't think 
the client_secret is useful, it doesn't return it. Or it always returns 
it and the client can throw it away as it knows it won't use it. 
However, it seems like the rest of the registration flow still holds.

Thanks,
George

---

From: Marius Scurtescu <[email-masked]>
Date: Fri, 11 Jun 2010 12:15:32 -0700

On Fri, Jun 11, 2010 at 11:46 AM, George Fletcher <[email-masked]> wrote:
>>>>> directly
>>>>> to
>>>>> advantages to using this approach, but it does require the "client" to
>>>>> be
>>>>> a
>>> for
> True... but the user will see another consent form. This might be a minor
> hurdle but at least it's not totally seamless. I think that is an advantage.

Why would the user see another consent form? Were you thinking
auto-approvals? For desktop apps auto-approvals don't make much sense
and authz servers should probably never do that.

> good. Now if we signed the requests with the unique client_secret from the
> desktop app... :)

Yes, but let's see how the signature specs work out.

> The web site could store client_secrets in a different database that is not
> exposed to the same SQL Injection attacks. Where the data is stored doesn't
> seem like it affects it's ability to be compromised or protected. If the web
> server is not well protected, getting the config file with the client_secret
> might be easier than getting data out of the database. I think the security
> of where the web app stores the data is orthogonal to the security of the
> protocol.

Maybe, not sure. If web clients are encouraged to put the secret in
the database then it will end up next to the refresh token, for sure.

> I suppose this also depends on which flow the desktop app is following. If
> using the web-user flow (by launching the default browser, then the
> client_secret (v2-06) is required. If following the device flow... then it's
> not (though it seems this flow is still being defined).

client_secret is required only if one was issued, "REQUIRED if the
client identifier has a matching secret." So the Web Server flow
should work just fine for unregistered or unsecure (registered but no
secret was issued) clients.

> So maybe the solution is that if the authorization server doesn't think the
> client_secret is useful, it doesn't return it. Or it always returns it and
> the client can throw it away as it knows it won't use it. However, it seems
> like the rest of the registration flow still holds.

Without client_secret I still don't see the point. Registration then
boils down to self asserted name, which can also be achieved with the
client_name paramter, no?

Marius

---

From: George Fletcher <[email-masked]>
Date: Fri, 11 Jun 2010 16:01:58 -0400

On 6/11/10 3:15 PM, Marius Scurtescu wrote:
> On Fri, Jun 11, 2010 at 11:46 AM, George Fletcher<[email-masked]>  wrote:
>    
This based on my assumptions about authorization approvals. In my 
experience, the authorization is based off the client_id (or it's 
equivalent... developer key, api key, etc). So if a user has already 
given consent to that client_id, why would the authorization service ask 
the user for consent again if presented with the same client_id? To do 
this, the authorization would have to consider some additional 
parameters beside client_id when determining whether to ask the user to 
consent to the authorization or not. I suppose if the authorization 
server required user consent every time the client requested 
authorization ( 2.5.1. Client Requests Authorization), then I agree that 
having a unique client_id doesn't provide much value.

> client_name paramter, no?
Well.. there might be a slight difference. By having a specific endpoint 
for registering a client, the authorization server can chose to give out 
a unique client_id every time the API is called (or based on some other 
rules). This prevents one level of "impersonation". It also keeps the 
existing model the same (clients are represented uniquely by a 
client_id). Some registered out-of-band, some registered dynamically.

As far as how to represent the client, I think that more than just the 
client_name (as in a string) is valuable. However, this can be 
accomplished via client_name being a URL with discoverable meta-data or 
a POST'd data structure.

Thanks,
George