Draft: draft-ietf-gnap-core-protocol

Commentary: This seems to follow the consensus of the working group as discussed at the meeting and on the list , changes will be merged unless there is a clear alternative proposal accepted by the working group . 
 How was comment about choosing just one method to keep it simple ? Why do we need an access token and a URL ? 
 not sure i understand your question 
 The AS is choosing how to identify a request by a unique URL , an access token , or having only request at a time from a client . Lots of implementation choices and opportunities to make mistakes -- and overly complex . 
 There seemed to be some agreement during the IETF109 call that we indeed had to chose between the 2 alternatives . Now that leaves the question of which alternative to select . Between the 2 , the editors have proposed ( with explanations ) to make access tokens mandatory . 
 Review access token rotation following previous work on Could race conditions occur if the AS rotates its token ? Should it be allowed to rotate ? See more discussion at 
 We should discuss the potential race condition upon any token rotation , and have an allowance for accepting the old token during a short interim window to account for this kind of race condition . The rotation request needs to be idempotent : a repeated rotation request needs to return the same information and not do another rotation . 
 Token rotation is now more thoroughly covered and separated from the grant management lifecycle . 
 Request Continuation : Editor 's note : The AS can use the optional " access_token " as a credential for the client to manage the grant request itself over time . This is in parallel with access token management as well as RS access in general . If the AS uses the access token , the continuation URL can be static , and potentially even the same as the initial request URL . If the AS does not use an access token here , it needs to use unique URLs in its response and bind the client 's key to requests to those URLs - or potentially only allow one request per client at a time . The optionality adds a layer of complexity , but the client behavior is deterministic in all possible cases and it re - uses existing functions and structures instead of inventing something special just to talk to the AS . The optional access token represents a design compromise , but the working group can decide to either require the access token on all requests or to remove the access token functionality and require the security of the continuation requests be based on unique URLs . 
 From yesterday 's discussion at IETF109 , it seemed we agreed that it would be best to have only one way to do the continuation . I personally would be in favor of having a mandatory access token ( not a bearer token , needs to prove key possession ) , and a simple uri . As remarked , " " is effectively an access token in a URL , also known as a capability URL , which the w3c has a whole document about the pros and cons of : 
 No , my proposal to rename to referred to two of the proposals to address , not to the example you are quoting . There we bundle a LOT more into a structure called . Slides 32 - 33 of the deck . 
 my bad , makes sense . I crossed the related line in the previous comment , and updated the json . note for the future : if we can avoid going back and forth in the presentation , will avoid such misunderstandings ;-) 
 Part of the confusion here is that we 're talking about changing the format of what 's currently in response messages . That construct gets used in both the continuation protocol ( here ) and in the access tokens for RS 's . The parallelism is deliberate , so if we change it in one place it 'll change in both . I 'm in favor of both requiring the access token for the continuation API and in renaming the structure to , but these are separate issues . 
 " " is an identifier just as " " is an identifier It is not a capability URL , as there is NO authentication with capability URLs . In GNAP , the API calls are all authenticated by the client proving possession of its key . Per my email to the list , what we are calling an access token is more like a cookie as it is maintaining state . How it is set , where it can be presented , are unlike other access tokens -- calling it an access token dilutes the meaning of access tokens and is confusing . 
 It 's not a cookie either . The goal is not to maintain state , it 's only to execute the next transition ( more details on the ) That 's the limit of analogies ( neither a capability nor a cookie ) . If I summarize we have the following issues : putting the token directly in the url exposes to potential unexpected url logging from proxies ( we do n't want that ) setting the token aside is the alternative , but the difference with a standard access token ( as used by RS ) might be confusing to implementers ( I agree there is a little risk here ) . That difference is currently expressed by the " key " boolean parameter , which could easily be overlooked . If we want to stress the difference with an access token used in the context of RS , there are a few options : name it differently altogether ( like " continue token " ) . We 'd loose the parallelism that Justin was talking about though ( which is nice if we can find a way to avoid the confusion at minor cost ) add a " type " within the json of the access token . But then we need to deal with mutual exclusivity with the key field . Not a good idea . change the key field to a name that is more meaningful , like " requireskeyauthentication " or " requireskeypop " ( proof of possession ) . It 's longer but I believe it conveys the meaning better , it becomes really hard to miss . With the last option we could have something like 
 The parameter is not different from the standard access token response , though -- it 's a required field for all access tokens , no matter which API they call ( whether it 's within the AS like the continuation API or an OpenID UserInfo Endpoint , or a separate RS alltogether ) . The only difference here is that the field is currently restricted a specific required value because we want to limit what we expect the client to be able to do when calling the continuation API . The boolean value of signals that the token is bound to the same key the client presented during its initial request . This means that the client needs to continue to present that key along with the access token for the continuation calls . I would argue ( as others have ) that this ought to be the default for : all : access tokens issued to the client within GNAP . We could relax this restriction , but it would mean that we 'd end up with a potentially more complex space for a client to deal with when an AS binds to a different key or proofing mechanism for continuation . Plus , I think we all agree that a bearer token for continuation is a non - starter . 
 What I meant before is that people might overlook the meaning of " key " and what it implies , so we might need to make it more obvious . If we were to make key verification mandatory , it would remove the issue altogether , improve the security , and I see no potential confusion for the implementer . But it might come as a challenge where bearer tokens are used today ( for APIs ) . Not hard to implement , but any change like that takes time to disseminate within the ecosystem . And there may still be some valid cases for bearer tokens , but indeed continuation is not one of them ;-) A possibility is to make key verification the default ( for AS as well as RS ) , and still be able to handle bearer tokens with a boolean " bearer " , by default set to false ( but that field would n't be valid in the context of the continuation endpoint ) . Here we would have : and for the resources we might indicate that it is actually a bearer token , only if it is declared explicitly : 
 This is an interesting approach . I 'm in favor of the proposed default behavior of binding to the client 's key , but I 'm not sure I 'm sold on default values when a field is absent , like this . In the current spec , the only way to get a bearer token is to set in the token response . Since is mandatory there is technically no ambiguity about the nature of a token since there 's no " default " value if it 's not present , it 's an error . An older version of the  draft had something similar , with a field alongside a separate field . The problem came from the situation of having a bearer flag alongside a key . That was an error condition that needed to be checked by the client now . With the current draft , that error is impossible at a syntax level , which I think is a benefit for client implementors . 
 To expand a bit : what I 'm saying is that the semantics of key binding need to be very clear for the token . A client implementor should never overlook the value in the current access token structure since it says exactly how the token is bound to outgoing requests . 
 I agree with that . I think we 're on similar lines of thought here . One could argue however that having a true / false flag makes it possible to overlook the field ( hence why I suggested that in the case of continuation , it 's not even present ; or if we want to make it explicit , the only valid json contains " key":true ) . 
 We could combine the concepts , and say that if the field is not present , its value is . 
 Thinking about this for half a second more , I think we need to refactor out the key presentation and its semantics from where it is in the spec right now , since it is n't just about the client presenting a key and it 's confusing people : 
 tbh does n't tell me much about what that is or why I need it . I 'd be in favor of naming it something more specific . 
 Since we had a lengthy discussion on the rationale for the change , I copy paste it here The access token pattern has a lot of benefits , otherwise we would n’t have an entire OAuth ecosystem based on it Magic URIs have a lot of drawbacks which are well understood ; while they can be mitigated , they can also be avoided Continuation is an API , and treating it like the other kinds of API the client would call makes sense Calling this by a special name , like “ grant access token ” or “ continuation access token ” is fine , but it should function like any other access token The heavy lift for clients is on protecting the message cryptographically , which they need to do anyway From 
 I 've looked at the rest ( besides Yaron 's comments ) , seems fine to me .
