Build flow design for signing process with Aaron

Status
Complete
Assignee
Edward Atter
Type
Documentation
Due
July 28, 2022
Slated Version
Email PRD for NFT Creators
Last Edited
Aug 2, 2022 1:49 PM
Last Edited By
Edward Atter
Priority
Blocked

Overview

Implement gasless signature functionality from SMS wallet in order to be used with other applications. The SMS wallet interface should be generic enough to support a wide array of purposes. Most of this document is specific to using signatures to verify a session and authenticate the user (Login with SMS Wallet).

Terms

Name
Description
Consumer
The consuming app initiating authentication (Dj3n)
SMS Wallet
Aaron’s SMS wallet

Example User Flow - Sign in w/ SMS Wallet

  1. User selects “Sign in with SMS Wallet”
    1. A unique code is generated and stored in consumer DB, this will be included as part of the message.
  2. User is redirected to SMS wallet website
    1. Success URL, failure URL, and string to sign are provided by consuming app
  3. If not logged in, present signup procedure
  4. If logged in (or post new signup), prompt to approve the signature request
  5. After approval or rejection, SMS Wallet redirects to consumer application using the success and failure callback URLs as appropriate
    1. Posts to the callback page information with:
      1. Error details, if applicable
      2. The user’s wallet address (if approved)
      3. The signed message (if approved)
      4. The original message provided (in all cases)
  6. The consumer application verifies the signed message and adds the user’s wallet address to the session (the user is now logged in).
D denotes functionality on Dj3n site, while A denotes SMS wallet
D denotes functionality on Dj3n site, while A denotes SMS wallet

Signing

Signed with user’s private key. The resulting signature should be compatible with ethers.utils.verifyMessage. Ethers uses signer.signMessage to create the signature, and may be helpful as a reference.

Consumer Flow

  1. Add unique token to database (serverside rather than in cookies to prevent client side tampering).
  2. Generate a unique message (including the unique token in step 1) for the user to sign
  3. Wait for response from SMS wallet callback
  4. On response, to…
    1. successCallback, verify the address provided by Aaron is the same as returned by ethers.utils.verifyMessage. Also verify the message is the same as generated in step 2.
    2. errorCallback, display the error message and prompt the user to try again, restarting the process.
  5. If successful, authenticate the user session.

Interface

I don’t really care about the HTTP method used. My suggestions are included, but feel free to change. I feel GET is convenient for initiating the request to simplify supporting QR code sign-in and other improvements later on.

Initiating a Signature Request

/sign/ GET

Parameter
Description
phone
Optional - will default the specified phone number during signup process if provided. E.123 format.
message
The message to be signed
successCallback
URL to redirect to on successful signing
errorCallback
URL to redirect to on failed signing

Success Callback

POST

Information POSTed to the successCallback provided during the signature initiation. This should be initiated client-side, redirecting the user here on completion, not via a webhook.

Parameter
Description
status
"SUCCESS”
message
The original message that was requested to be signed
signature
Signature corresponding to the original message
address
The 0x address of the signer

Error Callback

POST

Information POSTed to the errorCallback provided during the signature initiation. This should be initiated client-side, redirecting the user here on completion, not via a webhook.

Parameter
Description
status
"ERROR”
code
A machine-readable error code, to be defined by Aaron if desired
reason
A human-readable reason for the error. For example, “Signing request cancelled by user.” It should be acceptable to copy this message verbatim and display it to the user.
message
The original message that was requested to be signed

Consumer UX Considerations

It’s possible a user has their wallet on their phone but wants to access the site from their laptop. For v1, I suggest we assume the wallet is always available on the same device accessing Dj3n. In the future, we can use websockets (among others) to elegantly support multi-device login. (See Discord’s login with QR code feature for a real-life, pleasant example of logging in with a different device.)

In the future we can use a QR code to sign in on a laptop browser from your phone. The QR code (displayed in Dj3n) would take the user straight to SMS wallet to complete the signature. The consuming application would need to detect the signature was completed on a different device and notify the original device on success.

Questions

@Aaron Li, do you store the phone numbers in plain text? Curious if SMS wallet could detect if a user already has an account or not for a specific phone number. If so, could make user flow more intuitive.

Other Security Considerations

  • Enforce TLS requirement for callback URLs unless localhost, 127.0.0.1, etc.
  • A malicious consumer could obscure a dangerous transaction as an innocent signature. Do we want to whitelist who can use this feature? (I vote no for now unless we begin to see abuse).