diff --git a/examples/add-example-Web3Id/package.json b/examples/add-example-Web3Id/package.json index 28449575..2793deb6 100644 --- a/examples/add-example-Web3Id/package.json +++ b/examples/add-example-Web3Id/package.json @@ -8,6 +8,6 @@ "start": "live-server ./index.html --mount=/sdk.js:../../node_modules/@concordium/web-sdk/lib/concordium.min.js --mount=/helpers.js:../../packages/browser-wallet-api-helpers/lib/concordiumHelpers.min.js" }, "dependencies": { - "@concordium/web-sdk": "^6.2.1" + "@concordium/web-sdk": "^6.3.0" } } diff --git a/examples/eSealing/package.json b/examples/eSealing/package.json index e0a8b836..58fea74d 100644 --- a/examples/eSealing/package.json +++ b/examples/eSealing/package.json @@ -5,7 +5,7 @@ "license": "Apache-2.0", "dependencies": { "@concordium/react-components": "^0.3.0", - "@concordium/web-sdk": "^6.2.1", + "@concordium/web-sdk": "^6.3.0", "@thi.ng/leb128": "^2.1.18", "@types/sha256": "^0.2.0", "@walletconnect/types": "^2.1.4", diff --git a/examples/nft-minting/package.json b/examples/nft-minting/package.json index 0c19ae64..9f3ae96a 100644 --- a/examples/nft-minting/package.json +++ b/examples/nft-minting/package.json @@ -3,7 +3,7 @@ "packageManager": "yarn@3.2.0", "dependencies": { "@concordium/browser-wallet-api-helpers": "workspace:^", - "@concordium/web-sdk": "^6.2.1", + "@concordium/web-sdk": "^6.3.0", "cors": "^2.8.5", "express": "^4.18.1", "express-fileupload": "^1.4.0", diff --git a/examples/piggybank/package.json b/examples/piggybank/package.json index 24dc6d26..efd88d6c 100644 --- a/examples/piggybank/package.json +++ b/examples/piggybank/package.json @@ -3,7 +3,7 @@ "packageManager": "yarn@3.2.0", "dependencies": { "@concordium/browser-wallet-api-helpers": "workspace:^", - "@concordium/web-sdk": "^6.2.1", + "@concordium/web-sdk": "^6.3.0", "react": "^18.1.0", "react-dom": "^18.1.0" }, diff --git a/examples/two-step-transfer/package.json b/examples/two-step-transfer/package.json index 6ed259a5..15c1fcc1 100644 --- a/examples/two-step-transfer/package.json +++ b/examples/two-step-transfer/package.json @@ -8,6 +8,6 @@ "start": "live-server ../two-step-transfer/index.html --mount=/sdk.js:../../node_modules/@concordium/web-sdk/lib/concordium.min.js --mount=/helpers.js:../../packages/browser-wallet-api-helpers/lib/concordiumHelpers.min.js" }, "dependencies": { - "@concordium/web-sdk": "^6.2.1" + "@concordium/web-sdk": "^6.3.0" } } diff --git a/examples/voting/package.json b/examples/voting/package.json index 441681f1..6187a3bb 100644 --- a/examples/voting/package.json +++ b/examples/voting/package.json @@ -5,7 +5,7 @@ "packageManager": "yarn@3.2.0", "dependencies": { "@concordium/browser-wallet-api-helpers": "^2.0.0", - "@concordium/web-sdk": "^6.2.1", + "@concordium/web-sdk": "^6.3.0", "bootstrap": "^5.2.1", "cross-env": "^7.0.3", "moment": "^2.29.4", diff --git a/examples/wCCD/package.json b/examples/wCCD/package.json index 2dc7924f..edb97172 100644 --- a/examples/wCCD/package.json +++ b/examples/wCCD/package.json @@ -5,7 +5,7 @@ "license": "Apache-2.0", "dependencies": { "@concordium/react-components": "^0.2.0", - "@concordium/web-sdk": "^6.2.1", + "@concordium/web-sdk": "^6.3.0", "@thi.ng/leb128": "^2.1.18", "@walletconnect/types": "^2.1.4", "mathjs": "^11.4.0", diff --git a/packages/browser-wallet-api-helpers/package.json b/packages/browser-wallet-api-helpers/package.json index 4afcbb53..3c609b62 100644 --- a/packages/browser-wallet-api-helpers/package.json +++ b/packages/browser-wallet-api-helpers/package.json @@ -19,7 +19,7 @@ "url": "https://concordium.com" }, "dependencies": { - "@concordium/web-sdk": "^6.2.1" + "@concordium/web-sdk": "^6.3.0" }, "devDependencies": { "@babel/core": "^7.17.10", diff --git a/packages/browser-wallet-api/package.json b/packages/browser-wallet-api/package.json index ea653959..40179bac 100644 --- a/packages/browser-wallet-api/package.json +++ b/packages/browser-wallet-api/package.json @@ -7,7 +7,7 @@ "license": "Apache-2.0", "dependencies": { "@concordium/browser-wallet-api-helpers": "workspace:^", - "@concordium/common-sdk": "^9.2.1", + "@concordium/common-sdk": "^9.3.0", "@protobuf-ts/grpcweb-transport": "^2.8.2", "@protobuf-ts/runtime-rpc": "^2.8.2", "buffer": "^6.0.3", diff --git a/packages/browser-wallet/CHANGELOG.md b/packages/browser-wallet/CHANGELOG.md index d17d4b43..10e793bc 100644 --- a/packages/browser-wallet/CHANGELOG.md +++ b/packages/browser-wallet/CHANGELOG.md @@ -2,8 +2,14 @@ ## Unreleased +### Changed + +- Update according to the change to AttributeType from the SDK. In particular the timestamp type is now explicit, and therefore we have removed hhe special serialization/parsing of Dates when exporting/import verifiable credentials. + ### Fixed +- Verifiable credentials are now validated according to the schema when being added. This will e.g. block setting an attribute as an integer if the schema defines it as a string. +- Refreshed the schema for credential schemas so that attribute types are now restricted as expected (`string`, `integer` and the special types are allowed). - An issue where credential schemas were not updated with the correct key. ## 1.1.5 diff --git a/packages/browser-wallet/package.json b/packages/browser-wallet/package.json index 74ab31ee..ed66edcd 100644 --- a/packages/browser-wallet/package.json +++ b/packages/browser-wallet/package.json @@ -19,7 +19,7 @@ "dependencies": { "@concordium/browser-wallet-api": "workspace:^", "@concordium/browser-wallet-api-helpers": "workspace:^", - "@concordium/web-sdk": "^6.2.1", + "@concordium/web-sdk": "^6.3.0", "@noble/ed25519": "^1.7.0", "@protobuf-ts/runtime-rpc": "^2.8.2", "@scure/bip39": "^1.1.0", diff --git a/packages/browser-wallet/src/popup/pages/AddWeb3IdCredential/AddWeb3IdCredential.tsx b/packages/browser-wallet/src/popup/pages/AddWeb3IdCredential/AddWeb3IdCredential.tsx index 6d4c86a0..23679e08 100644 --- a/packages/browser-wallet/src/popup/pages/AddWeb3IdCredential/AddWeb3IdCredential.tsx +++ b/packages/browser-wallet/src/popup/pages/AddWeb3IdCredential/AddWeb3IdCredential.tsx @@ -24,6 +24,7 @@ import { fetchLocalization, findNextUnusedVerifiableCredentialIndex, getCredentialRegistryContractAddress, + withIdRemovedFromSchema, } from '@shared/utils/verifiable-credential-helpers'; import { APIVerifiableCredential } from '@concordium/browser-wallet-api-helpers'; import { grpcClientAtom, networkConfigurationAtom } from '@popup/store/settings'; @@ -31,6 +32,7 @@ import { MetadataUrl } from '@concordium/browser-wallet-api-helpers/lib/wallet-a import { parse } from '@shared/utils/payload-helpers'; import { logError } from '@shared/utils/log-helpers'; import { addToastAtom } from '@popup/state'; +import { Schema, Validator } from 'jsonschema'; import { VerifiableCredentialCard } from '../VerifiableCredential/VerifiableCredentialCard'; type Props = { @@ -115,23 +117,32 @@ export default function AddWeb3IdCredential({ onAllow, onReject }: Props) { useEffect(() => { if (schema) { - // Ensure that all attributes required by the schema are in the attributes. If not, then - // the credential should not be allowed to be added. - const missingRequiredAttributeKeys = []; - const requiredAttributes = schema.properties.credentialSubject.properties.attributes.required; - for (const requiredAttribute of requiredAttributes) { - if (!Object.keys(credential.credentialSubject.attributes).includes(requiredAttribute)) { - missingRequiredAttributeKeys.push(requiredAttribute); + // Use the schema to validate the credential. + const validator = new Validator(); + try { + const schemaWithNoId = withIdRemovedFromSchema(schema); + const validationResult = validator.validate( + { credentialSubject: credential.credentialSubject }, + schemaWithNoId as unknown as Schema + ); + if (!validationResult.valid) { + setError(t('error.schemaValidation', { errors: validationResult.errors.toString() })); + setValidationComplete(true); + return; } - } - - if (missingRequiredAttributeKeys.length > 0) { - setError(t('error.attribute.required', { attributeKeys: missingRequiredAttributeKeys })); + } catch (e) { + logError(e); + setError( + t('error.schemaValidation', { + errors: 'An error occurred while attempting to validate credential.', + }) + ); setValidationComplete(true); return; } // Ensure that a credential with more attributes than listed by the schema cannot be added. + // The schema might not check this in the current iteration of schemas (additionalProperties: false). const schemaAttributes = Object.keys(schema.properties.credentialSubject.properties.attributes.properties); for (const credentialAttribute of Object.keys(credential.credentialSubject.attributes)) { if (!schemaAttributes.includes(credentialAttribute)) { diff --git a/packages/browser-wallet/src/popup/pages/AddWeb3IdCredential/i18n/da.ts b/packages/browser-wallet/src/popup/pages/AddWeb3IdCredential/i18n/da.ts index 1e952c59..ee92483c 100644 --- a/packages/browser-wallet/src/popup/pages/AddWeb3IdCredential/i18n/da.ts +++ b/packages/browser-wallet/src/popup/pages/AddWeb3IdCredential/i18n/da.ts @@ -13,6 +13,7 @@ const t: typeof en = { attribute: en.error.attribute, localization: en.error.localization, findingNextIndex: en.error.findingNextIndex, + schemaValidation: en.error.schemaValidation, }, }; diff --git a/packages/browser-wallet/src/popup/pages/AddWeb3IdCredential/i18n/en.ts b/packages/browser-wallet/src/popup/pages/AddWeb3IdCredential/i18n/en.ts index ac24816e..90215cdf 100644 --- a/packages/browser-wallet/src/popup/pages/AddWeb3IdCredential/i18n/en.ts +++ b/packages/browser-wallet/src/popup/pages/AddWeb3IdCredential/i18n/en.ts @@ -14,6 +14,7 @@ const t = { }, localization: 'Failed to get localization', findingNextIndex: 'An error ocurred while attempting to add the credential. Please try again.', + schemaValidation: 'The credential did not validate according to the schema: [{{ errors }}]', }, }; diff --git a/packages/browser-wallet/src/popup/pages/VerifiableCredentialBackup/VerifiableCredentialImport.tsx b/packages/browser-wallet/src/popup/pages/VerifiableCredentialBackup/VerifiableCredentialImport.tsx index 74dd36a9..a981c7e3 100644 --- a/packages/browser-wallet/src/popup/pages/VerifiableCredentialBackup/VerifiableCredentialImport.tsx +++ b/packages/browser-wallet/src/popup/pages/VerifiableCredentialBackup/VerifiableCredentialImport.tsx @@ -15,7 +15,6 @@ import { decrypt } from '@shared/utils/crypto'; import { useHdWallet } from '@popup/shared/utils/account-helpers'; import JSONBigInt from 'json-bigint'; import { FileInput } from '@popup/shared/Form/FileInput'; -import { reviveDateFromTimeStampAttribute } from '@concordium/web-sdk'; import { VerifiableCredentialCardWithStatusFromChain } from '../VerifiableCredential/VerifiableCredentialList'; import { ExportFormat, VerifiableCredentialExport } from './utils'; @@ -47,7 +46,7 @@ async function parseExport(data: EncryptedData, encryptionKey: string): Promise< const backup: ExportFormat = JSONBigInt({ alwaysParseAsBig: true, useNativeBigInt: true, - }).parse(decrypted, reviveDateFromTimeStampAttribute); + }).parse(decrypted); // Change index to number, due to parse changing all numbers to bigints. backup.value.verifiableCredentials = backup.value.verifiableCredentials.map((v) => ({ ...v, diff --git a/packages/browser-wallet/src/popup/pages/VerifiableCredentialBackup/utils.ts b/packages/browser-wallet/src/popup/pages/VerifiableCredentialBackup/utils.ts index 5fc8d814..56cd74ed 100644 --- a/packages/browser-wallet/src/popup/pages/VerifiableCredentialBackup/utils.ts +++ b/packages/browser-wallet/src/popup/pages/VerifiableCredentialBackup/utils.ts @@ -12,7 +12,6 @@ import { import { networkConfigurationAtom } from '@popup/store/settings'; import { saveData } from '@popup/shared/utils/file-helpers'; import { stringify } from 'json-bigint'; -import { replaceDateWithTimeStampAttribute } from '@concordium/web-sdk'; export type VerifiableCredentialExport = { verifiableCredentials: VerifiableCredential[]; @@ -47,7 +46,7 @@ function createExport( // Use json-bigint to serialize bigints as json numbers. // Ensure that Dates are stored as timestamps to not lose typing (otherwise they are serialized as strings). - return encrypt(stringify(exportContent, replaceDateWithTimeStampAttribute), encryptionKey); + return encrypt(stringify(exportContent), encryptionKey); } export function useVerifiableCredentialExport() { diff --git a/packages/browser-wallet/src/popup/pages/Web3ProofRequest/Display/DisplayStatementLine.tsx b/packages/browser-wallet/src/popup/pages/Web3ProofRequest/Display/DisplayStatementLine.tsx index 1eb9b81d..ab84a9d7 100644 --- a/packages/browser-wallet/src/popup/pages/Web3ProofRequest/Display/DisplayStatementLine.tsx +++ b/packages/browser-wallet/src/popup/pages/Web3ProofRequest/Display/DisplayStatementLine.tsx @@ -20,9 +20,9 @@ export function DisplayStatementLine({ attribute, value, isRequirementMet, class