This is going to be a short walk-through on integrating the BrightID V5 Soulband with a dapp, to allow users to connect their BrightID and prove their uniqueness.
I’ve had to explain this process to my colleagues at Unitap many times, and now that I need to write an essay for my EPF Cohort 5 application, I thought that this would be a good topic to talk about.
A few key points before we start:
This might not be the best implementation of this topic, as it differs a little from the BrightID docs. Please read the docs for reference.
This guide is using the V5 API and not the V6. For the latter please refer to the docs.
You need a registered app, and a
BRIGHT_PRIVATE_KEYbefore being able to call the/sponsorendpoint.
BrightID (V5) defines a user, as a set of “context IDs”. A context ID is any URL-escaped string. These context IDs can be generated by anyone, but the user decides if they want to link that ID to their account or not. If they do, that ID can be used to retrieve the account from Bright nodes, which is just the set of all the context IDs linked to that account. So why do we need to do this? Well, when a user wants to connect their account to our dapp, we have no idea who they are, so what we need to do, is to generate a random context ID, and ask the user to link it to their account, then query the context ID and get all the user’s previously linked IDs, and as we do in Unitap, take their last (oldest) ID as their identifier in our system. (The entries are always in the same order)
The process of allowing users to connect their BrightID account, looks something like this:
At first, we will create a random context ID, and sponsor that ID through our app.
Then we ask the user to link this ID to their Bright account.
Then we query the ID from the Bright nodes, and we get the whole set of that user’s linked IDs.
Then we take the oldest (last) entry and save it to their user profile in our dapp. (You could treat this part as you wish)
We need to sponsor a randomly generated context ID so that the user can link it to their account. You can generate any URL-escaped string for this, but since we at Unitap do this in our front-end, we generate a key-pair, and then sign something and also verify it in our back-end before sponsoring to make sure it’s not tampered with.
To sponsor an ID, we use the operations API:
def sponsor(self, context_id):
URL = "https://app.brightid.org/node/v5/operations"
op = {
"name": "Sponsor",
"app": self.app_name,
"contextId": str(context_id).lower(),
"timestamp": int(time.time() * 1000),
"v": 5,
}
signing_key = ed25519.SigningKey(base64.b64decode(BRIGHT_PRIVATE_KEY))
message = json.dumps(op, sort_keys=True, separators=(",", ":")).encode("ascii")
sig = signing_key.sign(message)
op["sig"] = base64.b64encode(sig).decode("ascii")
r = requests.post(URL, json.dumps(op))
print("res: ", r.json())
if r.status_code != 200 or "error" in r.json():
return False
return True
This function creates an operation payload, which would sponsor an ID in the specified app. Then uses the app specific BRIGHT_PRIVATE_KEY to sign the serialized operation, and then posts it to the url. A success or error would be returned based on if the operation was received. (not completed, just received). We would need to check if the sponsorship has gone through before asking the user to try to link the ID, but usually it happens very fast.
Users need to link the now sponsored ID to their Bright account. This is done completely by the user and we just need to create a redirect link to the Bright app like this:
f"brightid://link-verification/http:%2f%2fnode.bright\
id.org/{self.app}/{str(contextId).lower()}"
This should be represented as a QR code.
Now that we have an ID linked to the user, we can query information about their verification from Bright nodes. We will check the Meets verification status:
def get_verification_status(self, context_id):
endpoint = f"https://aura-node.brightid.org/brightid/v5/verifications/{self.app}/{context_id}?verification=BrightID"
bright_response = requests.get(endpoint)
bright_response = bright_response.json()
try:
if bright_response["data"] is not None:
return True, bright_response["data"]["contextIds"]
else:
return False, bright_response["errorNum"]
except KeyError:
return False, bright_response["errorNum"]
This function queries the verification API and then checks if the data object is available in the response. If it is, then it means that the user has the Meets verification, and a contextIds object is returned which is the set of the ID’s linked to this user.
Then we can just take the `contextIds[-1]` as the user identifier in our system. This way we can always check if this is a new or old user when they want to connect their Bright account to our app.
That was a summary of how we can achieve this goal. For more information you should read the BrightID documentation and of course feel free to take a look at our implementation at Unitap here.
