SdJwt.Net.Oid4Vp 1.0.6

dotnet add package SdJwt.Net.Oid4Vp --version 1.0.6
                    
NuGet\Install-Package SdJwt.Net.Oid4Vp -Version 1.0.6
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="SdJwt.Net.Oid4Vp" Version="1.0.6" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="SdJwt.Net.Oid4Vp" Version="1.0.6" />
                    
Directory.Packages.props
<PackageReference Include="SdJwt.Net.Oid4Vp" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add SdJwt.Net.Oid4Vp --version 1.0.6
                    
#r "nuget: SdJwt.Net.Oid4Vp, 1.0.6"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package SdJwt.Net.Oid4Vp@1.0.6
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=SdJwt.Net.Oid4Vp&version=1.0.6
                    
Install as a Cake Addin
#tool nuget:?package=SdJwt.Net.Oid4Vp&version=1.0.6
                    
Install as a Cake Tool

SdJwt.Net.Oid4Vp - OpenID for Verifiable Presentations

NuGet Version License

Implementation of OpenID4VP 1.0 specification for verifiable presentation verification. Provides protocol support with DCQL, Presentation Exchange v2.1.1 integration, and cross-device flow support.

Features

  • OID4VP 1.0 Final: Specification implementation
  • DCQL Support: Credential query models, format metadata validation, credential sets, and DCQL vp_token maps
  • SIOPv2 Combined Responses: vp_token id_token request/response model support with subject-signed ID Tokens from SdJwt.Net.SiopV2
  • Presentation Exchange v2.1.1: DIF PE integration
  • Format Validators: Extensible validation hooks for dc+sd-jwt, mso_mdoc, jwt_vc_json, jwt_vc_json-ld, and ldp_vc
  • Cross-Device Flow: QR code-based presentation flows
  • Multi-Credential: Multi-credential presentation support
  • Security Validation: Nonce, audience, freshness, transaction data, and verifier info validation with key binding

Installation

dotnet add package SdJwt.Net.Oid4Vp

Quick Start

Create Presentation Request

using SdJwt.Net.Oid4Vp.Models;
using SdJwt.Net.Oid4Vp.Verifier;

var presentationRequest = new AuthorizationRequest
{
    ClientId = "https://verifier.example.com",
    ResponseType = "vp_token",
    ResponseMode = "direct_post",
    ResponseUri = "https://verifier.example.com/presentations",
    Nonce = "presentation_nonce_123",
    PresentationDefinition = new PresentationDefinition
    {
        Id = "employment_verification",
        InputDescriptors = new[]
        {
            new InputDescriptor
            {
                Id = "employment_credential",
                Constraints = new Constraints
                {
                    Fields = new[]
                    {
                        new Field { Path = new[] { "$.position" } },
                        new Field { Path = new[] { "$.employment_type" } }
                    }
                }
            }
        }
    }
};

Create a DCQL Presentation Request

using SdJwt.Net.Oid4Vp.Models;
using SdJwt.Net.Oid4Vp.Models.Dcql;
using SdJwt.Net.Oid4Vp.Models.Dcql.Formats;

var request = new AuthorizationRequest
{
    ClientId = "https://verifier.example.com",
    ResponseType = "vp_token",
    ResponseMode = "direct_post",
    ResponseUri = "https://verifier.example.com/presentations",
    Nonce = "presentation_nonce_123",
    DcqlQuery = new DcqlQuery
    {
        Credentials = new[]
        {
            new DcqlCredentialQuery
            {
                Id = "employee_credential",
                Format = Oid4VpConstants.SdJwtVcFormat,
                Meta = new SdJwtVcMeta
                {
                    VctValues = new[] { "https://issuer.example.com/credentials/employee" }
                }
            }
        }
    },
    TransactionData = new[] { base64UrlEncodedTransactionData }
};

Validate a DCQL Response

DCQL responses do not use presentation_submission. The vp_token response is a JSON object keyed by DCQL credential query id, and each value is one or more presentations for that query.

var options = VpTokenValidationOptions.CreateForOid4Vp("https://verifier.example.com");
options.ExpectedDcqlQuery = request.DcqlQuery;

var result = await validator.ValidateAsync(response, "presentation_nonce_123", options);

The validator enforces:

  • DCQL model structure, including unique credential ids, valid claim paths, valid claim_sets, and valid credential_sets references.
  • credential_sets option semantics: an option with multiple ids is an AND, multiple options are OR, and required sets must have at least one satisfied option.
  • vp_token response map shape, unknown ids, empty tokens, and multiple rules.
  • Verified disclosed claims for SD-JWT VC flows, including meta.vct_values, requested claim paths, claim value matching, and claim_sets.

