This document provides all the required steps to integrate a partner's site with Securitize-iD and the capability of registering attested wallets into a blockchain smart contract.
Securize provides the services to KYC users, as well as the ability to establish if that user complies with a certain set of requirements (attestation requirements) the partner requires from that user. These attestation requirements can simply be that the user is KYCed, but the partner might require that the user resides in a certain jurisdiction (e.g., the United States of America), but doesn’t in specific jurisdictions (e.g, not being a resident in Texas). The attestation rules are quite flexible, and can combine a whole set of user personal identification features to satisfy the partner’s requirements.
To be able to interact with Securitize-iD services:
- The user needs to sign-in (or up) in Securitize and have a Securitize ID
- The partner will need to require the user permission to access his profile
- The partner will need to authenticate in the system
- The partner will need to interact with the user to obtain his public crypto wallet address
In order to be able to access Securitize APIs, a set of information and variables have to be shared between Securitize and the Parner, which are summarized in the following table:
| Variable | Value | Comment |
| baseUrl
(SecuritizeID) |
|
Take into account, that depending on the environment (Production and Sandbox), issuerID and secret will be different, and the redirecturl will have to be configured in SecID for both environments |
| API_BASE_URL
(API Gateway) |
|
|
| issuerID | String, like this: "b462d564-7562-4528-a207-86fcdfc1c6d5" | Provided by Securitize |
| secret | String, like this: "95cacd3d-fbcf-487c-b8f0-60f986ea8968” | Provided by Securitize |
| contractAddress
(Deployed Smart Contract Address) |
String like this: “0xB8D7d897BdCe6f6454b54E808461B337058cDB0B” | Provided by Securitize |
| redirecturl | "https://{partnerSite}" | Provided by Partner |
Take into account to change these paramenters in the index.html file:
const baseUrl = "https://id.sandbox.securitize.io/";
const API_BASE_URL = "https://connect-gw.sandbox.securitize.io/api/";
const issuerID = "Provided by Securitize";
const secret = "Provided by Securitize";
const redirecturl = "Where the front end Application is hosted"
const contractAddress = "Provided by Securitize"; // Contract Address In order to access Securitize ID APIs a simple OAuth process takes place, as shown in the figure below:
- The user accesses the partner's site, and clicks on “Login with Securitize” button
- The user gets redirected to Securitize-iD’s site, and the redirection URL contains the following information: issuerId, scope of access (info, details, …) and the URL the user will be re-directed once he has finished signing in (or up).
The partner will need to whitelist the URL the user will be redirected to in Securitize. In order to do so, the following script in python can be used.
# Import the required libraries
import requests
from requests_oauthlib import OAuth1
from requests_oauthlib import OAuth2Session
import json
serviceUrl = 'https://sec-id-api.sandbox.securitize.io/v1/'
Issuer ="{Issuer Name}"
issuerID="{issuerID}"
Secret ="{secret}"
body = {'appIcon':{url of the icon},
'appName':'{Issuer Name}',
'redirectUrls':['{redirectUrl}']}
response = requests.patch(
serviceUrl + issuerID ,
headers={'Authorization': Secret},
data= body
)
if (response.status_code == 200):
print("Correctly updated")
else:
print('Error: ', response.content)Or using the following CURL:
curl -X PATCH "https://sec-id-api.sandbox.securitize.io/v1/{issuerID}" -H "accept: application/json" -H "Authorization: {secret}" -H "Content-Type: application/json" -d "{body}"Where:
| Parameter | Description |
| {issuerID} | Is the issuer ID provided by Securitize |
| {secret} | Is the {secret} provided by Securitize |
| body |
{
"appIcon": "Icon url",
"appName": "The Name of your App or [yourdomain]",
"redirectUrls": [
"https://[yourdomain]/*" ]
}
|
The partner can integrate the Securitize iD button within his own UI. The Partner’s landing page should show a button which links to Securitize iD.
For instance, the partner could use the following code to include in his landing page, which basically creates a button and, once clicked, re-directs the user to Securitize-iD authorization site:
function showSecuritizeIDLogInLogo(baseUrl, issuerID, redirecturl) {
var scope = "info";
var securitizeID = document.getElementById("SecuritizeID");
var link = document.createElement("a");
var logo = document.createElement("img");
var href = baseUrl + "#/authorize" + "?issuerId=" + issuerID + "&scope=" + scope +
"&redirecturl=" + redirecturl;
logo.src = "./images/securitizeID.png";
link.href = href;
link.id = "SecuritizeLogo";
link.appendChild(logo);
securitizeID.appendChild(link);
}Once the user has singed–in (or up) in Securitize-ID, he will be redirected back the the partners site. The URL of the redirection will look like this:
{Redirecturl}?code={code}&authorized=true
Hence, the partner will have to capture the information in the parameters of the URL. This can be simply done with the following JavaScript function:
function captureTOKEN() {
const queryString = window.location.search;
const urlParams = new URLSearchParams(queryString);
const code = urlParams.get("code");
const authorized = urlParams.get("authorized");
const country = urlParams.get("country");
console.log(code, country, authorized);
if (code != null) { // User has signed-up and has a SecuritizeID
return code;
}
}In case the user has not registered in Securitize-iD before, he will have to sign-up and follow the 5 KYC steps in order to be KYCed by Securitize.
In any case, this is not affecting the way the partner is interacting with the user. By the end of the process, the user will be redirected to the partner’s site exactly in the same way as he had already a verified Securitize-iD. However, in this case, the partner will have to check that the user has been KYCed by Securitize to access the rest of the APIs.
The partner will need to request Securitize API GW a JSON Access token to be able to interact with the rest of the APIs through a simple request:
curl --location --request POST '{API_BASE_URL}/api/auth/v1/authorize' \
--header 'Authorization: Bearer {secret}' \
--header 'Content-Type: application/json' \
--header 'clientid: {issuerID}' \
--data-raw '{
"code": "{code}"
}'Where:
| Parameter | Description |
| {API_BASE_URL} |
|
| {issuerID} | Is the {issuerID} provided by Securitize |
| {secret} | Is the {secret} provided by Securitize |
| {code} | The {code} returned in the redirect URL |
The following JavaScript function will request, and return, the access Token to be later used to access Securitize APIs:
function requestAccessToken(Url, code, secret, clientId) {
var xhr = new XMLHttpRequest();
var responseString = null;
xhr.addEventListener("readystatechange", function () {
if (this.readyState === 4) {
if (this.status === 200) {
response = JSON.parse(this.responseText);
console.log("Authorized with access Token: ", response.accessToken);
responseString =
JSON.parse('{"response":"OK", "accessToken":"' +
response.accessToken + '"}');
}
else {
responseString = JSON.parse('{"response":"NoAccessToken"}');
}
console.log(this.responseText);
} else {
console.log("Big Problem", this);
responseString = JSON.parse('{"response":"CORS_PROBLEM"}');
}
});
xhr.open("POST", Url, false);
xhr.setRequestHeader("Content-Type", "application/json");
xhr.setRequestHeader("Authorization", "Bearer " + secret);
xhr.setRequestHeader("clientid", issuerID);
try {
xhr.send(JSON.stringify({ "code": code }));
return responseString;
} catch (err) {
console.log(err);
return responseString;
}
}After the user has signed in into Securitize-iD, the partner will have to provide all the functionality to enable the user’s Crypto-Wallet connection. There are multiple ways of doing this, as well as packages and libraries to deal with the details. In this tutorial, and the code provided, we have used Web3Modal, which provides all the basic functionality to connect to a wallet and retrieve the user’s wallet public address.
In order to register the user’s wallet into the BlockChain registry, Securitze has developed the infrastructure to simplify the process as much as possible.Therefore, by hitting the following endpoint
curl 'https://connect-gw.sandbox.securitize.io/api/bc/v1/partners/{issuerID}/attestation' \
-H 'access-token: {accessToken}' \
-H 'Content-Type: application/json' Where:
| Parameter | Description |
| {issuerID} | Is the {issuerID} provided by Securitize |
| {accessToken} | Is the {accessToken} returned by the request JSON Access Token API |
The result might contain the following values
| Parameter | Description |
| {"status":"passed"} | If the user has passed all the Attestation Rules |
| {"status":"rejected"} | If the user does not pass all the Attestation Rules. In order to protect the user privacy, no further information will be provided of why the user did not pass the attestation rules. |
And with this endpoint:
curl 'https://connect-gw.sandbox.securitize.io/api/bc/v1/partners/{issuerID}/wallets/{wallet}/whitelist' \
-H 'access-token: {accessToken}' \
-H 'Content-Type: application/json' Where:
| Parameter | Description |
| {wallet} | Is the {wallet} address of the user, which will be registered and whitelisted in the Registry smart contract |
The Partner will receive a prepared meta-transaction which can be signed by the user, using his, e.g., metamask wallet, to sign the transaction and store his wallet in the BlockChain Registry contract, like this:
{
"preparedTransaction": "0xf9014a80843b9aca00835b8d8094b8d7d897bdce6f6454b54e808461b337058cdb0b80b901246e5832f2000000000000000000000000000000000000000000000000000000000000001b67d0a755ff7a6ccfab413c71ee5fac8a3d11c3a699dc2381b0bb0f9c077ccd471d1c3cc8fcd31936f63b67f66285b42f5c3233f7cafb75efe12309bf94d6bf5f00000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000005b8d8000000000000000000000000000000000000000000000000000000000000000440a2a9a01000000000000000000000000bf244e70c66b0a70d071cd0374e6b14397f0f55c0000000000000000000000000000000000000000000000000000000000a22b9200000000000000000000000000000000000000000000000000000000808080"
}A simple JavaScript snippet to call the API and use Web3 to trigger Metamask on the user’s browser to sign the transaction could look like this:
var transaction = await requestTransaction(Url, accessToken);
console.log("The transaction: ", transaction["preparedTransaction"]);
const tx = new ethereumjs.Tx(transaction["preparedTransaction"]);
const params = {
gas: '0x' + tx.gas.toString("hex"),
gasPrice: '0x' + tx.gasPrice.toString("hex"),
gasLimit: '0x' + tx.gasLimit.toString("hex"),
to: tx.to.toString("hex"),
value: tx.value.toString("hex"),
data: '0x' + tx.data.toString("hex"),
from: selectedAccount
}
await window.ethereum.request({
method: 'eth_sendTransaction',
params: [params],
}).then((result) => {
console.log('Transaction Hash:', result)
});The deployed Registry Smart Contract has a set of methods the partner can interact with:
function addOwner(address _newOwner) public onlyOwners {}
function removeOwner(address _owner) public onlyOwners {}
function addWalletFromOwner(address _wallet) public onlyOwners {}
function addWallet(address _wallet, uint256 _blockLimit) public onlyOwners {}
function removeWalletFromOwner(address _wallet) public onlyOwners {}
function removeWallet(address _wallet) public {}
function isWhitelisted(address _wallet) public view returns (bool) {}
function getTotalWallets() public view returns (uint256) {}
function getChainId() public view returns (uint256) {}In order to interact with the methods using Web3 in the browser, these simple calls can be used:
const totalWallets = await theContract.methods.getTotalWallets().call();const isWhitelisted = await theContract.methods.isWhitelisted(selectedAccount).call();await theContract.methods.removeWallet(selectedAccount).send({ from: selectedAccount }, function (err, res) {
if (err) {
showInfo("An error occured" + err, "error");
return
}
console.log("Hash of the transaction: " + res);
});