A library for fetching the public key from an activitypub actor, for use in fediverse applications. You can use this library to obtain a key for verifying an HTTP signature header, for example.
Note that you need to know the key ID URI in order to use this library - just knowing the actor's URI is not enough.
The document containing the key must use the sec:owner
and
sec:publicKeyPem
terms from the WC3 Security Draft vocabulary.
The document containing the key's owner must use the sec:publicKey
term.
import KeyFetcher from 'fedi-get-key';
// Bring your own fetch implementation (the global fetch is fine)
const keyFetcher = new KeyFetcher(globalThis.fetch);
const keyUri = 'https://example.com/users/Paul#main-key';
const result = await keyFetcher.get(keyUri);
// This is the public key for the given URI
console.log(result.key); // "-----BEGIN PUBLIC KEY-----\n...etc...\n-----END PUBLIC KEY-----\n"
// This is the parsed JSON-LD document representing the key's owner
console.log(result.owner); // { @context: { etc }, id: 'https://example.com/users/Paul', preferredUsername: 'Paul', /* ...etc... */ }
As well as fetching the key, this library will check that there's a two-way relationship
between the key and its owner; the key must have a sec:owner
property that
points to an actor, and that actor must have a sec:publicKey
property
that points to the key.
These objects may be in the same document or in different documents - if the actor is in a separate document to the key, a second fetch request will be made to resolve the actor.
The KeyFetcher constructor accepts a fetch-like function as its argument. This function doesn't
need to implement the full fetch specification, just certain parts; namely, it must accept a
string url
argument and options object of the form { headers: { accept: string } }
,
and return a response object with the ok
and json
properties and a headers
collection
with a get
function.
The typescript definitions are as follows:
type FetchLite = (url: string, options: FetchLiteOptions) => Promise<FetchLiteResponse>;
type FetchLiteOptions = {
headers: {
accept: string
}
}
type FetchLiteResponse = {
ok: boolean
status: number
headers: {
get(name: string): string | null
},
text(): Promise<string>
json(): Promise<unknown>
}
While you can use the global fetch, you may wish to create a wrapper function which—for example—enforces HTTPS, aborts the request after a timeout, or caches responses.
If there is a problem with your request, the library will through a KeyError
.
The error object has a meta
object with the url
, status
and content
of
the response.