Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Rethinking the Orion account creation/signup flow #320

Open
zeeshanakram3 opened this issue Mar 18, 2024 · 12 comments
Open

Rethinking the Orion account creation/signup flow #320

zeeshanakram3 opened this issue Mar 18, 2024 · 12 comments

Comments

@zeeshanakram3
Copy link
Contributor

zeeshanakram3 commented Mar 18, 2024

This issue attempts to propose an alternate way for the creation of User/Gateway accounts

Current Implementation

Current graphql schema definition for Account entity.

"A Gateway Account"
type Account @entity @schema(name: "admin") {
  "Unique identifier (can be sequential)"
  id: ID!

  "Gateway account's e-mail address"
  email: String! @unique

  "On-chain membership associated with the gateway account"
  membership: Membership! @unique

  "Blockchain (joystream) account associated with the gateway account"
  joystreamAccount: String! @unique

  ###
  # Other field
  # ... 
}

Problems/inconsistencies in current implementation

  • There is no input validation on the provided email address while creating the account
  • When provided email is associated with some other Account, the API response explicitly tells that the email exists in the system. This could lead to email enumeration attacks.
  • There is non-nullable one to one relation b/w Account and Membership entities. the major problem by having membership field in Account entity as well as in create account request is that the membership must be already created & processed by Orion. Now if somehow processor lags or requests timeout, then the flow would break and it has to be started again from the very first step.
  • Auth API allow changing the joystream account/adress associated with the Gateway account, but not the membership. Basically once the membship has been associated with given Gateway account, it cannot be changed.

I am not sure why this API design approach was picked (i.e. passing the membership to be associated with the account in the create account request), the alternate approach can be to associate membership later to the account using a separate endpoint by sending the memberId in request signed by account.joystreamAccount? (But I am going to suggestion a different approach)

Alternate Signup approach

Objectives of the signup flow rework

  • Don't expect users to create an on-chain membership before creating an Orion account
  • Ensure that users provide valid email during the signup process
  • Ensure that users prove the ownership of the provided email
  • Ensure that the same email cannot be used for multiple successful signups, but without revealing any info about email existence to prevent email enumeration attacks

Orion schema changes

The following changes have been proposed to the Orion Graphql/DB schema

Added EmailConfirmationToken entity

A new hidden entity will be created to securely store the email confirmation tokens issued for the emails.

type EmailConfirmationToken @entity @schema(name: "admin") {
  "The token itself (32-byte string, securely random)"
  id: ID!

  "When was the token issued"
  issuedAt: DateTime!

  "When does the token expire or when has it expired"
  expiry: DateTime!

  "The email the token was issued for"
  email: String!
}

Added BlockchainAccount entity

type BlockchainAccount @entity {
  "The blockchain account id/address"
  id: ID!

  "Membership associated with the blockchain account (controllerAccount)"
  memberships: [Membership!] @derivedFrom(field: "controllerAccount")
}

Updated Account entity

Updated Account entity to have a one-to-one relationship with the BlockchainAccount entity, which then would have a One-to-Many relationship with the Membership entity.

This way we would get rid of the membership column/field from the account (no direct association), and to know about account 's membership/s we can just traverse the relation i.e. account.joystreamAccount.memberships

Another benefit of using this approach is that we don't need to perform membership association action separately, it will happen automatically (once the Account owner create an on-chain membership using keypair of account.joystreamAccount).

type Account @entity @schema(name: "admin") {
  "Unique identifier (can be sequential)"
  id: ID!

  "Gateway account's e-mail address"
  email: String! @unique

  "Blockchain (joystream) account associated with the gateway account"
  joystreamAccount: BlockchainAccount! @unique

  ###
  # Other field
  # ... 
}

Orion Auth API changes

Updated POST /request-email-confirmation-token endpoint

Although, the email confirmation endpoint already existed, it was not used. Also, if the account/email was already verified it returned explicit response stating that given email is already verified (basically revealing emails)

So updated this endpoint to send an email with a confirmation token if the Gateway account does not exist. Otherwise, send an email asking the user to log in/reset the password. but the API response should be the same to avoid email enumeration attacks.

Updated POST /account endpoint

Update create account API request to also require emailConfirmationToken that was sent to user email.

Added createAccountMembership mutation

Added createAccountMembership to create a captcha-free membership for an existing Account (if no membership for account exists yet)

Sequence diagram of new flow

YPP User Flow

  1. Youtube Video URL Entry: The creator enters the Youtube Video URL in Atlas.
  2. Channel Verification: Atlas calls the YT-synch POST /users endpoint for channel verification.
    • If verification is successful, proceed to email address input.
    • f unsuccessful, indicate the user does not meet requirements but can still create an account on Atlas as a non-YPP user.
  3. Email Address Input: The User provides an email address for the new account.
  4. Request Email Confirmation: Atlas requests an email confirmation token from Orion.
  5. User Clicks Confirmation Link: In the received email.
  6. Password Input: The User provides a password for the new account.
  7. Show Mnemonic/Seed Phrase: Atlas shows the mnemonic/seed phrase to the user.
  8. Account Creation: Atlas calls Orion's POST /account endpoint.
    • If there's an error, stop the process and show the error message.
  9. Membership Check and Creation: If no Joystream membership exists, Atlas creates one.
  10. Channel Creation: Atlas creates a Joystream channel for the creator.
  11. Channel Association: Atlas associates the Joystream channel with the Youtube channel.

