I am seeking clarification on whether the externalAccountBinding field is required when posting to newAccount with onlyReturnExisting set. i.e. Finding an Account URL Given a Key.
My intuition says no, because my personal understanding is that EAB is a one-time binding of a new ACME account to some external credentials. Once the EAB credentials are spent and the binding is performed, the client isn't required to hold on to these forever.
The server MAY require a value for the "externalAccountBinding" field
to be present in "newAccount" requests. This can be used to
associate an ACME account with an existing account in a non-ACME
system, such as a CA customer database
What's the intention here? Is onlyReturnExisting excluded?
ZeroSSL/Sectigo does not seem to require EAB.
We have a library user that is trying to send EAB in an onlyReturnExisting query and I'm not feeling confident about telling them that it's not conformant.
If such a CA requires that newAccount requests contain an
"externalAccountBinding" field, then it MUST provide the value "true"
in the "externalAccountRequired" subfield of the "meta" field in the
directory object. If the CA receives a newAccount request without an
"externalAccountBinding" field, then it SHOULD reply with an error of
type "externalAccountRequired".
This can be read as: "if the ACME server has the externalAccountBinding field set to true" (the first sentence) "than it should reply witn an error if no externalAccountBinding was present in the newAccount request.
However, the RFC does not literally say it as such. Luckily, the term SHOULD leaves room for "valid reasons in particular circumstances to ignore a particular item" (RFC 2119). So even if there are perhaps multiple ways to interpret RFC 8555, I'd say ACME servers not enforcing EAB for already existing accounts are in their right.
Also, I'm not sure this is the problem the user on Github with their "is not JSON serializable" TypeError is running into. I think their issue comes from the fact that acme apparently doesn't like the EAB part of the regr body to be included like that. If one leaves out the EAB from the regr dict, use RegistrationResource.from_json() to build a regr and then update the regr bodys external_account_binding field with an acme.messages.ExternalAccountBinding using the from_data() function, that TypeError goes away.
I guess RegistrationResource.from_json doesn't like the EAB to be a dict of itself and translates it into a frozendict.
Yep, the serialization issue not exactly the same. The question for me personally is whether Certbot does the right thing wrt RFC8555, and how urgent it is to fix the issue in the acme library surrounding EAB serialization.
If the issue also pops up when registering a brand new account, then this RFC interpretation issue doesn't really matter, right? I tried to run their example.py on a Pebble instance without any account and I ran into the serialization issue anyway? Or am I missing something obvious?
Their example program will crash regardless of the server you use, because it will never actually send a request. It's the (completely local) deserialize→serialize cycle which leads to a crash.
I don't think it's possible to trigger this crash with Certbot in practice.
The only thing I could think of that could trigger this is the show_account subcommand, but that doesn't send the EAB credentials in the payload, even when --eab-kid and --eab-hmac-key are used on the command line.