feat: ESSR protected client APIs
This PR adds an alternative mechanism to authenticate with the KERIA API from a Signify client, and leaves the current RFC-9421 signed headers in place too. Beyond confidentiality, it also resolves other issues from before such as unsigned query params and bodies. (#287)
The unsigned HTTP request from the client is converted to a HTTP bytestream and embedded in an ESSR payload. This payload becomes the body of a wrapper HTTP request for the "/" path - so tunneled via ESSR. The wrapper could be handled by pure TCP but for now this works quite nicely in the Falcon middlewares with minimal changes.
Because nothing else uses "/" as the path, the authentication type is determined based on the path. A cleaner approach in a TCP world would just to have a CESR based command signed and optionally encrypted following ESSR, rather than complicating things with managing headers, or embedding HTTP requests within each other.
I have written the corresponding code in Signify and all integration tests pass.
Flow for generating request from Signify:
- Create HTTP request - e.g.
POST /identifiers <body> - Add
Signify-Resourceheader (Encrypt Sender) - Serialize HTTP request as a HTTP string
crypto_box_seal(http_request_string, public_key_of_keria_agent)- Create a new HTTP request to
POST /where the body of the request is the sealed box bytes (application/octet-stream) - Add
Signify-Resource,Signify-TimestampandSignify-Receiverheaders (receiver is Sign Receiver) - Sign the request and add as a header
Note: Like the keripy ESSR parser, the commitment to unsigned HTTP request is done by taking a digest:
payload = dict(
src=<sender>,
dest=<receiver>,
d=coring.Diger(ser=cipher, code=MtrDex.Blake3_256).qb64,
dt=dt,
)
A signature is created over this dict. I'm re-using the signature style of the signed headers.
https://github.com/WebOfTrust/signify-ts/pull/304 created on Signify side
Codecov Report
Attention: Patch coverage is 98.39572% with 6 lines in your changes missing coverage. Please review.
Project coverage is 93.99%. Comparing base (
676d7e8) to head (1d83e66). Report is 1 commits behind head on main.
| Files with missing lines | Patch % | Lines |
|---|---|---|
| src/keria/core/authing.py | 97.51% | 4 Missing :warning: |
| src/keria/app/aiding.py | 66.66% | 1 Missing :warning: |
| tests/core/test_authing.py | 99.51% | 1 Missing :warning: |
Additional details and impacted files
@@ Coverage Diff @@
## main #351 +/- ##
==========================================
+ Coverage 93.80% 93.99% +0.18%
==========================================
Files 37 37
Lines 8462 8704 +242
==========================================
+ Hits 7938 8181 +243
+ Misses 524 523 -1
:umbrella: View full report in Codecov by Sentry.
:loudspeaker: Have feedback on the report? Share it here.
:rocket: New features to boost your workflow:
- :snowflake: Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
- :package: JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.
Updated PR to allow both signed headers and ESSR. I'm leaving this as draft as I still have the edge case I need to test for in the comment I left on the PR above, and I need to update my Signify PR.