Auth server
The auth repository contains an application that lets users sign up for Chromia via various methods. As a dapp developer on Chromia, you want to use this to prevent attacks where users flood your dapp with accounts. Currently, the available options are:
- Staking
- Telegram
- Rate limit
- reCaptcha
The Setup section provides information on configuring which methods you want to support.
Staking
The staking module provides you with the possibility to allow your users to register an account if they have enough stake in a particular staking contract. Contracts are configured in the file staking/contracts/index.ts by updating the contracts
map. The structure of the map looks like the following:
const contracts = {
[contractAddress]: {
address: string;
url: string;
abi: AbiItem[]
}
}
Where contractAddress
is the contract's address, url
is the RPC URL of the chain that hosts the contract, and abi
is the ABI of the contract (can typically be found by looking at Etherscan or similar). By default, the application uses Chromia's staking contracts, deployed on Ethereum and Binance Smart Chain, but you are free to add your own contracts and add or remove the default ones. So long as the custom staking contracts comply with the same interface.
The application will sum the user's stake across all the provided contracts. For example, if the staking limit is 1000
and the user has 200
staked on Ethereum and 800
staked on BSC, then the user's total stake will be 200 + 800 = 1000
and will be considered to have reached the staking limit.
API
The staking module exposes the following REST APIs:
GET /auth/stake/enough?address=<evmAddress>
Determines if the provided address has enough stake to create an account. Example response:
{ "status": "SUCCESS", "data": { "hasEnoughStake": true } }
GET/auth/stake/signing-message
Retrieves the message to pass to MetaMask for user signing. Example response:
{
"data": {
"message": "Register an account on blockchain 1234"
},
"status": "SUCCESS"
}
POST /auth/stake/create
Creates a new postchain account for the user. The endpoint expects a MetaMask signature of the message returned by /auth/stake/signing-message
. If the address corresponding to the private key signing the message has enough total stake, a postchain account will be created. Example request:
{
"signature": "0xd8b9bc03ef2384f7fd404c723f702f3426a044191778cd8570a9d9ca0214d5f108a04629f86e6acbdad599a828956b9b0df25fd1768e3c8bedd077a76f9c997d1b"
}
Telegram
The Telegram module allows registration via Telegram. After sending the signed message to the correct endpoint, the user should be prompted with one of the following:
- a link to
t.me/<bot_username>?start=<address>
(for example,t.me/MyRegistrationBot?start=0x0000000000000000000000000000000000000000
) - the instructions to go to your telegram bot and use either
/start <address>
or/register <address>
It exposes two endpoints:
POST /auth/telegram/
Adds a signature for an address. The request body must include the address
and signature
.
Example:
{
"address": "0x1234...",
"signature": "0x5678..."
}
GET /auth/telegram/:id
Retrieves the signature for an address. Replace :id
with the address in the URL.
Example:
GET /auth/telegram/0x1234...
Rate limiting is implemented on both endpoints to prevent abuse.
Rate limit
The rate limit module provides you with the possibility to allow your users to register accounts with rate limiting,
but no further requirements. Each IP address can create up to ACCOUNTS_PER_IP
accounts per ACCOUNT_TIME_PERIOD
seconds.
This module is enabled when ACCOUNTS_PER_IP
is set.
API
The rate limit module exposes the following REST-api:
GET /auth/ratelimit/signing-message
Retrieves the message to pass to metamask for user signing. Example response:
{
"data": {
"message": "Register an account on blockchain 1234"
},
"status": "SUCCESS"
}
POST /auth/ratelimit/create
Creates a new account for the user. The endpoint expects a MetaMask signature of the message returned by
/auth/ratelimit/signing-message
. If the IP address of the request has not created too many accounts recently,
then an account will be created. Example request:
{
"signature": "0xd8b9bc03ef2384f7fd404c723f702f3426a044191778cd8570a9d9ca0214d5f108a04629f86e6acbdad599a828956b9b0df25fd1768e3c8bedd077a76f9c997d1b"
}
reCaptcha
The reCaptcha
module allows your users to register accounts if they first pass a Google reCaptcha
. Enabling this module will perform the required backend validations specified by the reCaptcha
documentation. The frontend part, however, needs to be provided by your client side. The relevant JavaScript part is as follows:
document
.getElementById("<your form element>")
.addEventListener("submit", (e) => {
e.preventDefault();
const resp = window.grecaptcha.getResponse();
fetch("<domain>/auth/captcha/create", {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({
["g-recaptcha-response"]: resp,
signature: "<user signature>",
}),
});
});
Where the value returned by reCaptcha
is passed to the auth server backend in the g-recaptcha-response
parameter, we pass the user's MetaMask signature in the' signature' parameter.
In order to use this module, you must register your site with reCaptcha
to acquire the API key.
This module is activated by providing the secret GOOGLE_RECAPTCHA_SECRET
in the .env
file.
API
GET /auth/captcha/signing-message
Retrieves the message to pass to metamask for user signing. Example response:
{
"data": {
"message": "Register an account on blockchain 1234"
},
"status": "SUCCESS"
}
POST /auth/captcha/create
Creates a new account for the user. The endpoint expects a MetaMask signature of the message returned by
/auth/captcha/signing-message
and the response value returned by the reCaptcha
form. If the signature and reCaptcha
are valid, an account corresponding to the address used to sign the request is created.
Installing auth server Rell module in your project
To include the auth server in your own Rell project, follow these steps:
-
Generate the auth server and the admin keys by running the following commands:
chr keygen --save .auth.secret | grep pubkey
chr keygen --save .admin.secret | grep pubkeyThis saves the keys to files named
.auth.secret
and.admin.secret
in the current directory. -
Add the following dependency to your
chromia.yml
:libs:
auth:
registry: https://bitbucket.org/chromawallet/auth-server-ft4.git
path: rell/src/auth
tagOrBranch: v2.1.0r
rid: x"7EC77529149B510F7863BA19CE2A8798AD8492A98A79F8B350FE8D774996F268"
insecure: false
ft4:
registry: https://bitbucket.org/chromawallet/ft3-lib
path: rell/src/lib/ft4
tagOrBranch: v0.7.0r
rid: x"F7C207AA595ABD25FDE5C2C2E32ECD3768B480AD03D1F2341548FF4F37D9B7AF"
insecure: falseThe auth server Rell module depends on FT4. Therefore, we've to add FT4 dependency as well.
-
Add the following module argument:
moduleArgs:
lib.ft4.core.admin:
admin_pubkey: <admin pubkey>
lib.auth:
auth_pubkey: <auth pubkey>Replace
<auth pubkey>
and<admin pubkey>
with the public keys generated in Step 1. -
Import the auth operations in your main Rell module:
import lib.auth;
Set up the project
This app is just a node backend. You'll need to create some way for the users to interact with it. This section only explains how to set up the server-side software.
To set up and configure the app:
-
Clone the repository:
git clone git@bitbucket.org:chromawallet/auth-server-ft4.git
-
Install dependencies:
npm ci
-
Create an
.env
file and set up the necessary configuration variables. Here's an example of what your.env
file could look like:PORT=3001
MODE=dev
BLOCKCHAIN_RID=0F8B260F653457A5C7942018ED31BAE5EF53D6AE04FC4D402EC5F0DE26B5913D
BLOCKCHAIN_URL=http://localhost:7740
AUTH_PRIV_KEY=132EC6A758DCAA832DAFE032C4B23ABD9615C56792687ADBC561FCC377430CEC
STAKE_LIMIT=1000
TELEGRAM_API_TOKEN=123456:ABC-DEF1234ghIkl-zyx57W2v1u123ew11 -
Start the server:
npm start
Available configuration options
These are the general options available:
Name | Description | Example | Required | Default value |
---|---|---|---|---|
PORT | The port on which the application will be listening | 3001 | no | 3001 |
MODE | Is this application running in development or in production mode | dev|prod | no | prod |
BLOCKCHAIN_RID | The blockchain rid of the blockchain on which the application should create accounts | 0F8B260F653457A5C7942018ED31BAE5EF53D6AE04FC4D402EC5F0DE26B5913D | yes | none |
BLOCKCHAIN_URL | The blockchain url of the blockchain on which the application should create accounts | http://localhost:7740 | yes | none |
AUTH_PRIV_KEY | The user private key to perform register account operation | 132EC6A758DCAA832DAFE032C4B23ABD9615C56792687ADBC561FCC377430CEC | yes | none |
AUTH_FLAGS | Comma-separated list of flags used for registering a new account | A,T | no | A, T |
IS_MANAGED_NETWORK | Is auth server used with a managed network (e.g., testnet)? If true, then the directory chain will be used to discover the blockchain node. BLOCKCHAIN_URL will be used as a system node URL | true | no | false |
TIME_BETWEEN_REQUESTS | Time which has to pass between each request from a given IP address, in seconds, zero to turn off rate limiting | 10 | no | 5 |
ORIGIN_IP_HEADER | HTTP request header to read the origin IP address from will use the actual origin IP address if not set. Use this only when behind a trusted proxy. | x-forwarded-for | no | none |
SUPPORTED_NETWORKS | Comma separated list of chainIds to check stake on. It is only relevant if a staking module is used. | 1,56,97 | no | 1,56 |
STAKE_LIMIT | The minimum value the user needs to stake to create an account. Required to use the staking module. | 100 | no | none |
TELEGRAM_API_TOKEN | Your Telegram API token. Required to use telegram module. | 123456:ABC-DEF1234ghIkl-zyx57W2v1u123ew11 | no | none |
ADMIN_CHAT_ID | The Telegram Chat ID of the admin, who can use the admin commands to debug the bot. If not set, the bot will work normally. Nobody will have admin permissions | 76694301 | no | none |
ACCOUNTS_PER_IP | Number of accounts to create for a given IP address per ACCOUNT_TIME_PERIOD seconds. Required to use rate limit module. | 10 | no | none |
ACCOUNT_TIME_PERIOD | Period for account creation rate limiting, in seconds. Required to use rate limit module. | 3600 | no | none |
GOOGLE_RECAPTCHA_SECRET | The secret value provided when registering your site with reCaptcha. | 6LeIxAcTAAAAAGG-vFI1TnRWxMZNFuojJ4WifJWe | no | none |