Re: [OAUTH-WG] review comments on draft-ietf-oauth-dyn-reg-11.txt

"Richer, Justin P." <jricher@mitre.org> Thu, 30 May 2013 23:11 UTC

Return-Path: <jricher@mitre.org>
X-Original-To: oauth@ietfa.amsl.com
Delivered-To: oauth@ietfa.amsl.com
Received: from localhost (localhost [127.0.0.1]) by ietfa.amsl.com (Postfix) with ESMTP id 3345D21F8F00 for <oauth@ietfa.amsl.com>; Thu, 30 May 2013 16:11:11 -0700 (PDT)
X-Virus-Scanned: amavisd-new at amsl.com
X-Spam-Flag: NO
X-Spam-Score: -4.87
X-Spam-Level:
X-Spam-Status: No, score=-4.87 tagged_above=-999 required=5 tests=[AWL=-0.572, BAYES_00=-2.599, HTML_MESSAGE=0.001, MANGLED_CREDIT=2.3, RCVD_IN_DNSWL_MED=-4]
Received: from mail.ietf.org ([12.22.58.30]) by localhost (ietfa.amsl.com [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id BMWPUOoQlm44 for <oauth@ietfa.amsl.com>; Thu, 30 May 2013 16:11:05 -0700 (PDT)
Received: from smtpksrv1.mitre.org (smtpksrv1.mitre.org [198.49.146.77]) by ietfa.amsl.com (Postfix) with ESMTP id 2A5DC21F9128 for <oauth@ietf.org>; Thu, 30 May 2013 16:11:04 -0700 (PDT)
Received: from smtpksrv1.mitre.org (localhost.localdomain [127.0.0.1]) by localhost (Postfix) with SMTP id 8D8D51F059D; Thu, 30 May 2013 19:11:03 -0400 (EDT)
Received: from IMCCAS03.MITRE.ORG (imccas03.mitre.org [129.83.29.80]) by smtpksrv1.mitre.org (Postfix) with ESMTP id 75EBC1F026A; Thu, 30 May 2013 19:11:03 -0400 (EDT)
Received: from IMCMBX01.MITRE.ORG ([169.254.1.137]) by IMCCAS03.MITRE.ORG ([129.83.29.80]) with mapi id 14.02.0342.003; Thu, 30 May 2013 19:11:03 -0400
From: "Richer, Justin P." <jricher@mitre.org>
To: Phil Hunt <phil.hunt@oracle.com>
Thread-Topic: [OAUTH-WG] review comments on draft-ietf-oauth-dyn-reg-11.txt
Thread-Index: AQHOXSFKoUPHFo+jJEeuqil8woB+1Jkd4A8XgABEGwCAAALvAIAAEjEAgAABU4CAAAv5AP//zhOmgAAJjwGAAAa4l4AAGWZYgAAdN8Q=
Date: Thu, 30 May 2013 23:11:03 +0000
Message-ID: <B33BFB58CCC8BE4998958016839DE27E08F97708@IMCMBX01.MITRE.ORG>
References: <20130524203638.25945.84709.idtracker@ietfa.amsl.com> <5071FA1C-F6F7-43AD-9EDC-13B0D480F97A@mitre.org> <51A3AE0B.1020802@lodderstedt.net> <51A4BF27.50800@mitre.org> <51A72B3E.9050300@lodderstedt.net> <51A76052.6040004@mitre.org> <0354062A-DEB8-4272-861B-43DC48887F54@ve7jtb.com> <2E872A80-1B5B-468D-910C-1D6E9DFEFF78@oracle.com> <9F86FCC6-E737-4086-8821-81A94AEC4BE2@oracle.com> <54C61883-4A00-441E-B6DB-2B4156B969F4@ve7jtb.com> <2674C9F9-0C49-4EC3-A69D-20AAC35E8AB8@oracle.com> <2F891558-6DDF-4FFB-B2D3-F1219EB6CFAF@oracle.com> <51A79B69.9090702@mitre.org> <7BB78EA6-B0F4-4A9E-853C-DB978C9DFB0B@oracle.com> <51A7A18F.1040104@mitre.org> <4CCD92A5-0800-4E4C-8952-C8B88E22C811@oracle.com> <51A7ADAE.4070005@mitre.org> <62636DE9-80BD-4B83-817B-3E6622434FD0@oracle.com> <51A7C00B.6050409@mitre.org>, <78BAEE23-FB66-4BA5-A1A5-5626D22AA014@oracle.com>
In-Reply-To: <78BAEE23-FB66-4BA5-A1A5-5626D22AA014@oracle.com>
Accept-Language: en-US
Content-Language: en-US
X-MS-Has-Attach:
X-MS-TNEF-Correlator:
x-originating-ip: [129.83.31.52]
Content-Type: multipart/alternative; boundary="_000_B33BFB58CCC8BE4998958016839DE27E08F97708IMCMBX01MITREOR_"
MIME-Version: 1.0
Cc: "oauth@ietf.org WG" <oauth@ietf.org>
Subject: Re: [OAUTH-WG] review comments on draft-ietf-oauth-dyn-reg-11.txt
X-BeenThere: oauth@ietf.org
X-Mailman-Version: 2.1.12
Precedence: list
List-Id: OAUTH WG <oauth.ietf.org>
List-Unsubscribe: <https://www.ietf.org/mailman/options/oauth>, <mailto:oauth-request@ietf.org?subject=unsubscribe>
List-Archive: <http://www.ietf.org/mail-archive/web/oauth>
List-Post: <mailto:oauth@ietf.org>
List-Help: <mailto:oauth-request@ietf.org?subject=help>
List-Subscribe: <https://www.ietf.org/mailman/listinfo/oauth>, <mailto:oauth-request@ietf.org?subject=subscribe>
X-List-Received-Date: Thu, 30 May 2013 23:11:11 -0000

Comments inline, marked by [JR].

________________________________
From: Phil Hunt [phil.hunt@oracle.com]
Sent: Thursday, May 30, 2013 5:25 PM
To: Richer, Justin P.
Cc: John Bradley; oauth@ietf.org WG
Subject: Re: [OAUTH-WG] review comments on draft-ietf-oauth-dyn-reg-11.txt

See below.
Phil

@independentid
www.independentid.com<http://www.independentid.com>
phil.hunt@oracle.com<mailto:phil.hunt@oracle.com>





On 2013-05-30, at 2:09 PM, Justin Richer wrote:

OK, I think see part of the hang up. I have not seen the scenario that you describe, where you trade a 3rd party token for a "local" token. I have seen where access tokens are federated directly at the PR. (Introspection lets you do some good things with that pattern.) But that's neither here nor there, as you can already do what you're asking for and I think I can clear things up:

In your case, the "3rd party bearer assertion" is simply *not* the Initial Registration Token. It's an assertion that can be used to *get* an Initial Registration Token. The token that you get from the Token Endpoint, in your case, would be "local" from your own AS. Your registration endpoint would look at this token on the way in, know how to validate it, do whatever else it wants to with it, and process the registration. Then it would issue a Registration Access Token that to the registering client to use at the RESTful endpoint. Incidentally, that token would also be "local", just like before.

How you (the client/developer) get the actual Initial Registration Token is completely and forever out of scope for the Dynamic Registration spec.

[PH]  Yes, the issuance of the third party bearer assertion token token would be out of scope of this spec.

If however the group decides to except federated direct access tokens as registration *access* tokens, then I think we have to define federation for access tokens first.   For me, I think this is something that should be discussed in a different charter.

[JR] It's an access token, plain and simple. The draft doesn't care -- and shouldn't care -- if it's federated or not. I agree, and have been arguing all along, that if you have a use case for federated access tokens, you need to define the mechanisms for such tokens, and that registration is *not* the place for that definition. It's orthogonal but they can be used together. Let's define them separately but in a compatible way.



This all still fits with the current definitions as they are. You don't have to use federated tokens if you don't want to. I can still use them if I want to. Everybody's happy! And this is all because we are not defining any content or semantics tied to the processing of the Initial Registration Token or calling it an Assertion or anything -- it's up to the AS to process it however it would normally process an OAuth Access token. So if your AS needs a local token, then you need to use a local token. If you don't want to use structured foreign tokens as your Initial Registration Tokens, don't. But that shouldn't preclude others of us from doing so.

[PH] The difference is where the client is expected to present the federated (aka 3rd party) assertion.  I would rather follow the standard 6749 4.5 method in all cases for consistency.

You can choose to short circuit, but I think the draft should follow a consistent methodology.

[JR] 6749 section 4.5 (extension grants) is irrelevant to registration as it's talking about access to the token endpoint and not to protected resources. Additionally, people do use assertions encoded inside of OAuth tokens directly at protected resources all the time (since OAuth2 tokens are opaque to clients but must be understood by protected resources), but that's *still* completely irrelevant to this discussion because it doesn't matter in terms of the interoperability of the protocol. If you want to use assertions or auth codes or client credentials or magic to get your Initial Registration Token, the dynamic registration protocol doesn't care how you did it. Just like any other OAuth2 protected resource doesn't care how you got the token. This abstraction was one of the key insights in how OAuth2 is structured as a framework and protocol. The important thing here is that if the client gets an Initial Registration Token it knows where to send it and how to use it. What I hear you saying is that you don't want to use a federated token as an Initial Registration Token. That's fine! Don't do it -- and you have that option precisely because of how we've already written it! If your clients get handed a token that *isn't* an Initial Registration Token and you want them to go through another step to *get* an Initial Registration Token, so be it! But it doesn't make sense to encode that behavior as required into the registration protocol, because (as you point out) not everything is going to be an assertion in the first place. Again I say that you can do everything that you want to do with existing mechanisms or self-contained extensions.


If you think it would be helpful, I can add language to the lifecycle discussion to clarify that the Initial Registration Token can be gotten through any number of means, not just the manual-portal approach that's talked about now. Or if you want to write up this specific use case we can add it as another concrete example.

[PH] I think there is potential to cut a lot of text out of the spec if we strictly define the registration endpoint as a normal OAuth2 protected endpoint.

[JR] I don't understand what you're saying here -- it already *is* an OAuth2 protected endpoint, like I've pointed out below. All OAuth2 protected endpoints don't care how you get the token, neither does this one. All OAuth2 protected endpoints don't care (from OAuth2's perspective) how the token is verified or processed, and neither does this one (from the draft's perspective). I explicitly want to keep that kind of token and assertion processing *out* of this draft because it's more useful to build generally applicable mechanisms. If we keep the registration endpoint as an OAuth2 protected endpoint -- like it already is -- then we can inherit whatever mechanisms you want, and that is a very powerful setup.

I will close by pointing out that I have *never* proposed that we dictate that the Registration Endpoint have to accept and process federated tokens, and it would be ludicrous to do so. I have been and still am committed to the Initial Registration Token and the Registration Access Token being plain old opaque-to-the-client OAuth 2 tokens.

[PH] Agreed.  However, the use case of a 3rd party signer for client applications is critical to both commercial organizations and open source orgs that publish software that are deployed by many separate entities.  The client developer needs to be able to contact the publisher in many cases to obtain a signed assertion.

I believe this is a core use case.

I believe as I've proposed it using the normal 4.5 exchange federated assertion for local token method, the draft doesn't have to get into the details of the assertion.  Though that said, I would suggest the draft make some suggestions on the contents of such assertions.

[JR] You can already do what you want to without mentioning assertions. The current draft doesn't mention assertions at all, either. All talk of use of assertions is outside the scope of registration. You're proposing adding it in, and I'm strongly against that.

I think it's possible that you're still conflating the work I'm doing with the BB+ *extension* to dynamic registration with the dynamic registration document itself. I have never suggested that we pull all the extended BB+ stuff down into Dyn Reg, and in fact I think quite the opposite as I don't believe it's as generally applicable without the larger BB+ stack (which includes discovery as well as reliance on policy and other frameworks).

[PH] I'm only using it as an example. Both Cisco (at IIW) and Oracle have very similar requirements.  As I said above, the use case is a key use case.

However I agree, the way you solve it in BB+ is not the way to solve it within the draft spec.  I think the BB+ does well inform our discussions though.

[JR] Considering that BB+ manages to do all of this with a cleanly defined extension without any changes in the existing draft text, I think that's as strong an argument as anything to keep it defined how it is, and that what's there is a sufficient base to build on.

 -- Justin

On 05/30/2013 03:54 PM, Phil Hunt wrote:
Justin,

So far, every time an OAuth server has accepted a 3rd party token it has been a bearer assertion. The common pattern is to exchange that assertion for a an access token issued by the local server for the local resource endpoint.

That's the pattern I am trying to follow.

Going this way means we do not have to define the initial registration token.

If however, you really want to use the initial registration token AS an access token, you are taking us into the question of using federated access tokens.  I prefer not to do that here.

Phil

@independentid
www.independentid.com<http://www.independentid.com/>
phil.hunt@oracle.com<mailto:phil.hunt@oracle.com>





On 2013-05-30, at 12:51 PM, Justin Richer wrote:

I don't understand which access token is being talked about here -- is this the Initial Registration Token? Because you can already do everything below. How you get the Initial Registration token is out of scope precisely so that the AS can decide what that means. We can add language in the lifecycle discussions to bring up the fact that you can get this token from an OAuth flow, if you think that'll help clear things up.

However, the client doesn't register using the client credential flow at all -- it registers using a POST to the registration endpoint, and that POST might have an OAuth token attached to it. How the client got that OAuth token is, again, out of scope. The client could have done some other OAuth flow (any OAuth flow) to get a hold of the token, but how is it supposed to get an OAuth token at an AS it hasn't been registered with?

Now, if you're talking about the Registration Access Token, though, that makes less sense to me. The client *has* to register first before it can get *anything* from the token endpoint. What you're suggesting is that all clients be given access to the token endpoint with the client credentials flow for the purposes of retrieving the Registration Access Token, unless I misread things. You probably don't want the client getting other scopes from the token endpoint using the client credentials flow, as it'd be an enormous security risk. Thing is, I don't think I can implement that level of separation in my app stack, and I haven't seen any others that do that. Separating access to different endpoints based on OAuth tokens (and the scopes attached) is par for the course, though.

Let me run down how it works in our own setup. When a client registers, we create a new token (using a TokenServices class) that has a special scope, "registration-token". This token is tied to the client_id to which it was issued. Clients cannot get tokens with this scope through the usual Token Endpoint means, by design. All of the Client Configuration Endpoint URLs are protected such that they require access from a valid token with the scope "registration-token", and the client_id tied to that token MUST match the client_id in the URL. Each client is limited to the OAuth flows (grant_types and response_types) that it's allowed to call from the token endpoint. All of this is specific to our implementation, but I can speak with some authority that it's at least implementable this way. This method lets us do public clients, confidential clients, public-key clients (that use JWT assertions to call the token endpoint), and all different OAuth flows.

If we were to switch things to what you're recommending (using client credentials to get the equivalent of the Registration Access Token), I would need to issue some form of client credentials to all clients (including public clients) and allow all dynamically registered clients access to the client_credentials flow at the token endpoint but only if they're asking for a registration-token scope, a scope value which hasn't been standardized either. I don't think this is even possible in my architecture, and it's certainly not desirable.

If we were to switch to having the client credentials used directly on the registration endpoint, then you get back into the situation that OIDC has already tried, and which failed. I see no reason to try the same thing again and expect different results.

I will admit that it was a little strange when I first pulled the TokenServices reference into our RegistrationEndpoint class, but doing so greatly simplified everything else. I can see the desire to have an ideological purity of "all tokens come from the token endpoint", but such purity just doesn't help in this case.

 -- Justin

On 05/30/2013 03:31 PM, Phil Hunt wrote:
For this, I would suggest:

Anonymous, user assisted registration - client registers using the client credential flow but may use an administrator (in the case of web app) or end-user (uid/password) .  Since resource owner would still require separate credential, then the client flow could be used even though we are passing end-user creds. Client obtains access token limited to registering the new entity.

Anonymous unassisted registration (no user present) - the only solution I can come up with is the client self asserted client_id (e.g. UUID) that the token endpoint chooses to accept if scope equals "registration" (or whatever the scope is to be for registration).   IMHO this should be avoided.

3rd Party Assertion - client presents signed assertion in the form of JWT or SAML Bearer assertion and exchanges for an access token. Access is limited to registering a new entity.

The value of the access token being short lived or potentially even single-use (or limited use, like 3 tries), would be to prevent abuse of the registration end-point.

Phil

@independentid
www.independentid.com<http://www.independentid.com/>
phil.hunt@oracle.com<mailto:phil.hunt@oracle.com>





On 2013-05-30, at 11:59 AM, Justin Richer wrote:

But this still doesn't address clients who don't have a client_secret. Do they now need one in order to talk to the registration endpoint? What you're suggesting is that a client use one set of credentials to get access tokens and another set of credentials to get registrations. This is certainly no simpler.

And this exact functionality was tried, implemented, and rejected as too complicated by the OpenID Connect community. I don't see why it'd be any different the second time around.

I really don't see any reason to change it.

 -- Justin

On 05/30/2013 02:56 PM, Phil Hunt wrote:
It's hard to say what the best solution here is regarding clarifications until we get clarity on the issue of registration access token.

I don't think using a client credential flow to obtain an access token to the registration endpoint is complex. It's the normal flow.

I concede that you are looking at it as using Client Credential to get an access token to get a new Client Credential. But that's not really what is happening in terms of protocol here.

If you take the perspective that the client needs to occasionally update registration (e.g. because of a pending credential expiry), then it is still simple. You use client credential flow to obtain an access token to update registration. Then, from the context of the REST API, the client credential is just another piece of JSON data.

IOW from the REST perspective, it is the registration endpoint that is being updated, not the client credential.  The client credential is just data in the perspective of REST.

I think you may be inferring complexity where there really is none.

Phil

@independentid
www.independentid.com<http://www.independentid.com/>
phil.hunt@oracle.com<mailto:phil.hunt@oracle.com>





On 2013-05-30, at 11:33 AM, Justin Richer wrote:

Thanks for clearing up where the confusion was taking place. I had tried to make it clear that these were absolutely standard, opaque OAuth2 bearer tokens and absolutely standard OAuth2-protected endpoints, but if that's not clear that needs to be updated. This is what the text says right now:

The Client Registration Endpoint MAY accept an Initial Access Token in the form of an OAuth 2.0 <http://tools.ietf.org/id/draft-ietf-oauth-dyn-reg-11.html#RFC6749> [RFC6749] access token to limit registration to only previously authorized parties. The method by which the Initial Access Token is obtained by the registrant is generally out-of-band and is out of scope of this specification.

And:

The Client Configuration Endpoint is an OAuth 2.0 protected resource that is provisioned by the server for a specific client to be able to view and update its registered information. The location of this endpoint is communicated to the Client through the registration_client_uri member of the Client Information Response<http://tools.ietf.org/id/draft-ietf-oauth-dyn-reg-11.html#client-info-response> [client-info-response]. The Client MUST use its Registration Access Token in all calls to this endpoint as an OAuth 2.0 Bearer Token<http://tools.ietf.org/id/draft-ietf-oauth-dyn-reg-11.html#RFC6750> [RFC6750].

Along with the definitions in the introduction:

Registration Access Token
OAuth 2.0 Bearer Token issued by the Authorization Server through the Client Registration Endpoint that is used to authenticate the caller when accessing the Client's registration information at the Client Configuration Endpoint. This Access Token is associated with a particular registered Client.
Initial Access Token
An OAuth 2.0 Access Token optionally issued by an Authorization Server granting access to its Client Registration Endpoint.

I'd welcome any proposed changes to the text to make this clearer.

As to the other suggestion, what you're saying is to use the client credentials to get an access token to get the client credentials ... ? I can see the argument for using the oauth client credentials flow, but I think that's far more complicated than an endpoint saying "here's a token, go use it", personally. Besides, not all clients have credentials at the token endpoint, so it's a bit of a non-starter for a large class of clients.

 -- Justin


On 05/30/2013 01:55 PM, Phil Hunt wrote:

I see what is happening.

I think the reason why I find this spec sooo confusing is that the terms imply new token types when they don't.

For example when you say "Registration Access Token" and "Initial Access Token" it implies to me that it is a totally new token type (and in one case it sorta is). When you read the spec (particularly draft 10) it is easy to assume something very different is going on. Hence my push back.

It is now clear to me that what you mean to say is *Access Token used for initial access* and *Access Token used for registration*.

Why not write the draft to make clear that the registration end point is just a NORMAL OAuth2 Enabled REST endpoint?  That way you can eliminate all of the terminology and lifecycle around access tokens except to say the endpoint is accessed by tokens issued based on the scope "oauth2:registration".

That only brings issues with the registration token.  The "Access Token used for registration" seems to have special lifecycle differences.
1.  Issed by reg endpoint as part of successful registration
2.  Has a different lifetime than the client credential (whatever it is).

Why not again simplify and follow normal OAuth2 pattern and have the access token issued for registration be *short* lived.  Each time the client wants to either initially register or update its profile it must request a normal access token with scope "oauth2:registration".

As for client credential expiry, why not simply require the client to update its registration before it expires?  Why have a long-lived "registration access token" that has to be managed as well?

Maybe now I am completely confused?

Phil

@independentid
www.independentid.com<http://www.independentid.com/>
phil.hunt@oracle.com<mailto:phil.hunt@oracle.com>





On 2013-05-30, at 10:12 AM, Phil Hunt wrote:



The issue is that it has different issuing/lifecycle than normal. E.g. Why is it issued by the registration endpoint?

Why doesn't the client just request an access token using its client credential for the registration endpoint when it wants to update its profile?

Phil

@independentid
www.independentid.com<http://www.independentid.com/>
phil.hunt@oracle.com<mailto:phil.hunt@oracle.com>





On 2013-05-30, at 10:08 AM, John Bradley wrote:



The reg access token is a OAuth bearer token that is issued as part of the registration response and used to access the new client resource for reads and or updates depending on the permissions.

They are both oauth access tokens.

On 2013-05-30, at 12:02 PM, Phil Hunt <phil.hunt@oracle.com><mailto:phil.hunt@oracle.com> wrote:



Seriously. The new dyn reg draft introduces two new tokens. The initial reg token and the registration access token.

As for the latter, the reg access token, my understanding is it has nothing to do with an access token. It is issued *after* registration to allow reg updates.  Right? I know some are confused about this.

Phil

On 2013-05-30, at 8:52, Phil Hunt <phil.hunt@oracle.com><mailto:phil.hunt@oracle.com> wrote:



No different issue. I was concerned about the initial client assertion being passed in as authen cred. It is a signed set of client reg metadata.

See we are confused. Hence my worry. :-)

Phil

On 2013-05-30, at 8:48, John Bradley <ve7jtb@ve7jtb.com><mailto:ve7jtb@ve7jtb.com> wrote:



I think Phil also had some processing reason why a Token endpoint or RS wouldn't want to tale the authentication as a header, as the processing was easier with them as parameters as they are potentially available to different parts of the stack.   That may have been mostly around RS, but the principal may apply to the token endpoint as well.

On 2013-05-30, at 10:21 AM, Justin Richer <jricher@mitre.org><mailto:jricher@mitre.org> wrote:



"client_secret_post vs client_secret_basic"
BASIC and POST are essentially the same just different ways to send the client secret. If an authorization server supports both, both should work for any client. So are both methods treated differently?


I agree, and this was one of my original arguments for making this field plural (or plural-able), but there hasn't been WG support for that so far.


I'm not arguing to make it plural. I think the authentication method is just "client_secret".


That was also an option that was brought up, but in the OIDC WG the counter-argument was (as I recall) that the two are syntactically separate and there's a desire to restrict to a single type, such as disabling client_secret_post. Basically, to make it unambiguous.


_______________________________________________
OAuth mailing list
OAuth@ietf.org<mailto:OAuth@ietf.org>
https://www.ietf.org/mailman/listinfo/oauth


_______________________________________________
OAuth mailing list
OAuth@ietf.org<mailto:OAuth@ietf.org>
https://www.ietf.org/mailman/listinfo/oauth


_______________________________________________
OAuth mailing list
OAuth@ietf.org<mailto:OAuth@ietf.org>
https://www.ietf.org/mailman/listinfo/oauth


_______________________________________________
OAuth mailing list
OAuth@ietf.org<mailto:OAuth@ietf.org>
https://www.ietf.org/mailman/listinfo/oauth