Re: [OAUTH-WG] Mail regarding draft-ietf-oauth-dyn-reg

"Richer, Justin P." <> Fri, 11 January 2013 17:10 UTC

Return-Path: <>
Received: from localhost (localhost []) by (Postfix) with ESMTP id 4E8A921F843C for <>; Fri, 11 Jan 2013 09:10:45 -0800 (PST)
X-Virus-Scanned: amavisd-new at
X-Spam-Flag: NO
X-Spam-Score: -5.719
X-Spam-Status: No, score=-5.719 tagged_above=-999 required=5 tests=[AWL=0.279, BAYES_00=-2.599, HTML_MESSAGE=0.001, J_CHICKENPOX_23=0.6, RCVD_IN_DNSWL_MED=-4]
Received: from ([]) by localhost ( []) (amavisd-new, port 10024) with ESMTP id RngIzdK-FS1a for <>; Fri, 11 Jan 2013 09:10:42 -0800 (PST)
Received: from ( []) by (Postfix) with ESMTP id BFCAE21F8825 for <>; Fri, 11 Jan 2013 09:10:41 -0800 (PST)
Received: from (localhost.localdomain []) by localhost (Postfix) with SMTP id 69A3D1F368B; Fri, 11 Jan 2013 12:10:40 -0500 (EST)
Received: from IMCCAS03.MITRE.ORG ( []) by (Postfix) with ESMTP id 2C3321F3684; Fri, 11 Jan 2013 12:10:40 -0500 (EST)
Received: from IMCMBX01.MITRE.ORG ([]) by IMCCAS03.MITRE.ORG ([]) with mapi id 14.02.0318.004; Fri, 11 Jan 2013 12:10:39 -0500
From: "Richer, Justin P." <>
To: "Boone, Keith W (GE Healthcare)" <>
Thread-Topic: Mail regarding draft-ietf-oauth-dyn-reg
Thread-Index: Ac3utCNS17plP6SWSbiehcbL+FvGpwA8KZMAAApcswAAHo/cgA==
Date: Fri, 11 Jan 2013 17:10:38 +0000
Message-ID: <B33BFB58CCC8BE4998958016839DE27E0687684E@IMCMBX01.MITRE.ORG>
References: <> <B33BFB58CCC8BE4998958016839DE27E0687614D@IMCMBX01.MITRE.ORG> <>
In-Reply-To: <>
Accept-Language: en-US
Content-Language: en-US
x-originating-ip: []
Content-Type: multipart/alternative; boundary="_000_B33BFB58CCC8BE4998958016839DE27E0687684EIMCMBX01MITREOR_"
MIME-Version: 1.0
Cc: " WG" <>
Subject: Re: [OAUTH-WG] Mail regarding draft-ietf-oauth-dyn-reg
X-Mailman-Version: 2.1.12
Precedence: list
List-Id: OAUTH WG <>
List-Unsubscribe: <>, <>
List-Archive: <>
List-Post: <>
List-Help: <>
List-Subscribe: <>, <>
X-List-Received-Date: Fri, 11 Jan 2013 17:10:45 -0000

Thanks for the thorough writeup, this is definitely an interesting use case. There are a few ways that you could go about this, from what I'm seeing, but there are also some things to untangle first. My apologies for the wall of text.

First, public clients can keep secrets, but there's a difference in the kind of secret they can keep. A client_secret in the traditional pre-registered out-of-band OAuth case is what's considered a configuration-time secret. This means that it effectively has to be configured with the software when it's deployed. This includes downloading the app to a smarphone or loading the Javascript app into the browser. The reason they can't keep these kinds of secrets is that all copies of the app would have the same secret and it would potentially be exposed to any end user. This is a bad thing since any end user could now fully impersonate the app with their own code. However, there is another class of secret: runtime. A runtime secret is something that the client gains after it has been configured and deployed, like the OAuth access token or any kind of client information (including an id and secret) gained from dynamic registration. This still doesn't change the fact that dynamic registration still can make sense with public clients (with no secret), but the very nature of the operation does change the nature of the secrets in question.

In your final example, if you're using a per-instance dynamic client registration, why wouldn't you want the iPad and iPhone app to re-register itself? That seems to be the whole point, since they'd necessarily be getting different client secrets. What do you see as the downside to this, especially when it can be automated? There are some approaches that you can take to group together sets of dynamically registered clients, too. More on how this might work in practice, below.

Regarding DoS, this is something that the DynReg spec starts to touch on in its security considerations section. You're basically going to want to do some kind of throttling and monitoring on an open endpoint like that, especially if it's internet-facing.

Now, on to what I see as some possible approaches for what you want to do:

1) Use well-known client_ids for public clients.

In this case, you don't use dynamic registration at all and just say that all clients are public clients, and tell every Authorization Server where to get the list of well-known client ids. You would want to take steps to protect the redirect_uri's for each of these client_ids to make them less susceptible to hijacking, since calls to the token endpoint would no longer have a client_secret to protect them.

Side note: On the RHEx project (which you mention in your blog post), it's true that we didn't profile public clients or dynamically registered clients, but the idea here was that if you were going to do that, you would want a different profile that called out the unique security issues that come with these kinds of things.

2) Use a centralized server to register all clients.

