Skip to content

Commit

Permalink
Add EIP-5573: SIWE ReCap Extension (ethereum#5573)
Browse files Browse the repository at this point in the history
* fix: added a lot of sections

* fix: first stab EIP

* fix: added cel

* fix: some fixes

* fix: some fixes

* fix: formatting

* fix: some fixes

* fix: some formatting

* fix: fixed example

* fix: made spec more clear

* fix: editorial

* fix: editorial

* fix: editorial

* fix: editorial

* fix: editorial

* fix: editorial

* fix: editorial

* Update EIPS/eip-4361-1.md

Co-authored-by: Jacob <93085583+cobward@users.noreply.github.com>

* Update EIPS/eip-4361-1.md

Co-authored-by: Jacob <93085583+cobward@users.noreply.github.com>

* Update EIPS/eip-4361-1.md

Co-authored-by: Jacob <93085583+cobward@users.noreply.github.com>

* Update EIPS/eip-4361-1.md

Co-authored-by: Jacob <93085583+cobward@users.noreply.github.com>

* Update EIPS/eip-4361-1.md

Co-authored-by: Jacob <93085583+cobward@users.noreply.github.com>

* Update EIPS/eip-4361-1.md

Co-authored-by: Jacob <93085583+cobward@users.noreply.github.com>

* Update EIPS/eip-4361-1.md

Co-authored-by: Jacob <93085583+cobward@users.noreply.github.com>

* Update EIPS/eip-4361-1.md

Co-authored-by: Jacob <93085583+cobward@users.noreply.github.com>

* Update EIPS/eip-4361-1.md

Co-authored-by: Jacob <93085583+cobward@users.noreply.github.com>

* Update EIPS/eip-4361-1.md

Co-authored-by: Jacob <93085583+cobward@users.noreply.github.com>

* Update EIPS/eip-4361-1.md

Co-authored-by: Jacob <93085583+cobward@users.noreply.github.com>

* Update EIPS/eip-4361-1.md

Co-authored-by: Jacob <93085583+cobward@users.noreply.github.com>

* Update EIPS/eip-4361-1.md

Co-authored-by: Jacob <93085583+cobward@users.noreply.github.com>

* Update EIPS/eip-4361-1.md

Co-authored-by: Jacob <93085583+cobward@users.noreply.github.com>

* fix: removed registry

* fix: changed EIP number

* fix: adjusted description

* fix: restructured EIP

* fix: updated authors

* fix: fixed structure

* fix: fixed description

* Use three letter names for capgrok fields.

* fix: added eth magician forum URL

* fix: fixed template

* Add link to EIP-4361.

* Update EIPS/eip-4362.md

Co-authored-by: Pandapip1 <45835846+Pandapip1@users.noreply.github.com>

* Update EIPS/eip-4362.md

Co-authored-by: Pandapip1 <45835846+Pandapip1@users.noreply.github.com>

* Update EIPS/eip-4362.md

Co-authored-by: Pandapip1 <45835846+Pandapip1@users.noreply.github.com>

* Update EIPS/eip-4362.md

Co-authored-by: Pandapip1 <45835846+Pandapip1@users.noreply.github.com>

* Update EIPS/eip-4362.md

Co-authored-by: Pandapip1 <45835846+Pandapip1@users.noreply.github.com>

* Update EIPS/eip-4362.md

Co-authored-by: Pandapip1 <45835846+Pandapip1@users.noreply.github.com>

* Update EIPS/eip-4362.md

Co-authored-by: Pandapip1 <45835846+Pandapip1@users.noreply.github.com>

* Update EIPS/eip-4362.md

Co-authored-by: Pandapip1 <45835846+Pandapip1@users.noreply.github.com>

* Update EIPS/eip-4362.md

Co-authored-by: Pandapip1 <45835846+Pandapip1@users.noreply.github.com>

* Update EIPS/eip-4362.md

Co-authored-by: Pandapip1 <45835846+Pandapip1@users.noreply.github.com>

* Update EIPS/eip-4362.md

Co-authored-by: Pandapip1 <45835846+Pandapip1@users.noreply.github.com>

* fix: changed title to be more descriptive

* Update EIPS/eip-4362.md

Co-authored-by: Sam Wilson <57262657+SamWilsn@users.noreply.github.com>

* Update EIPS/eip-4362.md

Co-authored-by: Pandapip1 <45835846+Pandapip1@users.noreply.github.com>

* Update EIPS/eip-4362.md

Co-authored-by: Sam Wilson <57262657+SamWilsn@users.noreply.github.com>

* Update EIPS/eip-4362.md

Co-authored-by: Sam Wilson <57262657+SamWilsn@users.noreply.github.com>

* Update EIPS/eip-4362.md

Co-authored-by: Sam Wilson <57262657+SamWilsn@users.noreply.github.com>

* Update EIPS/eip-4362.md

Co-authored-by: Bumblefudge <jcaballero@centre.io>

* fix: moved rationale text to motivation

* fix: added CapGroks ref

* fix: removed URI requirement from URI since defined by EIP-4361

* fix: added intended

* fix: add base64url ref

* fix: added bumblefudges comments on nbf

* fix: changed filename to eip-5573.md

* fix: fixed title

* fix: renamed urn:capability into urn:ocap to save space

* fix: renamed capgrok to recap based on community feedback

* fix: changed urn:ocap to urn:recap based on community feedback

* Update EIPS/eip-5573.md

Co-authored-by: Jacob <jacob.ward@spruceid.com>

Co-authored-by: Oliver Terbu <oliver@awoie.local>
Co-authored-by: Jacob <93085583+cobward@users.noreply.github.com>
Co-authored-by: Jacob <jacobbward0@gmail.com>
Co-authored-by: Pandapip1 <45835846+Pandapip1@users.noreply.github.com>
Co-authored-by: Sam Wilson <57262657+SamWilsn@users.noreply.github.com>
Co-authored-by: Bumblefudge <jcaballero@centre.io>
Co-authored-by: Jacob <jacob.ward@spruceid.com>
  • Loading branch information
8 people authored and nachomazzara committed Jan 13, 2023
1 parent 1b28889 commit c9771b6
Showing 1 changed file with 273 additions and 0 deletions.
273 changes: 273 additions & 0 deletions EIPS/eip-5573.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,273 @@
---
eip: 5573
title: Sign-In with Ethereum Capabilities, ReCaps
description: Mechanism on top of Sign-In with Ethereum for informed consent to delegate capabilities with an extensible scope mechanism
author: Oliver Terbu (@awoie), Jacob Ward (@cobward), Charles Lehner (@clehner), Sam Gbafa (@skgbafa), Wayne Chang (@wyc)
discussions-to: https://ethereum-magicians.org/t/eip-5573-siwe-recap
status: Draft
type: Standards Track
category: ERC
created: 2021-07-20
requires: 4361
---

## Abstract
[EIP-4361](./eip-4361.md), or Sign-In with Ethereum (SIWE), describes how Ethereum accounts authenticate with off-chain services. This proposal, known as ReCaps, describes a mechanism on top of SIWE to give informed consent to delegate capabilities with a certain extensible scope mechanism to an authorized delegee. How a delegee authenticates against the target resource is out of scope for this specification and depends on the implementation of the target resource.

## Motivation

SIWE ReCaps unlock integration of protocols and/or APIs for developers by reducing user friction, onchain state and increasing security by introducing informed consent and deterministic capability objects on top of Sign-In With Ethereum (EIP-4361).

While SIWE focuses on authenticating the Ethereum account against the service (relying party or SIWE client) initiating the SIWE flow, there is no canonical way to interact with a third-party service (resource service) on behalf of the authenticated Ethereum account. For example, a relying party might want to interact with another service on behalf of the Ethereum account, for example a service that provides data storage for the Ethereum account. This specification introduces a mechanism, that allows the service (or more generally a delegee) to combine authentication and authorization of such while preserving security and optimizing UX.

Note, this approach is a similar mechanism to combining OpenID Connect (SIWE auth) and OAuth2 (SIWE ReCap) whereas SIWE ReCap follows an Object Capability-based approach.

## Specification

This specification has three different audiences:
- Web3 application developers that want to integrate ReCaps to authenticate with any protocols and APIs that support object capabilities.
- Protocol or API developers that want to learn how to define their own ReCaps.
- Wallet implementers that want to improve the UI for ReCaps.

### Terms and Definitions

- ReCap - A SIWE Message complying with this specification, i.e., containing at least one ReCap URI in the `Resources` section and the corresponding human-readable ReCap Statement appended to the SIWE `statement`.
- ReCap URI - A type of URI under a certain namespace that resolves to a ReCap Details Object.
- ReCap Details Object - A JSON object describing the actions and optionally the resources associated with a ReCap Capability under a certain namespace.
- Resource Service (RS) - The entity that is providing third-party services for the Ethereum account.
- SIWE Client (SC) - The entity initiating the SIWE authentication and ReCap flow.
- Relying Party (RP) - same as SC in the context of authentication.

### Overview

This specification defines the following:
- ReCap SIWE Extension
- ReCap Capability
- ReCap URI Scheme
- ReCap Details Object Schema
- ReCap Translation Algorithm
- ReCap Verification

### ReCap SIWE Extension

A ReCap is an EIP-4361 message following a specific format that allows an Ethereum account to delegate a set of ReCap Capabilities to a delegee through informed consent. Each ReCap Capability MUST be represented by an entry in the `Resources` array of the SIWE message that MUST deterministically translate the ReCap Capability in human-readable form to the `statement` field in the SIWE message using the ReCap Translation Algorithm.

The following SIWE message fields are used to further define (or limit) the scope of all ReCap Capabilities:
- The `URI` field MUST specify the intended delegee, e.g., `https://example.com`, `did:key:z6MkhaXgBZDvotDkL5257faiztiGiC2QtKLGpbnnEGta2doK`. It is expected that the RS authenticates the delegee before invoking an action for the ReCap Capability.
- The `Issued At` field MUST be used to specify the issuance date of the ReCap Capabilities.
- If present, the `Expiration Time` field MUST be used as the expiration time of the ReCap Capabilities, i.e. the time at which the RS will no longer accept an invocation of the capabilities expressed in this form.
- If present, the `Not Before` field MUST be used as the time that has to expire before the RS starts accepting invocations of the capabilities expressed in the message.

The following is a non-normative example of a SIWE message with the SIWE ReCap Extension:
```text
example.com wants you to sign in with your Ethereum account:
0x0000000000000000000000000000000000000000
I further authorize https://example.com to perform the following actions on my behalf: (1) example: read for any. (2) example: append, delete for my.resource.1. (3) example: append for my.resource.2, my.resource.3.
URI: https://example.com
Version: 1
Chain ID: 1
Nonce: n-0S6_WzA2Mj
Issued At: 2022-06-21T12:00:00.000Z
Resources:
- urn:recap:example:eyJkZWYiOlsicmVhZCJdLCJ0YXIiOnsibXkucmVzb3VyY2UuMSI6WyJhcHBlbmQiLCJkZWxldGUiXSwibXkucmVzb3VyY2UuMiI6WyJhcHBlbmQiXSwibXkucmVzb3VyY2UuMyI6WyJhcHBlbmQiXX19
```

#### ReCap Capability

A ReCap Capability is identified by their ReCap URI that resolves to a ReCap Details Object which defines the associated actions and optional target resources. The scope of each ReCap Capability is attenuated by common fields in the SWIE message as described in the previous chapter, e.g., `URI`, `Issued At`, `Expiration Time`, `Not Before`.

##### ReCap URI Scheme

A ReCap URI starts with `urn:recap:` followed by the namespace discriminator, followed by `:` and the base64url-encoded payload of the ReCap Details Object. Note, the term base64url is defined in RFC4648 - Base 64 Encoding with URL and Filename Safe Alphabet.

The following is a non-normative example of a ReCap Capability that uses the `example` namespace:
```text
urn:recap:example:eyJkZWZhdWx0QWN0aW9ucyI6WyJyZWFkIl0sInRhcmdldGVkQWN0aW9ucyI6eyJteS5yZXNvdXJjZS4xIjpbImFwcGVuZCIsImRlbGV0ZSJdLCJteS5yZXNvdXJjZS4yIjpbImFwcGVuZCJdLCJteS5yZXNvdXJjZS4zIjpbImFwcGVuZCJdfX0
```

It is expected that RS implementers define their own namespace, e.g., `urn:recap:service:`.

##### ReCap Details Object Schema

The ReCap Details Object denotes which actions on which resources the delegee is authorized to invoke on behalf of the delegee for the validity period defined in the SIWE message. It can also contain additional information that the RS may require to verify a capability invocation. A ReCap Details Object MUST follow the following JSON Schema:

```jsonc
{
"$schema": "http://json-schema.org/draft-04/schema#",
"type": "object",
"properties": {
"def": {
"type": "array",
"items": {
"type": "string",
"minLength": 1
},
"minItems": 1
},
"tar": {
"type": "object",
"patternProperties": {
"^.+$": {
"type": "array",
"items": {
"type": "string",
"minLength": 1
},
"minItems": 1
}
},
"additionalProperties": false,
"minProperties": 1
},
"ext": {
"type": "object",
"minProperties": 1
}
},
"minProperties": 1,
"additionalProperties": false,
"dependentSchemas": {
"ext": {
"minProperties": 2
}
}
}
```

A ReCap Details Object defines the following properties:
- `def`: (CONDITIONAL) If present, `def` MUST be a JSON array of string values with at least one entry where each value describes an action the delegee MAY invoke in the RS on behalf of the Ethereum account without tying the scope to a particular target.
- `tar`: (CONDITIONAL) If present, `tar` MUST be a JSON object with variable properties where each property is a JSON array of string values each describing an action the delegee MAY invoke in the RS on behalf of the Ethereum account on the target resource denoted by the property name.
- `ext`: (OPTIONAL) If present, `ext` MUST be a JSON object with variable properties.

The following is a non-normative example of a ReCap Capability Object with `def`, `tar` and `ext`:
```jsonc
{
"def":[
"read"
],
"tar":{
"my.resource.1":[
"append",
"delete"
],
"my.resource.2":[
"append"
],
"my.resource.3":[
"append"
]
},
"ext":{
"parentCapability": "bafybeigk7ly3pog6uupxku3b6bubirr434ib6tfaymvox6gotaaaaaaaaa"
}
}
```

In the example above, the delegee is authorized to perform the action `read` independent of any resource, `append`, `delete` on resource `my.resource.1`, `append` on resource `my.resource.2` and `append` on `my.resource.3`. Note, the delegee can invoke each action invididually and independent from each other in the RS. Additionally the ReCap Capability Object contains some additional information that the RS will need during verification. The responsibility for defining the structure and semantics of this data lies with the RS.

It is expected that RS implementers define which resources they want to expose through ReCap Details Objects and which actions they want to allow to invoke on them.

#### ReCap Translation Algorithm

After applying the ReCap Translation Algorithm on a given SIWE message that MAY include a pre-defined `statement`, the `recap-transformed-statement` in a ReCap SIWE message MUST conform to the following ABNF:
```text
recap-transformed-statement = statement recap-preamble 1*(" " recap-statement-entry ".")
; see EIP-4361 for definition of input-statement
recap-preamble = "I further authorize " uri " to perform the following actions on my behalf:"
; see EIP-4361 for definition of uri
recap-statement-entry = "(" number ") " recap-namespace ": "
recap-action *("," recap-action) "for"
( "any" / ( recap-resource *(", " recap-resource) ) )
; see RFC8259 for definition of number
recap-namespace = string
; see RFC8259 for definition of string
recap-action = string
; see RFC8259 for definition of string
recap-resource = string
; see RFC8259 for definition of string
```

The following algorithm or an algorithm that produces the same output MUST be performed to generate the SIWE ReCap Transformed Statement.

Inputs:
- Let `uri` be the uri field of the input SIWE message conforming to EIP-4361.
- Let `recap-uris` be a non-empty array of ReCap URIs, which represent the ReCap Capabilities that are to be encoded in the SIWE message, and which contain ReCap Details Objects which conform to the ReCap Details Object Schema.
- [Optional] Let `statement` be the statement field of the input SIWE message conforming to EIP-4361.
Algorithm:
- Let `recap-transformed-statement` be an empty string value.
- If `statement` is present, do the following:
- Append the value of the `statement` field of `siwe` to `recap-transformed-statement`.
- Append a single space character `" "` to `recap-transformed-statement`.
- Append the following string to `recap-transformed-statement`: "I further authorize ".
- Append `uri` to `recap-transformed-statement`.
- Append the following string to `recap-transformed-statement`: " to perform the following actions on my behalf:".
- Let `numbering` be an integer starting with 1.
- For each entry in `recap-uris` (starting with the first entry), perform the following:
- Let `namespace` be the `namespace` in the ReCap URI entry and let `capDetails` be the base64url-decoded ReCap Details Object of the ReCap URI entry.
- Let `defaultActions` be the `def` JSON array in `capDetails`, where each value represents an action.
- If `defaultActions` is present, do the following:
- Let `actions` be the string concatenation of each action in the array with the delimiter `", "`.
- Append the string concatenation of `" ("`, `numbering`, `")"` to `recap-transformed-statement`.
- Append `namespace` concatenated with `": "` to `recap-transformed-statement`.
- Append `actions` to `recap-transformed-statement`.
- Append the string `" for any."` to `recap-transformed-statement`.
- Increase `numbering` by 1.
- Let `targetedActions` be the `tar` JSON object in `capDetails`, where each key-value pair represents the set of actions allowed for a target.
- If `targetedActions` is present, do the following:
- Let `actionSets` be an array of arrays of strings;
- For each key-value pair in `targetedActions`, ordered alphabetically by key, append the string array value to `actionSets`.
- For each array of strings `actionSet` in `actionSets`, do the following:
- Sort the strings in `actionSet` alphabetically.
- Let `actions` be the string concatenation of each action in the array with the delimiter `", "`.
- Let `targets` be the string concatenation of each key in `targetedActions` with the delimiter `", "`, for those keys such that the associated value (or any permutation of that value) is identical to `actionSet`.
- Append the string concatenation of `" ("`, `numbering`, `")"` to `recap-transformed-statement`.
- Append `namespace` concatenated with `": "` to `recap-transformed-statement`.
- Append `actions` to `recap-transformed-statement`.
- Append the string `" for "` to `recap-transformed-statement`.
- Append `targets` to `recap-transformed-statement`.
- Append the string `" ."` to `recap-transformed-statement`.
- Increase `numbering` by 1.
- Return `recap-transformed-statement`.

#### ReCap Verification Algorithm

The following algorithm or an algorithm that produces the same output MUST be performed to verify a SIWE ReCap.

Inputs:
- Let `recap-siwe` be the input SIWE message conforming to EIP-4361 and this EIP.
- Let `siwe-signature` be the output of signing `recap-siwe`, as defined in EIP-4361.
Algorithm:
- Perform EIP-4361 signature verification with `recap-siwe` and `siwe-signature` as inputs.
- Let `uri` be the uri field of `recap-siwe`.
- Let `recap-uris` be an array of recap URIs taken in order from the resources field of `recap-siwe`, such that URIs which are not valid ReCap URIs are ignored.
- Let `recap-transformed-statement` be the result of performing the above `ReCap Translation Algorithm` with `uri` and `recap-uris` as input.
- Assert that the statement field of `recap-siwe` ends with `recap-transformed-statement`.

### Implementer's Guide

TBD

#### Web3 Application Implementers

TBD

#### Wallet Implementers

TBD

#### Protocol or API Implementers

TBD

## Rationale

TBD

## Security Considerations

Resource service implementer's should not consider ReCaps as bearer tokens but instead require to authenticate the delegee in addition. The process of authenticating the delegee against the resource service is out of scope of this specification and can be done in various different ways.

## Copyright
Copyright and related rights waived via [CC0](../LICENSE.md).

0 comments on commit c9771b6

Please sign in to comment.