# X509Credential with UZI server certificates

Care organizations authenticate with an X509Credential, created from their UZI server certificate. This page explains how the certificate ends up in the credential, and what a use case's Discovery Service and policy definitions need to check.

For the X509Credential and `did:x509` in general, see [RFC023](https://nuts-foundation.gitbook.io/drafts/rfc/rfc023-x509credential). For how to create one, see "Get an X509Credential from a UZI certificate" in [Implementing a Nuts v2 Use Case](https://wiki.nuts.nl/books/implementing-a-nuts-v2-use-case).

## Which CA to trust: the CA tree

UZI server certificates are issued by the UZI register (CIBG), under the PKIoverheid hierarchy. The X509Credential's issuer is a `did:x509` DID, which contains the fingerprint (`ca-fingerprint`) of one CA in the certificate's chain. A definition trusts a CA by listing its fingerprint.

Use the fingerprint of the **UZI CA**: the CA that issues the UZI server certificates. Not the root or intermediate CA above it: those also issue certificates through other providers (e.g. KPN, DigiCert), which don't contain a URA.

```
Production G1
Staat der Nederlanden Private Root CA - G1
└── Staat der Nederlanden Private Services CA - G1
    ├── UZI-register Private Server CA G1                ◄ ca-fingerprint
    │   └── UZI server certificate
    └── KPN, DigiCert, QuoVadis, ... (other providers, no URA)

Production G4 (from 12 November 2026)
Staat der Nederlanden - G4 Root Priv G-TLS - 2024
└── Staat der Nederlanden - G4 Intm Priv G-TLS SYS - 2024
    ├── UZI Server - G4 PKIo Priv G-TLS SYS - 2025       ◄ ca-fingerprint
    │   └── UZI server certificate
    └── KPN, DigiCert, Digidentity, ... (other providers, no URA)

Test G1
TEST Zorg CSP Private Root CA G1
└── TEST Zorg CSP Level 2 Private Services CA G1
    └── TEST UZI-register Private Server CA G1           ◄ ca-fingerprint
        └── UZI server certificate

Acceptance G4
ACCEPTATIE Zorg CSP - G4 Root Priv G-TLS - 2024
└── ACCEPTATIE Zorg CSP - G4 Intm Priv G-TLS SYS - 2024
    └── ACCEPTATIE UZI Server - G4 Priv G-TLS SYS - 2025 ◄ ca-fingerprint
        └── UZI server certificate
```

| UZI CA | Environment | `ca-fingerprint` (SHA-256, base64url) |
|---|---|---|
| UZI-register Private Server CA G1 | Production | `vdhg746H4rLH67NN1unhdxo6PF3shQunCA4-KQTb2Jc` |
| UZI Server - G4 PKIo Priv G-TLS SYS - 2025 | Production, from 12 November 2026 | `sDTL__yv54TtrvSf7601TtvHgj2NZSLT2m-Okf8oqkI` |
| TEST UZI-register Private Server CA G1 | Test | `GwlhBZuEFlSHXSRUXQuTs3_YpQxAahColwJJj35US1A` |
| ACCEPTATIE UZI Server - G4 Priv G-TLS SYS - 2025 | Test, acceptance | `svKzNxhS07V1dKkekWOZV0d6Ao7_qvjqXegWB32YjZE` |

CIBG starts issuing G4 certificates on 12 November 2026; G1 certificates stop working on 12 November 2028. Until then, definitions should trust both.

## From certificate to credential

These certificate fields end up in the X509Credential:

| Certificate field | Credential field | Contains |
|---|---|---|
| `subject.O` | `credentialSubject.subject.O` | Name of the care organization |
| `subject.L` | `credentialSubject.subject.L` | City |
| `san.otherName` | `credentialSubject.san.otherName` | UZI number, URA and more, see below |

## The URA in `san.otherName`

`san.otherName` is one string with seven parts, separated by `-`:

```
<OID CA>-<version>-<UZI number>-<pass type>-<URA>-<role>-<AGB code>
2.16.528.1.1007.99.2110-1-900025039-S-90000382-00.000-00000000
```

| Part | Example | Meaning |
|---|---|---|
| OID CA | `2.16.528.1.1007.99.2110` | The CIBG |
| Version | `1` | Version of this format |
| UZI number | `900025039` | Number of the certificate holder, same as `subject.serialNumber` |
| Pass type | `S` | Always `S` (server) |
| URA | `90000382` | The care organization's URA ("abonneenummer") |
| Role | `00.000` | Always `00.000` |
| AGB code | `00000000` | The care organization's AGB code |

To get the URA in a definition, use a pattern with a capture group on this field. The node then returns only the captured part, e.g. in search results and token introspection:

```json
{
  "id": "organization_ura",
  "path": ["$.credentialSubject.san.otherName"],
  "filter": { "type": "string", "pattern": "^[0-9.]+-\\d+-\\d+-S-(\\d+)-00\\.000-\\d+$" }
}
```