Concept for discussion: Replacing HTTP Signatures with Bearer Tokens for ActivityPub Federation
Curious what other people think about this idea. What if federation security was re-worked to use target-assigned bearer tokens to authenticate GET/POST requests? This would remove the need for complicated signing schemes and reduce system load under heavy traffic bursts (as no cryptography is required).
A basic implementation could look like this:
1. When instance A (
2. Instance B makes a POST request back to a dedicated verification endpoint on instance A (for discussion, we'll say it's
3. Instance A checks the verification token (and verify that it matches the target domain name) and return a successful value. The verification code must be invalidated after this call!
4. Instance B, after verifying instance A's request, returns a securely-generated federation key back to instance A. This federation key is a bearer token used to authenticate all requests from instance A to instance B. This key must be unique to instance A!
5. Instance A completes the original request with the
6. Instance B receives the request, detects the federation key, and checks it against the list of registered instances.
7. If the key does not exist or A has been defederated, then a [
8. If the key is expired or revoked, then [
9. If the key is approved, then a [
Advantages versus HTTP Signatures:
- No cryptography requirements.
- Simple logic, no edge cases around HTTP query parameters or header order.
- Equally effective for all request types.
- Keys can be easily revoked or rotated.
- Supports authorized fetch and defederation use cases "by default".
Disadvantages versus HTTP Signatures: - Breaks the actor model - instances are required as a first-class concept. (but really, the actor model is basically dead already. you can't even federate reliably without a WebFinger server, at minimum.) - Requires multi-request "handshake" before communication. (but this is already required in practice, since a signature can't be validated without first requesting the signing actor.) - Out-of-band protocol - communication can't happen over ActivityPub / ActivityStreams because this is a prerequisite to authenticate any request. (but again, we already require WebFinger and some software requires NodeInfo for full support.) So, what are your thoughts? Good idea? Bad idea? Did I miss something? Please let me know, I welcome replies here! #ActivityPub #AP #Federation
A basic implementation could look like this:
1. When instance A (
a.example.com) first attempts to federate with instance B (b.example.com), a POST request is made to a dedicated registration endpoint. (for discussion, we'll say it's https://b.example.com/activity-pub/register-instance). This request includes fields necessary for verification, including the source domain name, target domain name, and a securely-generated verification token. Other metadata could be included to allow instance B to selectively allow/prohibit federation based on other criteria, but this is optional.2. Instance B makes a POST request back to a dedicated verification endpoint on instance A (for discussion, we'll say it's
https://a.example.com/activity-pub/verify-registration). This request must include the target domain name and verification token provided in step 2.3. Instance A checks the verification token (and verify that it matches the target domain name) and return a successful value. The verification code must be invalidated after this call!
4. Instance B, after verifying instance A's request, returns a securely-generated federation key back to instance A. This federation key is a bearer token used to authenticate all requests from instance A to instance B. This key must be unique to instance A!
5. Instance A completes the original request with the
Authorization header set to Bearer {federation_key}.6. Instance B receives the request, detects the federation key, and checks it against the list of registered instances.
7. If the key does not exist or A has been defederated, then a [
403 Forbidden error](https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Status/401) is returned.8. If the key is expired or revoked, then [
401 Unauthorized error](https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Status/401) is returned. Upon receiving a 401 error, instance A should start over from step 1 to re-authenticate and complete the request with a new token. This process should not be repeated for recursive failures!9. If the key is approved, then a [
200 OK response](https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Status/200) or [202 Accepted response](https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Status/202) is returned, and A can consider the request as successful.Advantages versus HTTP Signatures:
- No cryptography requirements.
- Simple logic, no edge cases around HTTP query parameters or header order.
- Equally effective for all request types.
- Keys can be easily revoked or rotated.
- Supports authorized fetch and defederation use cases "by default".
Disadvantages versus HTTP Signatures: - Breaks the actor model - instances are required as a first-class concept. (but really, the actor model is basically dead already. you can't even federate reliably without a WebFinger server, at minimum.) - Requires multi-request "handshake" before communication. (but this is already required in practice, since a signature can't be validated without first requesting the signing actor.) - Out-of-band protocol - communication can't happen over ActivityPub / ActivityStreams because this is a prerequisite to authenticate any request. (but again, we already require WebFinger and some software requires NodeInfo for full support.) So, what are your thoughts? Good idea? Bad idea? Did I miss something? Please let me know, I welcome replies here! #ActivityPub #AP #Federation