---
# System prepended metadata

title: UCAN delegation with w3up

---

# UCAN delegation with w3up

In our [Intro to UCAN post](https://blog.web3.storage/posts/intro-to-ucan), we gave a high-level overview of the new authorization protocol at the heart of our next-generation storage APIs. One of the most exciting things about UCAN is the ability for users to delegate access to their account's resources to other users, services, and devices. This post will highlight some of the ways that delegation can be used with `w3up`, our new upload API. But first, let's consider some use cases that don't require delegation. 

### User owned accounts by default

When applications use the w3ui components, or developers run the w3up CLI, the default behavior is provisioning a new "account" for the device and linking to their email address via registration.

If you're uploading files from your laptop using [the w3up command line tool](https://github.com/web3-storage/w3up-cli), you can just create your UCAN identity key on the laptop and register it with the w3up service using the `w3up register` command. The service will issue you a UCAN token that grants your UCAN identity some capabilities; in this case, you get the ability to upload data to web3.storage, list your uploads, unlink uploads from your account, etc. 

Because your laptop has access to the private key for your registered identity, there's no need to delegate anything. The `w3up` tool will just sign a UCAN request token with your private key and include the token from the w3up service as proof that you have the right permissions.

Another example is a fully decentralized app with a web frontend that interacts with a smart contract "backend." Let's say you're building a decentralized image sharing application, where users can get rewarded for sharing funny memes. You'd like your app's users to be able to upload images to web3.storage, but you don't want to coordinate their access or handle billing on their behalf.

In that case, you can use the [w3ui keyring component](https://beta.ui.web3.storage/keyring) to help your users create their own UCAN identity and register it with w3up. There's no need for delegation in this case, because each user has their own registered account with web.storage.

### App owned accounts - transparent to the user

Now let's look at a use case where delegation can improve the experience for users of apps that use web3.storage. By delegating user's session to upload to your app's w3up account, you can add uploads to an app, completely invisibly to users.

Let's say that you run a recipe sharing app written on traditional web2 technologies. You have a sizeable user-base, and you want to add recipe photo uploads without impacting your existing infrastructure. With UCAN delegation, users can upload directly to your w3up account with no visible impact on the user experience.

To do this, you can delegate access to your own web3.storage account, instead of having each user create their own account.

On the client side, each user will still create a UCAN identity key, but instead of registering it with web3.storage, they can send the public ID to your app's web API or cloud function. That service will issue a UCAN that grants some permissions to the user, without needing to coordinate anything between your app's backend and the web3.storage service. In that way, storage access is attached to your application's session.

When a new user signs into your web app, the frontend can use [`w3up-client`](https://github.com/web3-storage/w3up-client) to create a new UCAN identity. Instead of registering the identity with w3up directly, the frontend can send the public ID to your backend service instead.

Your backend service can use an instance of [`w3up-client`](https://github.com/web3-storage/w3up-client) that's been configured to use your service's registered UCAN identity. The client's `makeDelegation` method will create a delegation object that you can send to the user.

Here's what your backend code might look like:

```js
import W3Client from '@web3-storage/w3up-client'

async function delegationRequestHandler(request) {
  const userDID = await getDIDFromRequest(request)
  const client = await makeW3Client()
  const delegation = await client.makeDelegation(userDID)

  // The delegation object is a binary "blob" that encodes the UCAN
  // delegation into the CAR format. 
  // Here we're just returning it from our handler and assuming that the 
  // server-side framework will handle the details of setting the right 
  // Content-Type headers, etc.
  // Alternatively, you could encode the delegation to base64 and 
  // include it in a JSON response, etc.

  return delegation
}

async function makeW3Client() {
  // Your real service will need to initialize the client with
  // your registered UCAN identity (omitted for brevity).
  return new W3Client()
}

async function getDIDFromRequest(request) {
  // How to extract the user's public DID from the request will
  // depend on the server-side framework you're using and your
  // service API.
  //
  // Here we'll assume that the `request` object has a `json()`
  // method that does what you'd expect, and that the request
  // body has a "did" field containing the DID.
  const body = await request.json()
  return body.did
}
```

When the frontend recieves the delegation from your service, they can call `importDelegation` on their `w3up-client` instance and pass in the bytes of the delegation object. From then on, any requests that the client makes to w3up will use the delegated permissions from your web3.storage account.

### Delegate across apps and services

You can also use delegation to share access with other services, without requiring an explicit agreement between each service provider.

For example, you or your users could delegate access to an image resizing app that will create thumbnails of each uploaded image and write them back to web3.storage. While you could do this without delegation by having the image app use its own web3.storage account, the uploads would be attached to the account for the app. By using delegation, you'll be able to see the CIDs for the thumbnails in the upload listing for the user's account instead, and the resizing app doesn't need to have any kind of business relationship with web3.storage to use the service.

### Link devices through delegation

The last use case we'll look at today involves managing multiple devices belonging to the same user.

Earlier, we used the example of uploading files from your laptop as a case where delegation isn't needed, since the private key for your registered UCAN identity lives on the laptop.

If you also want to upload from your phone, you can use delegation to share access to your account without needing to go through the registration process on the new device. Instead, your laptop can generate a delegation for your phone's UCAN identity and send it to the phone. Because the w3up service doesn't need to be "in the loop," you can even add new devices to your account when you're offline, for example, by having your phone scan a QR code from the laptop's screen.

## Step-by-step delegation with w3up-cli

Now that we've seen some reasons why you might want to delegate, let's look at delegation in practice using the `w3up` command line tool.

If you haven't had a chance to check out the `w3up` tool yet, see our [intro to using w3up from the command line](https://blog.web3.storage/posts/using-w3up-from-the-command-line) to get an overview. 

To get started, make sure you have [Node.js](https://nodejs.org/en/) version 16 or greater installed on your computer. Then enter the following command at a terminal:

```bash
npm install -g @web3-storage/w3up-cli
```

This will install the `w3up` command, which we'll be using to create two UCAN identities. The first identity will be registered with the w3up service, and we'll delegate access to the second identity so that it can act on behalf of the first.

Let's go through the process step-by-step.

##### 1. Create your "main" UCAN identity using `w3up id`. 

Use the `w3up id` command to generate a new UCAN identity. This will print two DIDs to the console. It should look similar to the output below, but yours will have different keys.

```
✔ Agent DID: did:key:z6Mkinv7ZyMuqg8H3ctSZW76UKwTQxRR7JLwv5yVtxAi3PKC
✔ Account DID: did:key:z6MknNsrjU1Xajz1egt64hnrMWBsYbxkxg6iyiXqUjDYFA8
```

You might be wondering why there are two IDs and what the difference between them is.

The Account DID acts as a "namespace" for all the content you upload, sort of like the name of a cloud storage bucket. When you upload content with `w3up upload`, metadata about your uploads like the CID, file size, etc. are associated with the Account DID. Later if you run `w3up list`, you'll see all the CIDs that have been linked to your account.

When you delegate access to another UCAN identity, you're giving them permission to upload to your account, or in other words, to act as your "agent." When we ran `w3up id`, we automatically created an "agent" UCAN identity that can act on behalf of the "account" identity. The private key for the Agent is what's used to sign the UCAN request tokens used when we run `w3up upload`, but the "namespace" for the uploads will still be the Account DID.

Having separate Account and Agent identities may seem like overkill at first, but it will make more sense once we start delegating to other agents in the next few steps.

##### 2. Register your account with `w3up register`

So far, we've created a UCAN identity for our account, as well as an Agent identity that can upload to the account. Before we can make requests to the `w3up` service, we need to register our new IDs using  the `w3up register` command.

Run the following command, filling in your own email address:

```
w3up register your-email@your-provider.net
```

You should see a message in the console asking you to check your email. Once you click the link in your inbox, you'll see a success message. Now you're ready to start using the rest of the `w3up` commands.

##### 3. Upload something to your account

Let's upload a test file to confirm that things are working.

First, make a text file called `hello.txt` with some simple content:

```bash
echo "Hello, web3!" > hello.txt
```

Now you can use `w3up upload hello.txt` to upload the file. You should see something like this:

```
✔ Succeeded uploading bagbaieraonu5zsmebv2lvvqu7c24ezniyk4dxilrvtrl4oueo7b46tu2jzua with 200: OK
data CIDs:
 bafybeihs2dyjc6pxxyfpgofsca3l4364yrq3qhd65tos3zqhzuyupuqgp
```

You can use the HTTP gateway at `w3s.link` to quickly fetch the content and check that it resolves. With the CID above, the gateway URL would be `https://w3s.link/ipfs/bafybeihs2dyjc6pxxyfpgofsca3l4364yrq3qhd65tos3zqhzuyupuqgp`.

Running `w3up list` should now show your new upload:

```
✔ Listing Uploads...
Date         Data CID                                                     
--------     --------                                                     
10/21/2022   bafybeihs2dyjc6pxxyfpgofsca3l4364yrq3qhd65tos3zqhzuyupuqgpi  
```

##### 4. Create a second UCAN identity in a new profile

The `w3up` tool lets us manage multiple accounts (and their agents), using "profiles" to keep track and switch between them. We'll use profiles to demonstrate delegating permissions from our main UCAN identity to a new one.

Create the new identity using the following command:

```bash
w3up id --profile second
```

The `--profile` flag tells `w3up` to use a non-default profile using the name we pass in. In this case, we've named our profile "second," since it's our second identity.

This will print out a new Account DID and Agent DID belonging to the new profile, similar to the output in step one:

```
✔ Agent DID: did:key:z6MkkydmL5x7956KckmKf8nimRFHMuj78zEQvfsKbXKSYBsV
✔ Account DID: did:key:z6MkgnnMHMZLxjW9BW3xRc7LcBiUxv4nxx2kuACec9E8NFLB
```

Your keys will be different than the example. We'll be using the Agent DID in the following commands, so take note of it for future reference.

If you run `w3up list --profile second`, you should see a message indicating that your identity has not yet been registered. Instead of registering this second profile, we'll be using delegation to grant the new agent access to the original account.

##### 5. Delegate access to the new Agent DID

Run the `w3up delegate` command, passing in the Agent DID for the second profile:

```bash
w3up delegate did:key:z6MkkydmL5x7956KckmKf8nimRFHMuj78zEQvfsKbXKSYBsV
```

This will create a file called `delegation.car` in your current directory. Next, import this delegation to our second profile:

```bash
w3up import-delegation delegation.car main-account --profile second
```

Here we're assigning the name "main-account" to the delegation, so we can keep track of things in case we add more delegations in the future.

If you now run `w3up acounts --profile second`, you should see two acounts listed:

```
w3up accounts --profile second                                                                                                                                                                                                                                              
selected   alias          did                                                       
--------   --------       --------                                                  
           main-account   did:key:z6MkfF49n6r2r6tRiVD5XRQZz78u2acc4RB2ymTSCUyc3aso  
*          self           did:key:z6MkgnnMHMZLxjW9BW3xRc7LcBiUxv4nxx2kuACec9E8NFLB  
```

The "self" account is the default account for the `second` profile, and the `main-account` is name we gave when we made the delegation from our main profile. 

Running `w3up account` without the `--profile` flag will still show a single account:

```
selected   alias      did                                                       
--------   --------   --------                                                  
*          self       did:key:z6MkfF49n6r2r6tRiVD5XRQZz78u2acc4RB2ymTSCUyc3aso
```

You can see that the "self" account for the main profile has the same DID as our `main-account` delegation to the `second` profile.

##### 6. Use the delegated account

If we run `w3up list --profile second`, we'll still see a message that our account isn't registered. This is because that profile is still using the "self" account by default.

Use the `w3up switch-account` command to make the `second` profile target the delegated `main-account`:

```bash
w3up switch-account main-account --profile second
```

You should see something like this, showing the DID of your main account:

```
now using account: did:key:z6MkfF49n6r2r6tRiVD5XRQZz78u2acc4RB2ymTSCUyc3aso
```

Now, commands that use the `--profile second` flag can act upon the delegated main account. Try running `w3up list --profile second`. You should see the upload listing for the main account agains, just as if you'd run `w3up list` from the main profile.