Request a SIOPv2 ID Token with the VP Token

OpenID4VP can request a SIOPv2 subject-signed ID Token alongside the presentation by using the combined response type. SdJwt.Net.Oid4Vp models the request and response shape; SdJwt.Net.SiopV2 issues and validates the id_token.

var request = AuthorizationRequest.CreateCrossDevice(
    "https://verifier.example.com",
    "https://verifier.example.com/presentations",
    "presentation_nonce_123",
    presentationDefinition);

request.ResponseType = Oid4VpConstants.ResponseTypes.VpTokenIdToken;
request.Scope = "openid";
request.IdTokenType = Oid4VpConstants.IdTokenTypes.SubjectSigned;
request.Validate();

var response = AuthorizationResponse.SuccessWithIdToken(
    vpToken,
    presentationSubmission,
    idToken,
    request.State);
using SdJwt.Net.Oid4Vp.Verifier;

// Create validator with SD-JWT VC validation enabled (recommended)
var validator = new VpTokenValidator(
    keyProvider: async (jwtToken) => {
        // Resolve issuer's public key based on JWT header/payload
        return await GetIssuerPublicKeyAsync(jwtToken.Issuer);
    },
    useSdJwtVcValidation: true); // Enables vct, iss, typ validation

// Use factory method for OID4VP-compliant options
var options = VpTokenValidationOptions.CreateForOid4Vp("https://verifier.example.com");

// Optional: Customize validation
options.ValidIssuers = new[] { "https://trusted-issuer.example.com" };
options.MaxKeyBindingAge = TimeSpan.FromMinutes(5); // Stricter than default

// Optional: enforce the same DIF Presentation Exchange v2.1.1 definition
// that was sent in the authorization request. The validator checks
// presentation_submission after SD-JWT verification, using verified claims.
options.ExpectedPresentationExchangeDefinition = expectedPresentationDefinition;

// Validate VP token
var result = await validator.ValidateAsync(
    vpTokenResponse,
    expectedNonce: "presentation_nonce_123",
    options);

if (result.IsValid)
{
    foreach (var tokenResult in result.ValidatedTokens)
    {
        var vctClaim = tokenResult.Claims["vct"];
        var issuer = tokenResult.Claims["iss"];
        // Use verified claims safely
    }
}

ExpectedPresentationExchangeDefinition uses the shared SdJwt.Net.PresentationExchange.Models.PresentationDefinition model. OID4VP request models remain available for request serialization, but verifier-side PEX constraint enforcement should use the shared Presentation Exchange package.

Security Features

This library validates the following per OID4VP 1.0:

Nonce Validation (OID4VP Section 14.1)
// Nonce validation is AUTOMATIC when you provide expectedNonce
var result = await validator.ValidateAsync(response, expectedNonce, options);

// The validator ensures:
// - KB-JWT contains 'nonce' claim
// - Nonce matches the expected value from authorization request
// - Prevents replay attacks
Audience Validation (OID4VP Section 8.6)
// Enabled by default for security
var options = VpTokenValidationOptions.CreateForOid4Vp("https://verifier.example.com");

// The validator ensures:
// - KB-JWT 'aud' claim matches your client_id
// - Prevents token reuse across different verifiers
// - Can be customized or disabled if needed:
options.ValidateKeyBindingAudience = false; // Not recommended
Freshness Validation (OID4VP Section 14.1)
// Enabled by default to prevent replay attacks
var options = VpTokenValidationOptions.CreateForOid4Vp("https://verifier.example.com");
options.MaxKeyBindingAge = TimeSpan.FromMinutes(10); // Default

// The validator ensures:
// - KB-JWT 'iat' claim is present
// - KB-JWT was issued recently (within MaxKeyBindingAge)
// - Includes clock skew tolerance (default: 5 minutes)
SD-JWT VC Format Validation (draft-ietf-oauth-sd-jwt-vc)
// Enabled by default when using VpTokenValidator
var validator = new VpTokenValidator(keyProvider, useSdJwtVcValidation: true);

// The validator ensures:
// - 'vct' claim is present and valid
// - 'iss' claim is present
// - 'typ' header is 'dc+sd-jwt'
// - Collision-resistant names are validated

Testing/Development Mode

For testing or development, use relaxed validation:

var validator = new VpTokenValidator(keyProvider, useSdJwtVcValidation: false);
var options = VpTokenValidationOptions.CreateForTesting();

