Off-Chain Access Control

To restrict access to specific features or functionalities on your website based on the KYC/AML status of the user, you need to implement off-chain access control.

User verification flow

Steps

  1. Generate an API key/secret pair from the Authento Dashboard under the Settings tab

  2. [Backend] Configure the server to request and handle KYC/AML data from Authento.

  3. [Frontend] Implement access control based on the status response returned from your backend.

  4. [Backend] (Optional) Set up handlers for verification webhooks.

Backend

You have to set up a server which requests and handles KYC/AML data from Authento. The exact implementation depends on your use case. For example, you could configure your server to

  • Request KYC/AML status by wallet address upon user sign-in.

  • Confirm KYC/AML status when a user makes a withdrawal request.

Once the KYC/AML status is retrieved, it should be processed on your backend to derive the permissions which should be granted to the user.

For details on how KYC/AML status can be retrieved using the Authento API, please refer to the endpoints section.

Backend examples

const crypto = require("crypto");
const express = require("express");

const app = express();

// TODO: Configure your Authento settings
const apiKey = "YOUR_API_KEY";
const apiSecret = "YOUR_API_SECRET";
const basicUserInfoEndpoint = "https://api.authento.io/userinfo/basic";

/**
 * Returns the KYC status of an address retrieved using Authento API
 * @api {get} /userinfo/basic?address=:address
 * @apiParam {String} address EVM compatible address
 * @apiSuccess 
 *   {String="unverified","processing","info_required",verified","rejected"}
 *   status KYC status of the address
 * @apiError {String} detail Error detail
 */
app.get("/userinfo/basic", async (req, res) => {
  try {
    const address = req.query.address;

    if (!address) {
      throw new Error("Invalid address");
    }

    const url = `${basicUserInfoEndpoint}?address=${address}`;
    const timestamp = Date.now();
    const signature = crypto
      .createHmac("sha256", apiSecret)
      .update(`${timestamp}GET${url}`)
      .digest("hex");

    const { status, type } = await fetch(url, {
      headers: {
        "X-AUTHENTO-APIKEY": apiKey,
        "X-AUTHENTO-SIGNATURE": signature,
        "X-AUTHENTO-TS": timestamp,
      },
    })
      .then((response) => response.json())
      .then((data) => data.result);

    // TODO: Implement additional filters based on user attributes such
    //  as nationality/age/pep/riskScore as needed.
    //  Fields other than 'status' should NOT be included
    //  in the response as they might contain sensitive information.
    res.json({ status, type });
  } catch {
    res.status(400).json({ detail: "Failed to retrieve basic user info" });
  }
});

app.listen(3000, () => {
  console.log("Server listening on port 3000");
});

Frontend

Aside from restricting user access based on KYC status returned from your backend, your frontend should be set up to initialize Authento KYC on users' demand. You can do this using the authento-react package, or you can do this manually.

This package contains custom react hooks which makes it very simple to integrate Authento into your platform. For detailed instructions or usage examples, please refer to this section.

Manual integration

Take the following steps to initialize the Authento verification process manually:

  1. Create a signature for the following typed structured data:

    const domain = { name: YOUR_DOMAIN_NAME };
    const types = {
      Message: [
        { name: "content", type: "string" },
        { name: "for", type: "string" },
        { name: "timestamp", type: "string" },
        { name: "nonce", type: "string" },
      ],
    };
    const primaryType = "Message";
    const message = {
      content:
        "Sign this message to prove your ownership of this address " +
        "and proceed with the identity verification process.",
      for: domainName,
      timestamp: CURRENT_TIMESTAMP,
      nonce: NONCE,
    };
    • YOUR_DOMAIN_NAME: Your domain name registered with Authento. Please contact us if you are unsure of its value.

    • CURRENT_TIMESTAMP: The number of milliseconds elapsed since the Unix epoch as a string.

    • NONCE: Randomly generated string as a safeguard against replay attacks. You can use uuid or other packages to generate this.

    On the Wagmi library, the signature can be generated as follows:

    const signature = await signTypedData({
      domain,
      message,
      primaryType,
      types,
    })

Remember to refresh CURRENT_TIMESTAMP and NONCE just before the signature is generated.

  1. Upon successful generation of the signature, direct the user to https://www.authento.io/verify/${YOUR_DOMAIN_NAME} using a modal or a popup with the following query parameters:

    • address: The EVM address to verify

    • ts: CURRENT_TIMESTAMP as defined above

    • nonce: NONCE as defined above

    • signature: The signature generated

    • levelType: "BASIC" or "POA"

  1. Users will then proceed with the verification process on the newly opened modal or popup.

Webhooks Handling

In address-based verification, you are not assumed to be managing your own user database. In case you do, however, you can ensure that your user data is up to date by setting up an endpoint to handle and process webhooks data. For more information on webhooks, please refer to this section.

Examples

Last updated