# DAV Verifier
## Objective
Define the architecture for a reference implementation for a verifier application to be used to incorporate the Digital Age Verification process involving the BC Person credential in third-party processes, both in-person and online.
## Requirements
* ACA-Py to be used as Enterprise Agent, running in read-only mode (verifier only).
* Simplified API: no need to know how to build a proof-request, the API will abstract from VC-specific steps and knowledge.
* Verification UI: page with QR code (similar to [VC-AuthN](https://gitub.com/bcgov/vc-authn-oidc)) used to initiate a verification and see the result.
* Page needs to work both by scanning QR code and triggering an action via deep-linking.
* A database may be added to allow persistence of verification records
* Proof-requests should be generated by using the out-of-band protocol.
* Endpoints must be protected at least by using the `x-api-key` header
## Technology
The technical stack will match what has been used for VC-AuthN, in order to promote consistency and reduce variance in technologies used by the DITP team (who will likely maintain the application long term). Based on this:
* back-end will be Python, using FastAPI as framework.
* front-end can be vanilla Javascript, or an embedded Vue app served by the FastAPI service.
* all services will be dockerized
## API Design
### Statuses
An enumeration of the possible statuses for a verification, describing its lifecycle:
* *INITIATED*
* *IN_PROGRESS*
* *SUCCESS*
* *FAILURE*
* *EXPIRED*
* *ABORTED*
### POST /age-verification
Creates a new verification session.
:::info
Note:
* the optional `expiry_seconds` parameter defines the time for which this verification is valid, and after which - if the verification process has not started - it must be considered expired. When specified, it overrides the system-defined default value.
* if the optional parameter `notify_endpoint` is provided, the service will attempt to `POST` updates for this verification to teh specified endpoint.
* the optional `metadata` object is a container for verifier-specified metadata to be stored alongside the presentation, if needed
:::
```json
# Request
{
"expiry_seconds": 180 // optional
"notify_endpoint": "http://my-webhook-endpoint" // optional
"metadata": {} // optional
}
# Response
{
"id": "12cb1b06-cb20-4e11-b0be-6b1597012cbd",
"status": "INITIATED",
"url": "http://my-service/12cb1b06-cb20-4e11-b0be-6b1597012cbd" //shortened URL with presentation exchenge payload, for QR code use
}
```
### GET /age-verification/{verification-id}
Returns the specified verification session. Useful for polling, if push-notification was not requested or is not possible, or just to obtain the information.
```json
# Request
{}
# Response
{
"id": "12cb1b06-cb20-4e11-b0be-6b1597012cbd",
"status": "IN_PROGRESS",
"notify_endpoint": string | null (if not set)
"metadata": {} | null (if not set)
}
```
### Updating a verification
:::warning
Verifications **CANNOT** be modified by other services, once created they are read-only and will be updated by the verifier service based on their lifecycle.
:::
## Verification Lifecycle
The verification lifecycle describes the steps a verification process can/will go through, from its beginning until it is completed. It is tightly linked to the [statuses](#Statuses) used in the API.
* *INITIATED*: once a verification process is first created, it will be placed in the `INITIATED` state.
* *IN_PROGRESS*: when the verification API receives a webhook from ACA-Py indicating that the holder has accepted the request, the process transitions to this state.
* *SUCCESS*: when the webhook from ACA-Py indicates a verification is successful, the process transitions to this state (both proof vas received AND it was validated as verified - see [this example](https://github.com/bcgov/vc-authn-oidc/blob/d8f528a29ede7f21a6942d2f2c69af4267313496/oidc-controller/api/routers/acapy_handler.py#L54)).
* *FAILURE*: when the webhook from ACA-Py indicates the verification was NOT successful, the process transitions to this state (proof vas received, BUT it was not validated as verified).
* *EXPIRED*: the verification transitions to this status if it is still in `INITIATED` state when the defined expiry threshold (global or specific to the verification) is triggered.
* *ABORTED*: when the holder refuses to share their digital credentials and ACA-Py indicates an error report was received. See [this issue](https://github.com/bcgov/vc-authn-oidc/issues/374) for extra some information.
## UI / Visual verification
The companion UI for the Verifier Service will exposed a visual interface allowing users to complete a Digital Age Verification process without the need to integrate to a separete service.
### Start Page
On first use, the starting page will display a button with the label: "Initiate Digital Age Verification"
## Verification Page
The Verification page will display a QR code, containing the URL generated by the request to `/age-verification`. It will also, below the QR code, display a help text stating "Scan the QR-code with your wallet or `open in wallet`", where the `open in wallet` text will be clickable and link to `bcwallet://aries_proof-request?_oob=...` for deep-linking. This corresponds to the state `INITIATED`.
:::warning
I am not 100% sure what the support for deep linking in BC Wallet is, if issues arise, we'll need to collaborate with the BC Wallet team to resolve them.
:::
The verification page will update once the QR code is scanned, or the link is clicked - state `IN_PROGRESS`.
On completion of the verification, the UI will update as follows:
- If the age verification is successful (state `SUCCESS`), the space occupied by the QR code will be replaced by the photo attribute of the user presenting the credential and a green check mark will be displayed below it.
- If the age verification is NOT successful (state `FAILURE`), the space occupied by the QR code will be replaced by the photo attribute of the user presenting the credential and a red "X" will be displayed below it.
Similarly, if the verification takes too long (state `EXPIRED`) or is rejected by the holder (state `ABORTED`), the UI will display information about the new status.
In either one of teh above scenarios, a button with the label: "Verify Again" will appear below, and will allow for a new verification to be started.
For UI/UX, taking inspiration from VC-AuthN and/or consulting With a UI designer would be advisable.
## Proof Request
The proof request will initially only support the [BC Person Credential](https://candyscan.idlab.org/tx/CANDY_PROD/domain/14), but new credential definitions (with schemas compatible with the BC Person) may be added in the future. A list of acceptable credential definitions should be configurable by using a configuration (JSON) file that will be mounted at runtime.
The proof-request structure should allow for the following attribute sharing to be enabled/disabled:
- `given_names` and `family_name`: these attributes will not be shared y default, but may be turned on if the line-of-business application needs to reconcile the user completing the age verification and the user completing the transaction online.
- `picture`: the picture will not be shared by default, but will be requested - as an example - by the verifier page, in order to be able to display the result on screen upon successful verification.
The proof request will additionally use a restriction on `birthdate_dateint` that will be compiled at runtime to determine whether the user is ove rthe age of 19 at the time of the verification.
The proof-request will, additionally, require proof of non-revocation of the credentials presented (to be confirmed if necessary - might be okay even if the document is revoked in some cases).
A sample proof request may look like the following, in the case of the UI:
```json
{
"name": "age-verification",
"nonce": "1234567890",
"version": "1.0",
"requested_attributes": {
"holder": {
"names": [
"picture"
],
"restrictions": [
{
"credential_definition_id":
"RGjWbW1eycP7FrMf4QJvX8:3:CL:13:Person"
}
]
},
"non_revoked": {
"from": 1704954193,
"to": 1704954193
}
},
"requested_predicates": {
"not_expired": {
"name": "birthdate_dateint",
"p_type": "<=",
"p_value": 20050110,
"restrictions": [
{
"credential_definition_id":
"RGjWbW1eycP7FrMf4QJvX8:3:CL:13:Person"
}
]
},
"non_revoked": {
"from": 1704954193,
"to": 1704954193
}
},
}
```