Install the Verification Service
This article sets up an instance of the credential verification service. If you have not run either service before, work through the quickstart first — it brings up the verifier, the issuer and their database together and covers the prerequisites once.
Requirements
- Docker with the Compose plugin.
- OpenSSL, to generate the signing certificate.
- The certificate of the issuer whose credentials you verify — for our issuer, the one generated in Install the issuance service.
- Access to Partisia's container registry:
docker login registry.gitlab.com. Please book a call with us to arrange it. - A PostgreSQL database the service can reach, with a database created for it. See Database.
Configure the service
The service reads a single JSON configuration file, conventionally server.json. This example is a complete
working configuration:
{
"port": 8081, // (1)!
"baseUrl": "http://localhost:8081", // (2)!
"database": { // (3)!
"persistenceUnitName": "model",
"driver": "org.postgresql.Driver",
"url": "jdbc:postgresql://postgres:5432/verifier",
"user": "postgres",
"password": "postgres"
},
"clientMetadata": { // (4)!
"clientName": "Verifier",
"logoFile": "conf/static/partisia-logo.png"
},
"signing": { // (5)!
"keyFile": "conf/signing-key/verifier-localhost.key",
"certificateFiles": [
"conf/signing-key/verifier-localhost.pem"
]
},
"integrations": { // (6)!
"authentication": {
"api-key": "Local development"
}
},
"issuerTrustAnchors": "conf/issuer-trust-anchors" // (7)!
}
- REST endpoint port. Required.
- The address this service advertises to wallets. Required — the wallet uses it to fetch the authorization request and to submit the presentation, so it must be an address the wallet can reach.
- PostgreSQL connection. Required.
- For a full explanation of this field see Database.
- Information about this verifier, shown to the holder on the wallet's consent screen.
- For a full explanation of these fields see Client metadata.
- The signing key and certificate chain. Required — the service will not start without them, and this certificate
is what determines the verifier's identity to a wallet.
- For a full explanation of this field see Signing certificates.
- API keys accepted on the administrative endpoints. The JSON key is the token; the value is a label.
- For a full explanation of this field see API keys.
- The directory of root certificates for the issuers you accept. Required — the service will not start without it,
and a credential whose certificate chain does not lead to one of these roots is rejected. Filled in
Trust your issuer below.
- For a full explanation of this field see Issuer trust anchors.
Every other setting is optional — holder binding, the results callback. For the complete list see the configuration reference.
Paths are relative to the container
keyFile, certificateFiles, logoFile and issuerTrustAnchors are resolved against the container's working
directory, /app. Mount your configuration directory there — ./verifier/conf:/app/conf:ro — and a path of
conf/signing-key/x.key then refers to verifier/conf/signing-key/x.key on the host.
Generate the signing certificate
mkdir -p verifier/conf/signing-key
openssl req -x509 -newkey ec -pkeyopt ec_paramgen_curve:P-256 -nodes \
-keyout verifier/conf/signing-key/verifier-localhost.key \
-out verifier/conf/signing-key/verifier-localhost.pem \
-days 365 -subj "/CN=localhost" -sha256
This certificate is more than a formality on the verifier: its hash is the verifier's OID4VP client_id, and a
wallet validates it before showing the holder a consent screen. A self-signed pair works with a wallet you
configure yourself; wallets you do not operate will refuse it. See Trust model.
Trust your issuer
Copy your issuer's certificate into the verifier's trust anchors directory. This uses the certificate from Install the issuance service:
Copy the certificate (.pem), never the key. For an issuer whose certificate chains to a certificate authority,
copy that authority's root instead.
Do not skip this step. Without the directory the service will not start, and without the certificate in it every credential your issuer signs is rejected. See Issuer trust anchors.
Run it
Run the image with your configuration directory mounted:
docker run -d \
-p 8081:8081 \
-w /app \
-v "$(pwd)/verifier/conf:/app/conf:ro" \
registry.gitlab.com/secata/platform/did/release/verifier-backend:latest
The issuer and verifier are released independently but tested as pairs, so pull both at the same time. See Going to production for recording which version you run.
In practice you will run this alongside the database with Compose; the quickstart has a
complete docker-compose.yml.
The log prints Starting server when the service is ready. Navigate to
http://localhost:8081/openapi for the API specification, where you can try the
endpoints directly. Remember to supply your API key — the administrative endpoints return 401 without it.
Check it works
Create a verification query, then start a session from it:
curl -X POST http://localhost:8081/presentation/oid4vp/new-session \
-H 'Authorization: Bearer api-key' \
-H 'Content-Type: application/json' \
-d '{ "verification_query_id": "<your query id>" }'
A successful call returns a session_id and a request_uri. Confirm the session exists with
GET /presentation/oid4vp/status/{session_id}, which should report VERIFICATION_STARTED.
A 400 Bad Request here means verification_query_id was missing or names a query that does not exist — a session
cannot be started without one.
What's next?
The verification service is now able to talk to wallets and verify the presentations they send.
- Create a verification query. State which credentials and claims you are asking for. Required before any session can start.
- Request a presentation. What your own application calls, and when.
- Receive verified data. Configure a callback so results are pushed to your application instead of polled.
- Issuer trust anchors. Decide which issuers this verifier accepts.
Troubleshooting
Startup, connection and request failures are collected in Troubleshooting.