Subject: [OAUTH-WG] Non-repudiation for API requests and responses

From: Dave Tonge <[email-masked]>
Date: Fri, 31 Aug 2018 06:56:34 +0200

Hi all,

I'm working with financial APIs - APIs to initiate payments and APIs to
retrieve balances and transactions.

May of these APIs are protected by OAuth 2.0 profiles, however there is a
requirement to support the signing of API requests and responses for
non-repudiation purposes.

For example a bank may want to record an API request from a third party
that is used to set-up the details for a payment. If there is a dispute
with the payment, the bank can retrieve the signed API request as proof
that the third party set-up the payment.

On the response side, a third party may want to record an API response from
a bank that contains a list of transactions. Eventually such a signed
payload could be used as part of a loan application (rather than the
existing method of scanned in paper statements).

In Europe we have a number of standards groups who are defining these APIs
on behalf of banks. Unfortunately they are all taking different approaches
to this problem - including the use of a draft that I understand isn't on a
standards track.

Berlin Group (https://www.berlin-group.org/nextgenpsd2-downloads) requires
the use of the individual "Signing HTTP Messages" draft -
https://datatracker.ietf.org/doc/draft-cavage-http-signatures/

STET (https://www.stet.eu/en/psd2/) also requires the use of the same
"Signing HTTP Messages" draft.

OpenBanking UK specifies the use of RFC7515 (JWS) & RFC7797 (JWS Unencoded
Payload Option) - specifically with the detached payload option. However
they require a custom header: `x-jws-signature` and custom private header
parameter names that replicate `iat` and `iss` keys that are normally in
the JWT body. (
https://openbanking.atlassian.net/wiki/spaces/DZ/pages/5785171/Account+and+Transaction+API+Specification+-+v1.1.0#AccountandTransactionAPISpecification-v1.1.0-Non-repudiation
)

I have a number of questions that it would be great to hear your views on:

1. Does anyone have further information about
the draft-cavage-http-signatures spec - I am concerned about an individual
draft being used for these high value APIs?

2. Are there any views on a better way to solve this problem, for example:
https://tools.ietf.org/html/draft-erdtman-jose-cleartext-jws-00

The reason I've heard against just returning a JWT is that it means that
APIs are essentially just serving blobs of encoded data which could make
them harder to develop against or debug.

I don't like the idea of a detached signature in the header as it makes the
process of storing the data for later non-repudiation purposes harder and
more error prone (when compared to a message with a self-contained
signature).

While in some ways tangential to OAuth, I believe that this working group
is well placed to solve this problem. I am concerned that as things stand
we will end up without any interoperability for this problem due to the
lack of appropriate standards.

Thanks

Dave

---

From: Benjamin Kaduk <[email-masked]>
Date: Fri, 31 Aug 2018 09:45:10 -0500

On Fri, Aug 31, 2018 at 06:56:34AM +0200, Dave Tonge wrote:
[snip]
> draft being used for these high value APIs?

I don't, but I'll try to ask around.

> https://tools.ietf.org/html/draft-erdtman-jose-cleartext-jws-00

This one has been proposed in a couple of WGs and there was a late attempt
at a (related) BoF proposal for IETF 101; it doesn't seem to have garnered
much interest, due to historical work in the JSON canonicalization area.

-Ben

> _______________________________________________
> OAuth mailing list
> [email-masked]
> https://www.ietf.org/mailman/listinfo/oauth

---

From: Phil Hunt <[email-masked]>
Date: Fri, 31 Aug 2018 09:15:09 -0700

Phil

> On Aug 31, 2018, at 7:45 AM, Benjamin Kaduk <[email-masked]> wrote:
> 

If you read the draft it does not sign any request content. It really serves only to help prevent replay attacks by signing dates. 

The OAuth WG HTTP draft was far more complete but likewise suffers from worries about too many false negatives. 

If you want attestation, better to use SET or plain JWT. 
> much interest, due to historical work in the JSON canonicalization area.

+1

---

From: George Fletcher <[email-masked]>
Date: Fri, 31 Aug 2018 16:56:19 -0400

> If you read the draft it does not sign any request content. It really serves only to help prevent replay attacks by signing dates.
I had the same thought as I was reading through. To get message signing 
you have to use the Digest header which has a signature of the message 
and then sign that header in addition to the others. At least that is 
the way I read it for handing message signing. So basically a two-step 
signing/verification method.
+1

---

From: Dave Tonge <[email-masked]>
Date: Sat, 1 Sep 2018 00:05:54 +0200

Thanks for the replies.
You're absolutely right Phil and George - apologies I omitted the digest
step from the first email.
Both the STET and Berlin Group specs require the use of SHA-256 or SHA-512
digest header as per RFC3230 (https://tools.ietf.org/html/rfc3230)
They then use the draft cavage spec to sign a defined set of headers which
includes the date and digest headers.

> If you want attestation, better to use SET or plain JWT.

The pushback on this has been that to use JWTs for all API request bodies
and responses would make the APIs harder to develop against and debug.
However I do think it is a better option than having signatures in headers.
I like the idea of using content negotiation to allow clients to request
either application/json or application/jwt from an API endpoint.

I'd be interested if there is any interest in the working group for this
draft though:
https://tools.ietf.org/html/draft-erdtman-jose-cleartext-jws-00. As Ben
mentioned, does the issue of JSON canonicalization make this a non-starter?

Thanks

Dave

---

From: Phil Hunt <[email-masked]>
Date: Fri, 31 Aug 2018 16:06:24 -0700

Dave,

I’m not sure this is as useful as one might think - from RFC3230…
> 7 <https://tools.ietf.org/html/rfc3230#section-7> Security Considerations
> 
>    This document specifies a data integrity mechanism that protects HTTP
>    instance data, but not HTTP entity headers, from certain kinds of
>    accidental corruption.  It is also useful in detecting at least one
>    spoofing attack [9 <https://tools.ietf.org/html/rfc3230#ref-9>].  However, it is not intended as general
>    protection against malicious tampering with HTTP messages.
> 
>    The HTTP Digest Access Authentication mechanism [5 <https://tools.ietf.org/html/rfc3230#ref-5>] provides some
>    protection against malicious tampering.

For example, if you have a corporate web proxy or ISP that decides to help out by doing content compression as an example, all your requests will start failing (so-called accidental corruption).  We learned from XML that consistent canonicalization of the request data is important.

IOW…RFC3230 is valid when it works, but what about all the times it fails for no apparent reason? (false negatives)

In my humble experience with REST, the HTTP body is only a small part of the transaction. The headers, method, and URL parameters contain all of the semantics to an application transaction. Sure there are some requests that are just built on HTTP POST.  But you have to be sure, there are no parameters that matter in the headers or URL. 

The OAuth WG took a big ambitious stab at this (thanks Justin), but we weren’t convinced implementations would be stable. https://tools.ietf.org/html/draft-ietf-oauth-signed-http-request-03  

I can’t help but worry we are headed back to RPC style SOAP like containers based on JSON tokens that can be signed and that contain all the semantics and data of a transaction to be signed.  Now that I said that, I’m going to go wash my mouth out. Ugh.

Phil

> On Aug 31, 2018, at 3:05 PM, Dave Tonge <[email-masked]> wrote:
> 
> Thanks for the replies.
> You're absolutely right Phil and George - apologies I omitted the digest step from the first email.
> Both the STET and Berlin Group specs require the use of SHA-256 or SHA-512 digest header as per RFC3230 (https://tools.ietf.org/html/rfc3230 <https://urldefense.proofpoint.com/v2/url?u=https-3A__tools.ietf.org_html_rfc3230&d=DwMFaQ&c=RoP1YumCXCgaWHvlZYR8PZh8Bv7qIrMUB65eapI_JnE&r=na5FVzBTWmanqWNy4DpctyXPpuYqPkAI1aLcLN4KZNA&m=_ipDvDLnPDvRc4f-nizqhqic-6zojUcwkws7Fel97CU&s=y5Rg_ik_9mvP1Whrv68p0G885X7gRo32oxxeEeA08Ys&e=>)
> They then use the draft cavage spec to sign a defined set of headers which includes the date and digest headers.
> 
> The pushback on this has been that to use JWTs for all API request bodies and responses would make the APIs harder to develop against and debug.
> However I do think it is a better option than having signatures in headers. I like the idea of using content negotiation to allow clients to request either application/json or application/jwt from an API endpoint.
> 
> I'd be interested if there is any interest in the working group for this draft though: https://tools.ietf.org/html/draft-erdtman-jose-cleartext-jws-00 <https://urldefense.proofpoint.com/v2/url?u=https-3A__tools.ietf.org_html_draft-2Derdtman-2Djose-2Dcleartext-2Djws-2D00&d=DwMFaQ&c=RoP1YumCXCgaWHvlZYR8PZh8Bv7qIrMUB65eapI_JnE&r=na5FVzBTWmanqWNy4DpctyXPpuYqPkAI1aLcLN4KZNA&m=_ipDvDLnPDvRc4f-nizqhqic-6zojUcwkws7Fel97CU&s=0G1ikcDnNzvZqp7w6xlLnfhtq6GZGc0HlswqLcp4OK4&e=>. As Ben mentioned, does the issue of JSON canonicalization make this a non-starter?
> 
> Thanks
> 
> Dave