{"slug": "user-controlled-authorization-network-ucan-specification", "title": "User Controlled Authorization Network (UCAN) Specification", "summary": "Protocol Labs, Bluesky, number zero, and Witchcraft Software have published the User Controlled Authorization Network (UCAN) specification, a trustless, secure, local-first, user-originated, distributed authorization scheme that uses public-key verifiable, delegable capabilities and decentralized identifiers (DIDs). The specification aims to improve on traditional access control lists (ACLs) and role-based access control (RBAC) by enabling authorization to scale in distributed systems without a central authority, addressing issues such as confused deputies and data privacy.", "body_md": "[Irakli Gozalishvili](https://github.com/Gozala),[Protocol Labs](https://protocol.ai/)[Daniel Holmgren](https://github.com/dholms),[Bluesky](https://blueskyweb.xyz/)[Philipp Krüger](https://github.com/matheus23),[number zero](https://n0.computer/)[Brooklyn Zelenka](https://github.com/expede),[Witchcraft Software](https://github.com/expede)\n\nThe key words \"MUST\", \"MUST NOT\", \"REQUIRED\", \"SHALL\", \"SHALL NOT\", \"SHOULD\", \"SHOULD NOT\", \"RECOMMENDED\", \"NOT RECOMMENDED\", \"MAY\", and \"OPTIONAL\" in this document are to be interpreted as described in [BCP 14](https://www.rfc-editor.org/info/bcp14) when, and only when, they appear in all capitals, as shown here.\n\nUser-Controlled Authorization Network (UCAN) is a [trustless](https://blueskyweb.xyz/blog/3-6-2022-a-self-authenticating-social-protocol), secure, [local-first](https://www.inkandswitch.com/local-first/), user-originated, distributed authorization scheme. This document provides a high level overview of the components of the system, concepts, and motivation. Exact formats are given in [sub-specifications](#sub-specifications).\n\nUser-Controlled Authorization Network (UCAN) is a [trustless](https://blueskyweb.xyz/blog/3-6-2022-a-self-authenticating-social-protocol), secure, [local-first](https://www.inkandswitch.com/local-first/), user-originated, distributed authorization scheme. It provides public-key verifiable, delegable, expressive, openly extensible [capabilities](https://en.wikipedia.org/wiki/Object-capability_model). UCANs achieve public verifiability with late-bound certificate chains and principals represented by [decentralized identifiers (DIDs)](https://www.w3.org/TR/did-core/).\n\nUCAN improves the familiarity and adoptability of schemes like [SPKI/SDSI](https://theworld.com/~cme/html/spki.html) for web and native application contexts. UCAN allows for the creation, delegation, and invocation of authority by any agent with a DID, including traditional systems and peer-to-peer architectures beyond traditional cloud computing.\n\nIf we practice our principles, we could have both security and functionality. Treating security as a separate concern has not succeeded in bridging the gap between principle and practice, because it operates without knowledge of what constitutes least authority.\n\n—\n\n[Miller]et al,[The Structure of Authority]\n\nSince at least [Multics](https://en.wikipedia.org/wiki/Multics), access control lists ([ACL](https://en.wikipedia.org/wiki/Access-control_list)s) have been the most popular form of digital authorization, where a list of what each user is allowed to do is maintained on the resource. ACLs (and later [RBAC](https://en.wikipedia.org/wiki/Role-based_access_control)) have been a successful model suited to architectures where persistent access to a single list is viable. ACLs require that rules are sufficiently well specified, such as in a centralized database with rules covering all possible permutations of scenario. This both imposes a very high maintenance burden on programmers as a systems grows in complexity, and is a key vector for [confused deputies](https://en.wikipedia.org/wiki/Confused_deputy_problem).\n\nWith increasing interconnectivity between machines becoming commonplace, authorization needs to scale to meet the load demands of distributed systems while providing partition tolerance. However, it is not always practical to maintain a single central authorization source. Even when copies of the authorization list are distributed to the relevant servers, latency and partitions introduce troublesome challenges with conflicting updates, to say nothing of storage requirements.\n\nA large portion of personal information now also moves through connected systems. As a result, data privacy is a prominent theme when considering the design of modern applications, to the point of being legislated in parts of the world.\n\nAhead-of-time coordination is often a barrier to development in many projects. Flexibility to define specialized authorization semantics for resources and the ability to integrate with external systems trustlessly are essential as the number of autonomous, specialized, and coordinated applications increases.\n\nMany high-value applications run in hostile environments. In recognition of this, many vendors now include public key functionality, such as [non-extractable keys in browsers](https://developer.mozilla.org/en-US/docs/Web/API/CryptoKey), [certificate systems for external keys](https://fidoalliance.org/what-is-fido/), [platform keys](https://www.passkeys.com/), and [secure hardware enclaves] in widespread consumer devices.\n\nTwo related models that work exceptionally well in the above context are Simple Public Key Infrastructure ([SPKI](https://www.rfc-editor.org/rfc/rfc2693.html)) and object capabilities ([OCAP](http://erights.org/elib/capability/index.html)). Since offline operation and self-verifiability are two requirements, UCAN adopts a [certificate capability model](https://web.archive.org/web/20140724054706/http://wiki.erights.org/wiki/Capability-based_Active_Invocation_Certificates) related to [SPKI](https://theworld.com/~cme/html/spki.html).\n\nThe following analogies illustrate several significant trade-offs between these systems but are only accurate enough to build intuition. A good resource for a more thorough presentation of these trade-offs is [Capability Myths Demolished](https://srl.cs.jhu.edu/pubs/SRL2003-02.pdf). In this framework, UCAN approximates SPKI with some dynamic features.\n\nBy analogy, ACLs are like a bouncer at an exclusive event. This bouncer has a list attendees allowed in and which of those are VIPs that get extra access. People trying to get in show their government-issued ID and are accepted or rejected. In addition, they may get a lanyard to identify that they have previously been allowed in. If someone is disruptive, they can simply be crossed off the list and denied further entry.\n\nIf there are many such events at many venues, the organizers need to coordinate ahead of time, denials need to be synchronized, and attendees need to show their ID cards to many bouncers. The likelihood of the bouncer letting in the wrong person due to synchronization lag or confusion by someone sharing a name is nonzero.\n\nUCANs work more like [movie tickets](http://www.erights.org/elib/capability/duals/myths.html#caps-as-keys) or a festival pass. No one needs to check your ID; who you are is irrelevant. For example, if you have a ticket issued by the theater to see Citizen Kane, you are admitted to Theater 3. If you cannot attend an event, you can hand this ticket to a friend who wants to see the film instead, and there is no coordination required with the theater ahead of time. However, if the theater needs to cancel tickets for some reason, they need a way of uniquely identifying them and sharing this information between them.\n\nObject capability (\"ocap\") systems use a combination of references, encapsulated state, and proxy forwarding. As the name implies, this is fairly close to object-oriented or actor-based systems. Object capabilities are [robust](http://www.erights.org/talks/thesis/markm-thesis.pdf), flexible, and expressive.\n\nTo achieve these properties, object capabilities have two requirements: [fail-safe](https://en.wikipedia.org/wiki/Fail-safe), and locality preservation. The emphasis on consistency rules out partition tolerance 1.\n\nEach UCAN includes an assertions of what it is allowed to do. \"Proofs\" are positive evidence (elsewhere called \"witnesses\") of the possession of rights. They are cryptographically verifiable chains showing that the UCAN issuer either claims to directly own a resource, or that it was delegated to them by some claimed owner. In the most common case, the root owner's ID is the only globally unique identity for the resource.\n\nRoot capability issuers function as verifiable, distributed roots of trust. The delegation chain is by definition a provenance log. Private keys themselves SHOULD NOT move from one context to another. Keeping keys unique to each physical device and unique per use case is RECOMMENDED to reduce opportunity for keys to leak, and limit blast radius in the case of compromises. \"Sharing authority without sharing keys\" is provided by capabilities, so there is no reason to share keys directly.\n\nNote that a structurally and cryptographically valid UCAN chain can be semantically invalid. The executor MUST verify the ownership of any external resources at execution time. While not possible for all use cases (e.g. replicated state machines and eventually consistent data), having the Executor be the resource itself is RECOMMENDED.\n\nWhile certificate chains go a long way toward improving security, they do not provide [confinement](http://www.erights.org/elib/capability/dist-confine.html) on their own. The principle of least authority SHOULD be used when delegating a UCAN: minimizing the amount of time that a UCAN is valid for and reducing authority to the bare minimum required for the delegate to complete their task. This delegate should be trusted as little as is practical since they can further sub-delegate their authority to others without alerting their delegator. UCANs do not offer confinement (as that would require all processes to be online), so it is impossible to guarantee knowledge of all of the sub-delegations that exist. The ability to revoke some or all downstream UCANs exists as a last resort.\n\n[Inversion of control](https://en.wikipedia.org/wiki/Inversion_of_control) is achieved due to two properties: self-certifying delegation and reference passing. There is no Authorization Server (AS) that sits between requestors and resources. In traditional terms, the owner of a UCAN resource is the resource server (RS) directly.\n\nThis inverts the usual relationship between resources and users: the resource grants some (or all) authority over itself to agents, as opposed to an Authorization Server managing the relationship between them. This has several major advantages:\n\n- Fully distributed and scalable\n- Self-contained request without intermediary\n- Partition tolerance,\n[support for replicated data and machines](#beyond-single-system-image) - Flexible granularity\n- Compositionality: no distinction between resources residing together or apart\n\n```\n┌─────────────┐   ┌─────────────┐   ┌─────────────┐\n│             │   │             │   │             │\n│             │   │ ┌─────────┐ │   │             │\n│             │   │ │  Bob's  │ │   │             │\n│             │   │ │  Photo  │ │   │             │\n│             │   │ │ Gallery │ │   │             │\n│             │   │ └─────────┘ │   │             │\n│             │   │             │   │             │\n│   Alice's   │   │    Bob's    │   │   Carol's   │\n│    Stuff    │   │    Stuff    │   │    Stuff    │\n│             │   │             │   │             │\n│     ┌───────┼───┼─────────────┼───┼──┐          │\n│     │       │   │             │   │  │          │\n│     │       │   │         ┌───┼───┼──┼────────┐ │\n│     │       │   │ Alice's │   │   │  │        │ │\n│     │       │   │  Music  │   │   │  │Carol's │ │\n│     │       │   │ Player  │   │   │  │  Game  │ │\n│     │       │   │         │   │   │  │        │ │\n│     │       │   │         └───┼───┼──┼────────┘ │\n│     │       │   │             │   │  │          │\n│     └───────┼───┼─────────────┼───┼──┘          │\n│             │   │             │   │             │\n└─────────────┘   └─────────────┘   └─────────────┘\n```\n\nThis additionally allows UCAN to model auth for [eventually consistent and replicated state](#beyond-single-system-image).\n\nThere are several roles that an agent MAY assume:\n\n| Name | Description |\n|---|---|\n| Agent | The general class of entities and principals that interact with a UCAN |\n| Audience | The Principal delegated to in the current UCAN. Listed in the `aud` field |\n| Executor | The Agent that actually performs the action described in an invocation |\n| Invoker | A Principal that requests an Executor perform some action that uses the Invoker's authority |\n| Issuer | The Principal of the current UCAN. Listed in the `iss` field |\n| Owner | A Subject that controls some external resource |\n| Principal | An agent identified by DID (listed in a UCAN's `iss` or `aud` field) |\n| Revoker | The Issuer listed in a proof chain that revokes a UCAN |\n| Subject | The Principal who's authority is delegated or invoked |\n| Validator | Any Agent that interprets a UCAN to determine that it is valid, and which capabilities it grants |\n\n```\nflowchart TD\n    subgraph Agent\n        subgraph Principal\n            direction TB\n\n            subgraph Issuer\n                direction TB\n                \n                subgraph Subject\n                    direction TB\n                    \n                    Executor\n                    Owner\n                end\n\n                Revoker\n            end\n\n            subgraph Audience\n                Invoker\n            end\n        end\n\n        Validator\n    end\n```\n\nAt the very least every object should have a URL\n\nEvery Erlang process in the universe should be addressable and introspective\n\nA [Subject] represents the Agent that a capability is for. A Subject MUST be referenced by [DID](https://www.w3.org/TR/did-core/). This behaves much like a [GUID](https://en.wikipedia.org/wiki/Universally_unique_identifier), with the addition of public key verifiability. This unforgeability prevents malicious namespace collisions which can lead to [confused deputies](https://en.wikipedia.org/wiki/Confused_deputy_problem).\n\nA resource is some data or process that can be uniquely identified by a [URI](https://www.rfc-editor.org/rfc/rfc3986). It can be anything from a row in a database, a user account, storage quota, email address, etc. Resource MAY be as coarse or fine grained as desired. Finer-grained is RECOMMENDED where possible, as it is easier to model the principle of least authority ([PoLA](https://en.wikipedia.org/wiki/Principle_of_least_privilege)).\n\nA resource describes the noun of a capability. The resource pointer MUST be provided in [URI](https://www.rfc-editor.org/rfc/rfc3986) format. Arbitrary and custom URIs MAY be used, provided that the intended recipient can decode the URI. The URI is merely a unique identifier to describe the pointer to — and within — a resource.\n\nHaving a unique agent represent a resource (and act as its manager) is RECOMMENDED. However, to help traditional ACL-based systems transition to certificate capabilities, an agent MAY manage multiple resources, and [act as the registrant in the ACL system](#wrapping-existing-systems).\n\nUnless explicitly stated, the Resource of a UCAN MUST be the Subject.\n\nThe Issuer (`iss`\n\n) and Audience (`aud`\n\n) can be conceptualized as the sender and receiver (respectively) of a postal letter. Every UCAN MUST be signed with the private key associated with the DID in the `iss`\n\nfield.\n\nFor example:\n\n```\n\"aud\": \"did:key:z6MkiTBz1ymuepAQ4HEHYSF1H8quG5GLVVQR3djdX3mDooWp\",\n\"iss\": \"did:key:zDnaerDaTF5BXEavCrfRZEk316dpbLsfPDZ3WJ5hRTPFU2169\",\n```\n\nPlease see the [Cryptosuite](#cryptosuite) section for more detail on DIDs.\n\nThe UCAN lifecycle has four components:\n\n| Spec | Description | Requirement Level |\n|---|---|---|\n|\n\n[Invocation](https://github.com/ucan-wg/invocation)[Promise](https://github.com/ucan-wg/promise)[Revocation](https://github.com/ucan-wg/revocation)\n\n```\nflowchart TD\n    prm(Promise)\n    inv(Invocation)\n    del(Delegation)\n    rev(Revocation)\n\n    prm -->|awaits| inv\n    del -->|proves| inv\n    rev -.->|kind of| inv\n    rev -->|invalidates| del\n\n    click del href \"https://github.com/ucan-wg/delegation\" \"UCAN Delegation Spec\"\n    click inv href \"https://github.com/ucan-wg/invocation\" \"UCAN Invocation Spec\"\n    click rev href \"https://github.com/ucan-wg/revocation\" \"UCAN Revocation Spec\"\n```\n\nIt is often useful to talk about a UCAN in the context of some action. For example, a UCAN delegation may be valid when it was created, but expired when invoked.\n\n``` php\nsequenceDiagram\n    Alice -->> Bob: Delegate\n    Bob ->> Bob: Validate\n    Bob -->> Carol: Delegate\n    Carol ->> Carol: Validate\n    Carol ->> Alice: Invoke\n    Alice ->> Alice: Validate\n    Alice ->> Alice: Execute\n```\n\nThe period of time that a capability is valid from and until. This is the range from the latest \"not before\" to the earliest expiry in the UCAN delegation chain.\n\nThe moment at which a delegation is asserted. This MAY be captured by an `iat`\n\nfield, but is generally superfluous to capture in the token.\n\nThe moment a UCAN Invocation is created. It must be within the Validity Interval.\n\nValidation MAY occur at multiple points during a UCAN's lifecycle. The main two are:\n\n- On receipt of a delegation\n- When executing an invocation\n\nTo avoid the overloaded word \"runtime\", UCAN adopts the term \"execution-time\" to express the moment that the executor attempts to use the authority captured in an invocation and associated delegation chain. Validation MUST occur at this time.\n\n`nbf`\n\nand `exp`\n\nstand for \"not before\" and \"expires at,\" respectively. These MUST be expressed as seconds since the Unix epoch in UTC, without time zone or other offset. Taken together, they represent the time bounds for a token. These timestamps MUST be represented as the number of integer seconds since the Unix epoch. Due to limitations 2 in numerics for certain common languages, timestamps outside of the range from\n\nThe `nbf`\n\nfield is OPTIONAL. When omitted, the token MUST be treated as valid beginning from the Unix epoch. Setting the `nbf`\n\nfield to a time in the future MUST delay invoking a UCAN. For example, pre-provisioning access to conference materials ahead of time but not allowing access until the day it starts is achievable with judicious use of `nbf`\n\n.\n\nThe `exp`\n\nfield is RECOMMENDED. Following the [principle of least authority](https://en.wikipedia.org/wiki/Principle_of_least_privilege), it is RECOMMENDED to give a timestamp expiry for UCANs. If the token explicitly never expires, the `exp`\n\nfield MUST be set to `null`\n\n. If the time is in the past at validation time, the token MUST be treated as expired and invalid.\n\nKeeping the window of validity as short as possible is RECOMMENDED. Limiting the time range can mitigate the risk of a malicious user abusing a UCAN. However, this is situationally dependent. It may be desirable to limit the frequency of forced reauthorizations for trusted devices. Due to clock drift, time bounds SHOULD NOT be considered exact. A buffer of ±60 seconds is RECOMMENDED.\n\nSeveral named points of time in the UCAN lifecycle can be found in the [high level spec][UCAN].\n\nBelow are a couple examples:\n\n```\n{\n  // ...\n  \"nbf\": 1529496683,\n  \"exp\": 1575606941\n}\n{\n  // ...\n  \"exp\": 1575606941\n}\n{\n  // ...\n  \"nbf\": 1529496683,\n  \"exp\": null\n}\n```\n\nHere is a concrete example of all stages of the UCAN lifecycle for database write access.\n\n```\nsequenceDiagram\n    participant Database\n\n    actor DBAgent\n    actor Alice\n    actor Bob\n\n    Note over Database, DBAgent: Set Up Agent-Owned Resource\n    DBAgent ->> Database: createDB()\n\n    autonumber 1\n\n    Note over DBAgent, Bob: Delegation\n    DBAgent -->> Alice: delegate(DBAgent, write)\n    Alice -->> Bob: delegate(DBAgent, write)\n\n    Note over Database, Bob: Invocation\n    Bob ->> DBAgent: invoke(DBAgent, [write, [key, value]], proof: [➊,➋])\n    DBAgent ->> Database: write(key, value)\n    DBAgent ->> Bob: ACK\n\n    Note over DBAgent, Bob: Revocation\n    Alice ->> DBAgent: revoke(➋, proof: [➊,➋])\n    Bob ->> DBAgent: invoke(DBAgent, [write, [key, newValue]], proof: [➊,➋])\n    DBAgent -X Bob: NAK(➏) [rejected]\n```\n\nA capability is the association of an ability to a subject: `subject x command x policy`\n\n.\n\nThe Subject and Command fields are REQUIRED. Any non-normative extensions are OPTIONAL.\n\nFor example, a capability may used to represent the ability to send email from a certain address to others at `@example.com`\n\n.\n\n| Field | Example |\n|---|---|\n| Subject | `did:key:z6MkhaXgBZDvotDkL5257faiztiGiC2QtKLGpbnnEGta2doK` |\n| Command | `/msg/send` |\n| Policy | `[\"or\", [\"==\", \".from\", \"mailto:me@example.com\"], [\"match\", \".cc\", \"mailto:*@example.com\"]]` |\n\nFor a more complete treatment, please see the [UCAN Delegation](https://github.com/ucan-wg/delegation) spec.\n\nWhether to enable cooperation or to limit vulnerability, we care about\n\nauthorityrather thanpermissions.Permissions determine what actions an individual program may perform on objects it can directly access. Authority describes the effects that a program may cause on objects it can access, either directly by permission, or indirectly by permitted interactions with other programs.\n\nThe set of capabilities delegated by a UCAN is called its \"authority.\" To frame it another way, it's the set of effects that a principal can cause, and acts as a declarative description of delegated abilities.\n\nMerging capability authorities MUST follow set semantics, where the result includes all capabilities from the input authorities. Since broader capabilities automatically include narrower ones, this process is always additive. Capability authorities can be combined in any order, with the result always being at least as broad as each of the original authorities.\n\n```\n                   ┌───────────────────────┐  ┐\n                   │                       │  │\n                   │                       │  │\n                   │                       │  │\n                   │                       │  │\n                   │       Subject B       │  │\n┌──────────────────┼ ─ ─       x           │  │\n│                       │  Ability Z       │  ├──    BxZ\n│                  │                       │  │  Capability\n│                       │                  │  │\n│                  │                       │  │\n│       Subject A       │                  │  │\n│           x      │                       │  │\n│       Ability Y   ─  ─┼──────────────────┘  ┘\n│                       │\n│                       │\n│                       │\n│                       │\n│                       │\n└───────────────────────┘\n\n└─────────────────────┬────────────────────┘\n                      │\n                  AxY U BxZ\n                  Capability\n```\n\nThe capability authority is the total rights of the authorization space down to the relevant volume of authorizations. Individual capabilities MAY overlap; the authority is the union. Every unique delegated capability MUST have equal or narrower capabilities from their delegator. Inside this content space, you can draw a boundary around some resource(s) (their type, identifiers, and paths or children) and their capabilities.\n\nCommands are concrete messages (\"verbs\") that MUST be unambiguously interpretable by the Subject of a UCAN. Commands are REQUIRED in invocations. Some examples include `/msg/send`\n\n, `/crud/read`\n\n, and `/ucan/revoke`\n\n.\n\nMuch like other message-passing systems, the specific resource MUST define the behavior for a particular message. For instance, `/crud/update`\n\nMAY be used to destructively update a database row, or append to a append-only log. Specific messages MAY be created at will; the only restriction is that the Executor understand how to interpret that message in the context of a specific resource.\n\nWhile arbitrary semantics MAY be described, they MUST apply to the target resource. For instance, it does not make sense to apply `/msg/send`\n\nto a typical file system.\n\nCommands MUST be lowercase, and begin with a slash (`/`\n\n). Segments MUST be separated by a slash. A trailing slash MUST NOT be present. All of the following are syntactically valid Commands:\n\n`/`\n\n`/crud`\n\n`/crud/create`\n\n`/stack/pop`\n\n`/crypto/sign`\n\n`/foo/bar/baz/qux/quux`\n\n`/ほげ/ふが`\n\nSegment structure is important since shorter Commands prove longer paths. For example, `/`\n\ncan be used as a proof of *any* other Command. For example, `/crypto`\n\nMAY be used to prove `/crypto/sign`\n\nbut MUST NOT prove `/stack/pop`\n\nor `/cryptocurrency`\n\n.\n\n*\"Top\" ( /) is the most powerful ability, and as such it SHOULD be handled with care and used sparingly.*\n\nThe \"top\" (or \"any\", or \"wildcard\") ability MUST be denoted `/`\n\n. This can be thought of as something akin to a super user permission in RBAC.\n\nThe wildcard ability grants access to all other capabilities for the specified resource, across all possible namespaces. The wildcard ability is useful when \"linking\" agents by delegating all access to another device controlled by the same user, and that should behave as the same agent. It is extremely powerful, and should be used with care. Among other things, it permits the delegate to update a Subject's mutable DID document (change their private keys), revoke UCAN delegations, and use any resources delegated to the Subject by others.\n\n```\n%%{ init: { 'flowchart': { 'curve': 'linear' } } }%%\n\nflowchart BT\n  /\n\n  /msg --> /\n  subgraph msgGraph [ ]\n    /msg/send --> /msg\n    /msg/receive --> /msg\n  end\n\n  /crud --> /\n  subgraph crudGraph [ ]\n    /crud/read --> /crud\n    /crud/mutate --> /crud\n\n    subgraph mutationGraph [ ]\n        /crud/mutate/create --> /crud/mutate\n        /crud/mutate/update --> /crud/mutate\n        /crud/mutate/destroy --> /crud/mutate\n    end\n  end\n\n  ... --> /\n```\n\nThe `/ucan`\n\nCommand namespace MUST be reserved. This MUST include any ability string matching the regex `^\\/ucan\\/.*`\n\n. This is important for keeping a space for community-blessed Commands in the future, such as standard library Commands, such as [Revocation](https://github.com/ucan-wg/revocation).\n\nAttenuation is the process of constraining the capabilities in a delegation chain. Each direct delegation MUST either directly restate or attenuate (diminish) its capabilities.\n\nToken resolution is transport specific. The exact format is left to the relevant UCAN transport specification. At minimum, such a specification MUST define at least the following:\n\n- Request protocol\n- Response protocol\n- Collections format\n\nNote that if an instance cannot dereference a CID at runtime, the UCAN MUST fail validation. This is consistent with the [constructive semantics](https://en.wikipedia.org/wiki/Intuitionistic_logic) of UCAN.\n\nThe REQUIRED nonce parameter `nonce`\n\nMAY be any value. A randomly generated string is RECOMMENDED to provide a unique UCAN, though it MAY also be a monotonically increasing count of the number of links in the hash chain. This field helps prevent replay attacks and ensures a unique CID per delegation. The `iss`\n\n, `aud`\n\n, and `exp`\n\nfields together will often ensure that UCANs are unique, but adding the nonce ensures uniqueness.\n\nThe recommended size of the nonce differs by key type. In many cases, a random 12-byte nonce is sufficient. If uncertain, check the nonce in your DID's crypto suite.\n\nThis field SHOULD NOT be used to sign arbitrary data, such as signature challenges. See the [`meta`\n\n][Metadata] field for more.\n\nHere is a simple example.\n\n```\n{\n  // ...\n  \"nonce\": {\"/\": {\"bytes\": \"bGlnaHQgd29yay4\"}}\n}\n```\n\nThe OPTIONAL `meta`\n\nfield contains a map of arbitrary metadata, facts, and proofs of knowledge. The enclosed data MUST be self-evident and externally verifiable. It MAY include information such as hash preimages, server challenges, a Merkle proof, dictionary data, etc.\n\nThe data contained in this map MUST NOT be semantically meaningful to delegation chains.\n\nBelow is an example:\n\n```\n{\n  // ...\n  \"meta\": {\n    \"challenges\": {\n      \"example.com\": \"abcdef\",\n      \"another.example.net\": \"12345\"\n    },\n    \"sha3_256\": {\n      \"B94D27B9934D3E08A52E52D7DA7DABFAC484EFE37A5380EE9088F7ACE2EFCDE9\": \"hello world\"\n    }\n  }\n}\n```\n\nAcross all UCAN specifications, the following cryptosuite MUST be supported:\n\n| Role | REQUIRED Algorithms | Notes |\n|---|---|---|\n| Hash |\n|\n\n[Ed25519](https://en.wikipedia.org/wiki/EdDSA#Ed25519),[P-256](https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.186-4.pdf#page=111),`secp256k1`\n\n[DID](https://www.w3.org/TR/did-core/)`did:key`\n\nAll UCANs MUST be canonically encoded with [DAG-CBOR](https://ipld.io/specs/codecs/dag-cbor/spec/) for signing. A UCAN MAY be presented or stored in other [IPLD](https://ipld.io/) formats (such as [DAG-JSON](https://ipld.io/specs/codecs/dag-json/spec/)), but converted to DAG-CBOR for signature validation.\n\nA UCAN token MUST be configured as follows:\n\n| Parameter | REQUIRED Configuration |\n|---|---|\n| Version |\n|\n\n[Multibase](https://github.com/multiformats/multibase)`base58btc`\n\n[Multihash](https://www.multiformats.io/multihash/)[SHA-256](https://en.wikipedia.org/wiki/SHA-2)[Multicodec](https://github.com/multiformats/multicodec)[DAG-CBOR](https://ipld.io/specs/codecs/dag-cbor/spec/)Note\n\nAll CIDs encoded as above start with the characters `zdpu`\n\n.\n\nThe resolution of these addresses is left to the implementation and end-user, and MAY (non-exclusively) include the following: local store, a distributed hash table (DHT), gossip network, or RESTful service.\n\nAll UCAN formats MUST use the following envelope format:\n\n| Field | Type | Description |\n|---|---|---|\n`.0` |\n`Bytes` |\nA signature by the Payload's `iss` over the `SigPayload` field |\n`.1` |\n`SigPayload` |\nThe content that was signed |\n`.1.h` |\n`VarsigHeader` |\nThe\n|\n\n`.1.ucan/<subspec-tag>@<version>`\n\n`TokenPayload`\n\n```\nflowchart TD\n    subgraph Ucan [\"UCAN Envelope\"]\n        SignatureBytes[\"Signature (raw bytes)\"]\n      \n        subgraph SigPayload [\"Signature Payload\"]\n            VarsigHeader[\"Varsig Header\"]\n\n            subgraph UcanPayload [\"Token Payload\"]\n                fields[\"...\"]\n            end\n        end\n    end\n```\n\nFor example:\n\n```\n[\n  { \"/\": {\"bytes\": \"bdNVZn+uTrQ8bgq5LocO2y3gqIyuEtvYWRUH9YT+SRK6v/SX8bjt+VZ9JIPVTdxkWb6nhVKBt6JGpgnjABpOCA\"}},\n  {\n    \"h\": {\"/\": {\"bytes\": \"NAHtAe0BE3E\"}}, // i.e. signed with Ed25519, encoded with DAG-CBOR\n    \"ucan/example@1.0.0\": {\n      // Body fields, for example:\n      \"hello\": \"world\"\n    }\n  }\n]\n```\n\nA UCAN's Payload MUST contain at least the following fields:\n\n| Field | Type | Required | Description |\n|---|---|---|---|\n`iss` |\n`DID` |\nYes | Issuer DID (sender) |\n`aud` |\n`DID` |\nYes | Audience DID (receiver) |\n`sub` |\n`DID` |\nYes | Principal that the chain is about (the [Subject]) |\n`cmd` |\n`String` |\nYes | The\n|\n\n`args`\n\n`{String : Any}`\n\n`nonce`\n\n`Bytes`\n\n`meta`\n\n`{String : Any}`\n\n`nbf`\n\n`Integer`\n\n(53-bits)[2](#user-content-fn-js-num-size-c0fb6dbd18be1629eac0aa5ae2ef9a08)`exp`\n\n`Integer | Null`\n\n(53-bits)[2](#user-content-fn-js-num-size-c0fb6dbd18be1629eac0aa5ae2ef9a08)A validator MAY keep a local store of UCANs that it has received. UCANs are immutable but also time-bound so that this store MAY evict expired or revoked UCANs.\n\nThis store SHOULD be indexed by CID (content addressing). Multiple indices built on top of this store MAY be used to improve capability search or selection performance.\n\nAside from revocation, capability validation is idempotent. Marking a CID (or capability index inside that CID) as valid acts as memoization, obviating the need to check the entire structure on every validation. This extends to distinct UCANs that share a proof: if the proof was previously reviewed and is not revoked, it is RECOMMENDED to consider it valid immediately.\n\nRevocation is irreversible. Suppose the validator learns of revocation by UCAN CID. In that case, the UCAN and all of its derivatives in such a cache MUST be marked as invalid, and all validations immediately fail without needing to walk the entire structure.\n\nReplay attack prevention is REQUIRED. Every UCAN token MUST hash to a unique [CIDv1](https://docs.ipfs.io/concepts/content-addressing/#identifier-formats). Some simple strategies for implementing uniqueness tracking include maintaining a set of previously seen CIDs, or requiring that nonces be monotonically increasing per principal. This MAY be the same structure as a validated UCAN memoization table (if one is implemented).\n\nMaintaining a secondary token expiry index is RECOMMENDED. This enables garbage collection and more efficient search. In cases of very large stores, normal cache performance techniques MAY be used, such as Bloom filters, multi-level caches, and so on.\n\nAs we continue to increase the number of globally connected devices, we must embrace a design that considers every single member in the system as the primary site for the data that it is generates. It is completely impractical that we can look at a single, or a small number, of globally distributed data centers as the primary site for all global information that we desire to perform computations with.\n\nUnlike many authorization systems where a service controls access to resources in their care, location-independent, offline, and leaderless resources require control to live with the user. Therefore, the same data MAY be used across many applications, data stores, and users. Since they don't have a single location, applying UCAN to [RSM](https://en.wikipedia.org/wiki/State_machine_replication)s and [CRDT](https://en.wikipedia.org/wiki/Conflict-free_replicated_data_type)s MAY be modelled by lifting the requirement that the Executor be the Subject.\n\nUltimately this comes down to a question of push vs pull. In push, the subject MUST be the specific site being pushed to (\"I command you to apply the following updates to your state\").\n\nPull is the broad class of situations where an Invoker doesn't require that a particular replica apply its state. Applying a change to a local CRDT replica and maintaining a UCAN invocation log is a valid update to \"the CRDT\": a version of the CRDT Subject exists locally even if the Subject's private key is not present. Gossiping these changes among agents allows each to apply changes that it becomes aware of. Thanks to the invocation log (or equivalent integrated directly into the CRDT), provenance of authority is made transparent.\n\n```\nsequenceDiagram\n    participant CRDT as Initial Grow-Only Set (CRDT)\n\n    actor Alice\n    actor Bob\n    actor Carol\n    \n    autonumber\n\n    Note over CRDT, Bob: Setup\n    CRDT -->> Alice: delegate(CRDT_ID, merge)\n    CRDT -->> Bob: delegate(CRDT_ID, merge)\n    \n    Note over Bob, Carol: Bob Invites Carol\n    Bob -->> Carol: delegate(CRDT_ID, merge)\n\n    Note over Alice, Carol: Direct P2P Gossip\n    Carol ->> Bob: invoke(CRDT_ID, merge, {\"Carrot\"}, proof: [➋,❸])\n    Alice ->> Carol: invoke(CRDT_ID, merge, {\"Apple\"}}, proof: [➊])\n    Bob ->> Alice: invoke(CRDT_ID, merge, {\"Banana\", \"Carrot\"}, proof: [➋])\n```\n\nIn the RECOMMENDED scenario, the agent controlling a resource has a unique reference to it. This is always possible in a system that has adopted capabilities end-to-end.\n\nInteracting with existing systems MAY require relying on ambient authority contained in an ACL, non-unique reference, or other authorization logic. These cases are still compatible with UCAN, but the security guarantees are weaker since 1. the surface area is larger, and 2. part of the auth system lives outside UCAN.\n\n```\nsequenceDiagram\n    participant Database\n    participant ACL as External Auth System\n\n    actor DBAgent\n    actor Alice\n    actor Bob\n\n    Note over ACL, DBAgent: Setup\n    DBAgent ->> ACL: signup(DBAgent)\n    ACL ->> ACL: register(DBAgent)\n\n    autonumber 1\n\n    Note over DBAgent, Bob: Delegation\n    DBAgent -->> Alice: delegate(DBAgent, write)\n    Alice -->> Bob: delegate(DBAgent, write)\n\n    Note over Database, Bob: Invocation\n    Bob ->>+ DBAgent: invoke(DBAgent, [write, key, value], proof: [➊,➋])\n\n    critical External System\n        DBAgent ->> ACL: getToken(write, key, AuthGrant)\n        ACL ->> DBAgent: AccessToken\n        \n        DBAgent ->> Database: request(write, value, AccessToken)\n        Database ->> DBAgent: ACK\n    end\n\n    DBAgent ->>- Bob: ACK\n```\n\nUCANs always contain information about the sender and receiver. A UCAN is signed by the sender (the `iss`\n\nfield DID) and can only be created by an agent in possession of the relevant private key. The recipient (the `aud`\n\nfield DID) is required to check that the field matches their DID. These two checks together secure the certificate against use by an unauthorized party. [UCAN Invocations](https://github.com/ucan-wg/invocation) prevent use by an unauthorized party by signing over a request to use the capability granted in a delegation chain.\n\nAll UCAN Invocations MUST have a unique CID. The executing agent MUST check this validation uniqueness against a local store of unexpired UCAN hashes.\n\nThis is not a concern when simply delegating since receiving a delegation is idempotent.\n\n*UCAN does not have any special protection against person-in-the-middle (PITM) attacks.*\n\nIf a PITM attack was successfully performed on a UCAN delegation, the proof chain would contain the attacker's DID(s). It is possible to detect this scenario and revoke the relevant UCAN but this does require special inspection of the topmost `iss`\n\nfield to check if it is the expected DID. Therefore, it is strongly RECOMMENDED to only delegate UCANs to agents that are both trusted and authenticated and over secure channels.\n\nIt is possible to use other algorithms, but doing so limits interoperability with the broader UCAN ecosystem. This is thus considered \"off spec\" (i.e. non-interoperable). If you choose to extend UCAN with additional algorithms, you MUST include this metadata in the (self-describing) [Varsig](https://github.com/ChainAgnostic/varsig) header.\n\n[SPKI/SDSI](https://datatracker.ietf.org/wg/spki/about/) is closely related to UCAN. A different encoding format is used, and some details vary (such as a delegation-locking bit), but the core idea and general usage pattern are very close. UCAN can be seen as making these ideas more palatable to a modern audience and adding a few features such as content IDs that were less widespread at the time SPKI/SDSI were written.\n\n[ZCAP-LD](https://w3c-ccg.github.io/zcap-spec/) is closely related to UCAN. The primary differences are in formatting, addressing by URL instead of CID, the mechanism of separating invocation from authorization, and single versus multiple proofs.\n\n[CACAO](https://blog.ceramic.network/capability-based-data-security-on-ceramic/) is a translation of many of these ideas to a cross-blockchain delegated bearer token model. It contains the same basic concepts as UCAN delegation, but is aimed at small messages and identities that are rooted in mutable documents rooted on a blockchain and lacks the ability to subdelegate capabilities.\n\n[Local-First Auth](https://github.com/local-first-web/auth) is a non-certificate-based approach, instead relying on a CRDT to build up a list of group members, devices, and roles. It has a friendly invitation mechanism based on a [Seitan token exchange](https://book.keybase.io/docs/teams/seitan). It is also straightforward to see which users have access to what, avoiding the confinement problem seen in many decentralized auth systems.\n\n[Macaroon](https://theory.stanford.edu/~ataly/Papers/macaroons.pdf) is a MAC-based capability and cookie system aimed at distributing authority across services in a trusted network (typically in the context of a Cloud). By not relying on asymmetric signatures, Macaroons achieve excellent space savings and performance, given that the MAC can be checked against the relevant services during discharge. The authority is rooted in an originating server rather than with an end-user.\n\n[Biscuit](https://github.com/biscuit-auth/biscuit/) uses Datalog to describe capabilities. It has a specialized format but is otherwise in line with UCAN.\n\n[Verifiable credentials](https://www.w3.org/2017/vc/WG/) are a solution for data about people or organizations. However, they are aimed at a related-but-distinct problem: asserting attributes about the holder of a DID, including things like work history, age, and membership.\n\nThank you to [Brendan O'Brien](https://github.com/b5) for real-world feedback, technical collaboration, and implementing the first Golang UCAN library.\n\nThank you [Blaine Cook](https://github.com/blaine) for the real-world feedback, ideas on future features, and lessons from other auth standards.\n\nMany thanks to [Hugo Dias](https://github.com/hugomrdias), [Mikael Rogers](https://github.com/mikeal/), and the entire DAG House team for the real world feedback, and finding inventive new use cases.\n\nThank to [Hannah Howard](https://github.com/hannahhoward) and [Alan Shaw](https://github.com/alanshaw) at [Storacha](https://storacha.network/) for their team's feedback from real world use cases.\n\nMany thanks to [Brian Ginsburg](https://github.com/bgins) and [Steven Vandevelde](https://github.com/icidasset) for their many copy edits, feedback from real world usage, maintenance of the TypeScript implementation, and tools such as [ucan.xyz](https://ucan.xyz).\n\nMany thanks to [Christopher Joel](https://github.com/cdata) for his real-world feedback, raising many pragmatic considerations, and the Rust implementation and related crates.\n\nMany thanks to [Christine Lemmer-Webber](https://github.com/cwebber) for her handwritten(!) feedback on the design of UCAN, spearheading the [OCapN](https://github.com/ocapn/ocapn) initiative, and her related work on [ZCAP-LD](https://w3c-ccg.github.io/zcap-spec/).\n\nMany thanks to [Alan Karp](https://github.com/alanhkarp) for sharing his vast experience with capability-based authorization, patterns, and many right words for us to search for.\n\nThanks to [Benjamin Goering](https://github.com/gobengo) for the many community threads and connections to [W3C](https://www.w3.org/) standards.\n\nThanks to [Juan Caballero](https://github.com/bumblefudge) for the numerous questions, clarifications, and general advice on putting together a comprehensible spec.\n\nThank you [Dan Finlay](https://github.com/danfinlay) for being sufficiently passionate about [OCAP](http://erights.org/elib/capability/index.html) that we realized that capability systems had a real chance of adoption in an ACL-dominated world.\n\nThanks to [Peter van Hardenberg](https://www.pvh.ca) and [Martin Kleppmann](https://martin.kleppmann.com/) of [Ink & Switch](https://www.inkandswitch.com/) for conversations exploring options for access control on CRDTs and [local-first](https://www.inkandswitch.com/local-first/) applications.\n\nThanks to the entire [SPKI WG](https://datatracker.ietf.org/wg/spki/about/) for their closely related pioneering work.\n\nWe want to especially recognize [Mark Miller](https://github.com/erights) for his numerous contributions to the field of distributed auth, programming languages, and networked security writ large.\n\n## Footnotes\n\n-\nTo be precise, this is a\n\n[PC/EC](https://en.wikipedia.org/wiki/PACELC_theorem)system, which is a critical trade-off for many systems. UCAN can be used to model both PC/EC and PA/EL, but is most typically PC/EL.[↩](#user-content-fnref-pcec-c0fb6dbd18be1629eac0aa5ae2ef9a08) -\nJavaScript has a single numeric type ([\n\n`Number`\n\n][JS Number]) for both integers and floats. This representation is defined as a[IEEE-754](https://ieeexplore.ieee.org/document/8766229)double-precision floating point number, which has a 53-bit significand.[↩](#user-content-fnref-js-num-size-c0fb6dbd18be1629eac0aa5ae2ef9a08)[↩](#user-content-fnref-js-num-size-2-c0fb6dbd18be1629eac0aa5ae2ef9a08)2[↩](#user-content-fnref-js-num-size-3-c0fb6dbd18be1629eac0aa5ae2ef9a08)3", "url": "https://wpnews.pro/news/user-controlled-authorization-network-ucan-specification", "canonical_source": "https://github.com/ucan-wg/spec", "published_at": "2026-08-05 05:51:30+00:00", "updated_at": "2026-08-05 06:23:28.866516+00:00", "lang": "en", "topics": ["ai-policy"], "entities": ["Protocol Labs", "Bluesky", "number zero", "Witchcraft Software", "Irakli Gozalishvili", "Daniel Holmgren", "Philipp Krüger", "Brooklyn Zelenka"], "alternates": {"html": "https://wpnews.pro/news/user-controlled-authorization-network-ucan-specification", "markdown": "https://wpnews.pro/news/user-controlled-authorization-network-ucan-specification.md", "text": "https://wpnews.pro/news/user-controlled-authorization-network-ucan-specification.txt", "jsonld": "https://wpnews.pro/news/user-controlled-authorization-network-ucan-specification.jsonld"}}