// This disables strict OID4VP validations:
// - No issuer validation
// - No audience validation
// - No freshness validation
// - Extended time windows

Migration from v1.0

If you're upgrading from v1.0, note these changes:

// OLD (v1.0):
var options = new VpTokenValidationOptions
{
    ValidateKeyBindingAudience = false, // Was default
    ValidateKeyBindingFreshness = false, // Not available
};

// NEW (v1.1) - RECOMMENDED:
var options = VpTokenValidationOptions.CreateForOid4Vp("https://verifier.example.com");

// NEW (v1.1) - If you need old behavior:
var options = new VpTokenValidationOptions
{
    ValidateKeyBindingAudience = false,
    ValidateKeyBindingFreshness = false
};

Use Cases

  • Employment Verification: Bank loan applications requiring job verification
  • Age Verification: Privacy-preserving age proof for restricted services
  • Cross-Device Flows: QR code scanning from mobile to desktop
  • Complex Requirements: Multi-credential presentations for compliance
  • Mixed Format Verification: SD-JWT VC, W3C VCDM, and ISO mdoc presentations in DCQL flows

Test Notes

The test project targets net10.0. On Windows worktrees with restrictive inherited ACLs, use a serialized test run to avoid MSBuild worker buildup:

$env:MSBUILDDISABLENODEREUSE = "1"
dotnet test tests/SdJwt.Net.Oid4Vp.Tests/SdJwt.Net.Oid4Vp.Tests.csproj -f net10.0 -m:1 -nr:false -p:UseSharedCompilation=false

Documentation

For more examples and protocol implementation patterns, see the main repository.

License

Licensed under the Apache License 2.0.

Product Compatible and additional computed target framework versions.
.NET net5.0 was computed.  net5.0-windows was computed.  net6.0 was computed.  net6.0-android was computed.  net6.0-ios was computed.  net6.0-maccatalyst was computed.  net6.0-macos was computed.  net6.0-tvos was computed.  net6.0-windows was computed.  net7.0 was computed.  net7.0-android was computed.  net7.0-ios was computed.  net7.0-maccatalyst was computed.  net7.0-macos was computed.  net7.0-tvos was computed.  net7.0-windows was computed.  net8.0 is compatible.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed.  net9.0 is compatible.  net9.0-android was computed.  net9.0-browser was computed.  net9.0-ios was computed.  net9.0-maccatalyst was computed.  net9.0-macos was computed.  net9.0-tvos was computed.  net9.0-windows was computed.  net10.0 is compatible.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
.NET Core netcoreapp3.0 was computed.  netcoreapp3.1 was computed. 
.NET Standard netstandard2.1 is compatible. 
MonoAndroid monoandroid was computed. 
MonoMac monomac was computed. 
MonoTouch monotouch was computed. 
Tizen tizen60 was computed. 
Xamarin.iOS xamarinios was computed. 
Xamarin.Mac xamarinmac was computed. 
Xamarin.TVOS xamarintvos was computed. 
Xamarin.WatchOS xamarinwatchos was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages (3)

Showing the top 3 NuGet packages that depend on SdJwt.Net.Oid4Vp:

Package Downloads
SdJwt.Net.HAIP

OpenID4VC High Assurance Interoperability Profile (HAIP) helpers for the SD-JWT .NET ecosystem. Provides HAIP 1.0 Final flow/profile validation plus legacy policy helpers. Ready for .NET 10.

SdJwt.Net.Wallet

Generic, extensible identity wallet implementation for .NET, supporting SD-JWT VC and mdoc credentials. Provides credential management, key management, OpenID4VCI/VP protocol adapters, and integration with trust infrastructure. Based on EUDI Android/iOS wallet architectures.

SdJwt.Net.Eudiw

EU Digital Identity Wallet (EUDIW) profile implementation for the SD-JWT .NET ecosystem. Provides eIDAS 2.0 compliance, ARF validation, EU Trust List integration, PID credential handling, and QEAA/EAA support for European digital identity verification.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
1.0.6 198 5/10/2026
1.0.5 195 5/9/2026
1.0.4 202 4/30/2026
1.0.3 211 4/28/2026
1.0.3-alpha.0.2 58 4/28/2026
1.0.2 210 3/13/2026
1.0.1 206 3/1/2026
1.0.0 143 2/28/2026

Version 1.0.0: Complete OID4VP 1.0 protocol support with
                       cross-device flows, Presentation Exchange v2.1.1 validation, comprehensive security
                       validation, and production-ready SD-JWT integration. Ready for .NET 10.