w3up
w3up copied to clipboard
Sync access to spaces
We should make access sync really smooth across agents, it should be as simple as git pull
I suggest w3 access claim
command (as opposed to w3 can access claim
).
That sort of works today, but I don't believe it works quite like what I'd expect. Here is the scenario:
- User has two agents
A
andB
. - They have authorized both with the same account.
- On device
A
user created a space "Repo". - After running
w3 access claim
on deviceB
they should have access to space "Repo" and it must show when runningw3 space ls
.
I might be mistaken but I do not believe it currently works like that, because access claim will just pull down delegations for the agent. To make above work we also need to pull down delegations for the account and then locally:
- Redelegate access from account to an agent.
- Add all the new spaces to the list
Also I'm not sure if we capture space names anywhere, but it might be a good idea to do so in the delegation itself
so this does work in the simplest cases:
# create a space with agent 1
➜ W3_STORE_NAME=agent1 w3 space ls
➜ W3_STORE_NAME=agent1 w3 authorize [email protected]
⁂ agent authorized to use capabilities delegated to [email protected]
➜ W3_STORE_NAME=agent1 w3 space ls
did:key:z6Mkfy8k2JJUdNWCJtvzYrko5QRc7GXP6pksKDG19gxYzyi4
# now try to get the space with agent 2
➜ W3_STORE_NAME=agent2 w3 space ls
➜ W3_STORE_NAME=agent2 w3 authorize [email protected]
⁂ agent authorized to use capabilities delegated to [email protected]
➜ W3_STORE_NAME=agent2 w3 space ls
did:key:z6Mkfy8k2JJUdNWCJtvzYrko5QRc7GXP6pksKDG19gxYzyi4
# it worked!
but there does seem to be a bug where spaces created by agent 1 after agent 2 has authorized won't be accessible:
# create and provision _another_ space with agent 1
➜ W3_STORE_NAME=agent1 w3 space create
did:key:z6Mkm3DPFdNDqw3fGPDxyASZzHw9ndJoaFin4AFos5JNN1Nn
➜ W3_STORE_NAME=agent1 w3 space ls
did:key:z6Mkfy8k2JJUdNWCJtvzYrko5QRc7GXP6pksKDG19gxYzyi4
* did:key:z6Mkm3DPFdNDqw3fGPDxyASZzHw9ndJoaFin4AFos5JNN1Nn
➜ W3_STORE_NAME=agent1 w3 space register --email [email protected]
⁂ space registered to [email protected]
# now claim delegations with agent 2, hoping to get access to the new space
➜ W3_STORE_NAME=agent2 w3 space ls
did:key:z6Mkfy8k2JJUdNWCJtvzYrko5QRc7GXP6pksKDG19gxYzyi4
➜ W3_STORE_NAME=agent2 w3 can access claim
➜ W3_STORE_NAME=agent2 w3 space ls
did:key:z6Mkfy8k2JJUdNWCJtvzYrko5QRc7GXP6pksKDG19gxYzyi4
# it didn't work!
but! agents who authorize after that get both:
➜ W3_STORE_NAME=agent3 w3 authorize [email protected]
⁂ agent authorized to use capabilities delegated to [email protected]
➜ W3_STORE_NAME=agent3 w3 space ls
did:key:z6Mkm3DPFdNDqw3fGPDxyASZzHw9ndJoaFin4AFos5JNN1Nn
did:key:z6Mkfy8k2JJUdNWCJtvzYrko5QRc7GXP6pksKDG19gxYzyi4
and if I re-authorize (and work around a known issue where we don't wait for proofs when authorizing a second time), I do get the spaces I'm expecting:
➜ W3_STORE_NAME=agent2 w3 authorize [email protected]
⁂ agent authorized to use capabilities delegated to [email protected]
➜ W3_STORE_NAME=agent2 w3 space ls
did:key:z6Mkfy8k2JJUdNWCJtvzYrko5QRc7GXP6pksKDG19gxYzyi4
➜ W3_STORE_NAME=agent2 w3 can access claim
➜ W3_STORE_NAME=agent2 w3 space ls
did:key:z6Mkfy8k2JJUdNWCJtvzYrko5QRc7GXP6pksKDG19gxYzyi4
did:key:z6Mkm3DPFdNDqw3fGPDxyASZzHw9ndJoaFin4AFos5JNN1Nn
Me and @travis chatted about and looked into a fix which would require non-trivial changes. So we have decided that instead we can do following:
- Let user know on first authorization that to gain access to subsequent spaces they will need to reauthorize.
- Make
w3 access claim
top level command to pull delegations. - When user pulls delegations we will also pull delegations for account (assuming agent has been delegated access/claim capability) and if account has new spaces that we don't have access to we will ask user if they want to reauthorize to gain access
Separately I have also created https://github.com/web3-storage/ucanto/issues/325 which if fixed is going to allow to allow our to gain access to new spaces without having to go additional authorization loops.
Here is how I think we could solve this problem:
- When you call
w3 access claim
program should invokeaccess/claim
for own agent and all activeaccount
s. - Once delegations for agent are received they should be saved making them automatically available (which is what happens today I believe)
- For each account we filter out new delegations and we re-delegate each one to the local agent and save that delegation into a proofs.
We could do 1 and 2 but 3 is a tricky bit. Delegation from an account to the agent requires an attestation. Right now we create attestation only on authorization and perform interactive confirmation with a user over email.
So to accomplish no 3 I can think of the following options:
-
We revive https://github.com/web3-storage/ucanto/issues/325 so that existing account authorization (login) could be used to attest delegation from an account without having to go through a service backend and another email authorization flow.
- It is not a proper solution, because it goes against least authority design. When app is requesting access it should request minimum set of capabilities and user should choose which spaces to give access to. If app needs more permissions user should approve the request.
- If we go this route we are essentially putting apps on the track of asking for sudo access.
- However since we currently do not even give user an option to choose which spaces to give access to all of this is kind of moot point so we could go ahead and choose to address this when we give user a choice.
-
We could update UCAN validator so that on invocation you construct this kind of invocation and consider it valid:
{ iss: "did:key:zAlice" aud: "did:web:web3.storage" att: [{ can: "store/list", with: "did:key:zSpace" }] prf: [ { iss: "did:mailto:web.mail:alice", aud: "did:key:zAlice", att: [{ can: "*", with: "ucan:*" }] }, // This proof is misaligned by principal, according to spec it should be proof of ☝️, however new // spec does not need proofs in delegations it needs a proof path in invocations and this is // invocation so seems fine { iss: "did:key:zSpace", aud: "did:mailto:web.mail:alice", att: [{can: "*", with: "did:key:zSpace" }] }, ] }
- Please note that this is not aligned with principal of least authority, but at least we don't introduce new feature here just doing work we'll need for new version of UCANs.
-
We could implement API for creating attestations without the login flow. Specifically we could say if you send
access/request
oraccess/authorize
invocation where audience isdid:mailto
, we simply trigger email authorization flow where user is send an email if they click it in time we'll issue a delegation and corresponding attestation.- This requires no changes to ucanto and implementation should be fairly straight forward more or less what we do in
access/authorize
andaccess/confirm
. - It does imply however that when client discovers new spaces it would need to request authorization and make user click link in an email.
- Proper UX here would require discovering new spaces, and listing them as unauthorized so when you first try to use them is when you have to get email and click it. So while it's less work on the ucanto or a backend it's quite a bit of work in the clients
- This requires no changes to ucanto and implementation should be fairly straight forward more or less what we do in
Had a chat with @travis and we came up with a hybrid option which I think we should go with, specifically:
-
Extend
access/confirm
capability handler so thatwith
field could bedid:mailto
matching anaccount
here. So basically change following lineshttps://github.com/web3-storage/w3up/blob/e34eed1fa3d6ef24ce2c01982764f2012dbf30d8/packages/upload-api/src/access/confirm.js#L33-L38
To these
const { account, agent } = parse(capability) // Confirmation MUST be authorized either by an account or a service if (capability.with !== ctx.signer.did() && capability.with !== account.did()) { throw new Error(`Not a valid access/confirm delegation`) }
-
For accounts new spaces agent could issue
access/confirm
invocation using an accountwith
and store that delegation into proof store.