Nothing in OAuth says that each server has to have a local copy of the client credentials, especially if you're using a Client Assertion to authenticate to the Token Endpoint. You could pretty easily accomplish this by having a central location (or forest of them) that app developers can sign up at, where they're given a "developer key" to embed into their applications. This doesn't work very well with mobile and in-browser apps, because the developer key can leak, making it ultimately unsuitable for distributed-code clients like that. However, it could work just fine for any clients where the configuration-time secrets can be kept, like web servers.

And even in the distributed apps case, you do still have to have a resource owner click "Approve" for the client to get anywhere. Your Authorization Servers can put in appropriate warning boxes and

3) Preregister each client as a "class", use DynReg to register the "instance" of each class.

This is an interesting hybrid approach that the DynReg spec (and OpenID Connect) are built to handle explicitly. In this, developers get a "developer key" as in (2), but each instance of the application uses that developer key (which is really just an OAuth2 access token) to call the Registration Endpoint. This way, the Authorization Server can effectively group together multiple instances of the same client, logically. It could even decide to do something special and give them related client_ids, in order to help keep the books straight, but each client would be able to get its very own client_secret. The Authorization Server can also impose restrictions on things like allowed scopes and redirect_uris for each class of client, so that you don't have things going completely rogue on you.

With this, you could take an approach like in (2) and use a centralized server (or forest) for minting these developer keys, say as a signed JWT. The developer keys would be distributed with the applications themselves, so some will leak, but that's not so bad. The clients still have to register themselves, so you can't have your iPad impersonating your iPhone, or anybody else's iPad for that matter. They're all ultimately unique and it's easy for the AS to tell them apart (and group them together).

This approach is what I am currently thinking might be the best approach for your use case. Or at the very least, one to strongly consider in your approach.

4) UMA

In an ideal world, I think this would evolve into a User Managed Access, or UMA, type of system. I know there have been a few attempts at building out a healthcare-centric UMA, but nothing at that scale from what I've seen. In UMA (which uses OAuth, DynReg, Token Introspection, OpenID Connect, and other components), the different parties in OAuth are given a means of being introduced to each other with the right humans in the loop at the right time. We built the initial RHEx prototype in such a way that we could incorporate UMA in future work. I even have a really big, scary diagram to that effect someplace, I'll have to see if I can dig it up. While UMA is a bit more complicated of a platform (tons of moving parts), it's also very flexible and very powerful, and I'd encourage you to start looking in that direction, or at least get some discussion going around it.

tl;dr: You've got a few viable choices depending on the kind of ecosystem you want to have, but I'd recommend using a client-class approach or UMA.

Hope this was helpful, and I'd be interested to hear what the rest of the WG might think about this.

 -- Justin

On Jan 10, 2013, at 4:54 PM, "Boone, Keith W (GE Healthcare)" <<>>

The challenge is that we project an environment where there could be thousands of applications conforming to a particular API (see, with thousands of data holders making data available through those APIs, and several authorizers (in the OAuth 2.0 sense).  For public (locally installed or web-browser based applications), we'd like to avoid what I call the million registration problem<> (ignore the technical details), which would require thousands of developers to manually register their applications with all of the authorizers.

Because this is healthcare data, it is entirely possible that data holders will INSIST on being authorizers, which makes the problem even more challenging.

The issue that the ABBI Pull workgroup has been asked to address is to ensure that there is some way to manage bad actors in this eco-system, e.g., through a black-list, white-list or other trust-mechanism.  This wouldn't necessarily be required to be used, but would help an authorizer make an application access control decision.

The challenge with a public application using dynamic registration is that
a)     The application cannot keep it's credentials secret, and so must retrieve them in some way securely
b)    If the client_id is not tied back to the application identity, then we have concerns about the trust mechanism being able to protect the environment,
c)     And yet, we also want to protect clients from denial of service attacks where a client could be impersonated (to an authorizer), and obtain a client_id.

Imagine the case where I purchase an application and download it to my iPhone and to my iPad.  Then I connect that application to a data holder/authorizer combination it hasn't seen before.  Through dynamic client registration, I could register that application for my iPhone, but the instance of that same application running on my iPad would know nothing about the first registration.  So it would attempt to do it all over again.  What happens here?

Keith W. Boone
Standards Architect
GE Healthcare

M +1 617 640 7007<><>

116 Huntington Ave
Boston, MA 02116
GE imagination at work

From: Richer, Justin P. [<>]
Sent: Thursday, January 10, 2013 4:39 PM
To: Boone, Keith W (GE Healthcare)
Cc:<> WG
Subject: Re: Mail regarding draft-ietf-oauth-dyn-reg

Interesting use case, and not dissimilar to some others I've heard. How would you go about tracking this? Why would the instances need to know about each other?

One possible approach would be to use a common initializing Request Access Token that is used to call client_register on all instances of a given client. They wouldn't know about each other, per se, but the Authorization Server would at least know enough to be able to tie them together.

There's also the OAuth2 Instance Information extension that I had tried to push a few years ago that comes up every now and again, that might be of use here with some modifications:

I think I'd like to know more about your concerns and the parameters of your use case first.

I am CC'ing the IETF OAuth Working Group email list, where this draft is being discussed and worked on.

 -- Justin

On Jan 10, 2013, at 4:24 PM, "Boone, Keith W (GE Healthcare)" <<>> wrote:

I would like to be able to use this protocol to dynamically register clients, but am challenged by the fact that there could be multiple instances of a public client, each unaware of what others have done.  The current protocol doesn't seem to address this.

Keith W. Boone
Standards Architect
GE Healthcare

M +1 617 640 7007<><>

116 Huntington Ave
Boston, MA 02116
GE imagination at work