1. Introduction


DAPP account allows dApps to enable a simple login and blockchain transaction authentication mechanism which bridges the gap between dApps and standard web based applications. dApps can choose the level of security for their users by selecting the appropriate level of 2FA model. User accounts can have multiple keys and can login from multiple devices. Recovery of account is possible if a user logs in from a new device or loses his device that contains his keys.

2. DAPP account as a subscriber model


Contract Setup, Information about authorization level & Whitelisting dapp -

A dapp needs to follow certain steps before starting to register their users on dappaccount and authorize their actions with virtual users created and registered using dappaccount contract. The steps are - contract setup following the subscription model (sample code given), whitelisting of dapp on dappaccount contract and also whitelisting dapp’s actions with a level specification (described below)


2.1. Subscriber contract setup :

Dapp needs to modify their contract in order to act as a subscriber to our dappaccount contract so that it is able to use dappaccount’s functionalities. The link to the sample code is added below which can be followed to set up the contract. LInk to sample code : https://github.com/investingwad/dappaccountsample

Note : Please refer to the Readme file for detailed description of the contract setup and necessary action calls.


2.2. Information about authorization level :

Dappaccount defines some level of security inside the smart contract and type of authentication for each security level, which a dapp needs to follow to register its user through dappaccount platform. Right now, dappaccount has enabled two security levels, level 1 and level 2. Later more levels of security will come.

2.2.a) General Level information -
Level 1 :

This is the minimum security level and minimum requirement for registration with dappaccount. This level includes user authentication through his email. Later other options will be added like telegram. So later users can select an option (verification option) available under this security level, e.g email / telegram. Information for later use : Dapps may need to use below information at the time of dappaccount registration action call from smart contract

Level ID:1
Type of authentication (authtype) under this security level - “email”
Level 2 :

This is a higher security level. This level includes user authentication through his phone i.e contact number. Later other options will be added like google authentication. So later users can select an option (verification option) available under this security level, e.g phone / google authentication.

Right now, as per the implementation, if any dapp selects this security level, then every user registration from that dapp needs to undergo validation for both the levels, i.e both email and phone verification.

Information for later use : Dapps may need to use below information at the time of dappaccount registration action call from smart contract

Level ID:2
Type of authentication under this security level - “phone”

In both the levels, a field “Type of authentication” is mentioned. This is because, later, other options may get added under each security level as mentioned above. At that time the “Authentication type” is needed as an action parameter to distinguish between types and send access code and validate accordingly. That is why dapp needs to pass this field in many action executions. Detailed description like where and when, added later, Section 3.2

During registration on dappaccount, the user information like email , phone number are stored on-chain depending on which level dapp is selecting for registration. All the user’s information is stored in sha256 HASH format within smart contract. Refer to section 3.2.a for details.

Dappaccount uses these two levels of authentication during registration and recovery to generate keys for users and later use these keys to authorize their own action by user (detailed in Section 3.2), but dapp can also use two factor authentication from their side at the time of their action call.


2.2.b) Two-factor authentication on a dapp's action call

This is also a type of security check when the dapp calls any action with virtual user’s authorization. Dapp can again verify the user by sending access code to his email / phone. This type of action will have two factor authentication, one by user’s key (generated at the time of registration / recovery, details in Section 3.2) and other by verifying with access code. How the verification can be done through access code along with signature verification within dapp’s contract action , is described in the sample code, Section 2.1.


2.3. Whitelisting dapp :

Dapps need to be whitelisted first before it is allowed to register their user on dappaccount and create virtual account on blockchain.

The whitelisting has 2 parts -

2.3.a) Whitelisting dapp’s contract account - whitelisting EOS account where the dapp’s contract is deployed. Right now this action is performed with dappaccount contract’s permission, i.e any dapp needs to connect to dappaccount team first to add their contract as a whitelisted one. It can't be done with dapp’s permission. To give a better idea, the action parameters are described below.

Action - dappwhitelst
Permission - dappaccount’s contract
Parameters -
account : dapp’s contract account
actoracc : dapp’s array of public keys which can be used later for any signature verification. Initially only active key of dapp’s contract should be fine signperday : This is a quota defined for every dapp. This defines the number of time a dapp can push transaction into blockchain with dappaccount user (virtual user account’s permission) signature per day. This number is decided by dappaccount

