ACME v2 strict JWS "kid" header processing


As of Tuesday May 30th the ACME v2 staging environment enforces that all JWS "kid" KeyID headers contain the full account URL as returned by the Location header in a newAccount response. We will be promoting this change to the production environment on As of Thursday June 7th this change is active in the ACMEv2 production environment as well.

Prior to this change an oversight in our ACME v2 JWS "kid" handling allowed sending only the numeric portion of the full account URL as the JWS "kid" header (e.g. using 1234 instead of If your ACME client was relying on this oversight you will begin receiving errors of the form:

400 :: malformed :: KeyID header contained an invalid account URL

Our updated strict "kid" processing behaviour better matches the ACME specification:

For all other requests, the request is signed using an existing
account and there MUST be a "kid" field.  This field MUST contain the
account URL received by POSTing to the newAccount resource.

Please update your ACME v2 compatible clients to send the full unaltered “kid” value ahead of the June 7th production activation to avoid disruption. Both the staging environment and Pebble can be used to test that the correct “kid” is being sent.



Following up with an observation from the staging environment error logs:
Be sure your client code is not somehow mistakenly sending a production "kid" header to the staging environment (or vice versa!).

Accounts are not shared across environments and the URL prefix is different:

  • for staging
  • for production