---
# System prepended metadata

title: Web Page -> Electron Wallet Access Request Flow

---

# Web Page -> Electron Wallet Access Request Flow

[ToC]

## Sequence Diagram

```mermaid
sequenceDiagram
autonumber

actor H1 as Helga
participant A as Browser Web Page
participant B as Electron Wallet
actor H2 as Helga

B->>B: Register web5:// protocol listener
H1->>A: Visit Web5 Webapp
A->>A: Render Page with web5:// link
H1->>A: Click Web5 link
A->>B: trigger web5:// listener
par Web5 App <-> Electron Wallet
    loop until port is found 
        A->>B: Hit test localhost ports until correct port is found
    end
and Electron Wallet <-> Helga 
    B->>B: Raise Popup Requesting User Consent
    H2->>B: Select Grant/Decline
    B->>B: Store user response 
end
```

--- 

## Setup

### Web Page Setup
* Generate a [TweetNaCl](http://tweetnacl.cr.yp.to/) keypair
    * Store in local storage for future usage (e.g. if user revisits site)
* Render "Connect to Web5 Wallet" link on page with an `href` of `web5://connect?key=${public_key}` where `public_key` is the base64url-encoded TweetNaCl public key

### Electron Wallet Setup
* Generate a [TweetNaCl](http://tweetnacl.cr.yp.to/) keypair
* Register protocol handler for `web5://`

## Access Request Flow
* Helga clicks on "Connect to Web5 Wallet" Link
* **Loop** Web Page begins hit testing `http://localhost:${port}/connections/${public_key}` starting at port `55555`. `public_key` is the base64url-encoded TweetNacl public key generated by Web Page during [Web Page Setup](#Web-Page-Setup)
    * Wallet will respond with a JSON object containing:
        * `encryptedPort` - base64url-encoded encrypted numeric port value
        * `nonce`
        * `publicKey` - Wallet TweetNaCl public key
    * Decrypt `encryptedPort` using:
        * TweetNaCl private key generated by Web Page during [Web Page Setup](#Web-Page-Setup)
        * `nonce` in response from Wallet server
        * `publicKey` provided in response from Wallet server

* Wallet receives web5 "request" 
    * _I say "request" in quotes because the Web Page doesn't receive a response to this request_
* Wallet raises User Consent Popup UI. Something like "Grant Access to your DWN"
* _Assuming user clicks grant_. Wallet encrypts the numeric port value that the wallet server is listening on using:
    * the TweelNaCl public key provided in the `web5://` request
    * a randomly generated `nonce`
    * the Wallet's TweetNaCl private key

* Wallet writes the following stringified JSON Object to disk at location `connections/${public_key}` where `public_key` is the TweetNaCl public key provided in the `web5://` request:
    * `encryptedPort` - base64url-encoded encrypted numeric port value
    * `nonce`
    * `publicKey` - Wallet TweetNaCl public key


## Questions
### What is gained by encrypting the port?
The Web Page is going to know the port already because it's not going to stop making requests until it finds it...

### What is the benefit of encrypting anything in this flow?
will all responses to subsequent requests from the Web Page be encrypted using this key? The Wallet Server is using `https`

seems like the real benefit here is not encryption but rather, the _public key_ which is being used as the identifier for a connection. If this is the case, we should consider using `Ed25519` `did:key` with a derviced `X25519` encryption key if encryption is needed

> The encryption step would be more benefitial if it encrypted a jwt or proof value that only the initial caller could unwrap and use

###  What is the benefit of the user clicking the `web5://` link?

is it so that raising the user-consent popup requires human interaction?

> :bulb: running `open web5://connect?key=whatever` on the command line works with no issue

It's so you can tie the request to awareness of the calling entity that was user activated.

### How are subsequent requests sent from the Web Page to the Wallet Server authenticated?

We probably want to return a JWT in the response from `http://localhost:${port}/connections/${public_key}` 

## Concerns

### Race condition 

between steps 5-8. If Web5 App finds port before user has selected grant/decline.

#### Counter Argument: 
* Web5 app has a `sleep` for some arbitrary amount of time. 
* Electron wallet immediately stores `PROCESSING` placeholder for pubkey provided in `web5://` request
* Web5 app polls `PROCESSING` placeholder

### Cannot block a web page from continuously re-requesting access
If the user denies the web5 apps access request, there's no way to truly prevent a web5 app from repeatedly raising UI because we're blocking by DID or a public key vs. blocking by origin (aka page's domain). There's no reliable way to get the requesting page's domain in a manner that cannot be spoofed

> Same question about iframe 

#### Counter Argument
User has to click on a link to raise this UI so.. they could choose to just not click on the link.

_Rebutle: Web5 App could still be annoying with this_


### No reliable way to show origin of requesting page
origin is provided by web page which means the web page can spoof the origin and the electron wallet would have no way of knowing.

> have we fully explored iframe loading of the Electron server's page? This would give you origin access.

#### Counter Argument 1
The user has just clicked on a link on the page which likely says "Connect Wallet". They'll be expecting the pop-up which means that they know which web page triggered it


#### Counter Argument 2
Can require use of DIDs instead of public keys and then use [Well Known DID Configuration](https://identity.foundation/.well-known/resources/did-configuration/)

##### Rebuttal
use of well-known DID configuration means that decryption of message would have to happen on the server-side of the web page

### Unsure if we can make user consent popup the front-most window to catch the user's attention. 
We definitely need to test this. Not being able to raise the consent popup as the foremost window means that a user may not even realize that a pop-up is waiting for them.

This is just an option for electron windows:

> alwaysOnTop boolean (optional) - Whether the window should always stay on top of other windows. Default is false.