EIP-5573: SIWE ReCap

Crossposting Irakli’s response and suggestion: Multiple "can" for a "with" · Issue #123 · ucan-wg/spec · GitHub

An approach like this would be interesting and it solves for the merge approach you outlined above.


I think his suggestion also makes sense for ReCap:

Schema:

{
  $RESOURCE: {
    $ABILITY: $EXTENSION,
    ...
  },
  ...
  "prf": [&Link] // OCAP delegations
}

Example:

{
  "example://example.com/public/photos/": {
      "crud/delete": {}
  },
  "example://example.com/private/84MZ7aqwKn7sNiMGsSbaxsEa6EPnQLoKYbXByxNBrCEr": {
      "wnfs/append": {}
  },
  "example://example.com/public/documents/": {
    "crud/delete": {
      "matching": "/(?i)(\W|^)(baloney|darn|drat|fooey|gosh\sdarnit|heck)(\W|$)/" 
    }
  },
  "mailto:username@example.com": {
    "msg/send": {},
    "msg/receive": {
      "max_count": 5,
      "templates": ["newsletter", "marketing"]
    }
  }
}
1 Like

Unfortunately, it actually causes the merge problem above. [UPDATE @oed was talking the OTHER merge case. Sorry, entirely my bad :sweat_smile: The bit below is still useful I think]

Repeating here for the group/discussion here: duplicate key handling is under-specified in the JSON spec, and thus different libraries handle them differently:

From RFC 8259:

When the names within an object are not
unique, the behavior of software that receives such an object is
unpredictable. Many implementations report the last name/value pair
only. Other implementations report an error or fail to parse the object,
and some implementations report all of the name/value pairs,
including duplicates.

JSON parsing libraries have been observed to differ as to whether or
not they make the ordering of object members visible to calling
software. Implementations whose behavior does not depend on member
ordering will be interoperable in the sense that they will not be
affected by these differences.

However, we could solve this by wrapping it in an array. Adapting your example above:

[
  {
    "example://example.com/public/photos/": {
        "crud/delete": {}
  },
  {
    "example://example.com/private/84MZ7aqwKn7sNiMGsSbaxsEa6EPnQLoKYbXByxNBrCEr": {
      "wnfs/append": {}
  },
  {
    "example://example.com/public/documents/": {
      "crud/delete": {
        "matching": "/(?i)(\W|^)(baloney|darn|drat|fooey|gosh\sdarnit|heck)(\W|$)/" 
      }
    }
  },
  {
    "mailto:username@example.com": {
      "msg/send": {},
      "msg/receive": {
        "max_count": 5,
        "templates": ["newsletter", "marketing"]
      }
    }
  }
]

This adds two characters (the enclosing {}s) per capability, but makes it compatible with all parsers.

Ah! But agreed @oed that it solves the other case, on extensional fields! Sorry, so many kinds of merge happening there :stuck_out_tongue: :sweat_smile:

Will mention what I said in the other thread as well. I think it would be easier to solve the merge problem by simply not allowing duplicate resource keys?

That’s a change we could make, yeah. It does mean that there’s more things that people can mess up in an implementation, and it’s not a problem that we have in the existing version of UCAN. Not forcing this eliminates a Byzantine (buggy not malicious) case.

1 Like

Here’s my suggestion for how to update ReCap with the same structure as what is currently suggested for UCAN.

This looks really good to me! :tada: :clap:

We’ve updated the UCAN 0.10 WIP PR to use the above syntax :rocket:

1 Like

I am worried about uses like the example

{
   "def":[
      "read"
   ],
   "tar":{
      "my.resource.1":[
         "append",
         "delete"
      ],
      "my.resource.2":[
         "append"
      ],
      "my.resource.3":[
         "append"
      ]
   },
   "ext":{
       "parentCapability": "bafybeigk7ly3pog6uupxku3b6bubirr434ib6tfaymvox6gotaaaaaaaaa"
   }
}

If this example is used to make a request, you could be subject to a confused deputy vulnerability. That’s why a capability designates a single resource.

There are two options for this example. You could return a separate capability for each resource, or you could only accept a request if the capability designates a single resource. The former case takes up more space, and the latter requires delegating to yourself. I don’t view either of those to be much of a problem.

The example is just the delegation, the actual request (=invocation) happens on one specific capability, e.g., my.resource.1 + append, or my.resource.1 + delete, etc.
Does this address your concern?

I like the arrangement of the JSON representation, it’s great. w.r.t. the statement generation, we have been thinking about how to make namespaced actions like crud/read more obvious. We suggest factoring out the common namespace for actions into a prefix separated with a :, e.g. crud/read + crud/write becomes crud: read, write. In this way, a recap like

{
  att: {
    https://example.com/public/photos/: {
      crud/read: [],
      other/action: []
    },
    https://somewhere.else: {
      crud/read: [],
      crud/delete: []    
    }
  },
  prf: []
}

would become:
I further authorize https://example.com to perform the following actions on my behalf: (1) crud: "read" for "http://example.com/public/photos/". (2) other: "action" for "http://example.com/public/photos/". (3) crud: "read", "delete" for "https://somwhere.else".

It factors out the namespace to make each clause define the actions from one namespace for one resource. I think this helps emphasise the purpose and makes it a bit harder for a reader to skip over an action that isn’t expected to be there
I think that many URIs will be unparsable for regular users, but we couldn’t think of a way to make them easier to read in a general case by manipulating them somehow. That’s still a nice to have for us but we are fine right now with using whole URIs in the statement.

1 Like

Yes. And sorry for the delay in answering. For some reason your prompt response escaped my notice.

This approach looks quite reasonable to me.

The main concern I would have is that the crud part of your example doesn’t get wrapped in "". A developer could potentially introduce spaces and special characters there. Maybe ReCap should specify which strings are legal as actions?

I think quoting the crud would be a good suggestion. when it comes to legal strings in general, some characters will naturally have to be illegal, e.g. newlines which would break the siwe statement, or slashes / which conflict with the json representation (like crud/read)

1 Like

Update: We incorporated all suggestions from @oed and @expede and we merged the changes already. See ERC-5573: Sign-In with Ethereum Capabilities, ReCaps for more details.

Thanks a lot for the feedback to everybody in this thread.

1 Like