Verifying Credentials
Validate W3C Verifiable Credentials with the VCVerifier class.
Check signatures, expiration, issuer identity, and detect tampering.
Two verification modes
The SDK supports two ways to verify a credential:
- verifyWithKey — you supply the public key directly. No network calls.
- verify — resolves the issuer's DID to fetch the public key automatically.
verifyWithKey
Use when you already know the issuer's public key:
Verify with known key
import { VCVerifier } from '@attestto-com/vc-sdk' const verifier = new VCVerifier() const result = await verifier.verifyWithKey(vc, publicKey, 'Ed25519', { expectedType: 'ProfessionalLicense', expectedIssuer: 'did:web:issuer.example.com', checkExpiration: true, }) console.log(result.valid) // true or false console.log(result.checks) // detailed check results console.log(result.errors) // array of failure reasons
verify (with DID resolver)
Use when you want the SDK to resolve the issuer's DID document and extract the public key:
Verify with DID resolution
import { VCVerifier } from '@attestto-com/vc-sdk' const verifier = new VCVerifier({ resolver: myDidResolver, // implements DID resolution }) const result = await verifier.verify(vc, { expectedType: 'DrivingLicense', checkExpiration: true, checkStatus: true, }) if (result.valid) { console.log('Credential is valid') } else { console.log('Errors:', result.errors) }
VerifyOptions
VerifyOptions interface
interface VerifyOptions { expectedType?: string // Assert credential contains this type expectedIssuer?: string // Assert issuer DID matches expectedContext?: string // Assert @context includes this URI checkExpiration?: boolean // Check expirationDate against now (default: true) checkStatus?: boolean // Check credentialStatus endpoint (default: false) }
VerificationResult
VerificationResult interface
interface VerificationResult { valid: boolean // Overall pass/fail checks: CheckResult[] // Individual check outcomes errors: string[] // Failure reasons (empty if valid) warnings: string[] // Non-fatal issues }
Verification checks
The verifier runs these checks in order. Each produces a CheckResult entry:
- structure.context —
@contextincludes the W3C credentials URI. - structure.type —
typearray includesVerifiableCredential. - structure.issuer —
issuerfield is present and is a valid DID. - structure.subject —
credentialSubjectis present. - structure.issuanceDate —
issuanceDateis a valid ISO 8601 timestamp. - proof.signature — cryptographic signature is valid against the public key.
- proof.algorithm — proof type matches the expected algorithm.
- temporal.expiration — credential has not expired (if
checkExpirationis enabled). - temporal.notBefore — current time is after issuance date.
- policy.type — credential type matches
expectedType(if provided). - policy.issuer — issuer DID matches
expectedIssuer(if provided). - policy.context — context matches
expectedContext(if provided). - status.revocation — credential is not revoked (if
checkStatusis enabled).
Tamper detection
If any field in the credential is modified after signing, the signature check fails:
Detecting tampering
// Tamper with the credential const tampered = { ...vc } tampered.credentialSubject = { ...tampered.credentialSubject, profession: 'Brain Surgeon', // was 'Civil Engineer' } const result = await verifier.verifyWithKey(tampered, publicKey, 'Ed25519') console.log(result.valid) // false console.log(result.errors) // ['proof.signature: Signature verification failed']
Always verify before trusting. A credential is just a JSON object until
its proof is verified. Never extract claims from an unverified credential.
Next steps
- Issuing credentials — create credentials to verify
- Key management — generate and store verification keys
- Schemas & plugins — type-specific validation