Identification
Identification scopes simplify the onboarding process for users by providing apps with compact endpoints. pasby™ identification flows are most importantly used for:
- Authentication
- KYC
- Registration
On this note the identification scopes support 3 flow action types:
- login
- signup
- link
Each flow action acts differently when interfaced with by pasby™-users.
The identification model
An identification flow model will contain information about the flow reference ID, its date of creation and expected expiration, the IP address of where this flow originated, your apps information, a list of the ID data claims you've requested from your target user and a signature response from pasby™ servers.
The signature is used by pasby™ to process the flows origin and validity.
Properties
- Name
id
- Type
- string
- Description
Unique identifier for this flow.
- Name
consumer
- Type
- string
- Description
The ID of the flow creating apps organisation.
- Name
app
- Type
- string
- Description
The ID of the flow creating app.
- Name
name
- Type
- string
- Description
The alphabetic name of the flow creating app.
- Name
user
- Type
- string
- Description
pasby™ user.
- Name
mode
- Type
- string
- Description
e-ID mode of flow; would always be identification in this case.
- Name
iat
- Type
- number
- Description
Timestamp of request creation in unix format.
- Name
exp
- Type
- number
- Description
Timestamp of request expiration in unix format.
- Name
acquireClaims
- Type
- array
- Description
An array of requested ID data claims.
- Name
signature
- Type
- string
- Description
jwt signature stamp from pasby™-server.
- Name
ip
- Type
- string
- Description
IP address of where flow originated from.
- Name
useragent
- Type
- string
- Description
Identifies the application or operating system which propagated the flow request.
- Name
payload
- Type
- string
- Description
The description of the flow intent.
Same device
The identification:same
scope in pasby™ is otherwise called Autostart flow. As at the time of writing this, pasbys are distributed mobile first. This means every pasby user has a pasby mobile app, on their tablet or smartphone to manage their identity.
Same-device flows are when the user visits a service provider's application (web/mobile) on the same device as their pasby is installed.
Identification flows that begin this way are automatically picked up and handled by the pasby app once a pasby button variant is clicked/pressed/engaged.
Request Body
Key | Type | Description |
---|---|---|
action | (text) | Flow action to be performed |
claims | (array) | Array of ID data claims |
payload | (sting) | Describe the action intent to your user |
Request
cURL "https://s.pasby.africa/api/v1/identification/same-device" \
-H "x-access-secret: snb_" \
-H "x-api-key: bk-test_" \
-d "{"action": "signup", "claims": ["naming.family","naming.given","contact.email"], "payload": "A description of this flow action intent"}"
Request
cURL "https://s.pasby.africa/api/v2/identification/same-device" \
-H "x-api-key: bk-test_" \
-H "x-access-secret: snb_" \
-d "{"action": "signup", "claims": ["naming.family","naming.given","contact.email"], "payload": "A description of this flow action intent"}"
See pasby™ demo sample code server to better understand how to use autostart flows with the SDKs.
Response
{
"status": "successful",
"reason": "Identification request created",
"data": {
"link": "https://open.pasby.africa/app/?mode=identification&id=req_1714661447-NUkY&source=mobile",
"request": {
"id": "req_",
"consumer": "bcn_•••••••",
"app": "app_•••••••",
"mode": "identification",
"action": "signup",
"user": "",
"acquireClaims": [
"naming.family",
// ...
],
"signature": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6InJlcV8xNzE0NjYxNDQ3LU5Va1kiLCJtb2RlIjoiaWRlbnRpZmljYXRpb24iLCJhY3Rpb24iOiJzaWdudXAiLCJuYW1lIjoiQml2cmEiLCJjb25zdW1lciI6ImJjbl9jMjQzMWU2Ni1hN2Q3LTQwNmYtOGMyOC03MTVjOWRjNzI4ZTMiLCJwYXlsb2FkIjoiQSBzaW1wbGUgcGF5bG9hZCB1c2VkIGR1cmluZyBwYXNieeKEoiBzYW1lLWRldmljZSBhdXRoZW50aWNhdGlvbiBmbG93IiwiYXBwIjoiYXBwXzAzYzY5YzUwLTdhNGEtNWJhYS1iYTgyLWFhODEwODRhMTQ5ZSIsInVzZXJhZ2VudCI6IlBvc3RtYW5SdW50aW1lLzcuMzguMCIsInVzZXIiOiIiLCJpcCI6Ijo6MSIsImlhdCI6MTcxNDY2MTQ0NywiZXhwIjoxNzE0NjYxODA3LCJhY3F1aXJlQ2xhaW1zIjpbIm5hbWluZy5mYW1pbHkiLCJuYW1pbmcuZ2l2ZW4iLCJuYW1pbmcubWlkZGxlIiwiYmlvLmJpcnRobnVtYmVyIiwiYmlvLmJpcnRoZGF0ZSIsImJpby5nZW5kZXIiLCJuYXRpb25hbGl0eS5yZXNpZGVuY2UiLCJuYXRpb25hbGl0eS5wcmltYXJ5IiwiY29udGFjdC5lbWFpbCJdfQ.u6ygRZwrOw-Aet2AvfTBaiBpdJByTeDLAK8sFtU2TGU",
// ....
}
},
// ...
}
Response body
Object | Description |
---|---|
request | Standard Identification flow data model |
link | On the client end you call upon this string/url to begin identification flow. |
identification:same
returns a link object on a successful response. This link object should be opened on the client-end once received.
If the user has an active pasby on his/her device the pasby™-app will automatically handle this identification flow.
Otherwise the user will be shown a how to guide about how to get and activate a pasby for their national identity.
This scope only attributes a user to your identification flow if their pasby™ was the first to pick up the flow request when it was created. You are not allowed to direct an identification request to anyone's NIN using this scope.
Wildcard
The identification:wildcard
scope in pasby™ is otherwise called Secure start. This eliminates the need for users to write their NINs or any other identifier when trying to interact with your platform.
Secure starts: Use a QR code mechanism to begin an identification flow. The QR code data is returned as seeds
objects in the JSON response from pasby™. You must then present these seeds randomly as a QR code for your user audience to scan.
identification:wildcard
is ideal when the user visits a service provider on one device and uses the pasby™-app on another device.
Once the user scans any of the displayed QR codes created by your client with their pasby™-app, a session is created for just that user and your app. It's a first-pick, first-serve mechanism, meaning any other scans will be automatically void.
Request Body
Key | Type | Description |
---|---|---|
action | (text) | Flow action to be performed |
claims | (array) | Array of ID data claims |
seeds | (number) | Number of unique flow codes to generate for QR code generation purpose |
payload | (sting) | Describe the action intent to your user |
Request
cURL "https://s.pasby.africa/api/v1/identification/wildcard" \
-H "x-access-secret: snb_" \
-H "x-api-key: bk-test_"
-d "{"action": "login", "seeds": 4, "claims": ["naming.family","naming.given","contact.email"], "payload": "A description of this flow action intent"}"
Request
cURL "https://s.pasby.africa/api/v2/identification/wildcard" \
-H "x-api-key: bk-test_" \
-H "x-access-secret: snb_" \
-d "{"action": "login", "seeds": 4, "claims": ["naming.family","naming.given","contact.email"], "payload": "A description of this flow action intent"}"
See pasby™ demo sample code server to better understand how to use securestart flows with the SDKs.
Response
{
"status": "successful",
"reason": "Identification request created",
"data": {
"request": {
"id": "req_",
"consumer": "bcn_•••••••",
"app": "app_•••••••",
"mode": "identification",
"action": "login",
"user": "",
"acquireClaims": [
"naming.family",
// ...
],
"signature": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6InJlcV8xNzE0NjYxNDQ3LU5Va1kiLCJtb2RlIjoiaWRlbnRpZmljYXRpb24iLCJhY3Rpb24iOiJzaWdudXAiLCJuYW1lIjoiQml2cmEiLCJjb25zdW1lciI6ImJjbl9jMjQzMWU2Ni1hN2Q3LTQwNmYtOGMyOC03MTVjOWRjNzI4ZTMiLCJwYXlsb2FkIjoiQSBzaW1wbGUgcGF5bG9hZCB1c2VkIGR1cmluZyBwYXNieeKEoiBzYW1lLWRldmljZSBhdXRoZW50aWNhdGlvbiBmbG93IiwiYXBwIjoiYXBwXzAzYzY5YzUwLTdhNGEtNWJhYS1iYTgyLWFhODEwODRhMTQ5ZSIsInVzZXJhZ2VudCI6IlBvc3RtYW5SdW50aW1lLzcuMzguMCIsInVzZXIiOiIiLCJpcCI6Ijo6MSIsImlhdCI6MTcxNDY2MTQ0NywiZXhwIjoxNzE0NjYxODA3LCJhY3F1aXJlQ2xhaW1zIjpbIm5hbWluZy5mYW1pbHkiLCJuYW1pbmcuZ2l2ZW4iLCJuYW1pbmcubWlkZGxlIiwiYmlvLmJpcnRobnVtYmVyIiwiYmlvLmJpcnRoZGF0ZSIsImJpby5nZW5kZXIiLCJuYXRpb25hbGl0eS5yZXNpZGVuY2UiLCJuYXRpb25hbGl0eS5wcmltYXJ5IiwiY29udGFjdC5lbWFpbCJdfQ.u6ygRZwrOw-Aet2AvfTBaiBpdJByTeDLAK8sFtU2TGU",
// ....
},
"seeds": [
"pasby://edbee6303ddcd8d89b6f3052385954b4eb82e7-vi(eb4ae73b5f431deffaeb047cf028e8bc)",
// ...
]
},
// ...
}
Response body
Object | Description |
---|---|
request | Standard Identification flow data model |
seeds | On the client end you create an animated QR code for scanning by randomly shuffling the unique flow codes found in this array. |
identification:wildcard
returns a seed array object on a successful response. Use the string contents of this array to generate on your client-end a QR code for your user audience to scan.
The user will have to open the pasby app and then scan the QR code to process your flow request.
This scope only attributes a user to your identification flow if their pasby™ was the first to pick up the flow request as it was created. You are not allowed to direct an identification request to anyone's NIN using this scope.
Different device
The ---:another
scopes in pasby™ are a unique type of flow requests which adopts Direct starts.
This scope type require a NIN (National Identification Number) to operate.
Direct start: Uses a user's NIN entry to begin an identification flow.
identification:another
will immediately propagate a flow request to the pasby™-user's devices to process his/her consent to your identification flow.
To protect users and businesses, there will be an introduction of restricted scopes from 1st of October 2024.
The identification:another
, signature:same
, signature:another
and document:sign
will be greatly affected by these changes.
Request Body
Key | Type | Description |
---|---|---|
user | (text) | The unique NIN identifier of an African national. |
action | (text) | Flow action to be performed |
claims | (array) | Array of ID data claims |
payload | (sting) | Describe the action intent to your user |
Request
cURL "https://s.pasby.africa/api/v1/identification/different-device" \
-H "x-access-token: {bearer-token}" \
-H "x-api-key: bk-test_" \
-d "{"action": "login", "user": "12345678910", "claims": ["naming.family","naming.given","contact.email"], "payload": "A description of this flow action intent"}"
Request
cURL "https://s.pasby.africa/api/v2/identification/different-device" \
-H "x-api-key: bk-test_" \
-H "x-access-secret: snb_" \
-d "{"action": "login", "user": "12345678910", "claims": ["naming.family","naming.given","contact.email"], "payload": "A description of this flow action intent"}"
See pasby™ demo sample code server to better understand how to use direct starts flows with the SDKs.
Response
{
"status": "successful",
"reason": "Identification request created",
"data": {
"request": {
"id": "req_",
"consumer": "bcn_•••••••",
"app": "app_•••••••",
"mode": "identification",
"action": "login",
"user": "12345678910",
"acquireClaims": [
"naming.family",
// ...
],
"signature": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6InJlcV8xNzE0NjYxNDQ3LU5Va1kiLCJtb2RlIjoiaWRlbnRpZmljYXRpb24iLCJhY3Rpb24iOiJzaWdudXAiLCJuYW1lIjoiQml2cmEiLCJjb25zdW1lciI6ImJjbl9jMjQzMWU2Ni1hN2Q3LTQwNmYtOGMyOC03MTVjOWRjNzI4ZTMiLCJwYXlsb2FkIjoiQSBzaW1wbGUgcGF5bG9hZCB1c2VkIGR1cmluZyBwYXNieeKEoiBzYW1lLWRldmljZSBhdXRoZW50aWNhdGlvbiBmbG93IiwiYXBwIjoiYXBwXzAzYzY5YzUwLTdhNGEtNWJhYS1iYTgyLWFhODEwODRhMTQ5ZSIsInVzZXJhZ2VudCI6IlBvc3RtYW5SdW50aW1lLzcuMzguMCIsInVzZXIiOiIiLCJpcCI6Ijo6MSIsImlhdCI6MTcxNDY2MTQ0NywiZXhwIjoxNzE0NjYxODA3LCJhY3F1aXJlQ2xhaW1zIjpbIm5hbWluZy5mYW1pbHkiLCJuYW1pbmcuZ2l2ZW4iLCJuYW1pbmcubWlkZGxlIiwiYmlvLmJpcnRobnVtYmVyIiwiYmlvLmJpcnRoZGF0ZSIsImJpby5nZW5kZXIiLCJuYXRpb25hbGl0eS5yZXNpZGVuY2UiLCJuYXRpb25hbGl0eS5wcmltYXJ5IiwiY29udGFjdC5lbWFpbCJdfQ.u6ygRZwrOw-Aet2AvfTBaiBpdJByTeDLAK8sFtU2TGU",
// ....
}
},
// ...
}
Response body
Object | Description |
---|---|
request | Standard Identification flow data model |
Identity non-existent on pasby™
In such a situaion where the provided NIN hasn't been linked to pasby™ we return to you the below response.
Response
{
"status": "failed",
"reason": "National does not have a pasby™ digital ID",
}
Handling Claims
As established in the flows:ping
scope description, completed identification flows return an encrypted map object of the user's consented ID data claims.
Before these claims could be used within your app, you'd need to decypher each with your private keys. We wrote a simple typescript function to help you achieve this in real time.
Response
{
// ...,
"claims": {
"contact": {
"email": "y6l/srG+g/2l2QinsjXxnn4MxY0cTzIDFiRrChjtSIl/LUUkQt8zAUsY4UIPHJDb+LvMH8LHN6LWZ8HNZ+Y3L36Dwy3KdwWSheDrWsXskxVfl5gHGnPl/lvQjyWuxcfwAlH161oJZwKpLhGsVJ8UkI7mm/l+jKznhio+VRsaKcJexky92hE+0rkpsQfWKd25WV53hlXM9n8PQJHzkUOzZwpel3YYo/YPU8hhWaHkFJjY3qnzs9qE+qLQ6RazrwHZz9NtIOYOtajLumQ7QLlrsc3CyCEucPUfNmj/WAWSuikDTegDJmOMElt0Sqf7SsIOGT/Eewd0B+uPxuXtJPR0+ZmHF69IzrtlSSMtVYY5wZt5vjVCrbw9mhVkdkanGKrh3KyjHJE8m6rfNscYUy8768YJvA36FIvzWfk89aknKSaf2L+gLc9BM9zxAtPM5Qcz3K6D8zi2qKdcxZBCoqEvEZYltOsHE8TMRug3HfdEaihVr8VTGwBiNE7ii1D0XRxR36WdEymriy499DkXBri6rRPQxS0rRDr4RqJV0+7rlcmLxYUjvq/ii/ONGiZFtfw0zDtz42PqKyokUQOxZqVAdTc8SvrPoBk/bVpo7gvZUXfYSxG+5e3HqEixQKuCXHSeJH9tCgHilXJV2DaLgqx10TVJcW2NnaOOvIBbUNs2NSQ="
},
"naming": {
"family": "SsF83HO/6g6+Sf+6n0nl3NhSJoEsMYYy5KMuBkIrtH33pD+LanPTUlYcZSYtgOpYV2ozq8kEE7kYalsyh/Kg/JzRCVO35N/KLuwddVZAgkW1AmWpzjEa3yssCTI1HPSG6VFRuV+ITEq1tGnuNzbncRkTbfwdQbGDO4M7oYKg3o7z67Hv4lXWhKc1cDqee95Ja/JRmbsVqSssJbnNUgMxvCyWJQej2ALN1J4lhPsy+WWWX2l6ANsbCsKQMQcQeGQwPfCabiSBazZv2YxRL5CN/gaIpIvjNvBglnJoc2qFPSKzk5VNeJkpXQNvd3HY0O/5ZxzfHR7y/ZUqkyBB9TJc2XsANGtzbrmHnJy7fq6W0ixxJQDeGo3qfsZmoaUb9967RIQ/DRG9To1CbWw1KXDqSbwvaYfOCxR0kXLJKRzV/QNBRzAq8XTe6XgHBGEfkkJR7/dG7Cpt1Jf9tm1PdkRsMYQoNFPhHjAGRbLGsLYcawK1BgqOXM9JMpSZKizGxF6MvfIe4ovC2TS6Y+cWXdUDTFURdSvvY4D+bjAryiCkPYybAFjR1okLINdei0/KyfJXz4qYiZQd4tp+PAd7wi26fABwDeBA8NDFZOYB01P9ACT2pgHGoDIVopf8l2n5cEztKYkIze3PHgvhmGWZP7cz+3paX4kcIr8sg+Q2VVlOm4g=",
"given": "LqDr6DjnleWbPLESTCd8t9ttuwFL4fwiW1R3hS5Q/o/jk/7K8E1P2Kup2iSuVWwriQ9KLwpzUMhcs7rnDhChUZyJXyh1d2VNzgbTDRNaW2h0/1OHJLnQs6s+hsW5kFrfDyt2KPEHvn1vMVIaEdDSzLmtQC2JQjiFvcVw8oub/CQedXCYWsuui1A8GTef+0EGD78tz46iFEt1hJcijE4CdKTGuH8Ph7nd3rwSpg4APLVcU82ywx4sJkkz3Ym2Vk0Yk2yaDL8WBLqMWHh9jNMvpKgwA9RiocDP6ci8s/Elm2WNE+GspFYur7moEn04NVQvkZbDaKRXKU7FrPvtwX/Me8C2gv4/FnevNas4EOsx8rxhPvmWD20U1o9TCUHzecJg5AJMQ4Y4t90jjaINQ7f7IMIZZJ3RR5M2zs9uq2UdMcW0C2MCjqe9aydWs4WqkFeu2YoWlNoOs3FPVpP2OzAs77MDcnf/dltywz3LZMXrt62ZRCaVIIA1aj/tNewT9NBbrBYnaFzfpaHVOWaWFEyLrmTI1nb0k7pB7o3OAyRYoOCwQhJ6ox5L8PxVaJyjAADZxLkym76E4y6kCEHMe6xaM7L+BBuYhVg4TgOzxH/5b/A3q7ZAKzf9g3Pvm13JZMvsOJr9gUc+bnx7ZsNNrjjeTX4P9riDipU5fR250yT6/N8=",
},
}
}
You can simply decrypt the claims by passing the object to a custom function which parses each string against your RSA private key.
const JSEncrypt = require("node-jsencrypt");
/**
* Decrypt the claims received from your flow ping method. The decryption requires the calling apps private key certificate. This private-key can be found in the apps service-file
* @param {string} enb your apps private key
* @param {Record<string, unknown>} params argument
* @return {void}
*/
function perform(enb:string, claims:Record<string, unknown>) {
const crypt = new JSEncrypt();
crypt.setKey(enb);
var contact = claims['contact'] as Record<string, unknown>;
var text = crypt.decrypt(contact['email']);
console.log(`JSE === ${text}`);
}
A much compact function can be found in our open source demo sample code.
Once decrypted successfully you'll have the ID data claims in alphabetic letterings. Example below:
Decrypted claims
{
"claims": {
"contact": {
"email": "john.doe@example.com"
},
"naming": {
"family": "Doe",
"given": "John"
}
}
}