### UCAN: Authorizing Users Without a Back End
<!-- Put the link to this slide here so people can follow -->
slide: https://hackmd.io/@gozala/ucan-demo
---
### Decentralized Identifier (did:key)
- Just a public key (e.g EdDSA, RSA)
- Self sertifying
---
#### User Controlled Authorization Networks (UCAN)
- Object Capability Model (OCAP)
- JSON Web Tokens (JWTs)
- Controlled ahead of time (e.g. time limits)
- Support delegation
---
![](https://i.imgur.com/vraomzN.png)
---
![](https://i.imgur.com/BFmbLiJ.png)
---
![](https://i.imgur.com/dwoDCF7.png)
---
![](https://i.imgur.com/Gr00hLm.png)
---
![](https://i.imgur.com/cvXR55B.png)
---
### Capabilities
- **Operation** - Action that can be performed
- **ID** - Resource action can be perfromed to
- **Type** - Identifier to indicating the type of the thing
---
## Fission defines it as
```json
{
$TYPE: $IDENTIFIER,
"cap": $CAPABILITY
}
```
---
### They type it as
```ts
type Capability = {
[rsc: string]: string
cap: string
}
```
---
### In practice it's
```ts
interface Capability<OP extends string> = {
cap: OP
[constraint: string]: unknown
}
```
---
### Capabilities
- ๐ Open ended just requires `cap` discriminant.
- ๐ Too loose, can't catch escalation
---
### My definition
```ts
export interface Capability<
OP extends Uppercase<string>,
ID extends string
> extends Constraints {
cap: OP
id?: ID
}
export interface Constraints {
[key: string]: number | string | undefined
}
```
---
### Capabilities (simplified)
- **Operation** - Action that can be performed
- **ID** - Resource action can be perfromed to
- ~~**Type** - Identifier to indicating the type of the thing~~ (ID contains the type)
---
### Capabilities ๐ญ HTTP API
```md
PUT /uploads/did:key:foo/
```
```json
{
"cap":"PUT"
"id": "/uploads/did:key:gozala/"
}
```
---
### Capabilities ๐ช
```ts
const capabilities = [
{ // Capability to add stuff to namespace
cap: "POST", // Action
id: `/uploads/${user}/`, // Resource
// Constraints for this capability
storageLimit: 32 * 1.1e12, // 1TiB,
},
{ // Capability to list stuff in user namespace
cap: "LIST", // Action
id: `/uploads/${user}/`, // Resource
}
]
```
---
### ๐ค Authorizing ๐จ๐ฝโ๐ป
```ts
const root = UCAN.build({
issuer: service.keypair, // ๐ค who grants access
audience: user, // ๐จ๐ฝโ๐ป who is granted access
lifetimeInSeconds: 24 * 60 * 60, // โฑ how long
capabilities // ๐ช
})
```
---
### ๐จ๐ฝโ๐ป Constrainting Capabilities ๐ช๐งค
```js
const constrainedCapabilities = [
{ // Add stuff to user subspace
cap: "POST", // Action
id: `/uploads/${user}/${scope}/`, // ๐จ๐ฝโ๐ป๐ช๐งค๐จโ๐จ
storageLimit: 1.074e9, // 1GiB,
},
{ // List stuff in user subspace
cap: "LIST",
id: `/uploads/${user}/${scope}`, // ๐จ๐ฝโ๐ป๐ช๐งค๐จโ๐จ
},
{
// List stuff in public subspace
cap: "LIST",
id: `/uploads/${user}/public`, // ๐จ๐ฝโ๐ป๐ช๐งค๐จโ๐ฉโ๐งโ๐ฆ
}
]
```
---
![](https://i.imgur.com/xmr8pfe.png)
---
### ๐จ๐ฝโ๐ป Delegation ๐จโ๐จ
```ts
const delegate = UCAN.build({
issuer: user.keypair, // ๐๐จ๐ฝโ๐ป granted access
audience: comrade, // ๐๐จโ๐จ grantee
lifetimeInSeconds: 24 * 60 * 60, // โฑ a day
capabilities: constrainedCapabilities
})
```
---
### ๐จโ๐จ Requesting ๐ค
```ts
const requestToken = UCAN.build({
issuer: user.keypair, // ๐๐จโ๐จ granted access
audience: comrade, // ๐๐ค grantee
lifetimeInSeconds: 24 * 60 * 60, // โฑ a day
proof: delegate,
capabilities: [{
cap: "LIST",
id: `/uploads/${user}/public`
}]
})
```
---
## Authorization flow
1. Client generates keypair ๐
---
## Authorization flow
1. Client generates keypair ๐
2. Client derives [did:key] from public key ๐
[did:key]:https://w3c-ccg.github.io/did-method-key/
---
## Authorization flow
1. Client generates keypair ๐
2. Client derives [did:key][] from public key ๐
3. Client requests a UCAN for the [did:key] ๐
[did:key]:https://w3c-ccg.github.io/did-method-key/
---
## Authorization flow
1. Client generates keypair ๐
2. Client derives [did:key][] from public key ๐
3. Client requests a UCAN for the [did:key] ๐
4. Service sends back signed UCAN token ๐
[did:key]:https://w3c-ccg.github.io/did-method-key/
---
## Did you noitce ?
- Private key has never left a user device
- Service can verify user identity retroactively (e.g. send email & activate capability on confirmation)
---
## Exercise capabilities
1. ๐จ๐ฝโ๐ป derives UCAN ๐ addressed to a service ๐ค
1. ๐จ๐ฝโ๐ป attaches derived UCAN ๐ token to request
2. ๐ค Checks UCAN is addressed to it.
2. ๐ค Checks request has adequate capabilities
3. ๐ค Checks that root capability is signed by ๐ค private key.
4. ๐ค Fulfill / deny request accordingly.
---
### Delegation
1. ๐จ๐ฝโ๐ป Issues a new UCAN to ๐จโ๐จ๐๐
1. ๐จ๐ฝโ๐ป Attaches own UCAN ๐ as proof.
1. ๐จ๐ฝโ๐ป Signs token with a private key โ๏ธ.
1. ๐จโ๐จ Derives UCAN ๐ซ for the service ๐ค
1. ๐จโ๐จ Attaches derived UCAN ๐ซ to a request.
1. ๐ค Checks ๐ซ is addressed to it.
1. ๐ค Checks ๐ซ has subset of ๐ capabilities.
1. ๐ค Checks signature chain.
1. ๐ค Checks root token is issued by ๐ค
---
### Delegation
1. ๐จโ๐จ Issues a new UCAN ๐งพ for ๐ฉ๐ปโ๐ฌ
2. ....
---
### Cascading Revocation
---
## Iconography
- ๐ค - Service
- ๐จ๐ฝโ๐ป - Client
- ๐จโ๐จ - User
---
### Thank you!
{"metaMigratedAt":"2023-06-16T14:38:29.668Z","metaMigratedFrom":"YAML","title":"UCAN demo slides","breaks":false,"description":"View the slide with \"Slide Mode\".","slideOptions":"{\"theme\":\"white\"}","contributors":"[{\"id\":\"fff58d5d-df29-4dd3-93ef-42fd0194a26f\",\"add\":7233,\"del\":4054}]"}