Add Signer Abstraction Interface with Azure Key Vault Example#60
Open
warren-gallagher wants to merge 6 commits intoauth0-lab:mainfrom
Open
Add Signer Abstraction Interface with Azure Key Vault Example#60warren-gallagher wants to merge 6 commits intoauth0-lab:mainfrom
warren-gallagher wants to merge 6 commits intoauth0-lab:mainfrom
Conversation
added 5 commits
October 27, 2025 15:20
Add Azure Key Vault integration for hardware-backed cryptographic signing of mobile driver's licenses (mDL) compliant with ISO 18013-5. Key changes: - Introduce Signer abstraction interface for pluggable signing implementations - Implement AzureKeyVaultSigner with @azure/keyvault-keys and @azure/identity - Refactor existing signing logic into LocalKeySigner for backward compatibility - Add comprehensive test suite with certificate chain validation - Support ES256, ES384, ES512, and RSA signature algorithms - Document EdDSA/Ed25519 limitation (not supported by Azure Key Vault HSM) - Include setup guide and integration documentation All 115 tests passing with 100% backward compatibility maintained.
…tations Add Example Azure Key Vault integration for hardware-backed cryptographic signing of mobile driver's licenses (mDL) compliant with ISO 18013-5. Key changes: - Introduce Signer abstraction interface for pluggable signing implementations - Implement AzureKeyVaultSigner with @azure/keyvault-keys and @azure/identity - Refactor existing signing logic into LocalKeySigner for backward compatibility - Add comprehensive test suite with certificate chain validation - Support ES256, ES384, ES512 signature algorithms - Document EdDSA/Ed25519 limitation (not supported by Azure Key Vault HSM) - Include setup guide and integration documentation
The LocalKeySigner had two critical bugs that prevented signatures from being verified:
Double-hashing: Used createSign() which hashes data, but the data was already a Sig_structure
Wrong signature format: Used DER encoding instead of IEEE P1363 format required by COSE
Solution Implemented
Fixed src/mdoc/signing/LocalKeySigner.ts:
Changes Made:
Replaced createSign() with crypto.sign() - The one-shot API that matches cose-kit's behavior
Added dsaEncoding: 'ieee-p1363'
- Specifies COSE-compliant signature format (raw R||S concatenation)
Simplified digest mapping
- RSA algorithms now correctly map to digest names only (e.g., 'sha256' not 'RSA-SHA256')
Test Results
✅ All tests pass! The new tests/issuing/signerCompatibility.tests.ts confirms:
✅ Documents are verifiable - Both old (issuerPrivateKey) and new (LocalKeySigner) methods
produce valid, verifiable signatures
✅ Identical structure - Documents have the same COSE structure, algorithm identifiers,
and payload
✅ Backward compatibility - Old signing method still works perfectly
✅ Proper validation - Correctly rejects invalid parameter combinations
Technical Details
The fix ensures LocalKeySigner follows the same signing process as cose-kit:
Sig_structure → hash with SHA-256/384/512 → sign with private key → IEEE P1363 format
Instead of the broken:
Sig_structure → hash → hash again → sign → DER format ❌
The implementation now correctly uses:
cryptoSign(digestAlgorithm, data, {
key: key,
dsaEncoding: 'ieee-p1363', // COSE format!
});
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Add Signer Abstraction Interface with Azure Key Vault Example
Overview
This PR introduces a pluggable signing abstraction layer to
@auth0/mdl, enabling integration with Hardware Security Modules (HSMs) and cloud-based key management services while maintaining full backward compatibility with existing code.Addresses: #31
Key Changes
1. Signer Abstraction Interface
Added a new
Signerinterface (src/mdoc/signing/Signer.ts) that defines a standard contract for signing operations:This abstraction allows the library to support multiple signing backends without coupling to specific key storage implementations.
2. LocalKeySigner Implementation
Implemented
LocalKeySigner(src/mdoc/signing/LocalKeySigner.ts) that wraps traditional JWK-based signing to conform to the newSignerinterface. This provides:3. Enhanced Document Signing
Updated
Document.sign()to accept an optionalsignerparameter alongside the existingissuerPrivateKey:Backward Compatibility: All existing code using
issuerPrivateKeycontinues to work without any changes. The parameters are mutually exclusive with proper validation.4. IssuerAuth.signWithSigner()
Added new static method
IssuerAuth.signWithSigner()that manually constructs COSE_Sign1 structures following RFC 8152 Section 4.4, bypassing cose-kit's key handling to enable custom signers.5. Azure Key Vault Example
Included a complete example implementation in
examples/azure-keyvault-signer/demonstrating:AzureKeyVaultSignerclass that implements theSignerinterfaceNote: The Azure Key Vault implementation is provided as an example, not as part of the core library. Users can adapt this pattern for AWS KMS, Google Cloud KMS, or other signing services.
Benefits
SignerinterfaceFiles Changed
Core Library
src/mdoc/signing/Signer.ts- Signer interfacesrc/mdoc/signing/LocalKeySigner.ts- Local JWK signer implementationsrc/mdoc/signing/index.ts- Module exportssrc/mdoc/model/Document.ts- Enhanced to support custom signerssrc/mdoc/model/IssuerAuth.ts- AddedsignWithSigner()methodsrc/index.ts- ExportSignerandLocalKeySignerExample Implementation
examples/azure-keyvault-signer/src/AzureKeyVaultSigner.ts- Azure Key Vault signer exampleexamples/azure-keyvault-signer/AZURE_KEY_VAULT_EXAMPLE.md- Usage documentationexamples/azure-keyvault-signer/AZURE_KEY_VAULT_INTEGRATION.md- Integration guideexamples/azure-keyvault-signer/README.md- Overviewexamples/azure-keyvault-signer/__tests__/azureKeyVault.tests.ts- Testsexamples/azure-keyvault-signer/sample-azure-env.sh- Environment setup scriptTesting
Migration Guide
No migration needed! This is a purely additive change. Existing code continues to work:
To adopt the new signer interface: