Cookbook: Issue a Membership Credential
This is chapter 2 of the Issue and verify cookbook. You create a tenant with its own keys and issuer identity, define a membership credential, and send it to the wallet on your phone.
What you will build
A tenant membership-demo that issues an SD-JWT VC of type urn:example:membership:1 with the claims name: Max and member_id: M-001, using a pre-authorized offer that the wallet scans as a QR code.
Before you start
- Starts from: chapter 1, Install and connect. You are signed in to the Web Client as root, the tunnel is running, and the phone reaches
https://YOUR-HTTPS-HOST/health. - You know which certificates your wallet needs (Wallet and registrar requirements).
Step 1: Create a tenant for the recipe
-
Open Administration → Tenants and choose the + button (Create New Tenant).
-
Enter tenant ID
membership-demoand NameMembership Demo. -
Under Initial Admin Client → Client Roles, keep
clients:manageand add exactly these roles:Role Allows issuance:manageKeys, issuer settings and credential types issuance:offerCreating credential offers and viewing issuance sessions presentation:manageVerification configurations presentation:requestCreating presentation requests and viewing presentation sessions Add
registrar:manageonly if your wallet needs registrar certificates. Never give a tenant clienttenants:manage: it controls all tenants of the instance. -
Choose Create tenant. The dialog Client Secret Generated shows the client ID
membership-demo-adminand its secret. Copy both and store them; the secret is not shown again. -
Choose Login as this Client.
Checkpoint: the menu at the top right shows Client ID: membership-demo-admin, and the navigation shows Credential Issuance and Credential Verification. Create everything that follows in this tenant. All roles are listed in the roles reference.
Step 2: Create the signing and access keys
Open Cryptographic Assets → Keys, choose Create Key and run the wizard twice:
| Purpose | Wizard choices | Description |
|---|---|---|
| Sign the issued credential | Credential Signing (Attestation) → Create Key Chain (Recommended) | Membership credential signing |
| Sign presentation requests to the wallet | Access Certificate → the certificate source your wallet needs (see below) | Membership verifier access |
Keep KMS provider db and the other defaults, then choose Create Key Chain. For the access certificate, pick the source that matches your wallet:
- Self-Signed Certificate for wallet test setups that accept it, such as Paradym.
- External Certificate to import a key and certificate chain issued elsewhere, such as the EU Reference Implementation's ecosystem operator. Paste the key into External Private Key (JWK or PKCS#8 PEM) and the chain into Certificate Chain (PEM), then choose Import Key & Certificate.
- Registrar Enrollment for the German ecosystem. It needs a saved registrar configuration under Registrar → Registrar Config and the
registrar:managerole.
Checkpoint: both key chains appear under Keys, each with an active key and certificate. The wizard generates their IDs; the next steps select them by description. Other provisioning options are in Keys and certificates.
The HTTPS certificate of your tunnel and the credential and access certificates are unrelated. A reachable HTTPS endpoint does not make a wallet trust a self-signed issuer or verifier.
Step 3: Set up the issuer
Open Credential Issuance → Issuer Settings and choose Use guided setup.
- Identity: enter name
Membership Demoand localeen-US. A logo is optional. - Wallet access: keep the enabled built-in authorization server and batch size
1. Leave request and response encryption off. Under Issuance behavior (advanced), check that your wallet supports the DPoP setting. - Trust: leave wallet attestation optional and federation off. Leave the registration certificate off unless your wallet requires one.
- Review: choose Save settings.
Checkpoint: the issuer overview shows Membership Demo and an enabled built-in authorization server. Every option is explained in Issuer settings.
Step 4: Define the membership credential
Open Credential Issuance → Credential Types and choose + (Create New Credential Configuration). Use exactly these values; chapter 3 requests the credential by its VCT and claim paths.
Basics
| Field | Value |
|---|---|
| Configuration ID | membership |
| Description | Membership credential for the cookbook |
| Credential Format | dc+sd-jwt |
| Host VCT Metadata | No (Custom URI) |
| VCT URI | urn:example:membership:1 |
Choose Continue.
Claims
Choose Add Field twice and enter the values as plain text, without JSON quotes:
| Path | Type | Default Value | Mandatory | Selectively Disclosable |
|---|---|---|---|---|
name | string | Max | On | On |
member_id | string | M-001 | On | On |
Choose Continue.
Appearance
Enter Display Name Membership, Description Example membership card and Locale en-US. Choose Continue.
Settings
- Under Signing, lifetime and trust, select the key chain described as
Membership credential signingin Signing Key Chain, set Credential Lifetime to 1 day and keep SD-JWT Trust Formatx5c. - Under Credential Features, keep Key Binding on and turn Status Management off. Set Supported Proof Types to JWT only, so the first run does not need key attestation.
- Leave attribute providers, webhooks, authorization actions and reuse policy empty.
Choose Continue, check the review, and choose Create Configuration.
Checkpoint: membership appears under Credential Types with VCT urn:example:membership:1 and the two claims. Other formats and settings are in Credential configuration.
It keeps status lists out of the first run. Revocable credentials turns it on.
Step 5: Send an offer to the wallet
- Open Credential Issuance → New Issuance.
- In Select Flow, choose Pre-Authorized Code and Next.
- In Select Credentials, select
membershipunder Credential Configuration IDs and continue. - In Configure Claims, keep Form Input and choose Use Pre-configured Default Values. The form now shows
name: Maxandmember_id: M-001. - Leave Transaction Code (Optional) empty, then choose Generate Offer.
- Scan the QR code with the wallet's credential-offer scanner and accept the credential.
Checkpoint: the wallet shows a Membership credential with Max and M-001. Under Sessions → All Sessions, the issuance session has status fetched (the wallet received the credential) or completed (the wallet also confirmed it through the notification endpoint). A QR code alone does not mean that the wallet received the credential.
Troubleshooting
| Symptom | Cause | Fix |
|---|---|---|
membership is missing in the offer form | Created in another tenant, or saved with authorization actions | Check the client ID in the top-right menu; remove interactive authorization actions for this recipe. |
| Credential Issuance is missing in the menu | The tenant client lacks issuance:manage or issuance:offer | Open Administration → API Clients, add the roles to membership-demo-admin, then sign in again. |
| Wallet asks for an attestation | Proof type Attestation or required wallet attestation is set | Use proof type JWT only and keep wallet attestation optional. |
| Wallet shows other claim values | The offer overrode the defaults, or the credential is an older one | Generate a new offer with the default values; a wallet keeps the claims it was issued with. |
Wallet connection, certificate and metadata errors are covered in Troubleshooting.
Next steps
- Keep the credential in the wallet and stay in tenant
membership-demo. - Continue with chapter 3: Verify the membership credential.