Skip to content
Merged
Show file tree
Hide file tree
Changes from 13 commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
d75e96d
constrain to CAIP-25 session explicitly
Mar 2, 2023
4c4ae73
typo
bumblefudge Mar 3, 2023
be1aa1c
typo
bumblefudge Mar 3, 2023
95c5268
strawman CAIP-217
Mar 29, 2023
407691f
fine-tuning simple CAIP-217
Mar 29, 2023
2e54eaa
simplified CAIP-27
Mar 29, 2023
aa9506d
simplified CAIP-25
Mar 29, 2023
ac80b88
typo
bumblefudge Apr 5, 2023
e79a945
formatting tweak
bumblefudge Apr 5, 2023
0ef0acc
typo
bumblefudge Apr 5, 2023
03884a6
typo
bumblefudge Apr 5, 2023
9300226
typo
bumblefudge Apr 5, 2023
c1aaf10
language fine-tuning
Apr 6, 2023
f3cb8fc
make accounts optionality and semantics more explicit
Apr 12, 2023
66b56ff
make informational version of CAIP-211
Apr 12, 2023
859551d
add abstract to informational version of CAIP-211
Apr 12, 2023
d92e474
add wallet methods to caip-25
pedrouid Apr 13, 2023
48e0e3d
typo
pedrouid Apr 13, 2023
01459af
resolve
pedrouid Apr 13, 2023
555c005
fine-tune abstract
Apr 13, 2023
7f4801b
typo
Apr 13, 2023
5afcb22
Merge pull request #224 from ChainAgnostic/feat/caip-25-include-examp…
pedrouid Apr 13, 2023
0e72bb6
add security considerations with negotiation example
Apr 13, 2023
0fea9db
resolve conflicts
Apr 13, 2023
8a92f2b
to clarify scopes object semantics
May 19, 2023
5076373
to clarify the syntax of string to which each object is keyed
May 19, 2023
1037853
to clarify the semantics of the whole object in # spec section
May 19, 2023
96e7760
to clarify that responses are specified per namespace, not here
May 19, 2023
5097a2d
to clarify that 2 of 3 options in caip25 example are corner cases
May 19, 2023
0de8414
remove hard requirement on as-yet unmergeddefined CAIP-170
May 19, 2023
e45f802
restore property 5 in caip171
May 19, 2023
5fcdf9b
Merge branch 'master' into feat/update-caip27-to-be-constrained-by-25
bumblefudge May 19, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
91 changes: 91 additions & 0 deletions CAIPs/caip-217.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
---
caip: 217
title: Authorization Scopes
author: Pedro Gomes (@pedrouid), Hassan Malik (@hmalik88), Juan Caballero (@bumblefudge)
discussions-to: ["https://github.com/ChainAgnostic/CAIPs/discussions/217","https://github.com/ChainAgnostic/CAIPs/discussions/211"]
status: Draft
type: Standard
created: 2022-11-09
---

## Simple Summary

This CAIP defines a simple syntax for scopes of authorization between applications (e.g. dapps) and user-agents (e.g. "wallets" or signers). These are described in JSON objects as a building block across multiple protocols and mechanisms:
- A JSON-RPC protocol for persisting and synchronizing authorized sessions ([CAIP-25][])
- Routing individual RPC commands to an authorized network ([CAIP-27][])

## Motivation

The layering of today's cryptographic and decentralized systems favors
loosely-coupled combinations of protocols (representated in the CAIPs model as
[namespaces][]), instances or consensus-communities within those protocols
(addressed in the CAIPs model as [CAIP-2][] URNs), and sets of supported RPC
methods and notifications used in those namespaces. Bundling all of these into
an object facilitates unambiguous authorization schemes, including progressive
authorization patterns, feature discovery, authority negotiation (See
[CAIP-211][]) and delegations.

## Specification

An authorization scope is represented in JSON as a string that expresses its
scope and a JSON object defining the bundle of properties authorized there. When
embedded in any other JSON context (including the `params` of a JSON-RPC
message), the object MUST be expressed as the value of a property named by the
scope string.

### Language