2.3.b) Whitelisting dapp’s actions - Once a dapp is whitelisted by dappaccount, it has to whitelist its smart contract actions. Whitelisting action is basically defining action name and corresponding security level.

Explanation - whenever a dapp registers any user, it has to perform a level validation e.g email verification for registering user under security level 1 . At that time a key pair is also generated and registered into blockchain for that user and specifically for that security level. So if any dapp action (with virtual user’s permission) is marked as level 1, then only the user's level 1 registered key can be used to authorize the action. Same is applicable for level 2. If any action needs more security , then any dapp can mark that action as level 2 and the user's level 2 key can only be used to call that action not level 1.
Action name - adddappact
Permission - dapp’s account permission
Parameters -
account : string, dapp’s contract account
levelid : number, security level id specified for the action
actionlist : array of string, action names under the above level id specified Example of how to call this action is given on the sample code , Section 2.1
Dappaccount provides a library through which all the registration, recovery process, and dapp's own action call can take place. It is described below.

3. Integration with dappaccount library :


3.1 Installation & import :-

npm i dappaccount;

import { dappaccount, dappaccountauth } from 'dappaccount';


3.2 Useful Methods & Info:-
3.2.a) Registration with dappaccount :

Registration with dappaccount needs email of any user as a mandatory field. It also takes a contact number as a parameter but that is optional. The dappaccount name (a 12 character long virtual account name following EOS naming convention) is generated from email and it is unique for each unique email id. Registration method includes verification of email / contact within blockchain. Please refer to Section 2.2 for details about authorization methods and level of verification.

The register method returns an array of private keys for the user on successful registration. If dapp selects level 1 verification, the array will contain a single key for level 1, and if level 2 verification is selected during registration, the array will contain 2 keys for level 1 and 2 respectively. Each level of validation will have a unique key for a user.

As it is clear from the above that the registration method needs email / contact verification, so this registration process consists of 2 steps, one is an “Access code” request, and then a smart contract action call for registration through the library method.

1. Access code request -

This step will need level id as a parameter, i.e which level of verification a dapp wants will be decided in this step.

MInimum level of authorization is mandatory, i.e level id 1. Registration can’t take place without any validation.

In this step, nothing is stored on the smart contract. It only requests access code via email / contact

Method to call : regcodereq(env, email, contact, levelid, dappname)

How to call : dappaccountauth.regcodereq(env, email, contact, levelid, dappname)

Parameters explained :

env : “main” / “kylin” -> depends on which environment you are using

email : user’s email, where access code will be sent.

contact: user’s contact,

[ if level id is 1, then it is not mandatory, “” can be passed as a parameter, or if dapp wants contact number can be passed,

If level id is 2, then contact is mandatory, access code will be sent at this number as well]

levelid : 1 OR 2 , depending on level of verification

dappname : one word representing the dapp, it will be reflected on the subject line of the email sent with code. If not passed, i.e passed as blank “ “, “dappaccount” will be appeared.

e.g “Verification code for dappaccount registration”

OR “Verification code for < dappname> registration”


2. Smart contract action call for registration :

After the user gets access code, this step needs to be executed where the user gets registered in the blockchain.

Method to call : registerdapp(env, email, contact, levelid, dappcontract, emailcode, contactcode)

How to call : dappaccountauth.registerdapp(env, email, contact, levelid, dappcontract, emailcode, contactcode, dspoption)

Parameters explained :

env - “main” / “kylin”

email - email of user used in step 1

contact - user’s contact number, if level 2 is used in step 1 then mandatory, otherwise “”

levelid - 1 OR 2, whatever is passed in step1

dappcontract - dapp’s own contract name i.e EOS account where dapp’s contract is

deployed emailcode - code sent to email in step 1

contactcode - “” OR code sent to contact number if level 2 was selected in step 1

// This below field can be ignored for now. Dapp can pass upto “data” field -

dspoption : This field allows a dapp to choose which dsp the transaction will be pushed to. Not implemented right now. No need to pass anything now. Dapps can ignore this field

This step takes email / contact as input parameter and stores the data on-chain but the raw email is not stored inside smart contract tables. Within the contract action, the information like email / contact are first converted into sha256 hash and then the hash stored on-chain.

