40fa68b587
All checks were successful
Release to Production / build_and_release (push) Successful in 22s
3.9 KiB
3.9 KiB
Email Flow
In creating an email flow that maintains PRIVACY and SECURITY whilst also being convenient to use, the following principles were observed:
- Keypair must be generated client-side
- Keypair must be protected by a long and complex password
- It must be possible to change the password
- It must remain possible to work offline
- Network traffic must not contain identifying metadata
All of the above is achieved using a high level signup flow as follows:
- User provides email and complex password
- These are used to encrypt a locally generated keypair into a backup
- Email address, Public Key and encrypted backup are sent to the server
- Account is validated
The password is only used to encrypt/decrypt the local backup and is never stored or sent anywhere.
When perforing a login, the flow is:
- Generate a temporary key pair for secure server communication
- Validate the email
- Provide the encrypted keypair for the user to unlock
All key signing / encryption operations happen on client side using private class properties.
SIGNUP FLOW
sequenceDiagram
autoNumber
actor U as SIGit User
participant W as SIGit Website
participant D as Server
Participant DB
Note over W,D: All comms encrypted with throwaway <br>(ephemeral) client keys and a <br>.well-known server key
U->>W: Click SIGNUP
U->>W: Provide Email and Complex Password
Note over W: Validate Email<br>Ensure Complex Password<br>(Min 21 chars)
Note right of U: User is warned that they CANNOT<br>RESET PASSWORD, should USE <br>PASSWORD MANAGER etc
Note over W: Nostr Keypair Generated <br> & Encrypted inside a <br> PRIVATE method,<br>with COMPLEX password.<br> Password variable is not <br>stored, sent or printed <br> anywhere. <br>Any sensitive variables <br>are immediately destroyed.
W->>D: Request account activation
Note right of W: Event uses PoW and<br> encrypts PUBKEY, EMAIL,<br> and the encrypted BACKUP<br> to the dvm@sigit.io pubkey<br> using the ephemeral key
Note over D: Verify PoW, <br>event.created_at,<br>event.id
D -x DB: Check if email exists
Note over D: If email already exists, and <br>user.last_seen <> null then <br>send user to LOGIN.<br><br>If email exists and last_seen<br> is null, then DELETE the <br>current entry.<br><br> Otherwise#58;
D->>DB: Create DB entries
Note over DB: USER insert#58;<br>#128274;user.id=uid()<br>user.pubkey=lowcase($PUBKEY)<br>user.email=lowcase($EMAIL)<br>user.last_seen=null<br>user.created_at=now()<br>user.bkp=$BACKUP
Note over DB: SESSION insert#58;<br>#128274;session.pubkey="ephemeral pubkey"<br>session.email_code=INT (6 digits)<br>session.user_id=user.id<br>session.created_at=now()
D->>U: Send session.email_code via email
D->>W: Account created
Note left of D: Payload is the user.id and/or<br> an encrypted (and detailed)<br> error message
Note over W: Verify DVM pubkey, <br> event.created_at,<br>event.id
W->>U: Tell user to check email and<br>to open it in the <br> SAME BROWSER SESSION
Note over W: Screen to accept the 6 digits <br> is already displayed<br>(mobile optimised if relevant)
U->>W: User opens link or enters the code
W->>D: Verify Account
Note right of W: Event uses PoW and <br>encrypts both user_id <br>and email_code<br> to DVM pubkey
D -x DB: Check email_code where <br>session pk=event pk
D->>DB: If email_code matches, <br>update USER table where<br> session.user_id=user.id
Note over DB: USER update#58;<br>user.last_seen=now()
D->>W: Account activated
Note left of D: Payload is an empty string or<br> an encrypted (and detailed)<br> error message
Note over W: Verify DVM pubkey, <br> event.created_at,<br>event.id
W->>U: User is automatically logged in
Note over W: Ephemeral key is destroyed<br>Default relay list is broadcast<br> using the user pubkey