Change:
[[ See issue #105 [48] ]] <ins> In the following sections, unless otherwise noted, the "RS256" JOSE Signature Algorithm is applied using the following RSA key (presented here in JWK format): </ins> 7.3.1. This method is indicated by "jwsd" in the "proof" field.  A JWS RFC7515 object is created as follows: <del> The JOSE (JSON Object Signing and Encryption) header MUST contain the "kid" parameter of the key bound to this client instance for this request.  The "alg" parameter MUST be set to a value appropriate for the key identified by kid and MUST NOT be "none".  The "b64" parameter MUST be set to "false" and the "crit" parameter MUST contain at least "b64" as specified in RFC7797. </del> <ins> To protect the request, the JOSE header of the signature contains the following parameters: </ins> <del> To protect the request, the JOSE header MUST contain the following additional parameters. </del> <ins> The key identifier.  RECOMMENDED.  If the key is presented in JWK format, this MUST be the value of the "kid" field of the key. </ins> <del> The type header, value "gnap-binding+jwsd". </del> <ins> The algorithm used to sign the request.  REQUIRED.  MUST be appropriate to the key presented.  If the key is presented as a JWK, this MUST be equal to the "alg" parameter of the key.  MUST NOT be "none". The type header, value "gnap-binding+jwsd".  REQUIRED </ins> The HTTP Method used to make this request, as an uppercase ASCII <del> string. </del> <ins> string.  REQUIRED </ins> The HTTP URI used for this request, including all path and query <del> components. </del> <ins> components and no fragment component.  REQUIRED </ins> <del> A timestamp of the request in integer seconds </del> <ins> A timestamp of when the signature was created, in integer seconds since UNIX Epoch </ins> When a request is bound to an access token, the access token hash <del> value.  Its value is the base64url encoding of the left-most half of the hash of the octets of the ASCII representation of the "access_token" value, where the hash algorithm used is the hash algorithm used in the "alg" header parameter of the JWS's JOSE Header.  For instance, if the "alg" is "RS256", hash the "access_token" value with SHA-256, then take the left-most 128 bits and base64url encode them. </del> <ins> value.  The value MUST be the result of Base64url encoding (with no padding) the SHA-256 digest of the ASCII encoding of the associated access token's value.  REQUIRED if the request protects an access token. </ins> <del> The payload of the JWS object is the serialized body of the request, and the object is signed according to detached JWS RFC7797. </del> <ins> If the HTTP request has a message body, such as an HTTP POST or PUT method, the payload of the JWS object is the Base64url encoding (without padding) of the SHA256 digest of the bytes of the body.  If the request being made does not have a message body, such as an HTTP GET, OPTIONS, or DELETE method, the JWS signature is calculated over an empty payload. </ins> <del> The client instance presents the signature in the Detached-JWS HTTP Header field. </del> <ins> The client instance presents the signed object in compact form RFC7515 in the Detached-JWS HTTP Header field. </ins> <del> If the request being made does not have a message body, such as an HTTP GET, OPTIONS, or DELETE method, the JWS signature is calculated over an empty payload. </del> <ins> In this example, the JOSE Header contains the following parameters: The request body is the following JSON object: </ins> <del> When the server (AS or RS) receives the Detached-JWS header, it MUST parse its contents as a detached JWS object.  The HTTP Body is used as the payload for purposes of validating the JWS, with no transformations. </del> <ins> This is hashed to the following Base64 encoded value: This leads to the following full HTTP request message: When the verifier receives the Detached-JWS header, it MUST parse and validate the JWS object.  The signature MUST be validated against the expected key of the signer.  All required fields MUST be present and their values MUST be valid.  If the HTTP message request contains a body, the verifier MUST calculate the hash of body just as the signer does, with no normalization or transformation of the request. </ins> 7.3.2.

Discussion:
Updates a number of syntacitcal and semantic requirements for key proofing mechanisms and makes the language more generic around the use of the mechanisms in the protocol and its extensions. change "htu" claim to "uri" for JOSE-based methods, - align token hash with latest dpop 'ath' claim, - use body hash for detached JWS with body, - update HTTP message signature syntax, - include verification language,
~At this time, cryptographic and encoded content of examples has not been regenerated and recalculated.~
Deploy preview for gnap-core-protocol-editors-draft ready! Built with commit 89cb898b4b5275f44b3daf4edd8a15731895469c https://deploy-preview-250--gnap-core-protocol-editors-URL
Cryptographic examples have all been updated.
The security considerations should discuss the differences between PKI-based (with a CA) and non-PKI keys. This is especially relevant to MTLS signing as it changes how the server-side of the TLS connection is deployed.
See discussion on different deployments at: URL
Addressed by security considerations: URL
Key proof sections do not currently detail how to verify each method, including requirements for verifying fields, this needs to be added.
DPoP defines as not containing path or query components, GNAP's JOSE methods use the full URL. The JOSE methods should move to a different claim name to avoid confusion with DPoP.
See comments at URL
Doesn't make sense to me: JOSE is published as an RFC and is well established, so this sounds like an error in DPoP - which should move away from ... What am I missing?
We don't have control over DPoP's claims, those are defined by the OAuth WG. If we continue to keep DPoP signing in GNAP, we will use what they define as much as we can. JOSE as a signing suite is published as an RFC, GNAP is profiling JOSE (specifically JWS) to have a simple detached HTTP message signature method.
The HTTP Message Signatures draft has changed formats, our examples need to be updated to incorporate these changes.
There have been several questions about the parameter currently used to convey the hash of an access token in requests to the RS.

Right now we use the definition from OpenID Connect: URL In speaking with the DPoP editors I've proposed a simplified claim there: URL It's functionally similar but doesn't require the array truncation step, and it also fixes to a single hash algorithm (SHA-256) instead of having to figure out which hash to use based on the external signing envelope. I think this change makes it both simpler to implement and to understand.
Also, for cryptographic agility here we would rely on defining a new claim name and updating the requirements about inclusion. So would always be SHA-256 and once that hash is sufficiently broken and discarded we would define a new claim like for whatever new target there is.
+1 for that, much more intuitive than truncating (and the comment from DPoP editors seem to go in that direction too). In relation to what would happen if SHA-256 gets deprecated: the current method is already based on SHA-256, so it's not a new downside an idea would be to name it for instance, to give a minimal versioning (would currently relate to SHA2) and would simplify changes later on (like avoiding ;-))
I personally think that naming the next version of the field should be left to the next version. Someone might want to specify or even , but the important thing is that we aren't defining plus parameters, we're just defining and anything else comes along as its own unique string. That kind of guidance can be written around the registry for the claim and how it'd get used.
works too
Reopening this issue: we are not providing cryto-agility, because: We do not indicate how the algorithm could change. Renaming the field to would remedy that. An implementation that did not include would formally be non-compliant, because the field is REQUIRED. We should say something about that. See URL
NAME crypto agility would be provided by defining a new field entirely. The algorithm will not change for . This was discussed in the OAuth WG with DPoP's field which has the same semantics as this. I do not recommend we re-open this.
I'm not asking to reopen it. Just to add a note in the text. The IESG reviewers are bound to comment on this.

As I was working on a client implementation, it occurred to me that it would be a lot simpler and less error prone to include a hash of the request body in the JWS rather than doing the current "compute-the-JWS-then-remove-the-body" method. This would remove the and fields from the JWS header, and would add a new sentence describing how to calculate the body hash, dropping the dependency on RFC7797: This significantly cleans up the client code, since previously the client would have to generate the JWS, the pull out the header and signature components and reassemble them with an empty body, creating a string like "XXXXX..XXXXX". Now it can use a JWS library without any additional hacks on top.
Such JWS header wouldn't qualify RFC7797 in this case then.
how so?
RFC 7797 requires you to include "b64" in the "crit" header parameter and set the "b64" header parameter to . Lots of existing JWT parsers obey the "crit" parameter. As you mention, you may remove these parameters. Although, it will result in an inability to parse such JWTs by parsers that already support RFC 7797.
Some of the existing parsers provide a convenient way to get "XXXXX..XXXXX" without any hacks on top. For example, take a look at method in URL
Not relying on the additional rules specified in RFC7797 seems like a benefit, less specs to read and less edge cases to handle. Removing a dependency on another spec is a benefit.
Right, these wouldn't be RFC7797 values anymore, they would just be plain JWS objects with a specially calculated payload. We still will have the "XXXX..XXXX" format for payload-less requests (requests without the body, such as GET and DELETE).
I think I'm in favor of this idea, personally. It still fulfills the requirement of covering the message body with the signature method, but it does so in a way that's perhaps more native to most JOSE developers. It's also more conducive to the kinds of deployment models discussed in
I hear you. I would like to add & emphasize that there are two parts to this story. The first part where we create JWTs and accordingly, there is the second part where we verify them. The beauty is that there are lots of libraries that support RFC 7797.

The rest of the decently implemented libraries JWTs because they don't know how to proceed with b64 in the crit header parameter and it's really great IMO. It reduces the chances of errors. Now, let’s imagine we omitted b64 from the crit header parameter and started to put the SHA-256 hash in the payload of the JWS object. In this case, the verification process should fail by all existing libraries, right? If you decide to put something like “gnap-detached” in the crit header parameter then you will also need to change the code of a JWT library so this library will be able to process it. I am guessing that isn't always possible, rational, or just easy to do.
The body of this new method would be a base64 encoded hash value, so we actually don't :want: the header at all and we wouldn't be doing RFC7797 here. One thing that's different from what many libraries may expect is that the body doesn't decode into JSON -- but this was always a JWS, not a JWT. Just about every JWS library I've used, these days, allows for an arbitrary payload. Even URL allows for signing an arbitrary string for the payload, but it will base64 encode it first. I think this new approach benefits from not requiring any parameter, enforcement of which I've found hit-or-miss at best in the JOSE community.
NAME will you require the "typ" header parameter to be presented in such JWSs... with the values like "gnap+jwsd" and "gnap+jws"?
The Proving Possession of a Key with a Request section explicitly states that Unfortunately, I don't see how a client can make use of the jws param (Attached JWS payload) to make calls to "regular" RSs. Normally, they won't be ready to accept the "application/jose" content type and the corresponding payload for the endpoint that accepts say "application/json" and "application/xml". I also believe that this specification shouldn't require the payload (HTTP Body) to be included in the calculation of the JWS signature for RSs in case of Detached JWS payload. The reason is that the client (or any logic that validates access tokens) doesn't always have access to the payload and the bright example for this would be NGinx and .

Note, this approach isn't limited in any way to NGinx and is extremely popular among various cloud providers. There are also other minor reasons say just huge payloads (like a movie upload) or even a real-time stream (WebRTC) and so on and so forth. Both these items are totally fine and definitely should be required for any calls from a client to an AS though.
URL says this about the payload and HTTP headers and
Attached JWS is highly problematic and limited for exactly the reason you describe: it requires the API the client is calling to accept a JOSE encoded payload instead of its native payload (see ). Plus, this only works for requests with a message body (POST/PUT) so you need to fall back to the detached method for other verbs, and it's really only mostly applicable for JSON payloads though technically you can serialize anything in a JWS so that's just more it feeling "weird" than being wrong. I'm personally not a fan of the method for all these reasons, but several members of the WG have stated that it fits their use cases better than other methods. Inclusion of the body (when present) in the detached JWS request allows it to be validated along with the signature in the reset of the request. A library outsourcing GNAP with something like an auth_request module would need to include the signature calculation in that module, like here: URL An AS is just as likely to be behind a security layer proxy, either externalized as you describe or internal to the app like in Java's servlet filter system. In any event, to handle body integrity you're going to have to handle this as part of the filtering system, like here: URL ... and to me, it's really not any dissimilar to TLS reverse proxies. As for DPoP, note that we're only using the signature method of DPoP here, not the whole protocol extension in its context. The restrictions and guidance you've quoted come from the fact that DPoP is targeted specifically at SPA's running OAuth 2, and so the advice does not apply here.
The changes to get the whole request body in such externalized components in the Kubernetes (and its friends) world are very slim as that somehow defeats the benefits of their use. Note, these components don't act as a proxy.

They receive all or only certain headers of an HTTP request, do their own business, and then finally tells whether access is granted. If granted, the whole initial HTTP request gets a couple of new headers like X-Auth-User-* and then forwarded to the right service to be processed further. If not, a caller gets 401 or an HTTP redirect, etc. URL is another example of a component that does pretty much the same as NGinx's auth_request module. There is a bunch of other similar components. I do like that GNAP requires "body" integrity for all interactions between a client and an AS. It feels for me it should be optional for interactions between a client and an RS.
This is where things like the HTTP Message Signatures could help, since the body hash is separate from the signing. The client can calculate the body Digest header and pass that along to the signing component. It could also be that the security components get redesigned to accommodate the security protocols. We already saw that shift when API libraries started handling access tokens instead of just HTTP Basic username/password combos, which is all they used to do. Or when browsers adopted the fetch() API as opposed to the deeply limited capabilities that were there before. Now, I'm not saying that GNAP should count on the world bending to its will, or that we should ignore deployment patterns; but we also shouldn't limit the protocol based on a design choice in software that makes sense today and might not in the future. These libraries only look at a couple headers because that's all they need to do right now, much like in the past they would have just taken in a username and password.
These external components don't really have a choice to read only certain headers or the whole request. They get only what they get from ingress controllers in a cluster. It's very possible that in the future, these controllers (like NGinx or Traefic) will have to provide the SHA-256 hash of the request's payload in order to accommodate the security protocols as you said. It's hard to predict when and if it will happen at all. As of today, this is a very common and extremely popular deployment model.
The approach proposed in should address these concerns by and large, and this issue will close with
Looks fine, but tbh I must test to be sure