Original text:
the HTTP entity body.  Each possible field is detailed in the sections below <del> Indicates that the RC can continue the request by making an additional request using these parameters. </del>  A single access token that the RC can use to call the RS on behalf of the RO. RECOMMENDED.  The amount of time in integer seconds the RC SHOULD wait after receiving this continuation handle and calling the URI. <del> RECOMMENDED.  A unique access token for continuing the request, in </del>  the format specified in response-token-single.  This access token MUST be bound to the RC's key used in the request and MUST NOT be <del> a "bearer" token.  This access token MUST NOT be usable at resources outside of the AS.  If the AS includes an access token, the RC MUST present the access token in all requests to the continuation URI as described in use-access-token.  [[ See issue #66 [35] ]] </del>  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 <del> continuation requests with its key as described in binding-keys.  If the AS includes an "access_token", the RC MUST present the access token in its continuation request. </del>  This field SHOULD be returned when interaction is expected, to allow the RC to follow up after interaction has been concluded. used to allow the AS and RC to continue negotiating the parameters of the request. <del> To enable this ongoing negotiation, the AS returns a "continue" field response-continue that contains information the RC needs to continue this process with another request, including a URI to access as well as an optional access token to use during the continued requests. </del>  <del> When the RC makes any calls to the continuation URL, the RC MUST present proof of the most recent key associated with this ongoing request by signing the request as described in binding-keys.  The key in use will be either the key from request-key or its most recent rotation.  [[ See issue #85 [58] ]] </del>  <del> For example, here the RC makes a POST request and signs with detached JWS: </del>  <del> If the AS includes an "access_token" in the "continue" response in response-continue, the RC MUST include the access token the request as described in use-access-token.  Note that the access token is always bound to the RC's presented key (or its most recent rotation). For example, here the RC makes a POST request with the interaction reference, includes the access token, and signs with detached JWS: </del>  The AS MUST be able to tell from the RC's request which specific <del> ongoing request is being accessed.  Common methods for doing so include using a unique, unguessable URL for each continuation response, associating the request with the provided access token, or allowing only a single ongoing grant request for a given RC instance at a time.  If the AS cannot determine a single active grant request to map the continuation request to, the AS MUST return an error. </del>  The ability to continue an already-started request allows the RC to perform several important functions, including presenting additional information from interaction, modifying the initial request, and getting the current state of the request.  If a "wait" parameter was included in the response-continue, the RC MUST NOT call the continuation URI prior to waiting the number of seconds indicated.  If no "wait" period is indicated, the RC SHOULD sections below. If the AS determines that the RC can make a further continuation <del> request, the AS MUST include a new response-continue.  If the continuation was previously bound to an access token, the new </del>  "continue" response MUST include a bound access token as well, and <del> this token SHOULD be a new access token.  If the AS does not return a new "continue" response, the RC MUST NOT make an additional continuation request.  If a RC does so, the AS MUST return an error. [[ See issue #87 [60] ]] </del>  For continuation functions that require the RC to send a message body, the body MUST be a JSON object. references: Access is granted by the RO, and a token is issued by the AS.  In its <del> final response, the AS includes a "continue" field: </del>  <del> This allows the RC to make an eventual continuation call.  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. </del>  The AS replaces the previous "resources" from the first request, allowing the AS to determine if any previously-granted consent 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 <del> continuation requests.  To facilitate this requirement, all keys in the initial request request-key MUST be proved in all continuation requests continue-request and token management requests token- management, modulo any rotations on those keys over time that the AS knows about.  The AS MUST validate all keys request-key or referenced in an ongoing request for each call within that request. </del>  [[ See issue #105 [78] ]]

