There are no known implementations of w3-store Authorization + IPFS Pinning Service API.
See w3-store for implementations of the storage protocol that this refers to.
We reimagine IPFS pinning service as a web3 service, where:
- Users delegate necessary capabilities to the pinning service as UCANs opposed to sharing powerful bearer access tokens that must be kept secret by both client and pinning service, and client must trust pinning service to only use as intended
- As a layer on top of w3-store protocol
The following table maps IPFS pinning service API operations to capabilities necessary to execute them
Operation | Capabilities |
---|---|
add | store/add |
remove | store/remove |
list | store/list |
replace | store/add store/remove |
get | store/get |
a w3 pinning service accepts requests whose access token is a UCAN JWT where:
- Root issuer is the same DID as one in
with
field of the delegated capabilities. - DID in
with
field is associated with some account on the Pinning Service. - All the linked proofs are embedded inline.
Using UCANs for authorization offers following advantages to typical bearer tokens:
- Users are able to delegate access to pinning service to other DIDs.
- Users can delegate access to only a subset of their authorizations, restricting access to desired operations.
- Users can revoke and rotate tokens as they wish.
This also creates an opportunity for implementing better pinning service clients that issue short lived tokens for each operation and remove the need for keeping tokens secret. @ipld/dag-ucan library could be used to issue such tokens
Pinning service uses requestid
field to uniquely identify pinning requests. We extend IPFS pinning service specification with additional constraint.
Pin request MUST be identified with a requestid
derived from the pin request. More specifically it should be a CID of the CBOR encoded Pin
object with a sha256
(multi)hash. In typescript this can be encoded as follows:
import type { Link, DID } from "@ipld/dag-ucan"
import * as CBOR from "@ipld/dag-cbor"
import { sha256 } from "multiformats/hashes/sha2"
type RequestID = Link<Pin, typeof CBOR.code, typeof sha256.code> {}
interface Pin {
cid: CID
// Optional name for pinned data (can be used for lookups)
name?: string
// Optional list of multiaddrs known to provide the data
origins?: string[]
// Optional metadata for pin object
meta: { group: DID } & Record<string, string>
}
Please note
Link
is a type for CID destination type hint and is equivalent of Link IPLD Schema.
This design frees pinning service from doing any kind of access control or token validation. It simply needs to
- Parse access token as a UCAN.
- Ensure that
audience
corresponds to own DID. - Verify that UCAN is valid (has right signature, has not expired etc)
- Create UCAN invocation (corresponding to received request) and embed UCAN (from access token) as a proof.
While UCAN validation is not strictly necessary (as they get verified downstream anyway) it might be a good idea to avoid unnecessary work downstream.