Skip to content

Commit

Permalink
feat!: authorization and registration flows (storacha#1059)
Browse files Browse the repository at this point in the history
Implements flows described in storacha#945

## High level overview

### Accounts

This pull request starts differentiating between two kinds of
authorizations

1. Space authorization, allowing access to a space.
2. Account authorization, allowing account management and space
provisioning.

Most core functionality has been added in `Account` module which exposes
following functionality

- `Account.login(client, email)` - Request account level access though
`access/authorize` and awaits until access is granted (through email
link) or request expires.

It returns an `Account` object which is just a view over UCAN
delegations and an agent. That is convenience wrapper allowing us to add
e.g. `.provision(space)` method (for provisioning spaces) and `.save()`
method that will save account proofs into agent store.

- `Account.list()` - Lists all account (sessions) client has in storage.
It essentially goes over proofs and wraps ones that are "account
authorization"s into `Account` objects.

Above functionality should help us answer question whether user has
already logged-in or not ? Previously we had no good way to answer such
questions.

### Access

This fixes issues around authorization flows, where requests would
succeed but access was not gained. Issue was caused by imperfect
heuristics that tried to match received delegation with a requested
authorization.

To address this problem `access/authorize` and `access/confirm`
capabilities and their handler had been extended to capture request
CIDs. This allows client polling for delegations to detect whether
received delegation is corresponds to the request more precisely.

I have added new `Access` module that attempts to do the client side
work without much configurability.

- `Access.request` - will send `access/authorize` request and return
`PendingAccessRequest` object, which in turn could be used to poll for
the response via `.claim()` method. `.claim()` internally uses `.poll()`
until it gets the delegation, session expires or request is aborted.

- `Access.claim` - sends `access/claim` request and returns
`GrantedAccess` object that wraps received delegations. It also (just
like `Account`) has `.save()` method which can be used to save
delegations into client's store.

### Space

I have added new `Space` module that has has `Space.generate()` function
to generate new spaces, `Space.fromDelegation`, `Space.fromMnemonic` and
more. General idea here also is that `client.createSpace()` will give
you `OwnedSpace` object that has bunch of methods like `.toMnemonic`,
`.createAuthorization`, `.createRecovery` etc...

Notion of not registered spaces had been removed. If you create a space
you have an object, you can save it in your client using
`client.addSpace(await space. createAuthorization(agent))`.

### Attestation

I have moved `ucan/attest` capability definition from `access` to `ucan`
as former place was confusing and made no sense.

---

The
[account.test.js](https://github.com/web3-storage/w3up/pull/1059/files#diff-9a9133d8e343b56d7ef7bd18d01356b8ca7c630143b4687a51f683a5ebe1528f)
attempts to capture authorization / provisioning flows from the event
diagram.

There is one unfortunate problem right now, that is new spaces added
will not show in other devices unless you re-authorize. Fixing that
requires storacha/ucanto#326 and some more
work here. I think it's best to do it as a followup.

---

I had to rebase because things upstream have changed, unfortunately I
failed to do it cleanly so there is lot of strange changes which I don't
exactly know how they happened. I'll try to remove undo them tomorrow

---------

Co-authored-by: Alan Shaw <alan.shaw@protocol.ai>
  • Loading branch information
Gozala and Alan Shaw authored Nov 6, 2023
1 parent 40d0e7a commit b1f860b
Show file tree
Hide file tree
Showing 83 changed files with 3,178 additions and 2,089 deletions.
57 changes: 49 additions & 8 deletions packages/access-client/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,18 +25,57 @@
"rc": "npm version prerelease --preid rc"
},
"exports": {
".": "./dist/src/index.js",
"./agent": "./dist/src/agent.js",
"./drivers/*": "./dist/src/drivers/*.js",
"./stores/*": "./dist/src/stores/*.js",
"./types": "./dist/src/types.js",
"./encoding": "./dist/src/encoding.js"
".": {
"types": "./dist/src/index.d.ts",
"import": "./src/index.js"
},
"./agent": {
"types": "./dist/src/agent.d.ts",
"import": "./src/agent.js"
},
"./space": {
"types": "./dist/src/space.d.ts",
"import": "./src/space.js"
},
"./provider": {
"types": "./dist/src/provider.d.ts",
"import": "./src/provider.js"
},
"./access": {
"types": "./dist/src/access.d.ts",
"import": "./src/access.js"
},
"./encoding": {
"types": "./dist/src/encoding.d.ts",
"import": "./src/encoding.js"
},
"./types": {
"types": "./dist/src/types.d.ts",
"import": "./src/types.js"
},
"./drivers/*": {
"types": "./dist/src/drivers/*.d.ts",
"import": "./src/drivers/*.js"
},
"./stores/*": {
"types": "./dist/src/stores/*.d.ts",
"import": "./src/stores/*.js"
}
},
"typesVersions": {
"*": {
"agent": [
"dist/src/agent"
],
"space": [
"dist/src/space"
],
"access": [
"dist/src/access"
],
"provider": [
"dist/src/provider"
],
"types": [
"dist/src/types"
],
Expand Down Expand Up @@ -74,7 +113,8 @@
"one-webcrypto": "git://github.com/web3-storage/one-webcrypto",
"p-defer": "^4.0.0",
"type-fest": "^3.3.0",
"uint8arrays": "^4.0.6"
"uint8arrays": "^4.0.6",
"@scure/bip39": "^1.2.1"
},
"devDependencies": {
"@web3-storage/eslint-config-w3up": "workspace:^",
Expand Down Expand Up @@ -106,7 +146,8 @@
"mocha": true
},
"ignorePatterns": [
"dist"
"dist",
"src/types.js"
]
},
"depcheck": {
Expand Down
Loading

0 comments on commit b1f860b

Please sign in to comment.