Reviewer comments:
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 NAME comment about choosing just one method to keep it simple? Why do we need an access token and a URL?
NAME 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 URL
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 NAME remarked, "URL" 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: URL
NAME 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.
"URL" is an identifier just as "URL" 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 don'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). URL 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 wouldn'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 XYZ 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 isn't just about the client presenting a key and it's confusing people:
tbh doesn'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 wouldn’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 URL
I've looked at the rest (besides Yaron's comments), seems fine to me. The editors and chairs would like to confirm consensus on a current pull request: URL This pull request simplifies the continuation response and request by making the access token mandatory, and it clarifies the responsibilities of the AS in enforcing the security of the continuation request. Several WG members expressed specific support for keeping the access token to enable specific use cases, and there was general support for simplifying the process from what it currently is in the draft. The editors believe the pull request represents a solution that meets these goals. This call is open until Monday December 14. At that point, the PR will be merged unless the chairs determine there is not rough consensus for its inclusion. Thank you, Justin, Aaron, and Fabien
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 hasn’t been addressed by this PR): URL 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 doesn’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: URL 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 (URL ) and OpenID Connect (URL ). 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: URL 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. URL On the AS side, the most interesting code to this discussion is in the TransactionEndpoint class: URL 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: URL 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 doesn’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 wouldn’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
Hi Dick, In GNAP, the client isn't managing state (unlike a web app), the entire point is that the lifecycle should be managed by the AS. As in any state machine, there are states and transitions. Here we're not passing state, merely expressing "please continue". The client can be completely unaware of the underlying state. In effect the client only has the ability to ask the server to generate the next transition. So I don't think you can compare that to cookies. It's a different behavior. BTW if it was the case it would lead to a whole new class of issues, because there's an entire legal framework around cookies... To avoid confusion with a standard access token, we have the "key" field. My proposal would be to make it more explicitly (cf comment in issue 67). Fabien Le lun. 23 nov. 2020 à 02:06, Dick Hardt a écrit : >
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 can'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 RS may be sender constrained when used at the RS, will not result in rotation >From my perspective, most use-cases will require the RC to have a 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 doesn't seem like the right choice. I see no security benefit to having the continuation access token. It doesn'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 metadata, 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 Dave On Tue, 15 Dec 2020 at 10:11, Fabien Imbault wrote: Dave Tonge CTO [image: Moneyhub Enterprise] Moneyhub Financial Technology, 5th Floor, 10 Temple Back, Bristol, BS1 6FL t: +44 (0)117 280 5120 Moneyhub Enterprise is a trading style of Moneyhub Financial Technology Limited which is authorised and regulated by the Financial Conduct Authority ("FCA"). Moneyhub Financial Technology is entered on the Financial Services Register (FRN 809360) at URL . Moneyhub Financial Technology is registered in England & Wales, company registration number 06909772 . Moneyhub Financial Technology Limited 2019 DISCLAIMER: This email (including any attachments) is subject to copyright, and the information in it is confidential. Use of this email or of any information in it other than by the addressee is unauthorised and unlawful. Whilst reasonable efforts are made to ensure that any attachments are virus-free, it is the recipient's sole responsibility to scan all attachments for viruses. All calls and emails to and from this company may be monitored and recorded for legitimate purposes relating to this company's business. Any opinions expressed in this email (or in any attachments) are those of the author and do not necessarily represent the opinions of Moneyhub Financial Technology Limited or of any other group company. Moneyhub Enterprise is a trading style of Moneyhub Financial Technology Limited which is authorised and regulated by the Financial Conduct Authority ("FCA"). Moneyhub Financial Technology is entered on the Financial Services Register (FRN 809360) at URL . Moneyhub Financial Technology is registered in England & Wales, company registration number 06909772. Moneyhub Financial Technology Limited 2020 Moneyhub Enterprise, Regus Building, Temple Quay, 1 Friary, Bristol, BS1 6EA. DISCLAIMER: This email (including any attachments) is subject to copyright, and the information in it is confidential. Use of this email or of any information in it other than by the addressee is unauthorised and unlawful. Whilst reasonable efforts are made to ensure that any attachments are virus-free, it is the recipient's sole responsibility to scan all attachments for viruses. All calls and emails to and from this company may be monitored and recorded for legitimate purposes relating to this company's business. Any opinions expressed in this email (or in any attachments) are those of the author and do not necessarily represent the opinions of Moneyhub Financial Technology Limited or of any other group company.

Revised text:
the HTTP entity body.  Each possible field is detailed in the sections below  <ins> Indicates that the RC can continue the request by making one or more continuation requests. </ins> A single access token that the RC can use to call the RS on behalf of the RO. RECOMMENDED.  The amount of time in integer seconds the RC SHOULD wait after receiving this continuation handle and calling the URI.  <ins> REQUIRED.  A unique access token for continuing the request, in </ins> the format specified in response-token-single.  This access token MUST be bound to the RC's key used in the request and MUST NOT be  <ins> a bearer token.  As a consequence, the "key" field of this access token is always the boolean value "true".  This access token MUST NOT be usable at resources outside of the AS.  The RC MUST present the access token in all requests to the continuation URI as described in use-access-token.  [[ See issue #66 [35] ]] </ins> 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  <ins> continuation requests with its key as described in binding-keys and MUST present the access token in its continuation request. </ins> This field SHOULD be returned when interaction is expected, to allow the RC to follow up after interaction has been concluded. used to allow the AS and RC to continue negotiating the parameters of the request.  <ins> 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. </ins>  <ins> 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. </ins>  <ins> [[ See issue #85 [58] ]] </ins>  <ins> For example, here the RC makes a POST request to a unique URI and signs the request with detached JWS: </ins> The AS MUST be able to tell from the RC's request which specific  <ins> 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. </ins> The ability to continue an already-started request allows the RC to perform several important functions, including presenting additional information from interaction, modifying the initial request, and getting the current state of the request. <ins> All requests to the continuation API are protected by this bound access token.  For example, here the RC makes a POST request to a stable continuation endpoint URL with the continue-after-interaction, includes the access token, and signs with detached JWS: </ins> If a "wait" parameter was included in the response-continue, the RC MUST NOT call the continuation URI prior to waiting the number of seconds indicated.  If no "wait" period is indicated, the RC SHOULD sections below. If the AS determines that the RC can make a further continuation  <ins> request, the AS MUST include a new response-continue.  The new </ins> "continue" response MUST include a bound access token as well, and  <ins> this token SHOULD be a new access token, invalidating the previous access token.  If the AS does not return a new "continue" response, the RC MUST NOT make an additional continuation request.  If a RC does so, the AS MUST return an error.  [[ See issue #87 [60] ]] </ins> For continuation functions that require the RC to send a message body, the body MUST be a JSON object. references: Access is granted by the RO, and a token is issued by the AS.  In its  <ins> final response, the AS includes a "continue" field, which includes a separate access token for accessing the continuation API: </ins>  <ins> 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. </ins> The AS replaces the previous "resources" from the first request, allowing the AS to determine if any previously-granted consent 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  <ins> 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. </ins> [[ See issue #105 [78] ]]