Non-YPP User Flow

  1. Email Address Input: The flow starts from this step directly.
  2. Request Email Confirmation: Same as in the YPP flow.
  3. User Clicks Confirmation Link: Same as in the YPP flow.
  4. Password Input: Same as in the YPP flow.
  5. Show Mnemonic/Seed Phrase: Same as in the YPP flow.
  6. Account Creation: Same as in the YPP flow.
  7. Membership Check and Creation: Same as in the YPP flow.
  8. Channel Creation: Same as in the YPP flow.
    The flow ends here for non-YPP users.

Here is the sequence diagram for complete YPP/Orion signup flow

  • opt means the sequence component is optional
  • alt means there are alternate paths for the sequence
sequenceDiagram
    participant Creator
    participant Atlas
    participant YT-synch
    participant Orion
    participant Faucet
    participant RPC

    opt For YPP User
        Creator->>Atlas: [1] Enter Youtube Video URL
        Atlas->>YT-synch: [2] POST /users {youtubeVideoUrl: "string"}
        alt Verification Successful
            YT-synch-->>Atlas: [3] Response {channel details}
        else Verification Unsuccessful
            YT-synch-->>Atlas: [3] Error {does not meet requirements}
            Atlas-->>Creator: [4] Can still create account (Non-YPP)
        end
    end

    Atlas-->>Creator: [5] Ask for email address
    Atlas->>Orion: [6] requestEmailConfirmationToken {email}
    Orion-->>Atlas: [7] {success: true}
    Orion-->>Creator: [8] Email with confirmation link

    Creator->>Atlas: [9] Clicked confirmation link
    Atlas-->>Creator: [10] Ask to set password
    Atlas-->>Creator: [11] Show mnemonic/seed phrase

    Atlas->>Orion: [12] POST /account {account details with emailConfirmationToken}
    Orion-->>Atlas: [13] {success: true}

    Atlas->>Orion: [14] Check for existing membership
    alt No Existing Membership
        Creator->>Atlas: [15] Provide membership details
        Atlas->>Orion: [16] createAccountMembership {membership details}
        Orion->>Faucet: [17] Request membership creation
        Faucet-->>Orion: [18] Membership ID
        Orion-->>Atlas: [19] {membership details}
        Atlas->>RPC: [20] Create Joystream channel
        RPC-->>Atlas: [21] Channel creation confirmation
    else Existing Membership
        Atlas-->>Creator: [15] Membership exists, creating channel
        Atlas->>RPC: [16] Create Joystream channel
        RPC-->>Atlas: [17] Channel creation confirmation
    end

    opt For YPP User
        Atlas->>YT-synch: [22] POST /channels {channel association details}
        alt Channel Association Successful
            YT-synch-->>Atlas: [23] Channel association confirmation
        else Channel Association Error
            YT-synch-->>Atlas: [23] Error {reason}
        end
    end

Loading
@zeeshanakram3 zeeshanakram3 changed the title Rethinking the Gateway account creation flow Rethinking the Orion account creation/signup flow Mar 18, 2024
@kdembler
Copy link
Member

@zeeshanakram3 I only skimmed through, but since this is redesigned, do you think Orion could allow signup without an email, using only web3 wallet? Or would that mess up other things?

@msmadeline
Copy link

@bedeho
Copy link
Member

bedeho commented Apr 24, 2024

@zeeshanakram3 I only skimmed through, but since this is redesigned, do you think Orion could allow signup without an email, using only web3 wallet? Or would that mess up other things?

We briefly discussed this, and it requires substantial effort to rework backend, and it adds more complexity. Even if it did not though, I don't think it has enough value. Its a strictly worse experience also in terms of utility post signup, as you get no notifications, which are really quite important. Anyone who insists on doing extension based signer can still just add a throwaway email, and until a substantial number of users voiced this I think its hard to justify adding a separate mode for it.

My understanding is that you are really i favour of this because you feel it has bad optics, but I don't think this really is a big issue - people are by now very used to abstracted wallet experiences, and even if it did have bad optics, the severity is not high enough in my opinion.

@bedeho
Copy link
Member

bedeho commented Apr 24, 2024

I left full review in the Figma.

@msmadeline
Copy link

Hey @bedeho @zeeshanakram3 I have a question that I need to ask related to the sign up flows

  1. Are we creating a new Non-YPP/normal flow from scratch? So far I've done it based on the steps that @zeeshanakram3 provided but now looking at it and thinking about it - we already have a sign up flow in gleev where we already have a place where user has to provide an email address etc. So the question is should I just add the new elements to the already existing non YPP sign up flow? so the link that user has to click on etc. and make sure it's in the order that is correct now or are we doing it from scratch? Because then I will need to redesign it in all the places in the app.