This method will return an array of private keys which is specific for this user and this dapp and the user’s dappaccount name (virtual account’s name). Both are registered in blockchain. And the user’s email passed will always correspond to the same dappaccount name. This key can be used later to authorize any action from dapp’s contract with user’s authorization. Example contract is in Section 2.1


3.2.b) Recovery with dappaccount :

If any user loses the private key and is unable to authorize any action, he can recover his account by the following steps. Like registration, recovery also will include verification through access code and then confirmation of the code in blockchain

3) Access code request -

This step will need level id as a parameter, i.e which level of verification a dapp wants for recovery will be passed in this step.

Note : If dapp selected level 2 (highest level) authorization for any user at the time of registration, then for recovery the highest level needs to be passed, i.e 2 in this case. Recovery can not take place with lower level of verification at that time.

Method to call : actauthcodereq(env, email, authtype, authkey, levelid, dappname)

How to call : dappaccountauth.actauthcodereq(env, email, authtype, authkey, levelid, dappname)

Parameters explained :

env : “main” / “kylin” -> depends on which environment you are using

email : user’s email, used at the time of registration

authtype: “email” OR “phone”

[ if level id is 1, then authtype is “email”, i.e code will be send to email only. String not actual email,

If level id is 2, then authtype is “contact”, i.e access code will be sent to contact number only. String not actual contact ]

authkey : user’s email or user’s contact number , depending on levelid selected

[ if level id is 1, then authkey is user’s email used earlier, i.e code will be send to this email id only,

If level id is 2, then authkey is user’s contact, i.e access code will be sent to this contact number only ]

levelid : 1 OR 2

dappname : one word representing the dapp, it will be reflected on the subject line of the email sent with code. If not passed, i.e passed as blank “ “, “dappaccount” will be appeared.

e.g “Verification code for dappaccount action authorization”

OR “Verification code for < dappname> action authorization”


4) Smart contract action call for recovery :

After the user gets access code, this step needs to be executed where the new key gets generated and stored in the blockchain for the user.

Method to call : recoverdapp(env, email, dappcontract, auth_code, levelid, authkey)

How to call : dappaccountauth.recoverdapp(env, email, dappcontract, auth_code, levelid, authkey, dspoption)

Parameters explained :

env - “main” / “kylin”

email - email of user used at the time of registration so that dappaccount name can be generated

dappcontract - dapp’s own contract name i.e EOS account where dapp’s contract is deployed

auth_code : Access code sent to email / contact in previous step

levelid - 1 OR 2, whatever is passed in previous step

authkey : same used in previous step at the time of access code request

// This below field can be ignored for now. Dapp can pass upto “data” field

-

dspoption : This field allows a dapp to choose which dsp the transaction will be pushed to. Not implemented right now. No need to pass anything now. Dapps can ignore this field

This method will return a single private key (not array) which is specific for this user and this dapp and also the dappaccount name of the user

Note : If level id is 1, then email and authkey will have the same value, but these 2 are taken separately as later we might introduce different methods of validation under a particular level, i.e level id 1 can contain email verification , telegram verification etc. Similarly level 2 also may contain phone verification, google authentication etc. That is why this validation key and email have been taken separately as parameters in most of the steps.

[ Email is used to generate the user's dappaccount name in each step. So email used at the time of registration needs to be passed in any later step wherever email is a required field.]


3.2.c) DAPP’s Action call which is authorized by dappaccount user :

Registration and recovery , described above, are used to generate and store keys with dappaccount name for a particular user in blockchain. Now, when any action in the dapp’s contract has the user’s dappaccount authorization, those keys and account name need to be used. How a dapp can use a dappaccount user’s permission (virtual account) in an action (inside their contract), that is described in Section 2.1 where the contract setup example has been shared.

Any action with dappaccount user’s permission can be pushed using one of the library’s methods in the following way.

Method to call : pushtrx(env, contract, key, action, data, dspoption)

How to call : dappaccount.pushtrx(env, contract, key, action, data, dspoption)

Parameters explained :

env : “main” / “kylin”

contract: dapp’s contract name whose action needs to be pushed

key : user’s private key which is generated at the time of registration / recovery

action : action name which needs to be pushed

data : action data, in object form

dspoption : The dsp endpoint needs to be passed in this field.

