dm3 icon indicating copy to clipboard operation
dm3 copied to clipboard

DM3MAP: Authentication at Delivery Service and Backend

Open steffenkux opened this issue 11 months ago • 5 comments

Current situation

Authentication to services (delivery service, backend storage service) is done by a SIWE like message/signature which is shared for the DS and backend (cloud storage)

(see also: #650)

Requirement

To follow the DM3 specification (and vision), every user can be connected to various delivery services, the storage via cloud storage backend is optional and must not be coupled with any delivery service.

To log in to a service (delivery service, cloud storage service), the following message is passed signed with the signature key:

ENS: [...] Address: [...] URI: https://dm3.chat/ Version: 1 Chain ID: 1 Issued At: [...] Expiration Time: [...] Nonce: [...]

Additional to the standardized values (according to EIP-4361): ENS is the ENS name of the sender, Address is the sender's wallet address.

The authentication process: (client side)

  1. Sign-in with wallet signature (SIWE-like Message) or interaction-free sign-in -> encryption and signing keys are derived/generated
  2. Authentications for services are generated, signed with the signing key

The authentication process: (service side)

  1. SIWE-like message and signature are received,
  2. Extract ens name/address from the message
  3. Read the DM3 profile from the ens name (or from the reverse record for the address, if no ens name is given)
  4. Check if a valid signature (signing key)

The service returns an authentication token which is used for further communication. This token is provided as JWT: Header:

{
  "alg": "HS256",
  "typ": "JWT"
}

Payload:

{
  "name": "...",
  "valid_until": "YYYY-MM-DDTHH:mm:ssZ"
}

The name is the ens name or address, valid_until is the date until the toke is usable.

Tasks

  • [ ] Authentication mechanism (lib)
  • [ ] Include in Delivery Service
  • [ ] Include in Backend (Storage ...)
  • [ ] Include in UI components

steffenkux avatar Mar 08 '24 13:03 steffenkux

The user signs 2 messages during onboarding:

  1. the keyCreationMessage to create the seed for their signing and encryption keys
  2. the profileCreationMessage to connect their signing and encryption keys to their account: image

-> both signatures the user creates with their wallet will still be needed after the restructuring.

Flows

sign up:

  • login message -> create sig key
  • publish profile
    • either on-chain with transaction
    • or off-chain with second signature: sign(profile, accountPrivateKey)

sign in:

  • login message -> sign with signature key (which is known from public records like ens or offchain)

Future vision

It might be possible to create a zero knowledge proof that makes the second signature obsolete. Keep that in mind when implementing first step.

sign(login, accountPrivateKey) -> entropy -> key derivation -> signatureKeyPrivateA -> sign(profile, ) -> signature -> zkp(signature, entropy, accountPublicKey)

Proof that the sender has access to signature = sign(loginMessage, accountPrivateKey). loginMessage and accountPrivateKey, and signature must stay secret. Delivery service does not know loginMessage, and the backend does not always know it (e.g. if storage is not in backend).

malteish avatar Apr 25 '24 07:04 malteish

submitUserProfile is used both in backend and delivery service. It uses the signed profileCreationMessage, which is checked before a profile for the user is created with the service. Where should this actually happen? Others need to query the user's profile from ens or an offchain resolver -> submitUserProfile is needed with those. Is this the task of the delivery service or the backend? Currently, both seem to store the profile and serve a route to access it.

see https://github.com/dm3-org/dm3/issues/907

malteish avatar Apr 25 '24 08:04 malteish

Used this resource as a starter on how to use jwt: https://www.digitalocean.com/community/tutorials/nodejs-jwt-expressjs

malteish avatar Apr 25 '24 08:04 malteish

Both backend and delivery service already issue their own challenges to the user for authentication, and verify these challenges are signed with the user's publicSigningKey.

malteish avatar Apr 25 '24 09:04 malteish

Which information should be included in the jwt?

  • ensName (user)
  • expiration date (exp)
  • issuance date (iat)
  • do we need account? -> could theoretically change without invalidating the jwt

malteish avatar Apr 25 '24 11:04 malteish

implemented except for the zk part

malteish avatar May 28 '24 07:05 malteish