Skip to content

feat: Add example for external VC issuer, Keycloak OID4VCI integration - #34

Open
bucchi wants to merge 1 commit into
agent-intent:mainfrom
bucchi:example-extension-for-keycloak
Open

feat: Add example for external VC issuer, Keycloak OID4VCI integration#34
bucchi wants to merge 1 commit into
agent-intent:mainfrom
bucchi:example-extension-for-keycloak

Conversation

@bucchi

@bucchi bucchi commented Aug 23, 2026

Copy link
Copy Markdown

Related Issue

Fixes #33

Overview

To address the objective outlined in the related issue, this PR expands the provided examples to demonstrate how verifiable-intent can seamlessly integrate with a real-world, external Verifiable Credential issuer.

In this example, I implemented the integration flow using Keycloak 26 (OID4VCI). It retrieves a real L1 SD-JWT and the issuer's public key (via JWKS), demonstrating a standard external issuance flow in real-world setups.

Key Changes

1. Example Expansion (examples/autonomous_flow.py)

  • Added logic to conditionally fetch an L1 SD-JWT via the Pre-Authorized Code from an external issuer.
  • Added logic to fetch the issuer's active ES256 public key from the .well-known/openid-connect/certs (JWKS) endpoint for verification.
  • Backward Compatibility: When run without the external issuer configuration, the script gracefully falls back to generating the local mock L1, preserving the original default behavior.

2. Minor Core Tweaks (src/verifiable_intent/verification/chain.py)

To make the external integration work, I introduced two minor, backward-compatible tweaks:

  • Prevent Re-serialization: When l1_serialized is explicitly provided, verify_chain now directly extracts the raw signing input and uses the existing es256_verify utility. This prevents verification failures caused by JSON formatting differences (e.g., spacing/key order) between Java (Keycloak) and Python's json.dumps.
  • Support dc+sd-jwt Header Type: Updated the validation logic to accept dc+sd-jwt as a valid JWT typ header. This ensures compatibility with standard OID4VCI issuers like Keycloak that output Document Credentials.

How to Test

1. Local Mock Mode (Default)

Simply run the example script as usual. It will generate the mock L1 and pass all verifications.

python examples/autonomous_flow.py

2. External Integration Mode (Keycloak OID4VCI)

To run the script with a real Keycloak 26 OID4VCI flow, set up your Keycloak realm, initiate a VC issuance, and export the following environment variables before running the example:

# Keycloak Configuration
export KEYCLOAK_ISSUER_URL="http://localhost:8080/realms/vi-realm"
export KEYCLOAK_JWKS_URL="http://localhost:8080/realms/vi-realm/protocol/openid-connect/certs"
export KEYCLOAK_TOKEN_URL="http://localhost:8080/realms/vi-realm/protocol/openid-connect/token"
export KEYCLOAK_CREDENTIAL_URL="http://localhost:8080/realms/vi-realm/protocol/oid4vc/credential"
export KEYCLOAK_NONCE_URL="http://localhost:8080/realms/vi-realm/protocol/oid4vc/nonce"

# Client Credentials & Issued Code
export KEYCLOAK_CLIENT_ID="vi-client"
export KEYCLOAK_CLIENT_SECRET="<your_client_secret>"  # The secret generated when creating the client in Keycloak
export KEYCLOAK_PRE_AUTHORIZED_CODE="<your_pre_authorized_code>"  # The pre-authorized code obtained when you request/initiate the VC issuance in Keycloak

# Run the integration flow
python examples/autonomous_flow.py

This will fetch the real L1 SD-JWT from Keycloak, resolve the issuer's key via JWKS, and verify the full 3-layer chain successfully.

…ommit

Signed-off-by: Yutaka Obuchi <yutaka.obuchi.sd@hitachi.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Enhance examples to demonstrate interoperability with Verifiable Credentials issued by external issuers

1 participant