For registration or recovery or user level upgrade methods, the dspoption field was different. That was the dsp options available for pushing dappaccount specific transactions, i.e the dsp options to which dappaccount contract is staked to. If any dsp server is down, dapp can select the other one for the registration process. It is not implemented yet. So that field was said to be ignored above.

But in this case, the dsp endpoint refers to the DSP which DAPP has selected and staked to. As the dapp’s own contract is pushing the action with the virtual account’s permission, the endpoint of the DSP which the dapp has selected needs to be passed. If the dapp has selected the blockstart dsp, then this field can be ignored. No need to pass this field or can pass “”.

[DSP endpoints can be found on the package table of dappservices contract ]

Sample data : from contract’s action testdappact , example given in Section 2.1 data : { vaccount : user’s dappaccount name, received in the response at the time of user registration. Also can be found out at any point of time , following Section 3.2.f, balance : “1.0000 EOS”, dummyid : 1 }

Method returns success message on transaction is pushed into blockchain successfully.

Note : Actions for dapps are also level specific. Please refer to Section 2.3.b for more details on level specific action. If an action is marked ad level 1, then the user's level 1 “key” needs to be passed.

Explanation - When dapp registers any user with level 1, it gets an array of keys containing a single private key, specific for level 1. And if level 2 was passed, then the register method would have returned an array containing 2 keys - level 1, 2 respectively. So that is how every key is unique and specific to 3 things - User, dapp and level id.

Same for recovery also, instead of an array of keys, it returns a single key specific to the leve id passed in the recovery request.

So when any action of level 1 is called, then the user's level 1 key needs to be passed and the same for level 2. Otherwise action will throw an error for providing the wrong key.


3.2.d) Upgrade user’s authorization level :

When a dapp has registered its user with level 1 authorization and later it is found out that an action of the dapp’s contract needs level 2 authorization (what is level of an action - is defined in Section 2.3.b ), then the user can upgrade his level by calling a smart contract action.

This action will need the authorization of the user with his lower level key, in this case level 1 key needs to be used to call this action. And also level 1 key validation is performed before adding level 2 information, i.e if the user wants to upgrade to level 2, then his email (level 1 authorization type) needs to be verified first.

Access code request - This step will need lower level id as a parameter, i.e the lower level id than the level you want to register (upgrade), 1 in this case and corresponding authtype will be “email”

Method to call : actauthcodereq(env, email, authtype, authkey, levelid, dappname)

How to call : dappaccountauth.actauthcodereq(env, email, authtype, authkey, levelid, dappname)

Parameters explained :

env : “main” / “kylin” -> depends on which environment you are using

email : user’s email, used at the time of registration

authtype: “email” OR “phone”

[ if level id is 1, then authtype is “email”, i.e code will be sent to email only. String not actual email,

If level id is 2, then authtype is “contact”, i.e access code will be sent to contact number only. String not actual contact ]

authkey : user’s email or user’s contact number , depending on levelid selected

[ if level id is 1, then authkey is user’s email used earlier, i.e code will be send to this email id only,

If level id is 2, then authkey is user’s contact, i.e access code will be sent to this contact number only ]

levelid : 1 OR 2

dappname : one word representing the dapp, it will be reflected on the subject line of the email sent with code. If not passed, i.e passed as blank “ “, “dappaccount” will be appeared.

e.g “Verification code for dappaccount action authorization”

OR “Verification code for < dappname> action authorization”

Register level 2 information in blockchain -

Method to call : upgradeuserlev(env, dappcontract, vaccount_prvkey, email, authtype, authcode, upgradeto_levid, upgradeto_authkey, upgradeto_authtype, dspoption)

How to call : dappaccountauth.upgradeuserlev(env, dappcontract, vaccount_prvkey, email, authtype, authcode, upgradeto_levid, upgradeto_authkey, upgradeto_authtype)

Parameters explained :

env - “main” / “kylin”

dappcontract - dapp’s own contract name i.e EOS account where dapp’s contract is deployed

vaccount_prvkey - user’s level 1 key, received after registration / login

email - email of user used at the time of registration

authtype: “email”

[ the type used to send otp in previous step, authtype for lower level id. Only “email” is available now]

authcode : Access code sent to email in previous step

upgradeto_levid - 2

[the security level id user wants to upgrade to. Refer to Section 2.2 for level details]

