UNPKG

@credo-ts/core

Version:

<p align="center"> <br /> <img alt="Credo Logo" src="https://github.com/openwallet-foundation/credo-ts/blob/c7886cb8377ceb8ee4efe8d264211e561a75072d/images/credo-logo.png" height="250px" /> </p> <h1 align="center"><b>Credo - Core</b></h1

1 lines • 8.43 kB
{"version":3,"file":"MdocVerificationSessionRecord.mjs","names":[],"sources":["../../../../src/modules/mdoc/repository/MdocVerificationSessionRecord.ts"],"sourcesContent":["import { CredoError } from '../../../error'\nimport { BaseRecord, type TagsBase } from '../../../storage/BaseRecord'\nimport { DateTransformer, JsonTransformer } from '../../../utils'\nimport type { Constructable } from '../../../utils/mixins'\nimport { uuid } from '../../../utils/uuid'\nimport type { MdocDeviceRequestDefinition } from '../MdocOptions'\nimport type { MdocVerificationSessionState } from '../MdocVerificationSessionState'\n\n/**\n * Session transcript of an ISO/IEC TS 18013-7:2025 Annex C (`org-iso-mdoc`) DC API session.\n *\n * DCAPIHandover = [ \"dcapi\", SHA-256(CBOR([encryptionInfoBase64Url, origin])) ]\n */\nexport type MdocIsoDcApiVerificationSessionTranscript = {\n type: 'isoMdocDcApi'\n\n /**\n * Base64url encoded `EncryptionInfo` as sent to the wallet. The exact string matters: the\n * handover hashes this text, not the CBOR it encodes.\n */\n encryptionInfoBase64Url: string\n\n /**\n * Base64url encoded nonce contained in the `EncryptionInfo`. Contained in\n * `encryptionInfoBase64Url` as well, and kept here only so a session can be found by the nonce\n * of the request it was created for.\n */\n nonce: string\n\n /**\n * The origin the response was verified against, hashed into the handover together with the\n * `encryptionInfoBase64Url`. Only known once a response has been verified: the origin is carried\n * neither in the request nor in the response, so it has to be supplied by the verifier.\n */\n origin?: string\n}\n\n/**\n * The protocol-specific state of a verification session: what it takes to reconstruct the session\n * transcript the device response is bound to.\n *\n * This is the only part of a verification session that differs per mdoc protocol, so a new protocol\n * is added by extending this union rather than by widening the record.\n */\nexport type MdocVerificationSessionTranscript = MdocIsoDcApiVerificationSessionTranscript\n\nexport type DefaultMdocVerificationSessionRecordTags = {\n state: MdocVerificationSessionState\n\n /**\n * The mdoc protocol the session uses, from {@link MdocVerificationSessionRecord.sessionTranscript}.\n */\n sessionTranscriptType: MdocVerificationSessionTranscript['type']\n\n /**\n * Base64url encoded nonce of the request, for the protocols that have one. The Annex C response\n * carries no session identifier, so this is an index on the request side only — it cannot be used\n * to correlate a received response to its session.\n */\n nonce?: string\n}\n\nexport interface MdocVerificationSessionRecordProps {\n id?: string\n createdAt?: Date\n tags?: TagsBase\n\n state: MdocVerificationSessionState\n errorMessage?: string\n\n deviceRequestBase64Url: string\n deviceRequestDefinition: MdocDeviceRequestDefinition\n sessionTranscript: MdocVerificationSessionTranscript\n\n sessionKeyId: string\n expiresAt: Date\n}\n\n/**\n * A verification session for an mdoc presentation, currently the ISO/IEC TS 18013-7:2025 Annex C\n * (`org-iso-mdoc`) DC API.\n *\n * The device response is never persisted. It contains the disclosed claims, and the caller already\n * has it — for the DC API the exchange is synchronous, so the response is returned to the caller\n * rather than delivered out of band.\n */\nexport class MdocVerificationSessionRecord extends BaseRecord<DefaultMdocVerificationSessionRecordTags> {\n public static readonly type = 'MdocVerificationSessionRecord'\n public readonly type = MdocVerificationSessionRecord.type\n\n public state!: MdocVerificationSessionState\n\n /**\n * Error message of the error that occurred, set when state is {@link MdocVerificationSessionState.Error}.\n */\n public errorMessage?: string\n\n /**\n * Base64url encoded `DeviceRequest` as sent to the wallet.\n *\n * Only bound to the device response when the request was created with reader authentication.\n * Without reader auth the `DeviceRequest` is not covered by the session transcript, so it is a\n * record of what this agent asked for, not cryptographic evidence of it.\n */\n public deviceRequestBase64Url!: string\n\n /**\n * The device request as this agent defined it: the requested elements of every doc request, with\n * the options that only apply when matching the device response against it, such as whether an\n * element is optional or may be device signed.\n *\n * The doc requests are in the same order as in `deviceRequestBase64Url`.\n */\n public deviceRequestDefinition!: MdocDeviceRequestDefinition\n\n /**\n * The protocol-specific state needed to reconstruct the session transcript, and the protocol the\n * session uses.\n */\n public sessionTranscript!: MdocVerificationSessionTranscript\n\n /**\n * Key id of the ephemeral key this agent created for the session. For the DC API this is the\n * recipient key the device response is encrypted to.\n *\n * The key outlives the session: it is deleted when the session record is deleted, so a session\n * can be inspected and its response re-processed for as long as the record is kept.\n */\n public sessionKeyId!: string\n\n @DateTransformer()\n public expiresAt!: Date\n\n public constructor(props: MdocVerificationSessionRecordProps) {\n super()\n\n if (props) {\n this.id = props.id ?? uuid()\n this.createdAt = props.createdAt ?? new Date()\n this._tags = props.tags ?? {}\n\n this.state = props.state\n this.errorMessage = props.errorMessage\n this.deviceRequestBase64Url = props.deviceRequestBase64Url\n this.deviceRequestDefinition = props.deviceRequestDefinition\n this.sessionTranscript = props.sessionTranscript\n this.sessionKeyId = props.sessionKeyId\n this.expiresAt = props.expiresAt\n }\n }\n\n /**\n * The session transcript, asserted to be of a specific protocol.\n */\n public getSessionTranscript<Type extends MdocVerificationSessionTranscript['type']>(\n type: Type\n ): Extract<MdocVerificationSessionTranscript, { type: Type }> {\n if (this.sessionTranscript.type !== type) {\n throw new CredoError(\n `MdocVerificationSessionRecord uses mdoc protocol ${this.sessionTranscript.type}, but ${type} was expected.`\n )\n }\n\n return this.sessionTranscript as Extract<MdocVerificationSessionTranscript, { type: Type }>\n }\n\n public assertState(expectedStates: MdocVerificationSessionState | MdocVerificationSessionState[]) {\n const states = Array.isArray(expectedStates) ? expectedStates : [expectedStates]\n\n if (!states.includes(this.state)) {\n throw new CredoError(\n `MdocVerificationSessionRecord is in invalid state ${this.state}. Valid states are: ${states.join(', ')}.`\n )\n }\n }\n\n public get isExpired() {\n return this.expiresAt.getTime() < Date.now()\n }\n\n public getTags() {\n return {\n ...this._tags,\n state: this.state,\n sessionTranscriptType: this.sessionTranscript.type,\n nonce: this.sessionTranscript.nonce,\n }\n }\n\n public clone(): this {\n return JsonTransformer.fromJSON(JsonTransformer.toJSON(this), this.constructor as Constructable<this>)\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;AAsFA,IAAa,gCAAb,MAAa,sCAAsC,WAAqD;CA+CtG,YAAmB,OAA2C;EAC5D,MAAM;EA9CR,KAAgB,OAAO,8BAA8B;EAgDnD,IAAI,OAAO;GACT,KAAK,KAAK,MAAM,MAAM,KAAK;GAC3B,KAAK,YAAY,MAAM,6BAAa,IAAI,KAAK;GAC7C,KAAK,QAAQ,MAAM,QAAQ,CAAC;GAE5B,KAAK,QAAQ,MAAM;GACnB,KAAK,eAAe,MAAM;GAC1B,KAAK,yBAAyB,MAAM;GACpC,KAAK,0BAA0B,MAAM;GACrC,KAAK,oBAAoB,MAAM;GAC/B,KAAK,eAAe,MAAM;GAC1B,KAAK,YAAY,MAAM;EACzB;CACF;;;;CAKA,qBACE,MAC4D;EAC5D,IAAI,KAAK,kBAAkB,SAAS,MAClC,MAAM,IAAI,WACR,oDAAoD,KAAK,kBAAkB,KAAK,QAAQ,KAAK,eAC/F;EAGF,OAAO,KAAK;CACd;CAEA,YAAmB,gBAA+E;EAChG,MAAM,SAAS,MAAM,QAAQ,cAAc,IAAI,iBAAiB,CAAC,cAAc;EAE/E,IAAI,CAAC,OAAO,SAAS,KAAK,KAAK,GAC7B,MAAM,IAAI,WACR,qDAAqD,KAAK,MAAM,sBAAsB,OAAO,KAAK,IAAI,EAAE,EAC1G;CAEJ;CAEA,IAAW,YAAY;EACrB,OAAO,KAAK,UAAU,QAAQ,IAAI,KAAK,IAAI;CAC7C;CAEA,UAAiB;EACf,OAAO;GACL,GAAG,KAAK;GACR,OAAO,KAAK;GACZ,uBAAuB,KAAK,kBAAkB;GAC9C,OAAO,KAAK,kBAAkB;EAChC;CACF;CAEA,QAAqB;EACnB,OAAO,gBAAgB,SAAS,gBAAgB,OAAO,IAAI,GAAG,KAAK,WAAkC;CACvG;AACF;AAzGE,8BAAuB,OAAO;AA2C7B,WAAA,CAAA,gBAAgB,GAAA,mBAAA,eAAA,OAAA,SAAA,cAAA,SAAA,IAAA,CAAA,GAAA,8BAAA,WAAA,aAAA,KAAA,CAAA"}