The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD",
"SHOULD NOT", "RECOMMENDED", "NOT RECOMMENDED", "MAY", and "OPTIONAL" written in
uppercase in this document are to be interpreted as described in [RFC
2119](https://www.ietf.org/rfc/rfc2119.txt)

### Definition

The syntax is as follows:

```jsonc

scope: string

scopeObject: {
*scopes: [(chainId)+],
methods: [(method_name)+],
notifications: [(notification_name)+],
accounts: [(account_id)+]
*rpcDocuments: [(rpcDocument)+],
*rpcEndpoints: [(rpcEndpoint)+]
}
```

Where:

- `string` (conditional) = A namespace identifier string registered in the CASA [namespaces][] registry to authorize multiple chains with identical properties OR a single, valid [CAIP-2][] identifier, i.e., a specific `chain_id` within a namespace.
Comment thread
bumblefudge marked this conversation as resolved.
Outdated
- `scopes` (conditional) = An array of 0 or more [CAIP-2][] `chainId`s. Setting multiple `scopes` is equivalent to making multiple copies of the `scopeObject` for each member of `scopes`, simply in compact form.
Comment thread
bumblefudge marked this conversation as resolved.
Outdated
- This property MUST NOT be present if the object is already scoped to a single `chainId` in the string value above.
- This property MUST NOT be present if the scope is an entire [namespace][namespaces] in which `chainId`s are not defined.
- This property MAY be present if the scope is an entire [namespace][namespaces] in which `chainId`s are defined.
- `methods` = An array of 0 or more JSON-RPC methods that an application can call on the agent and/or an agent can call on an application.
- `notifications` = An array of 0 or more JSON-RPC notifications that an application send to or expect from the agent.
- `accounts` (optional) = An array of 0 or more [CAIP-10][] identifiers valid within the scope of authorization.
Comment thread
bumblefudge marked this conversation as resolved.
Outdated
- `rpcDocuments` (optional) = An array of URIs that each dereference to an RPC document specifying methods and notifications applicable in this scope.
- These are ordered from most authoritative to least, i.e. methods defined more than once by the union of entries should be defined by their earliest definition only.
- `rpcEndpoints` (optional) = An array of URLs that each dereference to an RPC endpoints for routing requests within this scope.
- These are ordered from most authoritative to least, i.e. priority SHOULD be given to endpoints in the order given, as per the CAIP-217 profile for that [namespace][namespaces], if one has been specified.

Whenever another CAIP uses the name `scopeObject` and has this CAIP in the
`required` front-matter property, it SHALL be interpreted as reference to this
specification.

## References

[CAIP-10]: https://chainAgnostic.org/CAIPs/CAIP-10
[CAIP-25]: https://chainAgnostic.org/CAIPs/CAIP-25
[CAIP-27]: https://chainAgnostic.org/CAIPs/CAIP-27
[CAIP-211]: https://chainAgnostic.org/CAIPs/CAIP-211
[namespaces]: https://namespaces.chainAgnostic.org/

## Copyright

Copyright and related rights waived via
[CC0](https://creativecommons.org/publicdomain/zero/1.0/).
181 changes: 83 additions & 98 deletions CAIPs/caip-25.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,68 +19,63 @@ protocol.
## Abstract

This proposal has the goal to define a standard procedure for decentralized
applications to interface with cryptocurrency wallets which govern accounts on
multiple chains and defining a set of rules to be followed during a session
managed by a provider construct.
applications to interface with chain agnostic cryptocurrency wallets and other
user agents which govern identities (including accounts) in multiple
cryptographic systems. It defines a lightweight protocol for negotiating and
persisting authorizations during a session managed by a provider construct.

## Motivation

The motivation comes from the lack of standardization across blockchains to
expose accounts and define the expected JSON-RPC methods to be used by an
application through a provider connecting to a wallet.
application through a provider connecting to a wallet or other user agent.

## Specification

The session is defined by a wallet's response to a provider's request, and
updated, extended, closed, etc by successive calls and notifications. The exact
parameters and assumptions of that session abstraction are defined in
[CAIP-171][], but note that a string identifier referring to it is absent from
the initial call (if authorization is granted) and present in both the initial
response and all future responses.

Given the session model of [CAIP-171][], this interface outlines the
authorization of a provider to handle a set of interfaces grouped into
namespaces, as well as to interact with a session abstraction used by both
caller and respondent to manage the authorization over time. The
`sessionIdentifier` defined in [CAIP-171][] enables this mutual management and
alignment across calls that are idempotent if identical. If a respondent (e.g. a
wallet) needs to initiate a new session, whether due to user input, security
policy, or session expiry reasons, it can simply generate a new session
identifier to signal this notification to the calling provider; if a caller
needs to initiate a new session, it can do so by sending a new request without
`sessionIdentifier`. In such cases, a respondent (e.g. wallet) may choose to
explicitly close all sessions upon generation of a new one from the same origin,
or leave it to time-out; maintaining concurrent sessions is discouraged (see
Security Considerations).

In the initial call, the application interfaces with a provider to populate a
session with a base state describing authorized chains, methods, notification,
and accounts. This negotation takes place by sending the application's REQUIRED
and REQUESTED authorizations of the session, grouped into objects scoping those
authorizations which in turn are grouped into two top-level objects (named
`requiredScopes` and `optionalScopes` respectively). These two objects are not
mutually exclusive (i.e., additional properties of a required scope may be
requested under the same keyed scope object key in the requested object). Note
that scopes can be keyed to an entire [CAIP-104][] "namespace", meaning
applicable to *any* current or future [CAIP-2][] chainID within that namespace,
or keyed to a specific [CAIP-2][] within that namespace.

If any properties in the required scope(s) are not authorized by the
respondent (e.g. wallet), a failure response expressive of one or more specific
failure states will be sent (see [#### failure states](#failure-states) below),
with the exception of user denying consent. For privacy reasons, an `undefined`
response (or no response, depending on implementation) should be sent to prevent
incentivizing unwanted requests and to minimize the surface for fingerprinting
of public web traffic (See Privacy Considerations below).
The session is proposed by a caller and the response by the respondent is used
as the baseline for an ongoing session that both parties will persist. The
properties of this session, which is identified mutually by an entropic
[identifier][CAIP-171] assigned in the initial response, get updated, extended,
closed, etc. by successive calls and notifications, each tagged by this
identifier.

If a respondent (e.g. a wallet) needs to initiate a new session, whether due to
user input, security policy, or session expiry reasons, it can simply generate a
new session identifier to signal this notification to the calling provider; if a
caller needs to initiate a new session, it can do so by sending a new request
without a `sessionIdentifier`. In such cases, a respondent (e.g. wallet) may
choose to explicitly close all sessions upon generation of a new one from the
same origin or identity, or leave it to time-out; maintaining concurrent
sessions is discouraged (see Security Considerations).

Initial and ongoing authorization requests are grouped into two top-level arrays
of [scopeObjects][CAIP-217], named `requiredScopes` and `optionalScopes`
respectively. These two objects are not mutually exclusive (i.e., additional
properties of a required scope may be requested in a separate `scopeObject` in
the optional array, keyed to the same scope string). Note that `scopeObject`s
can be keyed to a specific [CAIP-2][], or to a [CAIP-104][] namespace; if the
latter defines a [CAIP-2][] profile, a `scopes` array MAY be set within it
containing multiple [CAIP-2][] strings; this is functionally equivalent to
defining multiple identical `scopeObjects`, each keyed to one [CAIP-2]. See
[CAIP-217][] for more details on the structure of these objects.

If any properties in the required scope(s) are not authorized by the respondent,
a failure response expressive of one or more specific failure states will be
sent (see [#### failure states](#failure-states) below), with the exception of
user denying consent. For privacy reasons, an `undefined` response (or no
response, depending on implementation) should be sent to prevent incentivizing
unwanted requests and to minimize the surface for fingerprinting of public web
traffic (See Privacy Considerations below).

Conversely, a succesful response will contain all the required properties *and
the provider's choice of the optional properties* expressed as a unified set of
parameters. In the case of identically-keyed scopes appearing in both arrays in
the request where properties from both are returned as authorized, the two
scopes MUST be merged in the response (see examples below). However, respondents
MUST NOT restructure scopes (e.g., by folding properties from a [CAIP2][]-keyed,
chain-specific scope object into a [CAIP-104][]-keyed, namespace-wide scope
object) as this may introduce ambiguities (See Security Considerations below).
the provider's choice of the optional properties* expressed in a single unified
`scopeObject`. In the case of identically-keyed `scopeObject`s appearing in both
arrays in the request where properties from both are returned as authorized, the
two scopes MUST be merged in the response (see examples below). However,
respondents MUST NOT restructure scopes (e.g., by folding properties from a
[CAIP2][]-keyed, chain-specific scope object into a [CAIP-104][]-keyed,
namespace-wide scope object) as this may introduce ambiguities (See Security
Considerations below).

### Request

Expand All @@ -97,7 +92,7 @@ Example:
"params": {
"requiredScopes": {
"eip155": {
"chains": ["eip155:1", "eip155:137"],
"scopes": ["eip155:1", "eip155:137"],
"methods": ["eth_sendTransaction", "eth_signTransaction", "eth_sign", "get_balance", "personal_sign"],
"notifications": ["accountsChanged", "chainChanged"]
},
Expand All @@ -122,34 +117,24 @@ Example:
}
```

The JSON-RPC method is labelled as `provider_authorize` and its `params` object
contains "requiredScopes" and/or "optionalScopes" objects populated with "scope
objects" each named after the scope of authorization requested:
1. EITHER an entire [CAIP-104][] [namespace][]
2. OR a specific [CAIP-2][]-identified chain in a specific namespace.

Each scope object contains the following parameters:
- chains - array of [CAIP-2][]-compliant `chainId`'s. This parameter MAY be
omitted if a single-chain scope is already declared in the index of the object.
- methods - array of JSON-RPC methods expected to be used during the session
- notifications - array of JSON-RPC message/notifications expected to be emitted
during the session

The `requiredScopes` array MUST contain 1 or more of these objects, if present;
the `optionalScopes` array MUST contain 1 or more of them, if present.

A third object is the `sessionProperties` object, all of whose properties MUST
be in the interpreted as optional, since requesting applications cannot mandate
session variables to providers. Because they are optional, providers MAY respond
with all of the requested properties, or a subset of the session properties, or no
The JSON-RPC method is labeled as `provider_authorize` and its `params` object
contains "requiredScopes" and/or "optionalScopes" objects populated with
[CAIP-217][] "scope objects" keyed to [CAIP-217][] scope strings.
- The `requiredScopes` array MUST contain 1 or more `scopeObjects`, if present.
- The `optionalScopes` array MUST contain 1 or more `scopeObjects`, if present.

A third object is the `sessionProperties` object, all of whose properties MUST
be interpreted as optional, since requesting applications cannot mandate session
variables to providers. Because they are optional, providers MAY respond with
all of the requested properties, or a subset of the session properties, or no
`sessionProperties` object at all; they MAY even replace the values of the
optional session properties with their own values. The `sessionProperties`
optional session properties with their own values. The `sessionProperties`
object MUST contain 1 or more properties if present.

Requesting applications are expected to track all of these returned properties in
the session object identified by the `sessionId`. All properties and their values
MUST conform to definitions in [CAIP-170][], and MUST be ignored (rather than
tracked) if they do not.
Requesting applications are expected to persisted all of these returned
properties in the session object identified by the `sessionId`. All properties
and their values MUST conform to definitions in [CAIP-170][], and MUST be
ignored (rather than persisted) if they do not.

### Response

Expand All @@ -160,17 +145,15 @@ The wallet can respond to this method with either a success result or an error m
The successful result contains one mandatory string (keyed as `sessionId` with a value
conformant to [CAIP-171][]) and two session objects, both mandatory and non-empty.

The first is called `sessionScopes` and contains 1 or more scope objects.
* All required scope objects and all, none, or some of the optional scope object
(at the discretion of the provider) MUST be included if successful.
* As in the request, each scope object object MUST contain `methods` and
`notifications` objects, and a `chains` object if a specific chain is not
specified in the object's index.
The first is called `sessionScopes` and contains 1 or more `scopeObjects`.
* All required `scopeObjects` and all, none, or some of the optional
`scopeObject`s (at the discretion of the provider) MUST be included if
successful.
* Unlike the request, each scope object MUST also contain an `accounts` array,
containing 0 or more [CAIP-10][] conformant accounts authorized for the session
and valid in the namespace and chain(s) authorized by the scope object they are
in. Additional constraints on the accounts authorized for a given session MAY be
specified in the corresponding [CAIP-104][] namespaces specification.
containing 0 or more [CAIP-10][]-conformant accounts authorized for the session
and valid in that scope. Additional constraints on the accounts authorized for a
given session MUST be applied conformant to the namespace's [CAIP-10][] profile,
if one has been specified.

A `sessionProperties` object MAY also be present, and its contents MAY
correspond to the properties requested in the response or not (at the discretion
Expand Down Expand Up @@ -294,9 +277,10 @@ friction and user experience problems in the case of malformed requests.
* code = 5301
* message = "Session Properties can only be optional and global"

Note: respondents are RECOMMENDED to implement support for core RPC Documents
per each supported namespace to avoid sending error messages 5201 and 5202 in
cases where 0, 5101 or 5102 would be more appropriate.
Note: respondents SHOULD to implement support for core RPC Documents per each
supported namespace to avoid sending error messages 5201 and 5202 in cases where
0, 5101 or 5102 would be more appropriate. Failure to do so may leak versioning
or feature-completeness information to a malicious or fingerprinting caller.

## Security Considerations

Expand All @@ -319,9 +303,9 @@ deanonymize browsers and/or wallets deductively based on response times, error
codes, etc. To minimize this risk, and to minimize the data (including
behavioral data) leaked by responses to potentially malicious CAIP-25 calls,
respondents are recommended to ignore calls
1. which the respondent does not authorize,
2. which are rejected by policy, or
3. requests which are rejected for unknown reasons.
1. which the respondent explicitly does not authorize,
2. which are rejected automatically or by policy, or
3. which are rejected for unknown reasons.

"Ignoring" these calls means responding to all three in a way that is
*indistinguishable* to a malicious caller or observer which might deduce
Expand Down Expand Up @@ -354,6 +338,7 @@ was in violation of policy).

## Changelog

- 2023-03-29: refactored out scopeObject syntax as separate CAIP-217, simplified
- 2022-11-26: add mandatory indexing by session identifier (i.e. CAIP-171 requirement)
- 2022-10-26: Addressed Berlin Gathering semantics issues and params syntax;
consolidated variants across issues and forks post-Amsterdam Gathering
Expand All @@ -363,18 +348,18 @@ was in violation of policy).
- [CAIP-2][] - Chain ID Specification
- [CAIP-10][] - Account ID Specification
- [CAIP-25][] - JSON-RPC Provider Request
- [CAIP-75][] - Blockchain Reference for the Hedera namespace
- [CAIP-171][] - Session Identifier Specification
- [CAIP-171][] - Session Identifier, i.e. syntax and usage of `sessionId`s
- [CAIP-217][] - Authorization Scopes, i.e. syntax for `scopeObject`s

[CAIP-2]: https://chainagnostic.org/CAIPs/caip-2
[CAIP-10]: https://chainagnostic.org/CAIPs/caip-10
[CAIP-25]: https://chainagnostic.org/CAIPs/caip-25
[CAIP-75]: https://chainagnostic.org/CAIPs/caip-75
[CAIP-104]: https://chainagnostic.org/CAIPs/caip-104
[CAIP-170]: https://chainagnostic.org/CAIPs/caip-170
[CAIP-171]: https://chainagnostic.org/CAIPs/caip-171
[CAIP-217]: https://chainagnostic.org/CAIPs/caip-217
[namespaces]: https://namespaces.chainagnostic.org
[RFC3339]: https://datatracker.ietf.org/doc/html/rfc3339#section-5.6
[CAIP-170]: https://chainagnostic.org/CAIPs/caip-170

## Copyright

Expand Down
Loading