This proposal addresses the problem of authenticating access to the content of non-public groups. It is mostly intended to supplement FEP-400e.
Only the server that hosts the Group
actor knows for sure who can and can not access the content in the group. However, due to each object being hosted on the server of the actor that created it, it is not ordinarily possible for those other servers to restrict access to that object only to those actors who have the permission to see it.
This FEP defines an authentication mechanism, “actor tokens”, that allows an actor to issue tokens that serve as a temporary proof of group membership for other servers.
The key words “MUST”, “MUST NOT”, “REQUIRED”, “SHALL”, “SHALL NOT”, “SHOULD”, “SHOULD NOT”, “RECOMMENDED”, “MAY”, and “OPTIONAL” in this specification are to be interpreted as described in [RFC-2119].
To fetch an object from the server that hosts the group (including the Group
actor itself for private groups), the requesting server MUST sign the GET request with an HTTP signature using the key of any of its actors. It is RECOMMENDED to use a server-wide service actor for this purpose, e.g. /activitypub/serviceActor
in Smithereen. The rationale for this is that most ActivityPub servers only fetch and store a single copy of each remote object for all users to whom it may concern, and are responsible themselves for enforcing the visibility rules, if any, either way.
The process of fetching an object from other server involves an actor token. An actor token is a cryptographically signed temporary proof of membership in a group. Since it would be impractical to provide a revocation mechanism, an actor token has a limited validity time in order to account for cases when someone has left a group or was removed from it.
An actor token is a JSON object with the following REQUIRED fields:
issuer
: ID of the actor that generated this tokenactor
: ID of the actor that the token is issued to (and must be presented with a valid HTTP signature of)issuedAt
: timestamp when the token was generated, ISO-8601 instant (same format as ActivityPub timestamps)validUntil
: timestamp when the token expires, ISO-8601 instantsignatures
: array of signature objects, currently with only one possible, and REQUIRED, element defined:
algorithm
: must be the string rsa-sha256
keyId
: key ID, same as in HTTP signatures (e.g. https://example.com/groups/1#main-key
)signature
: the RSA-SHA256 signature itself encoded as base64, see below for detailssm:actorToken
endpointActors that are capable of issuing actor tokens have a sm:actorToken
endpoint (where sm
is an alias to JSON-LD namespace http://smithereen.software/ns#
) in their endpoints
object. This endpoint accepts signed GET requests and returns actor tokens.
To use an actor token when fetching an object, pass it as Authorization: ActivityPubActorToken {...}
HTTP header.
signature
, and transform them into the format key: value
. Add these strings to an array.\n
, U+000A).signature
). It is RECOMMENDED that the validity period is 30 minutes, and it MUST NOT exceed 2 hours.signature
, algorithm
, and keyId
fields.signatures
array.actor
in the token object matches the actor ID from keyId
in the HTTP signature. Otherwise, you MUST return a 403 and stop.signatures
array, find an object that has algorithm
set to rsa-sha256
to get the signature
value. If there isn’t any, you MUST return a 403 and stop.issuedAt
MUST be in the past, validUntil
MUST be in the future, and the difference between them MUST NOT exceed 2 hours. It is RECOMMENDED to apply some margin to these checks to account for imprecisely set clocks. Smithereen uses 5 minutes.issuer
.{
"issuer":"https://friends.grishka.me/groups/75",
"actor":"https://activitypub.academy/actor",
"issuedAt":"2024-05-03T14:02:18.680404311Z",
"validUntil":"2024-05-03T14:32:18.680404311Z",
"signatures":[
{
"algorithm":"rsa-sha256",
"keyId":"https://friends.grishka.me/groups/75#main-key",
"signature":"w+W1nNV+XBvXi8sDEUZB7muWSSnv1mEE4tNZJqF5LeoxAstBMiBZi8dtHF+v+vXKVPWBAdZUKLS5CttmgZ4tvnvZAfsBztCjYLyiolVQ71IO2Jxlu00Xo9FDoSTRZ61tXdfWufuzs5lRjG3t+S1t1lLllBFmvPLg6BwmdEPvlZvPYnTJzwNY0ljOjickPqfyvdzIslmdYX6dPC0Ayyi028ZmR2SN1Vooc9vnUQ7GMPrlAZtmXgjCVGw5X/cKlAVvGECxRjJnkKEKiLp3lv/SM1UUhP3VRpBSFhXnRX/1QhTUaFV1MhrfDFgWGPg8ypIf6O/M52+iSpJyIOGepmjmow=="
}
]
}
CC0 1.0 Universal (CC0 1.0) Public Domain Dedication
To the extent possible under law, the authors of this Fediverse Enhancement Proposal have waived all copyright and related or neighboring rights to this work.