Skip to main content

Prerequisites

Before you begin, ensure you have:
  • Docker installed on your machine
  • Basic understanding of Verifiable Credentials
  • A wallet capable of storing Verifiable Credentials (for testing)
For a complete local setup with all required components (Trusted Issuers Registry, credential issuers, etc.), see the VC-Integration-Test repository.

Run with Docker

The fastest way to get started is using the official Docker image:
1

Pull and run the container

docker run -p 8080:8080 quay.io/fiware/vcverifier
This starts VCVerifier on port 8080 with default configuration.
2

Verify the service is running

Check the health endpoint:
curl http://localhost:8080/health
You should receive a successful health check response.
3

Check the JWKS endpoint

Verify that the public keys are available:
curl http://localhost:8080/.well-known/jwks
This returns the public keys used to verify JWTs issued by the verifier.

Configuration

VCVerifier requires a configuration file to define verification rules, trust anchors, and credential scopes.

Basic configuration file

Create a server.yaml file:
server.yaml
server:
  port: 8080
  templateDir: "views/"
  staticDir: "views/static/"

logging:
  level: "INFO"
  jsonLogging: true
  logRequests: true

verifier:
  did: "did:key:your-verifier-did"
  clientIdentification:
    id: "did:key:your-client-id"
  supportedModes: ["urlEncoded", "byReference", "byValue"]
  sessionExpiry: 30
  generateKey: true
  keyAlgorithm: "ES256"

configRepo:
  services:
    - id: testService
      defaultOidcScope: "default"
      oidcScopes:
        default:
          credentials:
            - type: CustomerCredential
              trustedParticipantsLists:
                VerifiableCredential:
                  - https://tir-pdc.ebsi.fiware.dev
              trustedIssuersLists:
                VerifiableCredential:
                  - https://tir-pdc.ebsi.fiware.dev
The configuration supports dynamic updates via the Credentials Config Service for production deployments.

Run with custom configuration

docker run -p 8080:8080 \
  -v $(pwd)/server.yaml:/app/server.yaml \
  -e CONFIG_FILE=/app/server.yaml \
  quay.io/fiware/vcverifier

Testing the authentication flow

Let’s walk through a same-device authentication flow to see VCVerifier in action.

Step 1: Start the authentication flow

Initiate a same-device flow to get the authentication request:
curl -X GET 'http://localhost:8080/api/v1/samedevice?state=274e7465-cc9d-4cad-b75f-190db927e56a'
The state parameter is a unique identifier for this authentication session. In production, your frontend application would generate this.
Response: A 302 redirect with location header:
location: http://localhost:8080/?response_type=vp_token&response_mode=direct_post
  &client_id=did:key:z6MkigCEnopwujz8Ten2dzq91nvMjqbKQYcifuZhqBsEkH7g
  &redirect_uri=http://localhost:8080/api/v1/authentication_response
  &state=OUBlw8wlCZZOcTwRN2wURA
  &nonce=wqtpm60Jwx1sYWITRRZwBw

Step 2: Submit the Verifiable Presentation

The wallet responds with the Verifiable Presentation via the authentication response endpoint:
curl -X POST \
  'http://localhost:8080/api/v1/authentication_response?state=OUBlw8wlCZZOcTwRN2wURA' \
  -H 'Content-Type: application/x-www-form-urlencoded' \
  -d 'presentation_submission=<base64-url-encoded-submission>&vp_token=<base64-url-encoded-vp>'
Make sure to use Base64-URL-Safe encoding (not standard Base64) for the vp_token and presentation_submission parameters.
Response: Another 302 redirect with the authorization code:
location: http://localhost:8080/?state=274e7465-cc9d-4cad-b75f-190db927e56a
  &code=IwMTgvY3JlZGVudGlhbHMv

Step 3: Exchange code for JWT

Use the authorization code to retrieve the signed JWT:
curl -X POST \
  'http://localhost:8080/token' \
  -H 'Content-Type: application/x-www-form-urlencoded' \
  -d 'grant_type=authorization_code' \
  -d 'code=IwMTgvY3JlZGVudGlhbHMv' \
  -d 'redirect_uri=http://localhost:8080/'
Response: The verified credential as a signed JWT:
{
  "token_type": "Bearer",
  "expires_in": 3600,
  "access_token": "eyJhbGciOiJFUzI1NiIsImtpZCI6IldPSEZ1NEhaNTlTTTg1M0M3ZU4wT3ZsS0dyTWVlckRDcEhPVVJvVFF3SHciLCJ0eXAiOiJKV1QifQ..."
}
1

Decode the JWT

The JWT contains the verified credential in its payload. You can decode it at jwt.io or programmatically.
2

Verify the signature

Use the JWKS endpoint to get the public key and verify the JWT signature:
curl http://localhost:8080/.well-known/jwks
3

Use for authorization

Pass the JWT as a Bearer token to your downstream services:
curl -H "Authorization: Bearer <access_token>" \
  https://your-api.example.com/protected-resource

Frontend integration

For browser-based applications, VCVerifier provides a login page with QR code:

Display QR code for wallet scanning

curl 'http://localhost:8080/api/v1/loginQR?state=user-session-123&client_callback=https://my-app.com/auth/callback'
This returns an HTML page with:
  • A QR code containing the authentication request
  • The openid4vp:// connection string
  • JavaScript to handle the callback

Integration flow

1

Redirect user to login page

const state = generateRandomState();
const callbackUrl = encodeURIComponent('https://my-app.com/auth/callback');
window.location.href = `http://verifier.example.com/api/v1/loginQR?state=${state}&client_callback=${callbackUrl}`;
2

User scans QR code

The user scans the QR code with their wallet app, which contains the credential.
3

VCVerifier verifies and calls back

After verification, VCVerifier calls your callback URL:
https://my-app.com/auth/callback?state=user-session-123&code=authorization-code
4

Exchange code for token

Your backend exchanges the code for a JWT:
const response = await fetch('http://verifier.example.com/token', {
  method: 'POST',
  headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
  body: new URLSearchParams({
    grant_type: 'authorization_code',
    code: authorizationCode,
    redirect_uri: 'https://my-app.com/auth/callback'
  })
});
const { access_token } = await response.json();

Deploy to Kubernetes

For production deployments, use the Helm chart:
helm repo add i4trust https://i4trust.github.io/helm-charts
helm repo update
helm install vcverifier i4trust/vcverifier \
  --set verifier.did=did:key:your-verifier-did \
  --set configService.enabled=true
See the i4trust/vcverifier Helm chart for full configuration options.

Next steps

Architecture

Learn how VCVerifier works under the hood

Configuration

Configure trust anchors and credential policies

API Reference

Explore all available endpoints

Production Setup

Best practices for production deployment

Build docs developers (and LLMs) love