upgradeto_authkey : user’s level 2 authorization key. It will be stored in blockchain

[contact number in this case as no other level 2 authentication type is available now]

upgradeto_authtype : “phone”

[authentication type for security level 2. Refer to Section 2.2 for more details on level id and type]

// This below field can be ignored for now. Dapp can pass upto “data” field -

dspoption : This field allows a dapp to choose which dsp the transaction will be pushed to. Not implemented right now. No need to pass anything now. Dapps can ignore this field

This step takes contact as input parameter (for higher level security key) and stores the data on-chain but the raw format of contact is not stored inside smart contract tables. Within the contract action, the information like email / contact are first converted into sha256 hash and then the hash stored on-chain.


3.2.e) General method to call for access code request:

When a dapp wants to perform two factor authentication while calling an high level action (level 2 secured) within their smart contract (refer to Section 2.2.b for details on two factor authentication), it needs to request access code before calling the action. The access code verification is done within the smart contract action (Section 2.1 defines how to set up a contract to use this functionality).

Access code request - This step will need level id as a parameter, and that id should be equal to the action specific level id, i.e the level id dapp has marked the action with at the time of action whitelisting (refer to Section 2.3 and 2.3.b for details about security level of an action).

Method to call : actauthcodereq(env, email, authtype, authkey, levelid, dappname)

How to call : dappaccountauth.actauthcodereq(env, email, authtype, authkey, levelid, dappname)

Parameters explained :

env : “main” / “kylin” -> depends on which environment you are using

email : user’s email, used at the time of registration

authtype: “email” OR “phone”,

[ if level id is 1, then authtype is “email”, i.e code will be sent to email only. String not actual email,

If level id is 2, then authtype is “contact”, i.e access code will be sent to contact number only. String not actual contact ]

authkey : user’s email or user’s contact number , depending on levelid selected

[ if level id is 1, then authkey is user’s email used earlier, i.e code will be send to this email id only,

If level id is 2, then authkey is user’s contact, i.e access code will be sent to this contact number only ]

levelid : 1 OR 2, depends on the action level specified at the time of whitelisting

dappname : one word representing the dapp, it will be reflected on the subject line of the email sent with code. If not passed, i.e passed as blank “ “, “dappaccount” will be appeared.

e.g “Verification code for dappaccount action authorization”

OR “Verification code for < dappname> action authorization”


3.2.f) Convert an email address to corresponding dappaccount name :

This process is very useful for dapps to retrieve a user’s dappaccount name at any point of time by simply using a library method.

Method to call : converttodappacc(email)

How to call : dappaccount.converttodappacc(email)

Parameters explained :

email : User’s email address, which has been used at the time of registration with dappaccount.


3.2.g) Get available dsp options : This is yet to be implemented.:

This method basically returns the options of DSPs that dappaccount contract is staked to and all data are synced. This option can be used at the time of registration or recovery , by passing value in dspoption field.

Method to call : getdspoptions(env)

How to call : dappaccountauth.converttodappacc(env)

Parameters explained :

env : kylin” / “main” - depending on the network


3.3 FINALITY CHECK FOR TRANSACTION & DSP SELECTION :

All the transactions we are pushing for virtual accounts, i.e any action with virtual account’s permission, all is going to the DSP node selected by dapp (Section 2.1 contract setup). There is a chance that the transaction can go missing on chain even after successful submission and receiving a transaction id due to some certain issues on dsp. So, after pushing any transaction to dsp, Dapps need to ensure the finality of a transaction before going forward.

[ Note: The finality check for registration, recover actions are taken care of by the library. Dapps own contract actions need to be tracked for finality check. ]

Following are some suggestions for the same -

3.3.a)

To overcome this, few dsps have integrated with dfuse and push transaction through dfuse to ensure transaction goes through. Dapps can stake to those DSP at the time of contract setup. This ensures transaction finality. And at the time of transaction push, dapps can pass the endpoint of their selected dsp in dspoption field (section 3.2.c).

E.g blockstart DSP uses dfuse to push transactions

3.3.b)

Dapps will get transaction id from library after pushing a transaction of their own contract actions. The id can be verified on chain after a certain time. If not present , then can retry push transaction. Any retry logic for pushing a transaction with the library should work if Dapps are not using DSPs following 3.3.a.

Contact our Telegram Group for any query.