Guide: Use ZK Passport to verify citizenship off-chain
Before getting started with implementing the citizenship check, let’s quickly review all the steps of the process on the diagram below.
Basically, it goes likes this:
- User installs the RariMe App and scans the passport
- Scan a QR-code in the DApp
- Gets prompted to generate a proof of eligibility in RariMe App
- The app submits the proof to the callback URL(specified in the QR code) for verification
- DApp backend fetches the verification status and citizenship data from a REST API
QR code generation and all the interactions with the backend are facilitated by Rarimo's ZK Passport library, which is available as an NPM package: @rarimo/zk-passport
. The library provides a convenient API for generating QR codes and verifying the proof status.
You can check out this flow in the sandbox: ZK Passport Demo
Pre-requisites
You can use this public instance of verificator-svc
for testing: https://api.app.rarime.com/
To get started, you SHOULD deploy your own instance of https://github.com/rarimo/verificator-svc. This service encapsulates proof verification and provides a convenient REST API for requesting parameters for the QR code, checking the user verification status, etc. You need to trust the instance of verificator-svc
so the best option is to host your own instance.
API docs: verificator-svc | ReDoc
Step #1: Ask the user to install RariMe App and scan the passport
Links for installation:
Step #2: Install @rarimo/zk-passport-react
package
To install the package, run the following command in your project directory:
- npm
- Yarn
- pnpm
npm install @rarimo/zk-passport-react
yarn add @rarimo/zk-passport-react
pnpm add @rarimo/zk-passport-react
If you don't use React, you can use the @rarimo/zk-passport
package instead. It provides a low-level API for for requesting and passing for verification of ZK Passport proofs.
- npm
- Yarn
- pnpm
npm install @rarimo/zk-passport
yarn add @rarimo/zk-passport
pnpm add @rarimo/zk-passport
Step #3: Import the library and render the QR code
The following JS snippet uses the library to render a QR code with a proof of citizenship request and handles the results:
import ZkPassportQrCode from '@rarimo/zk-passport-react'
// this is a public instance of verificator-svc(https://github.com/rarimo/verificator-svc). Replace it with the URL of your instance
const apiUrl = 'https://api.app.rarime.com'
// `requestid` is a public unique ID associated with a user within your system. It will be used in the Step #3 to check the user status
const requestId = 'account-1'
// `event_id` is an arbitrary number that denotes the application scope of the proof
const eventId = 1337
const verificationOpts: RequestVerificationLinkOpts = {
uniqueness: true, // check if the user has already passed the verification
nationalityCheck: true, // include user's citizenship in the output(proof public signals)
eventId: eventId, // scope of the proof
}
return (
<ZkPassportQrCode
// Proof request params
apiUrl={apiUrl}
requestId={requestId}
verificationOptions={verificationOpts}
// QR code component props
qrProps={{ size: 256 }}
// place your callbacks here
onStatusChange={status => console.log(status)}
onSuccess={proof => console.log(proof)}
onError={error => console.error(error)}
/>
)
Step #3: Fetch the verification status and the citizenship code on the backend
You can fetch the verification status for a particular id
from this verificator endpoint:
https://rarimo.github.io/verificator-svc/#tag/User-verification/operation/getUserStatus
Here is a JS snippet for doing this
const backendUrl = 'https://api.app.rarime.com/'
const userId = 'some-user-id' // the `id` from step #2
const response = await fetch(`${backendUrl}/integrations/verificator-svc/private/verification-status/${userId}`)
const { data } = await response.json()
// responseUserId === userId
const responseUserId = data.id
// Verification status enum:
// - "not_verified" - user is not verified
// - "verified" - user is verified
// - "failed_verification" - user verification failed
// - "uniqueness_check_failed" - user uniqueness check failed
const verificationStatus = data.attributes.status
If the user has status verified
, you can fetch the verified citizenship code like this:
const response = await fetch(`${backendUrl}/integrations/verificator-svc/private/user/${userId}`)
const { data } = await response.json()
// ISO 3166 alpha-3 country code: https://www.iban.com/country-codes
// Note: German passports may have a single-letter "D" code
const citizenshipISOCode = data.attributes.nationality // e.g. "UKR"
Conclusion
In this guide, we set up off-chain citizenship verification using ZK Passport and the RariMe App, enabling secure proof of citizenship without exposing private user data.