From 4f08972c73ed6d123dfea3653178b4e0f5ccc0f5 Mon Sep 17 00:00:00 2001 From: Irakli Gozalishvili Date: Mon, 22 Jan 2024 13:07:59 -0800 Subject: [PATCH] feat: account revamp (#103) Based on #102 --------- Co-authored-by: Alan Shaw Co-authored-by: Benjamin Goering <171782+gobengo@users.noreply.github.com> --- .github/workflows/words-to-ignore.txt | 5 +- w3-account.md | 141 ++++++++++++++++++-------- w3-ucan.md | 3 +- 3 files changed, 101 insertions(+), 48 deletions(-) diff --git a/.github/workflows/words-to-ignore.txt b/.github/workflows/words-to-ignore.txt index 36cbbe8..98e8ff9 100644 --- a/.github/workflows/words-to-ignore.txt +++ b/.github/workflows/words-to-ignore.txt @@ -147,4 +147,7 @@ publicness NameDescriptionPrincipalThe fieldIssuerPrincipal fieldAudiencePrincipal -verifier \ No newline at end of file +verifier +fieldAccountPrincipal +installationIssuerPrincipal +iteratively \ No newline at end of file diff --git a/w3-account.md b/w3-account.md index 745fbd5..4fc3df5 100644 --- a/w3-account.md +++ b/w3-account.md @@ -1,4 +1,4 @@ -# Account +# W3 Account ![status:wip](https://img.shields.io/badge/status-wip-orange.svg?style=flat-square) @@ -12,7 +12,9 @@ # Abstract -The w3 family of open protocols defines user interactions with self-certified [PKI] based namespaces. These namespaces can be accessed through delegated [UCAN] capabilities that must be synchronized across multiple user agents on multiple devices. Since this is an open and decentralized system, there are unique challenges in providing a user-friendly experience, which is addressed through the concept of an **account** as described in this specification. +The W3 protocol governs user interactions within self-certified Public Key Infrastructure (PKI)-based namespaces. Access control to these namespaces, for simplicity referred to as spaces, is managed through delegated capabilities in [UCAN] format. + +Users access their spaces across various user agents operating on multiple devices. Here we introduce an [account] primitive designed to enable synchronization of access across authorized user agents with a user-friendly experience. ## Language @@ -20,20 +22,29 @@ The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "S # Introduction -In w3 family of protocols, a namespace is identified by a [`did:key`] identifier, which means that the owner of that namespace _(private key holder)_ has absolute authority over it. They can delegate some or all of the capabilities for the resources under that namespace to any other [principal]. However, managing these delegations across multiple user agents on multiple devices presents several user experience challenges: +In the W3 protocol, a namespace, or space for short, corresponds to an asymmetric keypair and is identified by a [`did:key`] URI. The private key holder, is the [owner] of that namespace and has absolute authority over it. They can delegate limited or absolute authority over the namespace to any other [principal]. However, managing delegations across multiple user agents on multiple devices presents several user experience challenges: + +1. To synchronizing namespace access across user agents they need to discover their [`did:key`] identifiers and level of access granted to them. +2. Recovering access in the case when all devices are lost becomes impossible. + +To address these issues, we propose the concept of an account. An account SHOULD have a human-meaningful identifier such as email address. We propose use of email addresses as account identifiers so that derived [`did:mailto`] can act as the [principal] in the [UCAN] delegation chain. This creates [principal] that can be used to aggregate capabilities and manage them. -1. Synchronizing delegations to namespaces across multiple user agents on multiple devices is difficult because of the use of non-memorable [`did:key`] identifiers. -2. Recovering access if the user loses access to all devices is also a challenge. +Account can be used to solve both discovery and recovery problems: -To address these issues, we propose the concept of an account as a way to aggregate and manage capabilities under a human-meaningful identifier such as an email address. +1. Instead of user agents trying to discover each other in order to delegate capabilities, all capabilities get delegated to an account which is then used to re-delegate them as necessary to individual agents. +2. Recovery is possible even if all devices have been lost as long as the user retains control of their email, because an account can always delegate capabilities to new agents. -Specifically, we propose deriving an account identifier from a user-controlled email address in the form of a [`did:mailto`] identifier, which can act as the [principal] in [UCAN] delegation chains. +Agent authorization can use familiar email-based authorization flows providing a smooth onboarding experience and hide complexity of the underlying [PKI]. This approach also better reflects user intuition: they have ambient authority over owned spaces and can authorize user agents (think apps) giving them necessary level of access. -Using an account identifier based on a memorable email address solves the discovery problem, and email-based authorization flows provide a smoother onboarding experience by hiding the complexity of [PKI]. With this approach, users can aggregate all of their delegations under a single account identifier and re-delegate desired capabilities to other agents. +> ℹ️ This specification mainly focuses on [`did:mailto`] identifiers, but implementations are free to extend it to various other [DID methods]. +> +> Also, note that [account] is defined as non [`did:key`] identifier because [`did:key`] identifiers can aggregate and re-delegate capabilities natively with [UCAN]s. [Account]s simply bring human-meaningful identifiers that users can type in on every agent. Use of out of bound authorization also frees users from key management. -> ℹ️ This specification mainly focuses on [`did:mailto`] identifiers, but it can be extended to various other types of identifiers. +## Serialization -# High-Level Concepts +[UCAN]s MUST be encoded with some [IPLD] codec. [DAG-CBOR] is RECOMMENDED. + +## Concepts ## Roles @@ -41,18 +52,39 @@ There are several distinct roles that [principals] may assume in described speci | Name | Description | | ----------- | ---------------------------------------------------------------------------------------------------------------------------------------------- | +| Principal | The general class of entities that interact with a UCAN. Listed in the `iss` or `aud` field | | Account | [Principal] identified by memorable identifier like [`did:mailto`]. | | Agent | [Principal] identified by [`did:key`] identifier, representing a user in some application installation | +| Issuer | Principal sharing access. It is the signer of the [UCAN]. Listed in the `iss` field | +| Audience | Principal access is shared with. Listed in the `aud` field | + +### Space + +Namespace, or space for short, is an owned resource that can be shared. It corresponds to the asymmetric keypair and is identified by the [`did:key`] URI. + +A space DID is always listed in the `with` field of the [UCAN] capability. + +### Owner + +The [owner] of the [space] is the holder of its private key. The space owner can share limited or full access to their owned space via a [UCAN] delegation issued by the [space] [`did:key`] and signed with the [space]'s private key. ### Account -An _account_ is a principal that is identified by a memorable identifier such as [`did:mailto`]. It can be used for the convenience of aggregating and managing capabilities across various user [agent]s. Additionally, an account can facilitate familiar user authorization and recovery flows. +An _account_ is a principal identified by a memorable identifier such as [`did:mailto`]. It is a principal that aggregates access to user spaces and that manages access of various user [agent]s. + +An account enables familiar authorization and recovery email flows. ### Agent -An _agent_ is a [principal] that is identified by a [`did:key`] identifier. Users interact with a system through different _agents_ across multiple devices and applications. It is strongly RECOMMENDED that _agents_ use [non-extractable keys] when possible. +An _agent_ is a principal identified by a [`did:key`] identifier. Users interact with a system through different _agents_ across multiple devices and applications. _Agents_ SHOULD use [non-extractable keys] where possible. + +> ℹ️ Note that _agents_ are meant to be ephemeral, implying that they could be disposed of or created on demand. -> ℹ️ Note that _agents_ are meant to be ephemeral, which means that they could be disposed of or created on demand. +### Authority + +Authority is a trusted [DID] identifier. For example various subsystems may recognize signatures from a global service authority. + +Various services run by different entities MAY also recognize each others authority and choose to trust their signatures as opposed to performing verification work. # Protocol @@ -60,13 +92,13 @@ An _agent_ is a [principal] that is identified by a [`did:key`] identifier. User ### Aggregating capabilities -Any [agent] identified by a [`did:key`] CAN delegate or re-delegate capabilities to an [account] identified by a [`did:mailto`] according to the [UCAN] specification. This CAN be used to delegate complete authority over a created namespace at the time of creation. +Any principal CAN delegate capabilities to an [account] identified by a [`did:mailto`] according to the [UCAN] specification. It is RECOMMENDED to delegate full authority over created namespace to the user [account] at creation to offer access recovery mechanism. ```mermaid sequenceDiagram actor Alice participant App as 💻

w3up #32; -participant Space as 📦

did:key:z6Mkk…sxALi +participant Space as 📦

did:key:z7Gf…xSpace participant Email as 📫 alice@web.mail @@ -76,12 +108,14 @@ Alice -->> App: alice@web.mail App->>Space:🔑 Create namespace Space ->> Email: 🎫 Delegate capabilities -note over Space,Email:can:*
with: ucan:* +note over Space,Email:can:*
with: did:key:z7Gf…xSpace ``` -> During the first run, a new namespace is generated and complete authority is delegated to the user account. Illustration leaves out steps in which application attempts to claim capabilities before deciding to create a new space. +> On first run, an application creates a new namespace and delegates full authority to the user account. For simplicity we omit steps where the application first requests access from an account before deciding to create a new space. + +### Delegating capabilities -Any user CAN delegate or re-delegate capabilities to their peer by delegating to their [account] identified by a [`did:mailto`] _(which can be derived from their email address)_. It's worth noting that no setup is required from the delegate until they decide to invoke the delegated capability. +[Account] CAN authorize user agents by re-delegating a set of capabilities. ```mermaid sequenceDiagram @@ -89,55 +123,63 @@ participant Alice as 👩‍💻

did:key:z6Mkk…sxALi participant Email as 📫 bob@gmail.com participant Bob as 👨🏽‍💻

did:key:z6Mkr…jnz2z - Alice ->> Email: 🎫 Delegate capabilities -note over Alice,Bob:
with: space://z6Mkr…jnz2z
can:store/add +note over Alice,Bob:
with: did:key:z6Mkk…sxALi
can:store/add Email ->> Bob: 🎫 Delegate capabilities ``` -> **Alice** delegates the `store/add` capability to **Bob**, who later creates an agent and re-delegates the capability to it. +> **Alice** delegates the `store/add` capability to **Bob**s [account]. Later **Bob**s user agent gets re-delegated the capability from the [account]. -### Delegating capabilities +### Authorization -Delegating capabilities from an [account] identified by a [`did:mailto`] to an [agent] is less straightforward because the signing key is not self-evident from the delegation. +Delegations issued by a [`did:key`] principal are authorized by signing the payload with their private key. Delegations issued by a [`did:mailto`] principal are not authorized by signing over the payload as there is no private key associated with [`did:mailto`] to sign it with. Instead, such delegations are authorized through an interactive email flow in which the [account] holder is able to review and approve the requested authorization through an action. -To address this issue, we propose an extension to the [UCAN] specification that allows signing and verification of delegations issued by [`did:mailto`] without requiring a [`did:mailto`] key resolution. +Since there is no private key to sign the [UCAN] payload, we define an extension to the [UCAN] specification that introduces two new signature types that can be used in delegations issued by [`did:mailto`] principals. -We define two alternative signature types that have different trade-offs, and protocol implementers MAY choose to support either or both signature types. +We also define a verification mechanism for these signature types. -> ℹ️ The signatures for [account]s identified by other DID methods are not defined. +> ℹ️ The signatures for [account]s identified by other [DID methods] are not defined. -#### DomainKeys Identified Mail (DKIM) Signature +## Signature Types -An [account] identified with the [`did:mailto`] identifier MAY issue a delegation that is signed using a DomainKeys Identified Mail ([DKIM]) signature. +### DomainKeys Identified Mail (DKIM) Signature -The signature MUST be generated by sending a message from the email address of the [account] with a `Subject` header set to an [authorization payload]. +> ⚠️ [w3up] implementation currently does not support this signature type. -The signer MUST derive the "DKIM payload" from the received message according to the [RFC6376] specification and encode it in UTF-8 encoding. The resulting bytes MUST be encoded as a [Nonstandard `VarSig` signature] with the `alg` parameter set to `"DKIM"`. +The [`did:mailto`] principal MAY issue a delegation signed using a DomainKeys Identified Mail ([DKIM]) signature. -##### Authorization Payload +This signature MUST be generated by sending a message from the [account] email address corresponding to the issuer [`did:mailto`] with the `Subject` header set to the [authorization payload]. -> ℹ️ Note that the UCAN standard signing payload would results in large signatures. Therefore, we propose an alternative payload format. +The signer MUST derive the "DKIM payload" from the received message according to the [RFC6376] specification and encode it in UTF-8 encoding. Resulting bytes MUST be encoded as a [Nonstandard `VarSig` signature] with the `alg` parameter set to `"DKIM"`. -The UCAN data model MUST follow the structure specified in the [UCAN-IPLD Schema], but the `s` field should be omitted. The IPLD [link] of the data model must be derived and formatted according to the [ABNF] definition below, where `cid` refers to the derived link: +#### Authorization Payload + +The [UCAN] data model for the desired delegation issued by [`did:mailto`] MUST be structured per [UCAN-IPLD Schema] specification, except for the `s` field, which MUST be omitted. + +The IPLD [link] of constructed data model MUST be derived and used the `cid` when formatting according payload according to the following [ABNF] definition. ```abnf auth := "I am signing ipfs://" cid "to grant access to this account" cid := z[a-km-zA-HJ-NP-Z1-9]+ ``` -#### Authorization Session Signature +### Attestation Signature + +Delegation MAY be authorized through an interactive email flow where the [account] holder is emailed a request to approve an authorization that gives an agent access to specific set of capabilities. If the user approves by clicking the embedded link, a signed [attestation] is issued that confirms that the delegation has been authorized through the interactive flow. + +In this scenario a delegation issued by the [`did:mailto`] identifier MAY be signed using the _attestation signature_ type. This signature alone MUST NOT be considered as a valid authorization. A delegation signed with an _attestation signature_ MUST be accompanied with a [UCAN attestation] issued by the trusted [authority]. + +If delegation is signed with an _attestation signature_, but is not accompanied with a [UCAN attestation] from a trusted [authority] it MUST be considered invalid. In this scenario the implementer MAY initiate an interactive verification flow and issue the [UCAN attestation] retroactively instead of denying service. -Delegation issued by [account] identified with the [`did:mailto`] identifier MAY be -signed using _authorization session signature_. However, this signature alone does not verify that the [account] owner authorized the delegation. For this reason, the delegation MUST also have an accompanying [authorization session] issued by a trusted [authority] that confirms the authorization by the [account] owner. In situations where the [authorization session] is not present in the proof, the validator is required to obtain it through an out-of-band authorization flow upon request. Failure to carry out this authorization flow will result in the signature being considered invalid. +> When the received delegation is issued by the `did:mailto:web.mail:alice`, signed with _attestation signature_, but is not accompanied by a [UCAN attestation], the receiver could iteratively confirm authorization by sending an email to `alice@web.mail` with a confirmation link, which, when followed, issues an [attestation] from the receiver resuming the invocation. -##### Authorization Session Signature Format +#### Attestation Signature Format -The authorization session signature is denoted by a [Nonstandard `VarSig` signature] with zero (`0`) signature bytes. +The attestation signature is denoted by a [Nonstandard `VarSig` signature] with zero (`0`) signature bytes. -##### Authorization Session Signature Example +##### Attestation Signature Example -> Authorization Session Signature in [DAG-JSON] format +> Attestation Signature in [DAG-JSON] format ```jSON { "/": { "bytes": "gKADAA" } } @@ -180,10 +222,10 @@ Examples [Protocol Labs]:https://protocol.ai/ [Irakli Gozalishvili]:https://github.com/Gozala [PKI]:https://en.wikipedia.org/wiki/Public_key_infrastructure -[ucan]: https://github.com/ucan-wg/spec/ -[`did:mailto`]: https://github.com/ucan-wg/did-mailto/ -[`did:key`]: https://w3c-ccg.github.io/did-method-key/ -[principal]:https://github.com/ucan-wg/spec/#321-principals +[UCAN]:https://github.com/ucan-wg/spec/blob/692e8aab59b763a783fe1484131c3f40d997b69a/README.md +[`did:mailto`]:./did-mailto.md +[`did:key`]:https://w3c-ccg.github.io/did-method-key/ +[principal]:https://github.com/ucan-wg/spec/blob/692e8aab59b763a783fe1484131c3f40d997b69a/README.md#321-principals [non-extractable keys]:https://crypto.stackexchange.com/questions/85587/what-do-people-use-non-extractable-webcrypto-keys-for/102695#102695 [agent]:#agent [account]:#account @@ -194,4 +236,13 @@ Examples [Nonstandard `VarSig` signature]:https://github.com/ucan-wg/ucan-ipld/#251-nonstandard-signatures [ABNF]:https://en.wikipedia.org/wiki/Augmented_Backus%E2%80%93Naur_form [DAG-JSON]:https://ipld.io/specs/codecs/dag-json/spec/ -[authorization session]:./w3-session.md +[ucan attestation]:./w3-ucan.md#attestation +[IPLD]: https://ipld.io/ +[DAG-CBOR]: https://ipld.io/specs/codecs/dag-cbor/spec/ +[DID methods]:https://www.w3.org/TR/did-core/#methods +[w3up]:https://github.com/web3-storage/w3up +[owner]:#owner +[space]:#space +[DKIM]:https://en.wikipedia.org/wiki/DomainKeys_Identified_Mail +[attestation]:./w3-ucan.md#attestation +[authority]:#authority diff --git a/w3-ucan.md b/w3-ucan.md index 444b3fa..2c8bd63 100644 --- a/w3-ucan.md +++ b/w3-ucan.md @@ -149,8 +149,7 @@ In other words it is desired to have ability to grant revocation power to some a ### Proposal -We propose extension to the core [UCAN] specification and define `ucan/revoke` -capability, that can be invoked to revoke a linked [UCAN]. +We propose extension to the core [UCAN] specification and define `ucan/revoke` capability, that can be invoked to revoke a linked [UCAN]. By making revocation a [UCAN] itself we allow delegating the ability to revoke to another principal, which is desired in scenario described above.