autogram-sdk
Version:
SDK for Autogram signer
1 lines • 22.6 kB
Source Map (JSON)
{"version":3,"sources":["../src/avm-api/lib/apiClient.ts"],"sourcesContent":["// import fetch from \"cross-fetch\";\nimport { SignJWT } from \"jose\";\nimport z from \"zod\";\nimport { paths } from \"./avm-api.generated\";\nimport { Base64 } from \"js-base64\";\n\nexport interface AvmIntegrationDocument {\n guid: string | null;\n encryptionKey: string | null;\n lastModified: string | null;\n}\n\n/**\n * Stateful integration with Autogram v mobile\n */\nexport class AutogramVMobileIntegration\n implements AutogramVMobileIntegrationInterface\n{\n private apiClient: AutogramVMobileIntegrationApiClient;\n\n /**\n * Key pair for encrypting documents sent to the server\n */\n private keyPair: CryptoKeyPair | null = null;\n /**\n * GUID of the integration - assigned by server\n */\n private integrationGuid: string | null = null;\n\n private _subtleCrypto: SubtleCrypto | null = null;\n private get subtleCrypto() {\n if (!this._subtleCrypto) {\n throw new Error(\"SubtleCrypto not available\");\n }\n return this._subtleCrypto;\n }\n\n private db: DBInterface;\n\n public constructor(db: DBInterface) {\n this.apiClient = new AutogramVMobileIntegrationApiClient();\n this.db = db;\n }\n\n public async loadOrRegister() {\n this.loadSubtleCrypto();\n // load\n this.keyPair = await this.getKeyPairFromDb();\n\n this.integrationGuid = await this.getIntegrationGuidFromDb();\n console.log(this.keyPair);\n\n if (!this.keyPair || !this.integrationGuid) {\n await this.register();\n }\n\n console.log(\"keys init\", {\n public: await this.getPublicKeyStr(),\n guid: this.integrationGuid,\n });\n }\n\n public async getQrCodeUrl(\n doc: AvmIntegrationDocument,\n enableIntegration = false\n ) {\n if (!this.integrationGuid) {\n throw new Error(\"Integration guid missing\");\n }\n\n if (!doc.guid || !doc.encryptionKey) {\n console.log(doc);\n throw new Error(\"Document guid or key missing\");\n }\n\n let integrationObj = {};\n if (enableIntegration) {\n const integration = await this.getIntegrationBearerToken(true);\n console.log(\"Integration JWT\", integration);\n integrationObj = { integration: integration };\n }\n\n return this.apiClient.qrCodeUrl({\n guid: doc.guid,\n key: doc.encryptionKey,\n ...integrationObj,\n });\n }\n\n private async register() {\n if (this.keyPair && this.integrationGuid) {\n throw new Error(\"Already registered.\");\n }\n\n await this.generateKeys();\n\n const publicKey = await this.getPublicKeyStr();\n\n console.log(\"Registering integration\", publicKey);\n\n const res = await this.apiClient.registerIntegration({\n platform: \"extension\",\n displayName: \"Autogram Extension\",\n publicKey:\n \"-----BEGIN PUBLIC KEY-----\\n\" +\n publicKey +\n \"\\n-----END PUBLIC KEY-----\",\n });\n\n this.integrationGuid = res.guid;\n await this.saveIntegrationGuid(res.guid);\n\n console.log(\"Integration registered\", res);\n }\n\n public async addDocument(\n document: DocumentToSign\n ): Promise<AvmIntegrationDocument> {\n // TODO zatial funguje iba pre jeden dokument\n const encryptionKey = await this.initDocumentKey();\n console.log(\"Sending document\", document);\n const res = await this.apiClient.postDocuments(\n document,\n await this.getIntegrationBearerToken(),\n encryptionKey\n );\n return {\n guid: res.guid,\n encryptionKey: encryptionKey,\n lastModified: res.lastModified,\n };\n }\n\n public async waitForSignature(\n documentRef: AvmIntegrationDocument,\n abortController: AbortController\n ): Promise<SignedDocument> {\n if (\n !documentRef.guid ||\n !documentRef.encryptionKey ||\n !documentRef.lastModified\n ) {\n console.log(documentRef);\n throw new Error(\"Document guid, key or last-modified missing\");\n }\n\n this.apiClient.signRequest(\n {\n documentGuid: documentRef.guid,\n documentEncryptionKey: documentRef.encryptionKey,\n },\n await this.getIntegrationBearerToken()\n );\n\n while (!abortController.signal.aborted) {\n const documentResult = await this.apiClient.getDocument(\n { guid: documentRef.guid },\n documentRef.encryptionKey,\n documentRef.lastModified\n );\n console.log(documentResult);\n if (documentResult.status === \"signed\") {\n return documentResult.document;\n } else if (documentResult.status === \"pending\") {\n // wait\n }\n await wait(1000);\n }\n throw new Error(\"Aborted\");\n }\n\n // private methods\n\n private async loadSubtleCrypto() {\n // We are doing this because of testing in jest jsdom\n if (!this._subtleCrypto) {\n const browserSubtle = globalThis.crypto.subtle;\n if (browserSubtle) {\n this._subtleCrypto = browserSubtle;\n return;\n }\n\n try {\n const crypto = await import(\"crypto\");\n // @ts-expect-error crypto\n this._subtleCrypto = crypto.webcrypto.subtle;\n return;\n } catch (e) {\n throw new Error(\"SubtleCrypto not available\");\n }\n }\n }\n\n private async getIntegrationBearerToken(withDevice = false) {\n if (!this.keyPair) {\n throw new Error(\"Key pair missing\");\n }\n if (!this.integrationGuid) {\n throw new Error(\"Integration guid missing\");\n }\n let jwt = new SignJWT({\n // aud: \"device\",\n // sub: this.integrationGuid,\n // exp: Math.floor(Date.now() / 1000) + 60,\n })\n .setProtectedHeader({ alg: \"ES256\" })\n .setJti(randomUUID())\n .setSubject(this.integrationGuid);\n\n if (withDevice) {\n jwt = jwt.setAudience(\"device\");\n }\n\n jwt = jwt.setExpirationTime(\"5min\");\n return jwt.sign(this.keyPair.privateKey);\n }\n\n private exportRawBase64(key: CryptoKey): Promise<string> {\n return this.subtleCrypto.exportKey(\"raw\", key).then(arrayBufferToBase64);\n }\n\n private async generateKeys() {\n console.log(\"Generating keys\");\n // ES256\n const keyPair = await this.subtleCrypto.generateKey(\n {\n name: \"ECDSA\",\n namedCurve: \"P-256\",\n },\n true,\n [\"sign\", \"verify\"]\n );\n console.log(\"Key pair generated\", keyPair);\n await this.saveKeyPair(keyPair);\n this.keyPair = keyPair;\n console.log(\"Keys generated\", this.keyPair);\n }\n\n private async saveKeyPair(keyPair: CryptoKeyPair) {\n return this.db.set(\"keyPair\", keyPair); // TODO: toto je zle, lebo zapisujeme v kontexte webu, nie rozsirenia\n }\n\n private async getKeyPairFromDb(): Promise<CryptoKeyPair | null> {\n return this.db.get(\"keyPair\").then((keyPair) => {\n if (keyPair) {\n return keyPair;\n }\n return null;\n });\n }\n\n private async saveIntegrationGuid(guid: string) {\n return this.db.set(\"integrationGuid\", guid);\n }\n\n private async getIntegrationGuidFromDb(): Promise<string | null> {\n return this.db.get(\"integrationGuid\").then((guid) => {\n if (guid) {\n return guid;\n }\n return null;\n });\n }\n\n private async getPublicKeyStr() {\n if (!this.keyPair) {\n throw new Error(\"Key pair missing\");\n }\n return this.subtleCrypto\n .exportKey(\"spki\", this.keyPair.publicKey)\n .then(arrayBufferToBase64);\n }\n\n private async initDocumentKey() {\n const documentKey = await this.subtleCrypto.generateKey(\n {\n name: \"AES-GCM\",\n length: 256,\n },\n true,\n [\"encrypt\", \"decrypt\"]\n );\n return await this.exportRawBase64(documentKey);\n }\n}\n\nexport interface AutogramVMobileIntegrationInterface {\n loadOrRegister(): Promise<void>;\n getQrCodeUrl(doc: AvmIntegrationDocument): Promise<string>;\n addDocument(documentToSign: DocumentToSign): Promise<AvmIntegrationDocument>;\n waitForSignature(\n doc: AvmIntegrationDocument,\n abortController?: AbortController\n ): Promise<SignedDocument>;\n}\n\nexport interface AutogramVMobileIntegrationInterfaceStateful {\n init(): Promise<void>;\n loadOrRegister(): Promise<void>;\n getQrCodeUrl(): Promise<string>;\n addDocument(documentToSign: DocumentToSign): Promise<void>;\n waitForSignature(abortController?: AbortController): Promise<SignedDocument>;\n reset(): Promise<void>;\n}\n\n/**\n * Client for the Autogram v mobile server API\n */\nexport class AutogramVMobileIntegrationApiClient {\n baseUrl: string;\n constructor() {\n this.baseUrl = \"https://autogram.slovensko.digital/api/v1\";\n }\n\n _registerIntegration = \"/integrations\" as const;\n registerIntegration(\n data: NonNullable<\n paths[typeof this._registerIntegration][\"post\"][\"requestBody\"]\n >[\"content\"][\"application/json\"]\n ): Promise<z.infer<typeof PostIntegrationResponse>> {\n const requestBody = JSON.stringify(data);\n const url = this.baseUrl + this._registerIntegration;\n console.log(\"Registering integration\", { url, requestBody });\n return (\n fetch(url, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n },\n body: requestBody,\n })\n .then(async (res) => {\n const text = await res.text();\n console.log(\"Integration registration response\", {\n text,\n status: res.status,\n statusText: res.statusText,\n });\n return JSON.parse(text);\n })\n // .then((res) => res.json())\n .catch((err) => {\n console.error(\"Integration registration failed\", err);\n throw err;\n })\n .then((res) => PostIntegrationResponse.parse(res))\n );\n }\n\n _getIntegrationDevices = \"/integration-devices\" as const;\n getIntegrationDevices() {\n return fetch(this.baseUrl + this._getIntegrationDevices, {\n method: \"GET\",\n }).then((res) => GetIntegrationDevicesResponseBody.parse(res.json()));\n }\n\n _documents = \"/documents\" as const;\n async postDocuments(\n data: NonNullable<\n paths[typeof this._documents][\"post\"][\"requestBody\"]\n >[\"content\"][\"application/json\"],\n bearerToken: string,\n documentEncryptionKey: string\n ) {\n if (!documentEncryptionKey) {\n throw new Error(\"Document encryption key missing\");\n }\n if (!bearerToken) {\n throw new Error(\"Bearer token missing\");\n }\n const res = await fetch(this.baseUrl + this._documents, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n Authorization: \"Bearer \" + bearerToken,\n \"X-Encryption-Key\": documentEncryptionKey,\n },\n body: JSON.stringify(data),\n });\n\n if (res.status !== 200) {\n console.log(\"API Error\", res.status, res.statusText);\n const json = await res.json();\n throw new Error(JSON.stringify(ApiErrorResponse.parse(json)));\n }\n const json = await res.json();\n return {\n ...PostDocumentsResponse.parse(json),\n lastModified: res.headers.get(\"Last-Modified\"),\n };\n }\n\n _getDocument = \"/documents/{guid}\" as const;\n async getDocument(\n params: paths[typeof this._getDocument][\"get\"][\"parameters\"][\"path\"],\n documentEncryptionKey: string,\n documentLastModified?: string\n ): Promise<GetDocumentResult> {\n if (!documentEncryptionKey) {\n throw new Error(\"Document encryption key missing\");\n }\n const res = await fetch(\n this.baseUrl + this._getDocument.replace(\"{guid}\", params.guid),\n {\n method: \"GET\",\n headers: {\n \"Content-Type\": \"application/json\",\n Accept: \"application/json\",\n \"X-Encryption-Key\": documentEncryptionKey,\n ...(documentLastModified\n ? { \"If-Modified-Since\": documentLastModified }\n : null),\n },\n }\n );\n if (res.status == 304) {\n return { status: \"pending\" };\n }\n if (res.status != 200) {\n const error = ApiErrorResponse.parse(await res.json());\n console.error(\"API Error\", error);\n throw new Error(JSON.stringify(error));\n }\n\n const resJson = await res.json();\n return {\n status: \"signed\",\n document: GetDocumentsResponse.parse(resJson),\n };\n }\n\n _signRequest = \"/sign-request\" as const;\n signRequest(\n data: NonNullable<\n paths[typeof this._signRequest][\"post\"][\"requestBody\"]\n >[\"content\"][\"application/json\"],\n bearerToken: string\n ) {\n return fetch(this.baseUrl + this._signRequest, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n Authorization: `Bearer ${bearerToken}`,\n },\n body: JSON.stringify(data),\n }).then((res) => res.json());\n }\n\n _getQrCodeUrl = \"/qr-code\" as const;\n qrCodeUrl(\n data: paths[typeof this._getQrCodeUrl][\"get\"][\"parameters\"][\"query\"]\n ) {\n return (\n this.baseUrl +\n this._getQrCodeUrl +\n \"?\" +\n new URLSearchParams(data).toString()\n );\n }\n}\n\n// Zod Types\n\nexport const PostIntegrationResponse = z.object({\n guid: z.string(),\n});\n\nexport const GetIntegrationDevicesResponseBody = z.array(\n z.object({\n deviceId: z.string(),\n platform: z.string(),\n displayName: z.string(),\n })\n);\n\nexport const PostDocumentsResponse = z.object({\n guid: z.string(),\n});\n\nexport const ApiErrorResponse = z.object({\n code: z.string(),\n message: z.string(),\n details: z.string().optional(),\n});\n\nexport const GetDocumentsResponse = z.object({\n filename: z.string(),\n mimeType: z.string(),\n content: z.string(),\n signers: z\n .array(\n z.object({\n signedBy: z.string().optional(),\n issuedBy: z.string().optional(),\n })\n )\n .optional(),\n});\n\n// Types\n\n/**\n * Interface for a key-value store used for persisting integration's state\n */\nexport interface DBInterface {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n set: (key: IDBValidKey, value: any) => Promise<void>;\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n get<T = any>(key: IDBValidKey): Promise<T | undefined>;\n}\n\nexport type DocumentToSign = NonNullable<\n paths[\"/documents\"][\"post\"][\"requestBody\"]\n>[\"content\"][\"application/json\"];\n\nexport type SignedDocument = z.infer<typeof GetDocumentsResponse>;\ntype GetDocumentResult =\n | {\n status: \"pending\";\n }\n | {\n status: \"signed\";\n document: SignedDocument;\n };\n\n// Helper functions\n\nfunction arrayBufferToBase64(buffer: ArrayBuffer): string {\n return Base64.fromUint8Array(new Uint8Array(buffer));\n // return btoa(String.fromCharCode.apply(null, new Uint8Array(buffer)));\n}\n\nexport function randomUUID() {\n return globalThis.crypto.randomUUID();\n}\n\nasync function wait(ms: number) {\n return new Promise((resolve) => setTimeout(resolve, ms));\n}\n"],"mappings":"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","names":["SignJWT","z","Base64","AutogramVMobileIntegration","db","AutogramVMobileIntegrationApiClient","__async","doc","enableIntegration","integrationObj","integration","__spreadValues","publicKey","res","document","encryptionKey","documentRef","abortController","documentResult","wait","browserSubtle","crypto","withDevice","jwt","SignJWT","randomUUID","key","arrayBufferToBase64","keyPair","guid","documentKey","data","requestBody","url","text","err","PostIntegrationResponse","GetIntegrationDevicesResponseBody","bearerToken","documentEncryptionKey","json","ApiErrorResponse","__spreadProps","PostDocumentsResponse","params","documentLastModified","error","resJson","GetDocumentsResponse","z","buffer","Base64","ms","resolve"]}