dm3
dm3 copied to clipboard
Profile, accounts, sessions
Background
Currently, both backend and delivery service store the user's "profile" in their database. Since the profile should ideally be managed on-chain, only one source of truth should ever exist. There are several options:
- Backend hosts profile: A user should be able to use many delivery services, but will most likely opt for only one backend - with this assumption, the backend should be the service responsible for publishing and providing the profile. The backend would then be used as a data source by the offchain resolver.
- Delivery service hosts profile: not feasible for the main profile, but a delivery service still keeps a profile for a user that contains things like max message size and ttl.
- Profile published on-chain: best option, but not our default approach.
Option 1 is the way to go.
Discussion and results
See notes.
Which data must be handled?
- dm3 profile: ENS name, signing and encryption keys
- account on delivery service: message ttl, max size, etc
- account on backend
Who handles what?
- backend
- sign up: publishes profile to offchain resolver for user
- creates account in local database/storage
- ens as id
- message storage
- some info about session
- (seed for key generation)
- delivery service
- queries dm3 profile from onchain or offchain data and verifies correct signature (using the published signature public key)
- stores account information for registered users
- ens
- received and not yet collected messages
- some info about session
- sign up: creates account in local db
- client
- handles multiple dm3 profiles (several ens names and keys) for user, including sign up at backend and delivery services
Sessions
The services store information about the user in "sessions", which is a very unfortunate term to use in this context.
- [ ] manage sessions statelessly using jwt
- [ ] create and track accounts for our users
- [ ] check which information is needed in an account
Estimate: 3 days
Reasons why we need to store the profile in the first place
- During the challenge response flow, the Backend checks if the challenge was signed by the users signing key
- When receiving a message the Postmark is signed by the receiver's encryption key DS
Reasons why we need to store the profile in the first place
- During the challenge response flow, the Backend checks if the challenge was signed by the users signing key
- When receiving a message the Postmark is signed by the receiver's encryption key DS
- I propose issuing challenges as short-lived jwt, in an effort to make session management stateless
- You are right. Even though it seems inefficient, I will start by querying the key from the ENS profile whenever it is needed. We should introduce caching later.
Account management in delivery service
creating accounts
Prerequisites: A user can have multiple ens names, e.g. alice.eth
and 0x95222290DD7278Aa3Ddd389Cc1E1d165CC4BAfe5.addr.dm3.network
. They must publish a dm3 profile for every ens name they want to use with dm3 (this is a one-time setup and is NOT done by the delivery service).
Once a profile is published, the user can create an account for that profile with a delivery service through the account
endpoint, which expects an account creation message that is signed with the profile's signature key.
- account creation message must contain the ens name, the delivery service URL, the topic
createAccount
and a timestamp to prevent replay attacks - account creation endpoint is accessible without authentication
- To use multiple profiles with the same delivery service, the user must create an account for each profile.
deleting accounts
An account can be deleted by the account owner through the account
endpoint. The account deletion message must be signed with the profile's signature key and contain the ens name, the delivery service URL, the topic deleteAccount
and a timestamp to prevent replay attacks.
Session management
- become stateless by moving challenge into jwt
- auth is enabled for known accounts only
Plan:
- [ ] rename and rework
- [ ] session -> account
- [ ]
getSession
->getAccount
- [ ]
setSession
->createAccount
. Create accounts in backend and ds to store information that exceeds the public profile, including "this profile is registered with this service". Since "account" already exists in postgres db in backend, check if it is needed in redis (and if redis is still needed at all).
- [ ] store profiles on-chain exclusively, and rely on caching (already implemented) to speed up reading them.
- [ ]
- [ ] move
- [ ] from
lib/delivery
tolib/server-side
- [ ]
UserProfile.ts
- [ ]
Keys.ts
- [ ]
Session.ts
- [ ]
- [ ] from
- unify
- [ ] check if
profile.ts
from backend and ds can be unified and move to server-side - [ ]
persistence
from backend and ds: redis part seems to be duplicated, check every file and extract - [ ]
- [ ] check if
Notes
Account
-
account
already exists in postgres-db of backend -
account
is also used as reference to the ethereum account (as in address 0x...), so it might not be the best name to use again. Defineaccount
andaccountId
instead? - ensName is sometimes referred to as
account
, e.g. in the jwt
Names
- address or evmAccount: 0x...
- ens or accountName: malteish.eth
Should an account be identifyable by it's unique ens name? That might be a good idea.
Update:
- in the backend, redis is ONLY used for the "Session" by now. Use postgres instead.
- after that, redis is only used in the ds, so unifying stuff does not make sense anymore
- therefore, cleanup redis in ds and rename
getSession
togetAccount
there