---
title: "Dynamic Verification Policies"
description: "Dynamic verification policies for verifiable credentials."
stack: "Community Stack (open source) — version 0.21.0"
stack_version: "0.21.0"
stack_comparison: https://docs.walt.id/community-vs-enterprise.md
canonical_url: https://docs.walt.id/community-stack/verifier/credential-verification/policies/dynamic-verification-policies
generated: 2026-07-20
---
# Dynamic Verification Policies with OPA and Rego

This guide provides comprehensive documentation for integrating **Open Policy Agent (OPA)** and **Rego policies** into a Verifier API. Learn how to define dynamic verification rules for verifiable credentials (VCs) using declarative policies.

---

## Table of Contents
1. [Introduction](#introduction)
2. [Prerequisites](#prerequisites)
3. [Installation](#installation)
4. [Policy Management](#policy-management)
5. [Integration with Verifier API](#integration-with-verifier-api)
6. [Examples](#examples)
7. [Troubleshooting](#troubleshooting)
8. [Conclusion](#conclusion)

---

### What is OPA?
**Open Policy Agent (OPA)** is an open-source policy engine that enables context-aware, dynamic authorization decisions. It uses the **Rego language** to define policies as code.

### Key Concepts
- **Rego**: Declarative query language for defining policies.
- **Verifiable Credentials (VCs)**: Digitally signed credentials that can be programmatically verified.
- **Dynamic Policies**: Rules evaluated at runtime to verify credentials based on custom logic (e.g., checking specific claims).

---

## Prerequisites

- Basic understanding of JSON and REST APIs.
- OPA server installed ([Installation Guide](#installation)).
- Access to a Verifier API instance.

---

## Installation

### Step 1: Install OPA
Download and run OPA locally:

```bash
# For Linux
wget https://openpolicyagent.org/downloads/v0.46.1/opa_linux_amd64 -O opa
chmod +x opa

# For macOS (Homebrew)
brew install opa

# For Windows (Docker)
docker run -p 8181:8181 openpolicyagent/opa run --server
```

### Step 2: Start OPA Server
```bash
./opa run --server
```
- Default endpoint: `http://localhost:8181`

### Step 3: Verify Installation
```bash
curl http://localhost:8181
```

---

## Policy Management

### Policy Structure
Policies are defined in Rego and stored in OPA. A policy consists of:
- **`package`**: Namespace for the policy (e.g., `vc.verification.test`).
- **`default allow`**: Default decision if no rules match.
- **Rules**: Conditions that evaluate to `true`/`false`.

### Example Policy
```rego
package vc.verification.example

default allow = false

# Allow if credential name matches parameter
allow if {
    input.parameter.name == input.credentialData.credentialSubject.achievement.name
}
```

---

## Integration with Verifier API

### Policy Configuration
Include policies in the Verifier API request under `request_credentials.policies`:

| Field           | Description                                                                 |
|-----------------|-----------------------------------------------------------------------------|
| `policy`        | Set to `"dynamic"` for OPA-based policies.                                  |
| `policy_name`   | Unique identifier for the policy.                                           |
| `rules.rego`    | Inline Rego policy (or `policy_url` for remote policies).                   |
| `argument`      | Key-value pairs passed to the policy for evaluation.                        |
| `opa_server`    | OPA server URL (default: `http://localhost:8181`).                          |
| `policy_query`  | OPA data query path (e.g., `data.test.allow`).                              |

### Workflow
1. Verifier API sends the credential data and arguments to OPA.
2. OPA evaluates the policy against the input.
3. OPA returns `allow: true` or `allow: false`.
4. Verifier API enforces the decision.

---

## Examples

### 1. Single Condition
**Goal**: Verify the credential's name matches a specific value.

**Request**:
```json
{
  "request_credentials": [
    {
      "format": "jwt_vc_json",
      "type": "OpenBadgeCredential",
      "policies": [
        {
          "policy": "dynamic",
          "args": {
            "policy_name": "name_check",
            "rules": {
              "rego": "package vc.verification\n\ndefault allow = false\n\nallow if input.parameter.name == input.credentialData.credentialSubject.name"
            },
            "argument": {
              "name": "JFF x vc-edu PlugFest 3 Interoperability"
            }
          }
        }
      ]
    }
  ]
}
```

---

### 2. Multiple Conditions (AND Logic)
**Goal**: Require both `name` and `id` to match.

**Rego**:
```rego
package vc.verification

default allow = false

allow if {
    input.parameter.name == input.credentialData.credentialSubject.name
    input.parameter.id == input.credentialData.credentialSubject.id
}
```

**Request**:
```json
{
  "args": {
    "argument": {
      "name": "PlugFest 3",
      "id": "urn:uuid:ac254bd5-8fad-4bb1-9d29-efd938536926"
    }
  }
}
```

---

### 3. Remote Policy URL
**Goal**: Fetch a policy from a remote server.

**Request**:
```json
{
  "args": {
    "policy_url": "http://example.com/policies/name_check.rego",
    "opa_server": "http://opa.example.com"
  }
}
```

**Full example**:

```json
{
  "request_credentials": [
    {
      "format": "jwt_vc_json",
      "type": "OpenBadgeCredential",
      "policies": [
        {
          "policy": "dynamic",
          "args": {
            "policy_name": "waltid",
            "opa_server": "http://opa.example.com",
            "policy_query": "data",
            "rules": {
              "policy_url": "http://example.com/policies/name_check"
            },
            "argument": {
              "name": "JFF x vc-edu PlugFest 3 Interoperability"
            }
          }
        }
      ]
    }
  ]
}
```
---

For advanced use cases, explore [OPA’s documentation](https://www.openpolicyagent.org/docs/latest/).