Mailing list commentary: I agree with Fabien that the persistent identifier is a separate issue . The current spec re - uses the access token for this artifact , but that ’s potentially brittle and could be changed out for something else . There ’s an issue asking for expanding on the use cases for this functionality ( which has n’t been addressed by this PR ): A potentially - rotating URI would be just as brittle , and so having a single codified identifier for this artifact would be useful , but it does assume some things about the nature of the AS . Every other use the client has to manage the ongoing request over time does n’t need an explicit identifier . Just like with OAuth - protected APIs , the server can determine the context not just from the URI but from the rest of the request , including the access token itself . This is both more common and more powerful than a strict reading of REST designs . It also follows the HATEOS principles as the entire HTTP request is taken into account , including the access token and signature portions . I ’ll also point out that the rotation of these credentials is also filed as a separate issue that ’s not being addressed right now , so we can revisit that discussion separately : As for the name , we could give it a different label . We have this same pattern of issuing a resource - specific access token alongside a URL in the Dynamic Registration specification , both in OAuth ( ) and OpenID Connect ( ) . Here it ’s called the “ registration access token ” — but what ’s important there , as it is here , is that it ’s not a different kind of artifact that the client now has to figure out how to use , it ’s an access token plain and simple . In the OAuth world this is a bearer token , since that ’s what OAuth 2 uses . In the GNAP world it ’ll be a bound token , as that ’s what we ’re looking to build on . This is also related to another future discussion about responses tying an access token to a specific API that ’s told to the client , as we could potentially re - use those components and concepts here as well : And finally , no speculation on the complexity is needed : I implemented this pattern several months ago during the design team discussions when we were considering this pattern , and the code is all online for people to see . On the AS side , the most interesting code to this discussion is in the TransactionEndpoint class : Here , you ’ll see that on initial request , the server looks up the client to see if it ’s been registered , but after that , it makes sure that the token and key are appropriate for the ongoing request . From the client side it ’s even simpler . The client ’s got a small service function to manage the different signature methods that are implemented , and all of them can take in an optional access token : The heavy lift is doing the actual signing , and you need that in order to start the process anyway . Managing the access token as an artifact to use at the API is completely trivial since the client already needs to manage its own state internally to do any of this . And note that all of this is changed from how it was before : Previously , the XYZ Protocol had used a “ transaction handle ” returned by the AS that the client would use to continue the request . However , this simple model was limiting , and the design team adopted XAuth ’s model of continuation being an API . In doing so , we made it like all of the other APIs the client is going to call : in the initial state , it does n’t have any kind of access rights , it ’s just calling . From that initial call forward , the AS just needs to know that the token and key match what it expects . In summary , my views are : The access token pattern has a lot of benefits , otherwise we would n’t have an entire OAuth ecosystem based on it Magic URIs have a lot of drawbacks which are well understood ; while they can be mitigated , they can also be avoided Continuation is an API , and treating it like the other kinds of API the client would call makes sense Calling this by a special name , like “ grant access token ” or “ continuation access token ” is fine , but it should function like any other access token The heavy lift for clients is on protecting the message cryptographically , which they need to do anyway — Justin
So we ' ve established that this is a different access token , that requires different handling at the client . So keeping it could cause more confusion ? As an RC , I will have to store the continue as although it could be static it could also be dynamic . Why do I need to store an access token as well . It brings me no benefit as an RC , in fact it brings more complexity . As I will now need to manage multiple types of tokens with different lifecycles : Continuation token can only be used at the continue endpoint ( the name of which is confusing as I can use this endpoint to revoke a grant or get metadata on the grant ) . may be rotated each time it is used , or may not be provided in the section of the response must be sender - constrained ca n't be used with the token management APIs ? can be used to identify the grant when making subsequent grants Access token(s ) to use at RS can only be used at the specified may be sender constrained when used at the RS , will not result in rotation persistent identifier for the grant . Why not bring this into the protocol and let the AS provide this persistent identifier ( through the form of the continue uri ) . Using a rotating access token as a persistent identifier does n't seem like the right choice . I see no security benefit to having the continuation access token . It does n't matter if the continue uri leaks as it is useless without an accompanying signature , i.e. any security benefit of having an access token is already provided by having a signature . The only benefits that I can see are : If the AS wants to be fully stateless , then you can encode more data in a token than in a uri If the AS wants to have a static endpoint for CRUD operations on the grant To allow the AS to identity a previous grant If we dropped the access token for the continue endpoint and rather mandated a dynamic uri this would make things conceptually easier to understand , easier for the RC to implement , easier to debug and less chance of errors when rotating tokens ( i.e. race conditions could be quite likely if the AS always rotates the token ) One - off grant with no continuation or ongoing management : RC sends signature and , no response provided , therefore no grant management possible Grant with ongoing management RC sends signature and metadata , AS responds with a continue uri that has these purposes : can be used by the RC to continue / update , read or revoke the grant can be used by the RC when making a new grant to identify the previous grant As an RC the only permanent items I need to store are : the continue uri associated with the grant any access tokens I receive for the grant
Paragraph (version B):
Indicates that the RC can continue the request by making one or
more continuation requests.
Paragraph (version B):
The RC can use the values of this field to continue the request as
described in continue-request.  Note that the RC MUST sign all
continuation requests with its key as described in binding-keys and
MUST present the access token in its continuation request.
Paragraph (version B):
To enable this ongoing negotiation, the AS provides a continuation
API to the RC.  The AS returns a "continue" field response-continue
that contains information the RC needs to access this API, including
a URI to access as well as an access token to use during the
continued requests.
Paragraph (version B):
The access token is initially bound to the same key and method the RC
used to make the initial request.  As a consequence, when the RC
makes any calls to the continuation URL, the RC MUST present the
access token as described in use-access-token and present proof of
the RC's key (or its most recent rotation) by signing the request as
described in binding-keys.
Paragraph (version B):
The AS MUST be able to tell from the RC's request which specific
ongoing request is being accessed, using a combination of the
continuation URL, the provided access token, and the RC instance
identified by the key signature.  If the AS cannot determine a single
active grant request to map the continuation request to, the AS MUST
return an error.
Paragraph (version B):
This "continue" field allows the RC to make an eventual continuation
call.  In the future, the RC realizes that it no longer needs "write"
access and therefore modifies its ongoing request, here asking for
just "read" access instead of both "read" and "write" as before.
Paragraph (version B):
When used for delegation in GNAP, these key binding mechanisms allow
the AS to ensure that the keys presented by the RC in the initial
request are in control of the party calling any follow-up or
continuation requests.  To facilitate this requirement, the response-
continue includes an access token bound to the request-key, and that
key (or its most recent rotation) MUST be proved in all continuation
requests continue-request.  Token management requests token-
management are similarly bound to either the access token's own key
or, in the case of bearer tokens, the RC's key.  The AS MUST validate
all keys request-key or referenced in an ongoing request for each
call within that request.