UNPKG

@ew-did-registry/claims

Version:

The package exposes functionality needed to create, inspect, approve, and verify Private and Public claims

148 lines (140 loc) 4.63 kB
import { IDIDDocumentFull } from '@ew-did-registry/did-document'; import { IJWT, JWT, JwtPayload } from '@ew-did-registry/jwt'; import { IDidStore } from '@ew-did-registry/did-store-interface'; import { IDIDDocument, IServiceEndpoint, } from '@ew-did-registry/did-resolver-interface'; import { EwSigner } from '@ew-did-registry/did-ethr-resolver'; import { IClaims, IPublicClaim, IPrivateClaim, VerificationPurpose, } from '../models'; import { hashes } from '../utils'; import { ProofVerifier } from '../claimsVerifier/proofVerifier'; /** * @class * Base class for extending by other claims classes */ export class Claims implements IClaims { public jwt: IJWT; public keys: { privateKey?: string; publicKey: string; }; public did: string; /** * @constructor * * @param { IKeys } keys * @param document * @param store */ constructor( owner: EwSigner, protected document: IDIDDocumentFull, protected store: IDidStore ) { this.keys = { publicKey: owner.publicKey, privateKey: owner.privateKey }; this.jwt = new JWT(owner); this.did = document.did; } /** * Verifies issuance and publishing of claim at `claimUrl`. * On success returns claim. * Verification takes into account purpose on which claim was issued. * * @param claimUrl: Url of claim to be verified. This method will retrieve * the claim using the didStore configured for the class * @param params.hashFns: The function used to determine the of hash of the claim * token used in the DID document. Used to verify that the DID document service endpoint * matches the retrieved claim. * @param params.issuerDoc: Document with verification methods to verify claim issuance with * @param params.holderDoc: Document with service endpoints to verify claim publishing with * @param params.verificationPurpose: Specifies which verification methods to use. * `VerificationPurpose.Authenticate` is used to verify claim issued to authenticate identity * `VerificationPurpose.Assertion` is used to assert issuer approval. * By default verification asserts claim approval. * */ async verify( claimUrl: string, { hashFns, issuerDoc, holderDoc, verificationPurpose = VerificationPurpose.Assertion, }: { hashFns?: { [alg: string]: (data: string) => string }; issuerDoc?: IDIDDocument; holderDoc?: IDIDDocument; verificationPurpose?: VerificationPurpose; } = {} ): Promise<IPublicClaim | IPrivateClaim> { const token = await this.store.get(claimUrl); const claim = this.jwt.decode(token) as (IPublicClaim | IPrivateClaim) & JwtPayload; if (!issuerDoc) { issuerDoc = await this.document.read(claim.iss); } if (!holderDoc) { holderDoc = await this.document.read(claim.sub); } await this.validateServiceEndpointToken(claimUrl, { hashFns, holderDoc, }); const proofVerifier = new ProofVerifier(issuerDoc); switch (verificationPurpose) { case VerificationPurpose.Authentication: if (await proofVerifier.verifyAuthenticationProof(token)) { return claim; } break; case VerificationPurpose.Assertion: if (await proofVerifier.verifyAssertionProof(token)) { return claim; } break; default: break; } throw new Error('Token is not verified'); } /** * @description Verifies that token stored at `claimUrl` is one of the services of `holderDoc`. * * @param claimUrl: url of the published claim * @param params.hashFns: The function used to determine the of hash of the claim * token used in the DID document. Used to verify that the DID document service endpoint * matches the retrieved claim. * @param params.holderDoc: Document in which to search for service endpoint. */ async validateServiceEndpointToken( claimUrl: string, { hashFns, holderDoc, }: { hashFns?: { [alg: string]: (data: string) => string }; holderDoc: IDIDDocument; } ) { const token = await this.store.get(claimUrl); const service = holderDoc.service.find( (s) => s.serviceEndpoint === claimUrl ) as IServiceEndpoint; if (!service) { throw new Error( `No service endpoint found for ${claimUrl} in holder DID document` ); } const { hash, hashAlg } = service; const createHash = { ...hashes, ...hashFns }[hashAlg as string]; if (hash !== createHash(token)) { throw new Error(`Claim at ${claimUrl} was changed`); } } }