From 1c632b202795798d946eebcc957d11f87c534480 Mon Sep 17 00:00:00 2001 From: Irakli Gozalishvili Date: Fri, 19 Jan 2024 10:23:04 -0800 Subject: [PATCH 01/20] chore: import did:mailto spec --- did-mailto.md | 148 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 148 insertions(+) create mode 100644 did-mailto.md diff --git a/did-mailto.md b/did-mailto.md new file mode 100644 index 0000000..19649e5 --- /dev/null +++ b/did-mailto.md @@ -0,0 +1,148 @@ +# did-mailto + +## Editors + +- [Irakli Gozalishvili](https://github.com/Gozala), [DAG House](https://dag.house/) + +## Authors + +- [Irakli Gozalishvili](https://github.com/Gozala), [DAG House](https://dag.house/) + +## Language + +The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in [RFC 2119](https://datatracker.ietf.org/doc/html/rfc2119). + +## Abstract + +This specification describes "mailto" [DID Method] that +conforms to the core [DID-CORE] specification. The method can be used independent of any central source of truth, and is intended for bootstrapping secure interaction between two parties that can span across arbitrary number of devices. It is suitable for long sessions that need to operating under network partitions. + +## Status of This Document + +This document is draft of a potential specification. It has no official standing of any kind and does not represent the support or consensus of any standards organization. + +## Introduction + +### Overview + +> This section is non-normative. + +Most documentation about decentralized identifiers (DIDs) describes them as identifiers that are rooted in a public source of truth like a blockchain, a database, or similar. This publicness lets arbitrary parties resolve the DIDs to an endpoint and keys. It is an important feature for many use cases. + +However, the vast majority of interactions between people, organizations, and things have simpler requirements. When Alice(Corp|Device) and Bob want to interact, there are exactly and only 2 parties in the world who should care: Alice and Bob. Instead of arbitrary parties needing to resolve their DIDs, only Alice and Bob do. + +One to one interactions are excellent fit for [did:key] identifiers, however they suffer from key discovery problem and introduce additional challenges when interaction sessions span across more than two devices. + +Mailto DIDs are designed to be used in conjunction with [did:key] and facilitate bootstrapping sessions between two parties that span across multiple devices. + +Mailto DIDs are more accessible alternative to [did:web] and [did:dns] because a lot more people have an email address than there are people with [did:web] or [did:dns] identifier or skills to acquire one. + +Mailto [did document]s are also verifiable offline, when [domain key][] of the email address is known, implying significantly less network requests than with most other DIDs. + +## The `did:mailto` Format + +The format for the `did:key` method conforms to the [DID-CORE] specification and is encoding of the [email address]. It consists of the `did:mailto:` prefix, followed by the `domain` part of an email address, `:` character and percent encoded `local-part` of the email address. + +The ABNF definition can be found below. The formal rules describing valid `domain-name` syntax are described in [RFC1035], [RFC1123], [RFC2181]. The `domain-name` and `user-name` corresponds to `domain` and `local-part` respectively of the email address described in [RFC2822]. All "mailto" DIDs MUST conform to the DID Syntax ABNF Rules. + +```abnf +did = "did:mailto:" domain-name ":" user-name +user-name = 1*idchar +idchar = ALPHA / DIGIT / "." / "-" / "_" / pct_enc +pct_enc = "%" HEXDIG HEXDIG +``` + +##### EXAMPLE 1. A + +``` +did:mailto:example.com:jsmith +``` + +##### EXAMPLE 2 + +``` +did:mailto:web.mail:tag%2Balice +``` + +## Operations + +The following section outlines the DID operations for the `did:mailto` method. + +### Create (Register) + +There is intentionally no specification for publishing `did:mailto` documents as single source of truth are not implied. Same `did:mailto` identifier MAY (intentionally) correspond to different [DID document] in different sessions. + +Creating a `did:mailto` document is done by: + +1. Creating a [did:key] identifier. +2. Sending an email from [DID Subject] email address with a [key authentication] message in the subject. + +#### Key Authentication + +Key authentication message must conform to the following ABNF definition, which refers to `did-key-format` defined in [did:key] specification + +```abnf +auth = "I am also known as " did-key-format +``` + +##### EXAMPLE 3 + +``` +I am also known as did:key:z6MkhaXgBZDvotDkL5257faiztiGiC2QtKLGpbnnEGta2doK +``` + +### Read (Resolve) + +Specification intentionally does not specify how to resolve [DKIM-Signature] for the given `did:mailto` identifier as those could be arranged out of bound between participants. Optional programmatic resolution over [SMTP] could be defined in the future iterations. + +The following steps MUST be executed to resolve the [DID document] from the [DKIM-Signature]: + +1. Extract [key authentication] from the `subject` header. +1. Extract [did:key] from the extracted [key authentication]. +1. Extract sender email address from the `from` header. +1. Resolve [DID document] from extracted [did:key]. +1. Set `id` of the [DID document] to the `did:mailto` identifier of the sender email address. +1. Set `alsoKnownAs` of the document to extracted [did:key]. + +### Deactivate (Revoke) + +Specification intentionally does not specify how to communicate [DKIM-Signature] for deactivating the DID Document. + +[DID Subject] may deactivate specific [DID document] by: + +1. Sending an email from [DID Subject] email address with with a [key revocation] message in the subject. + +#### Key Revocation + +Key revocation message must conform to the following ABNF definition, which refers to `did-key-format` defined in [did:key] specification + +```abnf +auth = "I revoke " did-key-format +``` + +##### EXAMPLE 3 + +``` +I revoke did:key:z6MkhaXgBZDvotDkL5257faiztiGiC2QtKLGpbnnEGta2doK +``` + +### Update + +This DID Method does not support updating the DID Document. + +[did subject]: https://www.w3.org/TR/did-core/#did-subject +[did method]: https://w3c-ccg.github.io/did-spec/#specific-did-method-schemes +[did-core]: https://w3c-ccg.github.io/did-spec/ +[did document]: https://www.w3.org/TR/did-core/#dfn-did-documents +[did:key]: https://w3c-ccg.github.io/did-method-key/ +[did:web]: https://w3c-ccg.github.io/did-method-web/ +[did:dns]: https://danubetech.github.io/did-method-dns/ +[email address]: https://www.rfc-editor.org/rfc/rfc2822.html#section-3.4.1 +[rfc2822]: https://www.rfc-editor.org/rfc/rfc2822.html#section-3.4.1 +[rfc1035]: https://www.rfc-editor.org/rfc/rfc1035 +[rfc1123]: https://www.rfc-editor.org/rfc/rfc1123 +[rfc2181]: https://www.rfc-editor.org/rfc/rfc2181 +[key authentication]: #Key_Authentication +[key revocation]: #Key_Revocation +[dkim-signature]: https://en.wikipedia.org/wiki/DomainKeys_Identified_Mail +[smtp]: https://en.wikipedia.org/wiki/Simple_Mail_Transfer_Protocol From 606af9c3c035f4dc291f6b7f2069c48bf2eda91b Mon Sep 17 00:00:00 2001 From: Irakli Gozalishvili Date: Fri, 19 Jan 2024 10:26:59 -0800 Subject: [PATCH 02/20] fix: ignore some words --- .github/workflows/words-to-ignore.txt | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/.github/workflows/words-to-ignore.txt b/.github/workflows/words-to-ignore.txt index 3c54472..8625fc7 100644 --- a/.github/workflows/words-to-ignore.txt +++ b/.github/workflows/words-to-ignore.txt @@ -134,3 +134,12 @@ Irakli Gozalishvili Vasco invoker +DIDs +dns +DNS +RFC1035 +RFC1123 +RFC2181 +RFC2822 +SMTP +publicness From 025e280b45a032727b71514234d6c362961f1356 Mon Sep 17 00:00:00 2001 From: Irakli Gozalishvili Date: Fri, 19 Jan 2024 17:49:11 -0800 Subject: [PATCH 03/20] fix: markdown --- did-mailto.md | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/did-mailto.md b/did-mailto.md index 19649e5..4fbdd32 100644 --- a/did-mailto.md +++ b/did-mailto.md @@ -37,7 +37,7 @@ Mailto DIDs are designed to be used in conjunction with [did:key] and facilitate Mailto DIDs are more accessible alternative to [did:web] and [did:dns] because a lot more people have an email address than there are people with [did:web] or [did:dns] identifier or skills to acquire one. -Mailto [did document]s are also verifiable offline, when [domain key][] of the email address is known, implying significantly less network requests than with most other DIDs. +Mailto [did document]s are also verifiable offline, when [domain key] of the email address is known, implying significantly less network requests than with most other DIDs. ## The `did:mailto` Format @@ -52,15 +52,15 @@ idchar = ALPHA / DIGIT / "." / "-" / "_" / pct_enc pct_enc = "%" HEXDIG HEXDIG ``` -##### EXAMPLE 1. A +### EXAMPLE 1. -``` +```txt did:mailto:example.com:jsmith ``` -##### EXAMPLE 2 +### EXAMPLE 2. -``` +```txt did:mailto:web.mail:tag%2Balice ``` @@ -87,7 +87,7 @@ auth = "I am also known as " did-key-format ##### EXAMPLE 3 -``` +```txt I am also known as did:key:z6MkhaXgBZDvotDkL5257faiztiGiC2QtKLGpbnnEGta2doK ``` @@ -110,7 +110,7 @@ Specification intentionally does not specify how to communicate [DKIM-Signature] [DID Subject] may deactivate specific [DID document] by: -1. Sending an email from [DID Subject] email address with with a [key revocation] message in the subject. +1. Sending an email from [DID Subject] email address with a [key revocation] message in the subject. #### Key Revocation @@ -122,7 +122,7 @@ auth = "I revoke " did-key-format ##### EXAMPLE 3 -``` +```txt I revoke did:key:z6MkhaXgBZDvotDkL5257faiztiGiC2QtKLGpbnnEGta2doK ``` @@ -142,7 +142,8 @@ This DID Method does not support updating the DID Document. [rfc1035]: https://www.rfc-editor.org/rfc/rfc1035 [rfc1123]: https://www.rfc-editor.org/rfc/rfc1123 [rfc2181]: https://www.rfc-editor.org/rfc/rfc2181 -[key authentication]: #Key_Authentication -[key revocation]: #Key_Revocation +[Key Authentication]: #key-authentication +[Key Revocation]: #key-revocation [dkim-signature]: https://en.wikipedia.org/wiki/DomainKeys_Identified_Mail [smtp]: https://en.wikipedia.org/wiki/Simple_Mail_Transfer_Protocol +[domain key]:https://en.wikipedia.org/wiki/DomainKeys_Identified_Mail From 215917ec49d3cfe6f6a5a81c97872eb8c99da6d8 Mon Sep 17 00:00:00 2001 From: Irakli Gozalishvili Date: Fri, 19 Jan 2024 17:53:39 -0800 Subject: [PATCH 04/20] feat: document UCAN spec extensions --- w3-ucan.md | 210 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 210 insertions(+) create mode 100644 w3-ucan.md diff --git a/w3-ucan.md b/w3-ucan.md new file mode 100644 index 0000000..5964b4d --- /dev/null +++ b/w3-ucan.md @@ -0,0 +1,210 @@ +# UCAN Specification Extensions + +![stable](https://img.shields.io/badge/status-stable-brightgreen.svg?style=flat-square) + +## Editors + +- [Irakli Gozalishvili], [Protocol Labs] + +## Authors + +- [Irakli Gozalishvili], [Protocol Labs] + +## Language + +The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in [RFC2119](https://datatracker.ietf.org/doc/html/rfc2119). + +## Abstract + +[UCAN] specification reserves `ucan/` ability namespace for the core functionality that may be introduced in future versions. Here we define W3 protocol extensions to the core namespace that we hope to standardize in core [UCAN] specification. + +# Terminology + +## Roles + +There are several roles that agents in the authorization flow may assume: + +| Name | Description | +| ----------- | ----------- | +| Principal | The general class of entities that interact with a UCAN. Listed in the `iss` or `aud` field | +| 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 | + +### Authority + +Authority is trusted [DID] identifier. For example various subsystems may recognize and 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. + +### Verifier + +Subsystem that performs [UCAN] validation. + +# Capabilities + +## Attestation + +### Motivation + +[UCAN] verification process involves going through a delegation chain and verifying that every delegation has a valid signature from the private key if the issuer and that principals in the chain align. As described it has following implications: + +1. Verifier MAY end up verifying same potentially long chain over and over. As an optimization they could implement caching strategy, but that may require access to some storage. +1. Invocations MAY have to send potentially long delegation chains over and over as validator MAY prune cache and may not even persist previously seen delegations. +1. Verifying delegations issued by principals other than [`did:key`] involves some, potentially expensive, [DID] document resolution. Mutable nature of [DID] document also imply that previously valid delegation chain could be rendered invalid. + +### Proposal + +We propose extension to the core [UCAN] specification and define `ucan/attest` +capability, that enables an [authority] to attest that linked [UCAN] delegation is valid. + +This effectively allows distributing verifiable cache records to interested principals so they could include those in subsequent invocations and take advantage of optimizations they unlock. + +#### Cached Verifications + +For example verifier could issue an attestation for the [UCAN] chain it validated and hand it back to the caller. In subsequent calls caller could include an attestation to take advantage of more optimal execution. + +#### Proof chain compaction + +Just like in the above scenario except not only caller can take advantage of more optimal execution they could also transfer proof chain up to a proof they have attestation for reducing size of the payload. + +#### Out of bound verification + +Attestations CAN be issued as a part of authorization process. For example [UCAN]s issued by [`did:mailto`] require out of bound authorization flow in which service sends confirmation email to the user. If user confirms through a link in the email service issues an attestation declaring that [UCAN] has been verified. + +### Notes on compatibility + +Attestations effectively are a cache records that if provided enables certain optimizations, when not provided, correct implementation SHOULD fallback to a less optimal path. + +Implementations that do not support this extension will simply disregard attestations in the proof chain as irrelevant and just under less optimal path. + +### IPLD Schema + +```ipldsch +type UCAN union { + | Attest "ucan/attest" +} representation inline { + discriminantKey "can" +} + +type Attest struct { + with Authority + nb Attestation +} + +type Attestation struct { + proof &UCAN +} +``` + +### Attestation Authority + +The value of the `with` field MUST be the DID of the [authority], indicating that ONLY [authority] authorized principals are able to issue attestations on behalf of the [authority]. + +### Attestation Subject + +The `nb.proof` field MUST be a [link] to the [UCAN] delegation covered by the attestation. + +### Attestation Lifetime + +Attestation MUST be considered valid ONLY within the [time bounds] of enclosing [UCAN]. In other words enclosing [UCAN] `nbf` and `exp` fields SHOULD be used to specify [time bounds] within which attestation is valid. + +### Attestation Revocation + +Attestation MUST be considered revoked if enclosing [UCAN] has been revoked. This also implies that attestation can be revoked by revoking their enclosing [UCAN]s. + +### Attestation Example in DAG-JSON + +```json +{ + "v": "0.9.1", + "iss": "did:web:web3.storage", + "aud": "did:key:z6Mkk89bC3JrVqKie71YEcc5M1SMVxuCgNx6zLZ8SYJsxALi", + "att": [ + { + "with": "did:web:web3.storage", + "can": "ucan/attest", + "nb": { + "proof": { + "/": "bafyreifer23oxeyamllbmrfkkyvcqpujevuediffrpvrxmgn736f4fffui" + } + }, + } + ], + "exp": null, + "s": { + "/": { + "bytes": "7aEDQBj34uAed7Mup+aVCTKuUtcKWwJtzMZ5yPA6tptMrcRrbE3o7uHKG/wBqF+OKJYGY7epQOV+OUuzseZvXuJN2QI" + } + } +} +``` + +## Revocation + +### Motivation + +[UCAN] specification defines [revocation record] that MUST be signed by the issuer in the delegation chain of the [UCAN] been revoked. From real world experience we find that requirement unfortunate. In plenty of cases various actors are delegated specific subset of capabilities from the supervisor to carry out their work. Supervisor MAY want give specific actor to revoke some capabilities on its behalf without giving it ability to invoke them and [revocation record] does not allow that. + +### Proposal + +We propose extension to the core [UCAN] specification and define `ucan/revoke` +capability, that can be invoked to revoke linked [UCAN]. + +By making revocation a [UCAN] itself we gain ability to delegate ability to revoke to another principal, which is desired in scenario described above. + +### IPLD Schema + +```ipldsch +type UCAN union { + | Revoke "ucan/revoke" +} representation inline { + discriminantKey "can" +} + +type Revoke struct { + with Authority + nb Revocation +} + +type Revocation struct { + ucan &UCAN + proof &UCAN[] +} +``` + +### Revocation Authority + +The value of the `with` field MUST be the [DID] of the principal that issued the [UCAN] been revoked or some [UCAN] in its proof chain. + +Revocation where [DID] in the `with` field is not an issuer of the [UCAN] or the proofs it depends on SHOULD be considered obsolete. + +Implementations MAY choose to consider revocations from certain [authority] even if they are not part of the proof chain. For example service could proactively revoke [UCAN] chain when actual issuer keys are is compromised. + +### Revocation Subject + +The `nb.ucan` field MUST be a [link] to the [UCAN] been revoked. + +### Revocation Proof + +It is RECOMMENDED to set `nb.proof` field to a list of [UCAN] [link]s illustrating the path from [UCAN] been revoked to the [UCAN] issued by the [authority] (`with` field). + +Implementations MAY choose to require a valid `nb.proof` to avoid storing potentially invalid revocations. + +### Revocation Lifetime + +It is RECOMMENDED to treat revocations permanent. Even though enclosing [UCAN] will have [time bounds] those MUST NOT be interpreted as a time frame within which revocation is active. + +Enclosing [UCAN] [time-bounds] MUST be interpreted as time frame within which authorized issuer is able to exercise revocation on behalf of the [authority]. More simply it is a mechanism to limit issuers ability to perform revocation on behalf of the [authority]. + +### Revocation Revocation + +It is RECOMMENDED to treat revocations permanent. Even though enclosing [UCAN] could be revoked it MUST NOT be interpreted as revocation of the revocation. + +Enclosing [UCAN] revocation offers a mechanism to revoke authorization that [authority] MAY have given to another principal to revoke [UCAN]s on their behalf. + +[UCAN]:https://github.com/ucan-wg/spec/blob/692e8aab59b763a783fe1484131c3f40d997b69a/README.md +[DID]:https://www.w3.org/TR/did-core/ +[link]:https://ipld.io/docs/schemas/features/links/ +[time bounds]: https://github.com/ucan-wg/spec/#322-time-bounds +[`did:mailto`]: ./did-mailto.md +[revocation record]:https://github.com/ucan-wg/spec/blob/692e8aab59b763a783fe1484131c3f40d997b69a/README.md#66-revocation From 07c38413eea33eb924beb463a2264278f202d14b Mon Sep 17 00:00:00 2001 From: Irakli Gozalishvili Date: Fri, 19 Jan 2024 23:23:03 -0800 Subject: [PATCH 05/20] fix: spelling issues --- w3-ucan.md | 1 + 1 file changed, 1 insertion(+) diff --git a/w3-ucan.md b/w3-ucan.md index 5964b4d..d1d72f3 100644 --- a/w3-ucan.md +++ b/w3-ucan.md @@ -208,3 +208,4 @@ Enclosing [UCAN] revocation offers a mechanism to revoke authorization that [aut [time bounds]: https://github.com/ucan-wg/spec/#322-time-bounds [`did:mailto`]: ./did-mailto.md [revocation record]:https://github.com/ucan-wg/spec/blob/692e8aab59b763a783fe1484131c3f40d997b69a/README.md#66-revocation +[authority]:#authority From 67f947ea1cac260ebb70f121abe1fdaa1a017895 Mon Sep 17 00:00:00 2001 From: Irakli Gozalishvili Date: Fri, 19 Jan 2024 23:30:59 -0800 Subject: [PATCH 06/20] chore: add ignored words --- .github/workflows/words-to-ignore.txt | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/workflows/words-to-ignore.txt b/.github/workflows/words-to-ignore.txt index 9ac8e2a..333ff1d 100644 --- a/.github/workflows/words-to-ignore.txt +++ b/.github/workflows/words-to-ignore.txt @@ -144,3 +144,6 @@ RFC2181 RFC2822 SMTP publicness +NameDescriptionPrincipalThe +fieldIssuerPrincipal +fieldAudiencePrincipal From 81da626cdbc7100544803f606ac1e3780d63479e Mon Sep 17 00:00:00 2001 From: Irakli Gozalishvili Date: Fri, 19 Jan 2024 23:32:40 -0800 Subject: [PATCH 07/20] fix: spelling errors --- w3-ucan.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/w3-ucan.md b/w3-ucan.md index d1d72f3..2983466 100644 --- a/w3-ucan.md +++ b/w3-ucan.md @@ -59,7 +59,7 @@ capability, that enables an [authority] to attest that linked [UCAN] delegation This effectively allows distributing verifiable cache records to interested principals so they could include those in subsequent invocations and take advantage of optimizations they unlock. -#### Cached Verifications +#### Cached Verification For example verifier could issue an attestation for the [UCAN] chain it validated and hand it back to the caller. In subsequent calls caller could include an attestation to take advantage of more optimal execution. @@ -209,3 +209,5 @@ Enclosing [UCAN] revocation offers a mechanism to revoke authorization that [aut [`did:mailto`]: ./did-mailto.md [revocation record]:https://github.com/ucan-wg/spec/blob/692e8aab59b763a783fe1484131c3f40d997b69a/README.md#66-revocation [authority]:#authority +[Protocol Labs]:https://protocol.ai/ +[Irakli Gozalishvili]:https://github.com/Gozala From 9c05ba7a5a5f72727bb5e680207c184619f61a06 Mon Sep 17 00:00:00 2001 From: Irakli Gozalishvili Date: Fri, 19 Jan 2024 23:33:56 -0800 Subject: [PATCH 08/20] chore: ignore more words --- .github/workflows/words-to-ignore.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/words-to-ignore.txt b/.github/workflows/words-to-ignore.txt index 333ff1d..f4fb168 100644 --- a/.github/workflows/words-to-ignore.txt +++ b/.github/workflows/words-to-ignore.txt @@ -147,3 +147,4 @@ publicness NameDescriptionPrincipalThe fieldIssuerPrincipal fieldAudiencePrincipal +verifier From 3cf783328e92e3e5ef7f3de394edd53d54c154c1 Mon Sep 17 00:00:00 2001 From: Irakli Gozalishvili Date: Sat, 20 Jan 2024 00:51:12 -0800 Subject: [PATCH 09/20] feat: w3-account revamp --- w3-account.md | 139 ++++++++++++++++++++++++++++++++++---------------- 1 file changed, 95 insertions(+), 44 deletions(-) diff --git a/w3-account.md b/w3-account.md index 745fbd5..8316060 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 [account] primitive designed to enable synchronization of the 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 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 case when all devices are lost becomes impossible. + +To address these issues, we propose the concept of an account. 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 discovering each to delegate capabilities with one another, 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 has been lost as long as the user retains control of their email, because 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. + +Space is always listed in the `with` field of the [UCAN] capability. + +### Owner + +The [owner] of the [space] is the holder of its private key. Space owner can share limited or full access to owned space via [UCAN] delegation issued by the [space] [`did:key`] and signed with a [space] 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. + +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. It is strongly RECOMMENDED that _agents_ 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 trusted [DID] identifier. For example various subsystems may recognize and 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, application creates a new namespace and delegates full authority to the user account. For the simplicity we omit steps where application first requests access from an account before deciding to create 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 [`did:key`] principal are authorized by signing payload with private key. Delegations issued by a [`did:mailto`] principal are not authorized by signing over payload as there is no public key associated with [`did:mailto`] to sign it with. Instead, such delegations are authorized through an interactive email flow in which [account] holder is able to review and approve 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 public key to sign the [UCAN] payload define an extension to the [UCAN] specification introducing 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 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 [account] holder is emailed request to approve an authorization that gives an agent access to specific set of capabilities. If user approves by clicking embedded link signed [attestation] is issued that confirms that delegation has been authorized through an interactive flow. + +In this scenario delegation issued by the [`did:mailto`] identifier MAY be signed using _attestation signature_ type. This signature alone MUST NOT be considered as a valid authorization. Delegation signed with _attestation signature_ MUST be accompanied with [ucan attestation] issued by the trusted [authority]. + +If delegation is signed with _attestation signature_, but is not accompanied with [ucan attestation] from trusted [authority] it MUST be considered invalid. In this scenario implementer MAY initiate interactive verification flow and issue [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 received delegation is issued by the `did:mailto:web.mail:alice`, signed with _attestation signature_, but is not accompanied by [ucan attestation], receiver could iteratively confirm authorization by sending an email to `alice@web.mail` address with a confirmation link, which when followed issues [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/ +[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/#321-principals +[principal]:[UCAN]: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 From 9c0f6734f87e0acc5f50601891b4b3f3f04c1ecf Mon Sep 17 00:00:00 2001 From: Irakli Gozalishvili Date: Sat, 20 Jan 2024 00:57:48 -0800 Subject: [PATCH 10/20] fix: lint errors --- .github/workflows/words-to-ignore.txt | 3 +++ w3-account.md | 4 ++-- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/.github/workflows/words-to-ignore.txt b/.github/workflows/words-to-ignore.txt index f4fb168..24eef7e 100644 --- a/.github/workflows/words-to-ignore.txt +++ b/.github/workflows/words-to-ignore.txt @@ -148,3 +148,6 @@ NameDescriptionPrincipalThe fieldIssuerPrincipal fieldAudiencePrincipal verifier +fieldAccountPrincipal +installationIssuerPrincipal +iteratively diff --git a/w3-account.md b/w3-account.md index 8316060..5eaf08b 100644 --- a/w3-account.md +++ b/w3-account.md @@ -167,9 +167,9 @@ cid := z[a-km-zA-HJ-NP-Z1-9]+ Delegation MAY be authorized through an interactive email flow where [account] holder is emailed request to approve an authorization that gives an agent access to specific set of capabilities. If user approves by clicking embedded link signed [attestation] is issued that confirms that delegation has been authorized through an interactive flow. -In this scenario delegation issued by the [`did:mailto`] identifier MAY be signed using _attestation signature_ type. This signature alone MUST NOT be considered as a valid authorization. Delegation signed with _attestation signature_ MUST be accompanied with [ucan attestation] issued by the trusted [authority]. +In this scenario delegation issued by the [`did:mailto`] identifier MAY be signed using _attestation signature_ type. This signature alone MUST NOT be considered as a valid authorization. Delegation signed with _attestation signature_ MUST be accompanied with [UCAN attestation] issued by the trusted [authority]. -If delegation is signed with _attestation signature_, but is not accompanied with [ucan attestation] from trusted [authority] it MUST be considered invalid. In this scenario implementer MAY initiate interactive verification flow and issue [ucan attestation] retroactively instead of denying service. +If delegation is signed with _attestation signature_, but is not accompanied with [UCAN attestation] from trusted [authority] it MUST be considered invalid. In this scenario implementer MAY initiate interactive verification flow and issue [UCAN attestation] retroactively instead of denying service. > When received delegation is issued by the `did:mailto:web.mail:alice`, signed with _attestation signature_, but is not accompanied by [ucan attestation], receiver could iteratively confirm authorization by sending an email to `alice@web.mail` address with a confirmation link, which when followed issues [attestation] from the receiver resuming the invocation. From b86eb8d604d6afdd8c569a9c2c6dccfad0c87e50 Mon Sep 17 00:00:00 2001 From: Irakli Gozalishvili Date: Sat, 20 Jan 2024 00:59:04 -0800 Subject: [PATCH 11/20] fix: more typos --- w3-account.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/w3-account.md b/w3-account.md index 5eaf08b..765132c 100644 --- a/w3-account.md +++ b/w3-account.md @@ -171,7 +171,7 @@ In this scenario delegation issued by the [`did:mailto`] identifier MAY be signe If delegation is signed with _attestation signature_, but is not accompanied with [UCAN attestation] from trusted [authority] it MUST be considered invalid. In this scenario implementer MAY initiate interactive verification flow and issue [UCAN attestation] retroactively instead of denying service. -> When received delegation is issued by the `did:mailto:web.mail:alice`, signed with _attestation signature_, but is not accompanied by [ucan attestation], receiver could iteratively confirm authorization by sending an email to `alice@web.mail` address with a confirmation link, which when followed issues [attestation] from the receiver resuming the invocation. +> When received delegation is issued by the `did:mailto:web.mail:alice`, signed with _attestation signature_, but is not accompanied by [UCAN attestation], receiver could iteratively confirm authorization by sending an email to `alice@web.mail` address with a confirmation link, which when followed issues [attestation] from the receiver resuming the invocation. #### Attestation Signature Format From 2c3927c673b563c483a4230825a065da277ae195 Mon Sep 17 00:00:00 2001 From: Irakli Gozalishvili Date: Sat, 20 Jan 2024 01:02:01 -0800 Subject: [PATCH 12/20] fix: bad link --- w3-account.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/w3-account.md b/w3-account.md index 765132c..5aa9964 100644 --- a/w3-account.md +++ b/w3-account.md @@ -223,9 +223,9 @@ Examples [Irakli Gozalishvili]:https://github.com/Gozala [PKI]:https://en.wikipedia.org/wiki/Public_key_infrastructure [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]:[UCAN]:https://github.com/ucan-wg/spec/blob/692e8aab59b763a783fe1484131c3f40d997b69a/README.md#321-principals +[`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 From 80cc7384544ced76b0dd2913734156bdc0d6a7cf Mon Sep 17 00:00:00 2001 From: Irakli Gozalishvili Date: Mon, 22 Jan 2024 01:57:21 -0800 Subject: [PATCH 13/20] feat: revamp access protocol --- w3-access.md | 572 ++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 406 insertions(+), 166 deletions(-) diff --git a/w3-access.md b/w3-access.md index dffbf16..5eba501 100644 --- a/w3-access.md +++ b/w3-access.md @@ -1,7 +1,6 @@ -# User Access +# W3 Access Protocol -![status:wip](https://img.shields.io/badge/status-wip-orange.svg?style=flat-square) -[![hackmd-github-sync-badge](https://hackmd.io/8NywALT8Qp-cf0MSugZMDw/badge)](https://hackmd.io/8NywALT8Qp-cf0MSugZMDw) +![stable](https://img.shields.io/badge/status-stable-brightgreen.svg?style=flat-square) ## Editors @@ -13,7 +12,9 @@ # Abstract -In web3.storage we manage access across various user spaces and agents through delegated capabilities. Here we define the protocol for aggregating and managing delegated capabilities across various user agents. +The W3 protocol governs user interactions within self-certified Public Key Infrastructure (PKI)-based namespaces. Access to these namespaces, for simplicity referred to as spaces, is authorized through delegated capabilities in [UCAN] format. + +Here we define the protocol for delivering authorized delegations to their audience. ## Language @@ -21,42 +22,103 @@ The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "S # Introduction -## Motivation +[Space] [access] is represented as a signed authorization in [UCAN] format. It is not enough to issue the [UCAN] authorization, issuer needs some channel to deliver it to an audience. + +We propose a protocol where implementation can act as a delivery channel. + +## Intuition + +### Message Channel + +At the very high level signed authorization is a message addressed to a specific recipient (audience). Implementer of this protocol represent a [message channel] allowing sender (issuer) to send a message and allow recipient (audience) to receive massages sent to them. + +### Shared Space + +Alice has set up space for sharing photos with her family and friends. She wants to authorize her partner Bob with write access so he can also upload photos. She wants to authorize her less tech savvy parent Mallory with just read access so she can look at photos but not add or delete them. + +> In this scenario Alice delegates `upload/add` capability to Bob and `upload/list` capability to Mallory. Application used by Alice leverages access protocol to send issued delegations to Bob and Mallory. Applications used by Bob and Mallory leverage access protocol to receive messages sent to them transparently gaining access to the space Alice has shared access to. + +### Multidevice Access + +Alice has created a new space for storing photos on her laptop and uploaded some photos. Later she picks up her phone logs with her account and upload some photos to her space. -In web3.storage users may create (name)space by generating an asymmetric keypair and deriving [`did:key`] identifier from it. (Name)space owner (private key owner) can delegate some or all capabilities to other identifiers without anyone's permission, however managing keypairs across multiple agents and devices can be complicated. +> In this scenario after space is created access protocol is used to delegate full authority over to Alice's [account]. Later, when Alice logs in on her phone her [account] receives delegated capabilities over access protocol gaining access to the space. -Here we propose protocol for relaying delegations between agents that have no direct channel between them. +## Serialization -# Terminology +[UCAN]s MUST be encoded with some [IPLD] codec. [DAG-CBOR] is RECOMMENDED. -## Delegate Access +## Concepts -An agent MAY delegate some capabilities to any other agent +### Roles -> `did:key:zAlice` delegates `store/*` capabilities to `did:key:zBob` +| Name | Description | +| ------ |-------------| +| Principal | The general class of entities that interact with with a UCAN. Listed in the `iss` or `aud` field | +| 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. + +Space is always listed in the `with` field of the [UCAN] capability. + +### Owner + +The [owner] of the [space] is the holder of its private key. Space owner can share limited or full access to owned space via [UCAN] delegation issued by the [space] [`did:key`] and signed with the [space] private key. + +### Access + +Access is defined in terms of [UCAN] delegation, where level of the access is denoted by the set of capabilities delegated. + +#### Example in [DAG-JSON] + +[Space] [owner] authorizes `did:key:zBob` _(`aud` field)_ by delegating `store/*` capabilities _(`can` field)_ for `did:key:zSpace` space _(`iss` field)_. ```json { - "iss": "did:key:zAlice", + "v": "0.9.1", + "iss": "did:key:zSpace", "aud": "did:key:zBob", - "att": [{ "with": "did:key:zAlice", "can": "store/*" }], - "exp": null, - "sig": "..." + "att": [ + { + "can": "store/*" + "with": "did:key:zSpace", + } + ], + "prf": [], + "fct": [], + "exp": 1740357624, + "s": {"/": {"bytes": "7aED...A0"}}, } ``` -Agent MAY send such a delegation(s) to the service implementing this protocol so that it's there for the audience to collect at their convenience. +## Capabilities -### `access/delegate` +### IPLD Schema -Agent CAN invoke `access/delegate` capability with arbitrary delegations which will be stored and made available for collection to their respective audiences. +```ipldsch +type Access union { + | AccessDelegate "access/delegate" + | AccessClaim "access/claim" + | AccessRequest "access/request" +} representation inline { + discriminantKey "can" +} +``` + +### Access Delegate -#### Example +The `access/delegate` capability MAY be invoked by an authorized agent to send set of delegations to their respective audiences. -> Invoke `access/delegate` asking web3.storage to record delegation from the previous example +#### Access Delegate Example + +Example illustrates `did:key:zAlice` invoking `access/delegate` capability with web3.storage requesting it to send a delegation from [access example] to their audience. ```json { + "v": "0.9.1", "iss": "did:key:zAlice", "aud": "did:web:web3.storage", "att": [ @@ -64,177 +126,294 @@ Agent CAN invoke `access/delegate` capability with arbitrary delegations which w "with": "did:key:zAlice", "can": "access/delegate", "nb": { - // Map of delegation links to be stored for their audiences. "delegations": { "bafy...prf1": { "/": "bafy...prf1" } } } } ], - "prf": [ - { - "iss": "did:key:zAlice", - "aud": "did:key:zBob", - "att": [ - { - "with": "did:key:zAlice", - "can": "store/*" - } - ], - "exp": null, - "sig": "..." - } - ], - "sig": "..." + "prf": [], + "exp": 1705622469, + "s": {"/": {"bytes": "7aED...A0"}}, +} +``` + +##### Delegate IPLD Schema + +```ipldsch +type AccessDelegate struct { + with AgentDID + nb Delegate } + +type Delegate struct { + delegations { String: &UCAN } +} + +type AgentDID = string ``` -#### delegate `with` +##### Delegate `with` -Field MUST be a space DID with a storage provider. Delegation will be stored just like any other DAG stored using `store/add` capability. +The `with` field MUST be set the [`did:key`] identifying the [space] where delegations will be stored. -Provider SHOULD deny service if DID in the `with` field has no storage provider. +Implementation MAY deny request if specified [space] has no capacity to store supplied [UCAN]s, or if the give space does not have `access/delegate` capability provisioned. -#### delegate `nb` +Protocol intentionally does not prescribe how to transfer linked [UCAN]s leaving it up to implementations. -##### delegate `nb.delegations` +> ⁂ [w3up] implementation REQUIRES that all linked [UCAN]s be bundled in the invocation. -Field is a set of delegation links represented as JSON. Keys SHOULD be CID strings of the values to make encoding deterministic. +Please note that all the following [DID]s could be differnt from one another -Delegations MUST be included with an invocation. Invocations that link to delegations not included with invocation MUST be denied. +1. Issuer of the linked delegations (in the `nb.delegation`) +1. Issuer of the invocation. +1. [Space] where delgations will be stored -> ⚠️ Note that currently only way to include delegations with invocation requires putting them in proofs, which will be addressed by [#39](https://github.com/web3-storage/ucanto/issues/39) +To put it differently delegation MAY be sent by anyone, it does not have to be the issuer of the delegation. Send delegation MAY be delegating capability to resource different from the [space] where sent delegation will be stored. -## Claim Access +##### Delegate `nb.delegations` -Agent MAY claim capabilities that delegated to it using `access/claim` capability. +Field MUST be set to a set of [UCAN] [IPLD Link]s represented via [IPLD Map]. Map keys SHOULD be their corresponding values encoded as strings. It is RECOMMENDED to use base32 encoding. - +> ⁂ [w3up] implementation REQUIRES that all linked [UCAN]s be bundled with the invocation. -### `access/claim` +##### Delegate Receipt -Agent CAN invoke `access/claim` capability to the service implementing this protocol to collect all the valid delegations where audience matches `with` field. +Implementation MUST respond with [UCAN Receipt]. On success result MUST be a `Unit` (empty [IPLD Map]) type. + +On failure result MUST have `message` string field describing the error. + +### Access Claim + +The `access/claim` capability MAY be invoked by an authorized agent to receive the +capabilities that were delegated to the audience corresponding to the `with` field. + +#### Access Claim Example + +Example illustrates `did:key:zBob` invoking `access/claim` capability with web3.storage requesting delegations where `did:key:zBob` is an audience like one in the [access example]. ```json { + "v": "0.9.1", "iss": "did:key:zBob", "aud": "did:web:web3.storage", "att": [ { "with": "did:key:zBob", - "can": "access/claim" + "can": "access/claim", } ], - "sig": "..." + "prf": [], + "exp": 1705622469, + "s": {"/": {"bytes": "7aED...A0"}}, } ``` -# Examples +#### Access Claim Schema + +```ipldsch +type AccessClaim struct { + with DID +} + +type DID = string +``` + +#### Access Claim `with` -## Access across multiple devices +The `with` field MUST be set to the [DID] identifying the audience of the +delegations. -> Access protocol implies that delegation issuer be aware of the audience DID. Often complementary [authorization] protocol can be utilized to remove need for passing around cryptographic [`did:key`] identifiers as following example attempt to illustrate. +#### Access Claim Receipt -When Alice first runs `w3up` program it asks for the user identity she'd like to use. After Alice types `alice@web.mail` program initiates [authorization] protocol and creates a new (user) space by deriving `did:key:zAliceSpace` [`did:key`] from it. It immediately delegates capabilities to this space to Alice's identity: +Implementation MUST respond with [UCAN Receipt]. On success result MUST set of [UCAN] [IPLD Link]s represented via [IPLD Map] where keys SHOULD be corresponding values encoded as strings. It is RECOMMENDED to use base32 base encoding for the keys. + +Protocol intentionally does not specify how to transfer linked [UCAN]s leaving it up to implementations to prescsribe. + +> ⚠️ [w3up] implementation currently is incompatible as it sends binary encoded [UCAN]s as values of the map as opposed to links. + +### Access Request + +The `access/request` capability MAY be invoked by a user agent / application to get access to the required capabilities. + +> ⚠️ [w3up] implementation currently does not support this capability. + +#### Access Request Example + +User [agent] `did:key:z6Mkk...xALi` (`with` field) is requesting authorization from `alice@web.mail` [account] (`aud` field) on a [space] with following capabilities: + +- `store/add` where `size` is greater or equal than `1024`. +- `store/list` +- `store/get` ```json { - "iss": "did:key:zAliceSpace", - "aud": "did:web:web3.storage", + "v": "0.9.1", + "iss": "did:key:z6Mkk...xALi", + "aud": "did:mailto:web.mail:alice", "att": [ { - "with": "did:key:zAliceSpace", - "can": "access/delegate", + "with": "did:key:z6Mkk...xALi", + "can": "access/request", "nb": { - // Map of delegation links to be stored for their audiences. - "delegations": { "bafy...prf1": { "/": "bafy...prf1" } } + "can": { + "store/add": [ + {">=": {"size": 1024}} + ], + "store/list": [], + "store/get": [] + }, } } ], - "prf": [ - // delegation to - { - "iss": "did:key:zAliceSpace", - "aud": "did:mailto:web.mail:alice", - "att": [ - { - "with": "did:key:zAliceSpace", - "can": "*" - } - ], - "exp": null, - "sig": "..." + "prf": [], + "exp": 1685602800, + "s": { + "/": { + "bytes": "7aEDQJbJqmyMxTxcK05XQKWfvxG+Tv+LWCJeE18RSMnciCZ/RQ21U75LA0uFSvIjdqnF5RaauZTE8mh2ZYMBBejdJQ4" } - ], - "sig": "..." + } } ``` -When Alice runs `w3up` program on her other device, and she enters the same email address, it also initiates [authorization] flow to obtain access on a new device. +#### Access Request Schema -```json -{ - "iss": "did:key:zAli", - "aud": "did:web:web3.storage", - "att": [ - { - "with": "did:key:zAli", - "can": "access/authorize", - "nb": { "as": "did:mailto:web.mail:alice" } - } - ], - "sig": "..." +```ipldsch +type AccessRequest struct { + can { Ability: [Clause] } } +type Ability = string + + +type Clause union { + # Logic combinators + "not": Clause + "or": Clause + "and": Clause + # Predicates + ">": CompareClause + "<": CompareClause + ">=": CompareClause + "<=" CompareClause + "=" CompareClause + "!=" CompareClause + "like" LikeClause +} representation keyed + + +type CompareClause = { Attribute: Compare } +type Compare union { + | CompareClause map + | Float float + | Int int + | String string + | Bytes bytes + | Link link +} representation kinded + + +type LikeClause { Attribute: Like } +type Like union { + | LikePattern string + | LikeClause map +} representation kinded + + +# Similar to SQLite like pattern +# - Any except for "%" and "_" characters matches itself. +# - An underscore "_" matches any single character. +# - A percent "%" symbol matches any single character. +type LikePattern = string ``` -After receiving an email and clicking a link to approve authorization, an agent on a new device receives a delegation allowing that agent to sign delegations via local (non-extractable) `did:key:zAli` key +#### Requesting Principal + +The resource (`with` field) MUST be set to the [DID] of the principal requesting an authorization. + +> ℹ️ It should be noted that the resource specified in the `with` field of the authorization request is NOT REQUIRED to be the same as the issuer of the request. + +#### Authorizing Principal + +The [audience] (`aud` field) MUST be set to the [account] [DID] from which authorization is being requested. + +> ℹ️ Implementations MAY choose to support requests from non [account] principals if they choose so. + +#### Requested Capabilities + +The `nb.can` field MUST be an [IPLD Map] describing requested capabilities. Keys of `nb.can` map MUST be abilities requested. Values of the `nb.can` map MUST be constraints that capability corresponding to the key SHOULD satisfy. All requested capabilities SHOULD be for the same resource [space]. + +### Access Authorize + +![deprecated](https://img.shields.io/badge/status-deprecated-red.svg?style=flat-square) + +> ⚠️ Has been deprecated in favor of [access request] + +The `access/authorize` capability MAY be invoked by a user agent / application to get access to the required capabilities. + +#### Access Authorize Example ```json { - "iss": "did:web:web3.storage", + "v": "0.9.1", + "iss": "did:key:z6Mkk...xALi", "aud": "did:mailto:web.mail:alice", "att": [ { - "with": "did:web:web3.storage", - "can": "./update", - "nb": { "key": "did:key:zAli" } + "with": "did:key:z6Mkk...xALi", + "can": "access/request", + "nb": { + "iss": "did:mailto:web.mail:alice", + "att": [{"can": "store/add"}] + } } ], - "sig": "..." + "prf": [], + "exp": 1685602800, + "s": { + "/": { + "bytes": "7aEDQJb...dJQ4" + } + } } ``` -Using this authorization, a new device can claim capabilities that were delegated to it +#### Access Authorize Schema -```json -{ - "iss": "did:mailto:web.mail:alice", - "aud": "did:web:web3.storage", - "att": { - "with": "did:mailto:web.mail:alice", - "can": "access/claim" - }, - "prf": [ - { - "iss": "did:web:web3.storage", - "aud": "did:mailto:web.mail:alice", - "att": [ - { - "with": "did:web:web3.storage", - "can": "./update", - "nb": { "key": "did:key:zAli" } - } - ] - } - ], - "sig": "..." +```ipldsch +type AccessAuthorize struct { + iss DID + att [CapabilityRequest] +} + +type CapabilityRequest struct { + can Ability } +type Ability = string ``` -Service will respond with delegations where audience is `did:mailto:web:mail:alice` which will give agent on this new device access to `did:key:zAliceSpace`: +#### Authorization Requesting Principal + +The resource (`with` field) MUST be set to the [DID] of the principal requesting an authorization. + +#### Authorization Authorizing Principal + +The [`nb.iss`] MUST be set to the [account] [DID] from which authorization is being requested. + +#### Authorization Level + +The `nb.att` field MUST be an array of objects. Each object in `nb.att` field MUST +have `can` field set to requested ability. All requested abilities SHOULD be for +the same resource [space]. + +## Usage Patterns + +### Access across multiple devices + +Alice installs `w3up` program and runs it the first time. Program asks what email address to use for the [account]. Alice types `alice@web.mail`. Program derives `did:mailto:web.mail:alice` [DID] and requests authorization from it. Program invokes [access claim] capability and discovers that [account] has no [space] so it creates a new keypair and a corresponding space `did:key:zAliceSpace`, provisions it and after confirmation from Alice sets up space recovery by delegating full authority to Alice's [account]: ```json { + "v": "0.9.1", "iss": "did:key:zAliceSpace", "aud": "did:mailto:web.mail:alice", "att": [ @@ -243,19 +422,21 @@ Service will respond with delegations where audience is `did:mailto:web:mail:ali "can": "*" } ], + "prf": [], "exp": null, - "sig": "..." + "s": { + "/": { + "bytes": "7aEDQJb...dJQ4" + } + } } ``` -## Sharing access with a friend - -> Access protocol could be utilized to share access with a friend who may have never used web3.storage. - -Alice wants to share access to her space with her friend Bob. She does not know if Bob has ever heard of web3.storage, but she knows his email address `bob@gmail.com` allowing her to delegate capabilities to it: +Program invokes [access delegate] capability with the account delegation so it can be received anywhere Alice logs in with her account. ```json { + "v": "0.9.1", "iss": "did:key:zAliceSpace", "aud": "did:web:web3.storage", "att": [ @@ -268,56 +449,78 @@ Alice wants to share access to her space with her friend Bob. She does not know } } ], - "prf": [ - // delegation to + "prf": [{ "/": "bafy...prf1" }], + "exp": null, + "s": { + "/": { + "bytes": "7aEDQJb...dJQ4" + } + } +} +``` + +When Alice runs `w3up` program on her other device, and logs in to her account, program invokes [access authorize] capability to get access on this device. + +```json +{ + "v": "0.9.1", + "iss": "did:key:zAli", + "aud": "did:web:web3.storage", + "att": [ { - "iss": "did:key:zAliceSpace", - "aud": "did:mailto:gmail.com:bob", - "att": [ - { - "with": "did:key:zAliceSpace", - "can": "store/list" - } - ], - "exp": "...", - "sig": "..." + "with": "did:key:zAli", + "can": "access/authorize", + "nb": { + "iss": "did:mailto:web.mail:alice", + "att": [{"can": "*"}] + } } ], - "sig": "..." + "prf": [], + "exp": null, + "s": { + "/": { + "bytes": "7aEDQJb...dJQ4" + } + } } ``` -When Bob runs `w3up` agent the first time and authorizes as `bob@gmail.com` program will collect capabilities delegated to it: +On invocation service sends an authorization confirmation email to `alice@web.mail`. Alice clicks a link in the email to approving requested authorization, on which service issues [attestation] proving that Alice has authorized requested authorization to `did:key:zAli` (an agent DID on new device). ```json { - "iss": "did:mailto:gmail.com:bob", - "aud": "did:web:web3.storage", - "att": { - "with": "did:mailto:gmail.com:bob", - "can": "access/claim" - }, - "prf": [ + "v": "0.9.1", + "iss": "did:web:web3.storage", + "aud": "did:key:zAli", + "att": [ { - "iss": "did:web:web3.storage", - "aud": "did:mailto:gmail.com:bob", - "att": [ - { - "with": "did:web:web3.storage", - "can": "./update", - "nb": { "key": "did:key:zBobAgent" } - } - ] + "with": "did:web:web3.storage", + "can": "ucan/attest", + "nb": { + "proof": { "/": "bafy...auth" } + } } ], - "sig": "..." + "prf": [], + "exp": null, + "s": { + "/": { + "bytes": "7aEDQJb...dJQ4" + } + } } ``` -Service responds with a delegation from Alice giving Bob's agent capability to execute `store/list` on `did:key:zAliceSpace` space +In the background new device polled [access claim] and once request was authorized it received delegation from an account along with the [attestation] from the service proving that Alice has authorized it. This allows new device to access to the [space]. + +### Sharing access with a friend + +Alice wants to share access to her [space] with her friend Bob. She does not know if Bob has ever heard of web3.storage, but she knows his email address `bob@gmail.com` allowing her to delegate capabilities: ```json { + "v": "0.9.1", "iss": "did:key:zAliceSpace", "aud": "did:mailto:gmail.com:bob", "att": [ @@ -326,18 +529,55 @@ Service responds with a delegation from Alice giving Bob's agent capability to e "can": "store/list" } ], - "exp": "...", - "sig": "..." + "prf": [], + "exp": 1685602800, + "s": { "/": { "bytes": "7aEDQJb...dJQ4" } } } ``` -# Related Notes - -## Free provider +And [access delegate] capability allows her to send the delegation so it could be claimed by Bob. -web3.storage offers one "free provider" per account. It will be denied if a `consumer` space is not specified or if account has already claimed it with a different `consumer` space. +```json +{ + "v": "0.9.1", + "iss": "did:key:zAliceSpace", + "aud": "did:web:web3.storage", + "att": [ + { + "with": "did:key:zAliceSpace", + "can": "access/delegate", + "nb": { + // Map of delegation links to be stored for their audiences. + "delegations": { "bafy...prf1": { "/": "bafy...prf1" } } + } + } + ], + "prf": [{ "/": "bafy...prf1" }], + "exp": 1685602800, + "s": { "/": { "bytes": "7aEDQJb...dJQ4" } } +} +``` -Note that adding the "free provider" to a space more than once has no effect _(even when obtained through different accounts)_, because a space has _set_ of providers, and "free provider" is either in that set or not. +When Bob runs `w3up` agent the first time and authorizes as `bob@gmail.com`, the program invokes [access claim] capability and collects all capabilities available to the account, including one sent by Alice, gaining access to her space. [`did:key`]: https://w3c-ccg.github.io/did-method-key/ -[authorization]: w3-session.md#authorization +[UCAN]:https://github.com/ucan-wg/spec/blob/692e8aab59b763a783fe1484131c3f40d997b69a/README.md +[UCAN Receipt]:https://github.com/ucan-wg/invocation/tree/f28f682bcb484cb515785b2a268d8a5b4cfc2b58#225-receipt +[IPLD]: https://ipld.io/ +[DAG-CBOR]: https://ipld.io/specs/codecs/dag-cbor/spec/ +[space]:#space +[owner]:#owner +[access]:#access +[DID]:https://www.w3.org/TR/did-core/ +[DAG-JSON]:ipld.io/specs/codecs/dag-json/spec +[access example]:#Example_in_DAG-JSON +[w3up]:https://github.com/web3-storage/w3up +[IPLD Map]:https://ipld.io/docs/schemas/features/typekinds/#map +[IPLD Link]:https://ipld.io/docs/schemas/features/links +[message channel]:https://en.wikipedia.org/wiki/Channel_(programming) +[account]:./w3-account.md +[access delegate]:#access-delegate +[access request]:#access-request +[access claim]:#access-claim +[access authorize]:#access-authorize +[attestation]:./w3-ucan.md#attestation From ff71d1b5915b9084eb51ba7b5264758f86c66cd4 Mon Sep 17 00:00:00 2001 From: Irakli Gozalishvili Date: Mon, 22 Jan 2024 13:20:23 -0800 Subject: [PATCH 14/20] chore: undo unintended changes --- w3-account.md | 38 +++++++++++++++++++------------------- w3-ucan.md | 45 +++++++++++++++++++++++---------------------- 2 files changed, 42 insertions(+), 41 deletions(-) diff --git a/w3-account.md b/w3-account.md index 5aa9964..4fc3df5 100644 --- a/w3-account.md +++ b/w3-account.md @@ -14,7 +14,7 @@ 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 [account] primitive designed to enable synchronization of the access across authorized user agents with a user-friendly experience. +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 @@ -22,17 +22,17 @@ The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "S # Introduction -In 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: +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 case when all devices are lost becomes impossible. +2. Recovering access in the case when all devices are lost becomes impossible. -To address these issues, we propose the concept of an account. 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. +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. Account can be used to solve both discovery and recovery problems: -1. Instead of user agents trying discovering each to delegate capabilities with one another, 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 has been lost as long as the user retains control of their email, because account can always delegate capabilities to new agents. +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. 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. @@ -62,27 +62,27 @@ There are several distinct roles that [principals] may assume in described speci 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. -Space is always listed in the `with` field of the [UCAN] capability. +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. Space owner can share limited or full access to owned space via [UCAN] delegation issued by the [space] [`did:key`] and signed with a [space] private key. +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 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. -Account enables familiar authorization and recovery email flows. +An account enables familiar authorization and recovery email flows. ### Agent -An _agent_ is a principal 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] where 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. ### Authority -Authority is trusted [DID] identifier. For example various subsystems may recognize and signatures from a global service 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. @@ -111,7 +111,7 @@ Space ->> Email: 🎫 Delegate capabilities note over Space,Email:can:*
with: did:key:z7Gf…xSpace ``` -> On first run, application creates a new namespace and delegates full authority to the user account. For the simplicity we omit steps where application first requests access from an account before deciding to create 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 @@ -132,11 +132,11 @@ Email ->> Bob: 🎫 Delegate capabilities ### Authorization -Delegations issued by [`did:key`] principal are authorized by signing payload with private key. Delegations issued by a [`did:mailto`] principal are not authorized by signing over payload as there is no public key associated with [`did:mailto`] to sign it with. Instead, such delegations are authorized through an interactive email flow in which [account] holder is able to review and approve requested authorization through an action. +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. -Since there is no public key to sign the [UCAN] payload define an extension to the [UCAN] specification introducing two new signature types that can be used in delegations issued by [`did:mailto`] principals. +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 also define verification mechanism for these 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. @@ -165,13 +165,13 @@ cid := z[a-km-zA-HJ-NP-Z1-9]+ ### Attestation Signature -Delegation MAY be authorized through an interactive email flow where [account] holder is emailed request to approve an authorization that gives an agent access to specific set of capabilities. If user approves by clicking embedded link signed [attestation] is issued that confirms that delegation has been authorized through an interactive flow. +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 delegation issued by the [`did:mailto`] identifier MAY be signed using _attestation signature_ type. This signature alone MUST NOT be considered as a valid authorization. Delegation signed with _attestation signature_ MUST be accompanied with [UCAN attestation] issued by the trusted [authority]. +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 _attestation signature_, but is not accompanied with [UCAN attestation] from trusted [authority] it MUST be considered invalid. In this scenario implementer MAY initiate interactive verification flow and issue [UCAN attestation] retroactively instead of denying service. +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. -> When received delegation is issued by the `did:mailto:web.mail:alice`, signed with _attestation signature_, but is not accompanied by [UCAN attestation], receiver could iteratively confirm authorization by sending an email to `alice@web.mail` address with a confirmation link, which when followed issues [attestation] from the receiver resuming the invocation. +> 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. #### Attestation Signature Format diff --git a/w3-ucan.md b/w3-ucan.md index 2983466..2c8bd63 100644 --- a/w3-ucan.md +++ b/w3-ucan.md @@ -16,7 +16,7 @@ The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "S ## Abstract -[UCAN] specification reserves `ucan/` ability namespace for the core functionality that may be introduced in future versions. Here we define W3 protocol extensions to the core namespace that we hope to standardize in core [UCAN] specification. +The [UCAN] specification reserves the `ucan/` ability namespace for the core functionality that may be introduced in future versions. Here we define W3 protocol extensions to the core namespace that we hope to standardize in core [UCAN] specification. # Terminology @@ -32,7 +32,7 @@ There are several roles that agents in the authorization flow may assume: ### Authority -Authority is trusted [DID] identifier. For example various subsystems may recognize and signatures from a global service authority. +Authority is 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. @@ -46,7 +46,7 @@ Subsystem that performs [UCAN] validation. ### Motivation -[UCAN] verification process involves going through a delegation chain and verifying that every delegation has a valid signature from the private key if the issuer and that principals in the chain align. As described it has following implications: +The [UCAN] verification process involves going through a delegation chain and verifying that every delegation has a valid signature from the private key of the issuer and that the principals in the chain align. As described it has the following implications: 1. Verifier MAY end up verifying same potentially long chain over and over. As an optimization they could implement caching strategy, but that may require access to some storage. 1. Invocations MAY have to send potentially long delegation chains over and over as validator MAY prune cache and may not even persist previously seen delegations. @@ -54,28 +54,28 @@ Subsystem that performs [UCAN] validation. ### Proposal -We propose extension to the core [UCAN] specification and define `ucan/attest` -capability, that enables an [authority] to attest that linked [UCAN] delegation is valid. +We propose an extension to the core [UCAN] specification and define a `ucan/attest` +capability, that enables an [authority] to attest that a linked [UCAN] delegation is valid. -This effectively allows distributing verifiable cache records to interested principals so they could include those in subsequent invocations and take advantage of optimizations they unlock. +This effectively allows distributing verifiable cache records to interested principals so they can include those in subsequent invocations and take advantage of the optimizations they unlock. #### Cached Verification -For example verifier could issue an attestation for the [UCAN] chain it validated and hand it back to the caller. In subsequent calls caller could include an attestation to take advantage of more optimal execution. +For example, a verifier could issue an attestation for the [UCAN] chain it validated and hand it back to the caller. In subsequent calls the caller could include an attestation to take advantage of more optimal execution. #### Proof chain compaction -Just like in the above scenario except not only caller can take advantage of more optimal execution they could also transfer proof chain up to a proof they have attestation for reducing size of the payload. +Just like in the above scenario except not only can a caller take advantage of more optimal execution, they can also transfer a proof chain up to a proof they have an attestation for, thereby reducing the size of the payload. #### Out of bound verification -Attestations CAN be issued as a part of authorization process. For example [UCAN]s issued by [`did:mailto`] require out of bound authorization flow in which service sends confirmation email to the user. If user confirms through a link in the email service issues an attestation declaring that [UCAN] has been verified. +Attestations CAN be issued as a part of authorization process. For example [UCAN]s issued by [`did:mailto`] require out of bound authorization flow in which a service sends a confirmation email to the user. If the user confirms through a link in the email, the service issues an attestation declaring that the [UCAN] has been verified. ### Notes on compatibility -Attestations effectively are a cache records that if provided enables certain optimizations, when not provided, correct implementation SHOULD fallback to a less optimal path. +Attestations are effectively cached records that, if provided, enable certain optimizations. When not provided, correct implementations SHOULD fallback to a less optimal path. -Implementations that do not support this extension will simply disregard attestations in the proof chain as irrelevant and just under less optimal path. +Implementations that do not support this extension will simply disregard attestations in the proof chain as irrelevant and just take a less optimal path. ### IPLD Schema @@ -106,11 +106,11 @@ The `nb.proof` field MUST be a [link] to the [UCAN] delegation covered by the at ### Attestation Lifetime -Attestation MUST be considered valid ONLY within the [time bounds] of enclosing [UCAN]. In other words enclosing [UCAN] `nbf` and `exp` fields SHOULD be used to specify [time bounds] within which attestation is valid. +The attestation MUST be considered valid ONLY within the [time bounds] of the enclosing [UCAN]. In other words the enclosing [UCAN]'s `nbf` and `exp` fields SHOULD be used to specify [time bounds] within which the attestation is valid. ### Attestation Revocation -Attestation MUST be considered revoked if enclosing [UCAN] has been revoked. This also implies that attestation can be revoked by revoking their enclosing [UCAN]s. +The attestation MUST be considered revoked if the enclosing [UCAN] has been revoked. This also implies that the attestation can be revoked by revoking its enclosing [UCAN]s. ### Attestation Example in DAG-JSON @@ -143,14 +143,15 @@ Attestation MUST be considered revoked if enclosing [UCAN] has been revoked. Thi ### Motivation -[UCAN] specification defines [revocation record] that MUST be signed by the issuer in the delegation chain of the [UCAN] been revoked. From real world experience we find that requirement unfortunate. In plenty of cases various actors are delegated specific subset of capabilities from the supervisor to carry out their work. Supervisor MAY want give specific actor to revoke some capabilities on its behalf without giving it ability to invoke them and [revocation record] does not allow that. +[UCAN] specification defines [revocation record] that MUST be signed by the issuer in the delegation chain of the [UCAN] been revoked. From real world experience we find this requirement problematic, it is common to have a primary authority that delegates subset of their capability to various actors based on their role. In such setup it is often desired to have auditors that can revoke capabilities from misbehaving actors without been in the delegation chain. + +In other words it is desired to have ability to grant revocation power to some actor without granting them invocation power. ### Proposal -We propose extension to the core [UCAN] specification and define `ucan/revoke` -capability, that can be invoked to revoke 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 gain ability to delegate ability to revoke to another principal, which is desired in scenario described above. +By making revocation a [UCAN] itself we allow delegating the ability to revoke to another principal, which is desired in scenario described above. ### IPLD Schema @@ -174,15 +175,15 @@ type Revocation struct { ### Revocation Authority -The value of the `with` field MUST be the [DID] of the principal that issued the [UCAN] been revoked or some [UCAN] in its proof chain. +The value of the `with` field MUST be the [DID] of the principal that issued the [UCAN] being revoked or some [UCAN] in its proof chain. Revocation where [DID] in the `with` field is not an issuer of the [UCAN] or the proofs it depends on SHOULD be considered obsolete. -Implementations MAY choose to consider revocations from certain [authority] even if they are not part of the proof chain. For example service could proactively revoke [UCAN] chain when actual issuer keys are is compromised. +Implementations MAY choose to consider revocations from a certain [authority] even if they are not part of the proof chain. For example service could proactively revoke [UCAN] chain when an issuer's keys are compromised. ### Revocation Subject -The `nb.ucan` field MUST be a [link] to the [UCAN] been revoked. +The `nb.ucan` field MUST be a [link] to the [UCAN] being revoked. ### Revocation Proof @@ -192,9 +193,9 @@ Implementations MAY choose to require a valid `nb.proof` to avoid storing potent ### Revocation Lifetime -It is RECOMMENDED to treat revocations permanent. Even though enclosing [UCAN] will have [time bounds] those MUST NOT be interpreted as a time frame within which revocation is active. +It is RECOMMENDED to treat revocations as permanent. Even though enclosing [UCAN] will have [time bounds] those MUST NOT be interpreted as a time frame within which the revocation is active. -Enclosing [UCAN] [time-bounds] MUST be interpreted as time frame within which authorized issuer is able to exercise revocation on behalf of the [authority]. More simply it is a mechanism to limit issuers ability to perform revocation on behalf of the [authority]. +Enclosing [UCAN] [time-bounds] MUST be interpreted as the time frame within which an authorized issuer is able to exercise revocation on behalf of the [authority]. More simply it is a mechanism to limit an issuers ability to perform revocation on behalf of the [authority]. ### Revocation Revocation From 45a316cb78ae9c9ae7152814729e27b4a0dd2dce Mon Sep 17 00:00:00 2001 From: Irakli Gozalishvili Date: Mon, 22 Jan 2024 13:30:08 -0800 Subject: [PATCH 15/20] Apply suggestions from code review Co-authored-by: Alan Shaw --- w3-access.md | 72 ++++++++++++++++++++++++++-------------------------- 1 file changed, 36 insertions(+), 36 deletions(-) diff --git a/w3-access.md b/w3-access.md index 5eba501..a5dff03 100644 --- a/w3-access.md +++ b/w3-access.md @@ -22,31 +22,31 @@ The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "S # Introduction -[Space] [access] is represented as a signed authorization in [UCAN] format. It is not enough to issue the [UCAN] authorization, issuer needs some channel to deliver it to an audience. +[Space] [access] is represented as a signed authorization in [UCAN] format. It is not enough to issue the [UCAN] authorization, the issuer needs some channel to deliver it to an audience. -We propose a protocol where implementation can act as a delivery channel. +We propose a protocol where an implementation can act as a delivery channel. ## Intuition ### Message Channel -At the very high level signed authorization is a message addressed to a specific recipient (audience). Implementer of this protocol represent a [message channel] allowing sender (issuer) to send a message and allow recipient (audience) to receive massages sent to them. +At the very high level signed authorization is a message addressed to a specific recipient (audience). The implementer of this protocol represents a [message channel] allowing the sender (issuer) to send a message and allowing the recipient (audience) to receive messages sent to them. ### Shared Space -Alice has set up space for sharing photos with her family and friends. She wants to authorize her partner Bob with write access so he can also upload photos. She wants to authorize her less tech savvy parent Mallory with just read access so she can look at photos but not add or delete them. +Alice has set up a space for sharing photos with her family and friends. She wants to authorize her partner Bob with write access so he can also upload photos. She wants to authorize her less tech savvy parent Mallory with just read access so she can look at photos but not add or delete them. -> In this scenario Alice delegates `upload/add` capability to Bob and `upload/list` capability to Mallory. Application used by Alice leverages access protocol to send issued delegations to Bob and Mallory. Applications used by Bob and Mallory leverage access protocol to receive messages sent to them transparently gaining access to the space Alice has shared access to. +> In this scenario Alice delegates `upload/add` capability to Bob and `upload/list` capability to Mallory. The application used by Alice leverages the access protocol to send issued delegations to Bob and Mallory. Applications used by Bob and Mallory leverage the access protocol to receive messages sent to them, transparently gaining access to the space that Alice has shared access to. -### Multidevice Access +### Multi-device Access -Alice has created a new space for storing photos on her laptop and uploaded some photos. Later she picks up her phone logs with her account and upload some photos to her space. +Alice has created a new space for storing photos on her laptop and uploaded some photos. Later she picks up her phone and logs in with her account to upload some photos to her space. -> In this scenario after space is created access protocol is used to delegate full authority over to Alice's [account]. Later, when Alice logs in on her phone her [account] receives delegated capabilities over access protocol gaining access to the space. +> In this scenario after the space is created the access protocol is used to delegate full authority over to Alice's [account]. Later, when Alice logs in on her phone her [account] receives delegated capabilities over the access protocol, thereby gaining access to the space. ## Serialization -[UCAN]s MUST be encoded with some [IPLD] codec. [DAG-CBOR] is RECOMMENDED. +[UCAN]s MUST be encoded with an [IPLD] codec. [DAG-CBOR] is RECOMMENDED. ## Concepts @@ -62,15 +62,15 @@ Alice has created a new space for storing photos on her laptop and uploaded some 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. -Space is always listed in the `with` field of the [UCAN] capability. +A space is always listed in the `with` field of the [UCAN] capability. ### Owner -The [owner] of the [space] is the holder of its private key. Space owner can share limited or full access to owned space via [UCAN] delegation issued by the [space] [`did:key`] and signed with the [space] private key. +The [owner] of the [space] is the holder of its private key. The space owner can share limited or full access to their space via a [UCAN] delegation issued by the [space] [`did:key`] and signed with the [space]'s private key. ### Access -Access is defined in terms of [UCAN] delegation, where level of the access is denoted by the set of capabilities delegated. +Access is defined in terms of [UCAN] delegation, where the level of the access is denoted by the set of capabilities delegated. #### Example in [DAG-JSON] @@ -110,11 +110,11 @@ type Access union { ### Access Delegate -The `access/delegate` capability MAY be invoked by an authorized agent to send set of delegations to their respective audiences. +The `access/delegate` capability MAY be invoked by an authorized agent to send a set of delegations to their respective audiences. #### Access Delegate Example -Example illustrates `did:key:zAlice` invoking `access/delegate` capability with web3.storage requesting it to send a delegation from [access example] to their audience. +The following example illustrates `did:key:zAlice` invoking `access/delegate` capability with web3.storage, requesting it to send a delegation from [access example] to their audience. ```json { @@ -153,35 +153,35 @@ type AgentDID = string ##### Delegate `with` -The `with` field MUST be set the [`did:key`] identifying the [space] where delegations will be stored. +The `with` field MUST be set to the [`did:key`] identifying the [space] where delegations will be stored. -Implementation MAY deny request if specified [space] has no capacity to store supplied [UCAN]s, or if the give space does not have `access/delegate` capability provisioned. +An implementation MAY deny a request if tje specified [space] has no capacity to store the supplied [UCAN]s, or if the space does not have the `access/delegate` capability provisioned. -Protocol intentionally does not prescribe how to transfer linked [UCAN]s leaving it up to implementations. +The protocol intentionally does not prescribe how to transfer linked [UCAN]s leaving it up to implementations. -> ⁂ [w3up] implementation REQUIRES that all linked [UCAN]s be bundled in the invocation. +> ⁂ [w3up] implementation REQUIRES all linked [UCAN]s be bundled in the invocation. -Please note that all the following [DID]s could be differnt from one another +Please note that all the following [DID]s could be different from one another 1. Issuer of the linked delegations (in the `nb.delegation`) 1. Issuer of the invocation. 1. [Space] where delgations will be stored -To put it differently delegation MAY be sent by anyone, it does not have to be the issuer of the delegation. Send delegation MAY be delegating capability to resource different from the [space] where sent delegation will be stored. +In other words, a delegation MAY be sent by anyone, it does not have to be the issuer of the delegation. Sent delegation MAY be delegating capability to a resource different from the [space] where sent delegation will be stored. ##### Delegate `nb.delegations` -Field MUST be set to a set of [UCAN] [IPLD Link]s represented via [IPLD Map]. Map keys SHOULD be their corresponding values encoded as strings. It is RECOMMENDED to use base32 encoding. +This field MUST be set to a set of [UCAN] [IPLD Link]s represented by an [IPLD Map]. Map keys SHOULD be their corresponding values encoded as strings. It is RECOMMENDED to use base32 encoding. -Protocol intentionally does not specify how to transfer linked [UCAN]s leaving it up to the implementations to decide. +The protocol intentionally does not specify how to transfer linked [UCAN]s leaving it up to the implementations to decide. > ⁂ [w3up] implementation REQUIRES that all linked [UCAN]s be bundled with the invocation. ##### Delegate Receipt -Implementation MUST respond with [UCAN Receipt]. On success result MUST be a `Unit` (empty [IPLD Map]) type. +The implementation MUST respond with [UCAN Receipt]. On success result MUST be a `Unit` (empty [IPLD Map]) type. -On failure result MUST have `message` string field describing the error. +On failure, the result MUST have a `message` string field describing the error. ### Access Claim @@ -190,7 +190,7 @@ capabilities that were delegated to the audience corresponding to the `with` fie #### Access Claim Example -Example illustrates `did:key:zBob` invoking `access/claim` capability with web3.storage requesting delegations where `did:key:zBob` is an audience like one in the [access example]. +The following example illustrates `did:key:zBob` invoking `access/claim` capability with web3.storage requesting delegations where `did:key:zBob` is an audience like one in the [access example]. ```json { @@ -226,9 +226,9 @@ delegations. #### Access Claim Receipt -Implementation MUST respond with [UCAN Receipt]. On success result MUST set of [UCAN] [IPLD Link]s represented via [IPLD Map] where keys SHOULD be corresponding values encoded as strings. It is RECOMMENDED to use base32 base encoding for the keys. +The implementation MUST respond with a [UCAN Receipt]. On success, the result MUST include the set of [UCAN] [IPLD Link]s represented as an [IPLD Map] where keys SHOULD be corresponding values encoded as strings. It is RECOMMENDED to use base32 encoding for the keys. -Protocol intentionally does not specify how to transfer linked [UCAN]s leaving it up to implementations to prescsribe. +The protocol intentionally does not specify how to transfer linked [UCAN]s leaving it up to implementations. > ⚠️ [w3up] implementation currently is incompatible as it sends binary encoded [UCAN]s as values of the map as opposed to links. @@ -334,7 +334,7 @@ The resource (`with` field) MUST be set to the [DID] of the principal requesting #### Authorizing Principal -The [audience] (`aud` field) MUST be set to the [account] [DID] from which authorization is being requested. +The [audience] (`aud` field) MUST be set to the [account] [DID] from which the authorization is being requested. > ℹ️ Implementations MAY choose to support requests from non [account] principals if they choose so. @@ -402,14 +402,14 @@ The [`nb.iss`] MUST be set to the [account] [DID] from which authorization is be #### Authorization Level The `nb.att` field MUST be an array of objects. Each object in `nb.att` field MUST -have `can` field set to requested ability. All requested abilities SHOULD be for +have the `can` field set to the requested ability. All requested abilities SHOULD be for the same resource [space]. ## Usage Patterns ### Access across multiple devices -Alice installs `w3up` program and runs it the first time. Program asks what email address to use for the [account]. Alice types `alice@web.mail`. Program derives `did:mailto:web.mail:alice` [DID] and requests authorization from it. Program invokes [access claim] capability and discovers that [account] has no [space] so it creates a new keypair and a corresponding space `did:key:zAliceSpace`, provisions it and after confirmation from Alice sets up space recovery by delegating full authority to Alice's [account]: +Alice installs the `w3up` program and runs it the first time. The program asks what email address to use for the [account]. Alice types `alice@web.mail`. The program derives a `did:mailto:web.mail:alice` [DID] and requests authorization from it. Next the program invokes an [access claim] capability and discovers that the [account] has no [space] so it creates a new keypair and a corresponding space `did:key:zAliceSpace`, provisions it and after confirmation from Alice sets up space recovery by delegating full authority to Alice's [account]: ```json { @@ -432,7 +432,7 @@ Alice installs `w3up` program and runs it the first time. Program asks what emai } ``` -Program invokes [access delegate] capability with the account delegation so it can be received anywhere Alice logs in with her account. +The program invokes an [access delegate] capability with the account delegation so it can be received anywhere that Alice logs in with her account. ```json { @@ -459,7 +459,7 @@ Program invokes [access delegate] capability with the account delegation so it c } ``` -When Alice runs `w3up` program on her other device, and logs in to her account, program invokes [access authorize] capability to get access on this device. +When Alice runs the `w3up` program on her other device, and logs in to her account, the program invokes an [access authorize] capability to get access on this device. ```json { @@ -486,7 +486,7 @@ When Alice runs `w3up` program on her other device, and logs in to her account, } ``` -On invocation service sends an authorization confirmation email to `alice@web.mail`. Alice clicks a link in the email to approving requested authorization, on which service issues [attestation] proving that Alice has authorized requested authorization to `did:key:zAli` (an agent DID on new device). +When the invocation is received, the service sends an authorization confirmation email to `alice@web.mail`. Alice clicks the link in the email to approve the requested authorization. The service then issues an [attestation] proving that Alice has authorized requested authorization to `did:key:zAli` (an agent DID on new device). ```json { @@ -512,7 +512,7 @@ On invocation service sends an authorization confirmation email to `alice@web.ma } ``` -In the background new device polled [access claim] and once request was authorized it received delegation from an account along with the [attestation] from the service proving that Alice has authorized it. This allows new device to access to the [space]. +In the background, the new device polled [access claim] and once the request was authorized it received the delegation from an account along with an [attestation] from the service proving that Alice has authorized it. This allows the new device to acces the [space]. ### Sharing access with a friend @@ -535,7 +535,7 @@ Alice wants to share access to her [space] with her friend Bob. She does not kno } ``` -And [access delegate] capability allows her to send the delegation so it could be claimed by Bob. +...and the [access delegate] capability allows her to send the delegation so it can be claimed by Bob. ```json { @@ -558,7 +558,7 @@ And [access delegate] capability allows her to send the delegation so it could b } ``` -When Bob runs `w3up` agent the first time and authorizes as `bob@gmail.com`, the program invokes [access claim] capability and collects all capabilities available to the account, including one sent by Alice, gaining access to her space. +When Bob runs the `w3up` agent the first time and authorizes as `bob@gmail.com`, the program invokes the [access claim] capability and collects all capabilities available to the account, including the one sent by Alice, gaining access to her space. [`did:key`]: https://w3c-ccg.github.io/did-method-key/ [UCAN]:https://github.com/ucan-wg/spec/blob/692e8aab59b763a783fe1484131c3f40d997b69a/README.md From cd106eacc30cb9d17cc7ee70a37c16aa0ffdead0 Mon Sep 17 00:00:00 2001 From: Irakli Gozalishvili Date: Mon, 22 Jan 2024 13:31:14 -0800 Subject: [PATCH 16/20] chore: ignore more words --- .github/workflows/words-to-ignore.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/words-to-ignore.txt b/.github/workflows/words-to-ignore.txt index 24eef7e..7a8c8f3 100644 --- a/.github/workflows/words-to-ignore.txt +++ b/.github/workflows/words-to-ignore.txt @@ -151,3 +151,4 @@ verifier fieldAccountPrincipal installationIssuerPrincipal iteratively +base32 From 49daad8cfb9e48ef3ba4562c87ebb42ae0626360 Mon Sep 17 00:00:00 2001 From: Irakli Gozalishvili Date: Mon, 22 Jan 2024 13:33:08 -0800 Subject: [PATCH 17/20] Apply suggestions from code review Co-authored-by: Alan Shaw --- w3-access.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/w3-access.md b/w3-access.md index a5dff03..32d0f03 100644 --- a/w3-access.md +++ b/w3-access.md @@ -397,7 +397,7 @@ The resource (`with` field) MUST be set to the [DID] of the principal requesting #### Authorization Authorizing Principal -The [`nb.iss`] MUST be set to the [account] [DID] from which authorization is being requested. +The [`nb.iss`] MUST be set to the [account] [DID] from which the authorization is being requested. #### Authorization Level @@ -512,7 +512,7 @@ When the invocation is received, the service sends an authorization confirmation } ``` -In the background, the new device polled [access claim] and once the request was authorized it received the delegation from an account along with an [attestation] from the service proving that Alice has authorized it. This allows the new device to acces the [space]. +In the background, the new device polled [access claim] and once the request was authorized it received the delegation from an account along with an [attestation] from the service proving that Alice has authorized it. This allows the new device to access the [space]. ### Sharing access with a friend From e6ebb8f86dc38dfc1c6a4b174cc1a24590873370 Mon Sep 17 00:00:00 2001 From: Irakli Gozalishvili Date: Mon, 22 Jan 2024 13:38:04 -0800 Subject: [PATCH 18/20] fix: typo --- w3-access.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/w3-access.md b/w3-access.md index 32d0f03..72241f3 100644 --- a/w3-access.md +++ b/w3-access.md @@ -155,7 +155,7 @@ type AgentDID = string The `with` field MUST be set to the [`did:key`] identifying the [space] where delegations will be stored. -An implementation MAY deny a request if tje specified [space] has no capacity to store the supplied [UCAN]s, or if the space does not have the `access/delegate` capability provisioned. +An implementation MAY deny a request if the specified [space] has no capacity to store the supplied [UCAN]s, or if the space does not have the `access/delegate` capability provisioned. The protocol intentionally does not prescribe how to transfer linked [UCAN]s leaving it up to implementations. From d2c52c065132fec64ed7079d27ff6fd7d629f71d Mon Sep 17 00:00:00 2001 From: Irakli Gozalishvili Date: Mon, 22 Jan 2024 13:39:51 -0800 Subject: [PATCH 19/20] fix: broken link --- w3-access.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/w3-access.md b/w3-access.md index 72241f3..c837e28 100644 --- a/w3-access.md +++ b/w3-access.md @@ -569,7 +569,7 @@ When Bob runs the `w3up` agent the first time and authorizes as `bob@gmail.com`, [owner]:#owner [access]:#access [DID]:https://www.w3.org/TR/did-core/ -[DAG-JSON]:ipld.io/specs/codecs/dag-json/spec +[DAG-JSON]:https://ipld.io/specs/codecs/dag-json/spec [access example]:#Example_in_DAG-JSON [w3up]:https://github.com/web3-storage/w3up [IPLD Map]:https://ipld.io/docs/schemas/features/typekinds/#map From 1eae8ead4744c9af0d57421be7c8c4accd031d41 Mon Sep 17 00:00:00 2001 From: Irakli Gozalishvili Date: Mon, 22 Jan 2024 13:41:57 -0800 Subject: [PATCH 20/20] fix: anchor link --- w3-access.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/w3-access.md b/w3-access.md index c837e28..5cc986d 100644 --- a/w3-access.md +++ b/w3-access.md @@ -570,7 +570,7 @@ When Bob runs the `w3up` agent the first time and authorizes as `bob@gmail.com`, [access]:#access [DID]:https://www.w3.org/TR/did-core/ [DAG-JSON]:https://ipld.io/specs/codecs/dag-json/spec -[access example]:#Example_in_DAG-JSON +[access example]:#example-in-dag-json [w3up]:https://github.com/web3-storage/w3up [IPLD Map]:https://ipld.io/docs/schemas/features/typekinds/#map [IPLD Link]:https://ipld.io/docs/schemas/features/links