@msmadeline
Copy link

Hey @bedeho @ZeeshanAkram I recorded a very quick video about my question related to non - YPP sign up flow. Let me know If I missed anything

🎥https://www.loom.com/share/f5948fe816424aa18b2db7e80d328a71?sid=4a0949e5-6c02-4a39-91df-1dec84ca302c

@msmadeline
Copy link

@bedeho
Copy link
Member

bedeho commented Apr 30, 2024

Upload YouTube Video modal

Confusion

I don't think this works still I'm afraid.

The user will not know what we want to them to do or why.
I think the title and copy is suboptimal, it just tells the user what to do, but this does not address what the point is, and a very large share of users will not pick up that the purpose of the upload is not to promote something to their users.

But even if it was optimal, I think it will unfortunately require too much tiny text in one screen, this dialog has way too much going on now

  1. tell user to upload a video, but unclear which video or if any video is ok
  2. tell user to get URL and enter it below
  3. tell user it can be unlisted, so its not that someone else needs to see it, its so we can see it, but even this latter point is not so clear
  4. tell user it has to have a very especific title
  5. tell user where to enter video and allow them to go to next page.
  6. also it will now, if you add next section (Validation), need to tell user what may be going wrong with current candidate video

This is just too much, and the user will still not understand why.

--

If you feel there is no alternative solution that can address this in some more fundamental way, my guess for at least what would be an improvement would be

  • A title which explains goal or reason for the step: Prove Channel Ownership
  • A text which just tells them exactly what to do : Have an unlisted video on your channel with title "Joining Gleev", the video content can be anything.
  • Inputbox: URL to unlisted video titled "Joining Gleev" under your channel.

Then when the user clicks continue, then some sort of indication about cause of failure is displayed if the valiation failed.

Validation

  • First off, here we can do very reliable client side validation before we allow the user to proceed.

So whenver the user enters a URL, we can directly in Atlas do the check to make sure

  • its a valid youtube url
  • the video actually exists
  • the URL is actually what we need it to be.

By checking this client side, we can immediately indicate to the user that the video very likely will bea ccepted.

I guess it can be as simple as when the user clicks continue, ew do all the checks, which will be possible in 1-3seconds, and then we give some sort of indication about what conditions are or are not satisified, if not all are satisfied. If all are satisfied, then we can proceed to the nxt screen.

Verifying channel ownerhsip...

My understanding is that this should only take a few seconds, because the video does not even need to be downloaded.

User click on the confirmation link

Perhaps I'm missing something ,but I don't see a screen which comes after the user has submitted the email? There needs to be a screen which says something like "go to your email and click on link we sent you," type of thing.

@bedeho
Copy link
Member

bedeho commented May 3, 2024

Prove channel owernship

So thank you for trying a new iteration. I can see you have tried to explain as much as possible to the user, to make them undrestand why they are doing somtehing, but I'm worried this is too much, people will just skip and zone out.

Can we try a super simple alternative, so I can see how it works.

  • Title: "Prove channel ownership"
  • Subtitle: "Link to an unlisted video in your channel titled "Joining Gleev":" <== can we make this much bigger? its just so small now.
  • input field

By default we have nothing else, there is also no "sign in" button, as I dont see a need for it?

When user clicks "continue", which we should just call "Verify video", we do client side check, and only if it fails do we display some error information, so we drop the "your video must:..". The errors will be one among:

  • URL not valid: this would be if its not a well formatted URL
  • Not link to a youtube video: this would be if the URL is not to youtube domain, or is not to a video on youtube.
  • Video has title "...", but it must be "Joining Gleev" exactly.
  • This channel "..." is already part of our partner program: Here I'm not sure what the user is supposed to do? do you?

These errors can just be displayed as red text, and we only need to show one at a time, and we don't need to show the requirements that are satisfied, again just to simplify. Notice that we don't need to actually require that the video is unlisted, this is only something the creator needs to understand is possible as an option. Notice that everything above is on one screen.

If client side verification passes, we should show a new window where we have their channel avatar, name, and title of window is something like "Ownership Verified". This tells the use very clearly that the prior step suceeded, and this may be required as I suspect people may end up failing a few times in the prior step. This window just has button "Create Account" or something, and "cancel" of course. When user clicks "create...", we just have this screen in some loading state, like with a spinner over the button or sometihng, we dont need a new window. Currentyl we have "Veryinf channel woernship", but at this point it is misleading, as the user would think that we have already done that, as the user does not understand the difference between client and server validation. If there is any error, we need to send user back to prior screen with appropriate error message, just like we already do when client side validation is being done.

User click on the confirmation link

I think we need a first success window after the user has clicked link, which says something like "email verified" like a success case, so the user understand they did the right thing after leaving the prodcut, and they are suppose dto continue. If we just send user directly to create password, they may be unsure about perhaps they have been asked to start again, or if the old stuff they did failed in some way, so we need to show them the continuiity of the process is intaact. We only need a single button with "Set password" as title"

@bedeho
Copy link
Member

bedeho commented May 8, 2024

perfect

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants