diff --git a/waltid-applications/waltid-web-portal/components/sections/IssueSection.tsx b/waltid-applications/waltid-web-portal/components/sections/IssueSection.tsx index d01607867..1b6275b4c 100644 --- a/waltid-applications/waltid-web-portal/components/sections/IssueSection.tsx +++ b/waltid-applications/waltid-web-portal/components/sections/IssueSection.tsx @@ -1,6 +1,6 @@ import RowCredential from '@/components/walt/credential/RowCredential'; import Dropdown from '@/components/walt/forms/Dropdown'; -import {AuthenticationMethods, VpProfiles} from '@/types/credentials' +import { AuthenticationMethods, VpProfiles } from '@/types/credentials' import Checkbox from '@/components/walt/forms/Checkbox'; import InputField from '@/components/walt/forms/Input'; import Button from '@/components/walt/button/Button'; @@ -115,11 +115,11 @@ export default function IssueSection() { Authentication Method - +
@@ -155,16 +155,16 @@ export default function IssueSection() {
-
+
VP Token Requested Profile
- +

@@ -173,7 +173,11 @@ export default function IssueSection() { Cancel
diff --git a/waltid-applications/waltid-web-portal/components/walt/forms/Checkbox.tsx b/waltid-applications/waltid-web-portal/components/walt/forms/Checkbox.tsx index f1f976030..cdbc52100 100644 --- a/waltid-applications/waltid-web-portal/components/walt/forms/Checkbox.tsx +++ b/waltid-applications/waltid-web-portal/components/walt/forms/Checkbox.tsx @@ -22,7 +22,7 @@ export default function Checkbox({ name="comments" type="checkbox" checked={value} - onClick={() => { + onChange={() => { onChange(!value); }} className="h-4 w-4 rounded border-gray-300 text-indigo-600 focus:ring-indigo-600" diff --git a/waltid-applications/waltid-web-portal/utils/getOfferUrl.tsx b/waltid-applications/waltid-web-portal/utils/getOfferUrl.tsx index b690790a4..7f9893524 100644 --- a/waltid-applications/waltid-web-portal/utils/getOfferUrl.tsx +++ b/waltid-applications/waltid-web-portal/utils/getOfferUrl.tsx @@ -1,23 +1,17 @@ import axios from 'axios'; import { v4 as uuidv4 } from 'uuid'; -import {AvailableCredential, CredentialFormats, DIDMethods, DIDMethodsConfig} from '@/types/credentials'; +import { AvailableCredential, CredentialFormats, DIDMethods, DIDMethodsConfig } from '@/types/credentials'; -const getOfferUrl = async (credentials: Array, NEXT_PUBLIC_VC_REPO: string, NEXT_PUBLIC_ISSUER: string, authenticationMethod?: string, vpRequestValue?: string, vpProfile?: string) => { +const getOfferUrl = async (credentials: Array, NEXT_PUBLIC_VC_REPO: string, NEXT_PUBLIC_ISSUER: string, authenticationMethod?: string, vpRequestValue?: string, vpProfile?: string) => { const data = await fetch(`${NEXT_PUBLIC_ISSUER}/.well-known/openid-credential-issuer`).then(data => { return data.json(); }); const credential_configurations_supported = data.credential_configurations_supported; const payload = await Promise.all(credentials.map(async (c) => { - c = {...c, selectedFormat: c.selectedFormat ?? CredentialFormats[0], selectedDID: c.selectedDID ?? DIDMethods[0]}; + c = { ...c, selectedFormat: c.selectedFormat ?? CredentialFormats[0], selectedDID: c.selectedDID ?? DIDMethods[0] }; const offer = { ...c.offer, id: uuidv4() }; - const mapping = await (await fetch(`${NEXT_PUBLIC_VC_REPO}/api/mapping/${c.id}`).then(data => { - return data.json(); - }).catch(err => { - return null; - })); - let payload: { 'issuerDid': string, 'issuerKey': { "type": string, "jwk": object }, @@ -35,27 +29,13 @@ const getOfferUrl = async (credentials: Array, NEXT_PUBLIC_ credentialData: offer } - if (c.selectedFormat === "SD-JWT + W3C VC") { - payload.selectiveDisclosure = { - "fields": { - "credentialSubject": { - sd: false, - children: { - fields: {} - } - } - } - } - for (const key in offer.credentialSubject) { - if (typeof offer.credentialSubject[key] === 'string') { - payload.selectiveDisclosure.fields.credentialSubject.children.fields[key] = { - sd: true - } - } - } - } - - if (c.selectedFormat === "SD-JWT + IETF SD-JWT VC"){ + if (c.selectedFormat === "SD-JWT + IETF SD-JWT VC") { + payload.mapping = { + id: "", + iat: "", + nbf: "", + exp: "" + }; // Hack - remove the following fields as they used for w3c only delete payload.credentialData["@context"]; @@ -66,80 +46,70 @@ const getOfferUrl = async (credentials: Array, NEXT_PUBLIC_ delete payload.credentialData["issued"]; delete payload.credentialData["issuer"]; - // Hack - replace the "mapping" object with the new one - // delete payload.mapping; - - payload.mapping = { - id: "", - iat: "", - nbf: "", - exp: "" - }; - payload.credentialConfigurationId = Object.keys(credential_configurations_supported).find(key => key === c.id + "_vc+sd-jwt") as string; - - interface SelectiveDisclosureField { - sd: boolean; - children: { - fields: Record; - }; - } - - const selectiveDisclosure: { - fields: Record; - } = { - fields: {} - }; - + payload.selectiveDisclosure = { "fields": {} } for (const key in offer.credentialSubject) { if (typeof offer.credentialSubject[key] === 'string') { - // Add a field entry for each property in credentialSubject - selectiveDisclosure.fields[key] = { - sd: true, // Default selective disclosure state - children: { - fields: {} // Placeholder for potential future nested fields + payload.selectiveDisclosure.fields[key] = { + sd: true + } + } + } + } + else { + payload.mapping = await (await fetch(`${NEXT_PUBLIC_VC_REPO}/api/mapping/${c.id}`).then(data => { + return data.json(); + }).catch(err => { + return null; + })); + + if (c.selectedFormat === "SD-JWT + W3C VC") { + payload.selectiveDisclosure = { + "fields": { + "credentialSubject": { + sd: false, + children: { + fields: {} + } + } + } + } + for (const key in offer.credentialSubject) { + if (typeof offer.credentialSubject[key] === 'string') { + payload.selectiveDisclosure.fields.credentialSubject.children.fields[key] = { + sd: true } - }; + } } } - - payload.selectiveDisclosure = selectiveDisclosure - } + if (authenticationMethod) { payload.authenticationMethod = authenticationMethod; } - if (vpRequestValue) { payload.vpRequestValue = vpRequestValue; } - if (vpProfile) { payload.vpProfile = vpProfile; } - // If true, return the payload as is - if (credentials[0]?.selectedFormat === "SD-JWT + IETF SD-JWT VC") { - + if (c.selectedFormat === "SD-JWT + IETF SD-JWT VC") { const { credentialSubject, ...restOfCredentialData } = payload.credentialData; // Destructure credentialSubject and the rest - - const updatedPayload = { + return { ...payload, // Keep the rest of the payload unchanged credentialData: { ...restOfCredentialData, // Spread other fields from credentialData (e.g., id, issuer) ...credentialSubject // Spread fields from credentialSubject to the top level of credentialData } }; - - return updatedPayload } - - // Otherwise, return the payload with mapping if mapping exists, or just payload - return mapping ? { ...payload, mapping } : payload; + else { + return payload; + } })); - - const issueUrl = NEXT_PUBLIC_ISSUER + `/openid4vc/${credentials.length === 1 && (credentials[0].selectedFormat === "SD-JWT + W3C VC" || credentials[0].selectedFormat === "SD-JWT + IETF SD-JWT VC") ? "sdjwt" : "jwt"}/${(payload.length > 1 ? 'issueBatch' : 'issue')}`; + const issueUrl = NEXT_PUBLIC_ISSUER + `/openid4vc/${credentials[0].selectedFormat === "SD-JWT + W3C VC" || credentials[0].selectedFormat === "SD-JWT + IETF SD-JWT VC" ? "sdjwt" : "jwt"}/${(payload.length > 1 ? 'issueBatch' : 'issue')}`; return axios.post(issueUrl, payload.length > 1 ? payload : payload[0]); } diff --git a/waltid-applications/waltid-web-wallet/apps/waltid-demo-wallet/src/pages/wallet/[wallet]/exchange/issuance.vue b/waltid-applications/waltid-web-wallet/apps/waltid-demo-wallet/src/pages/wallet/[wallet]/exchange/issuance.vue index e638a4f0c..bc38b422b 100644 --- a/waltid-applications/waltid-web-wallet/apps/waltid-demo-wallet/src/pages/wallet/[wallet]/exchange/issuance.vue +++ b/waltid-applications/waltid-web-wallet/apps/waltid-demo-wallet/src/pages/wallet/[wallet]/exchange/issuance.vue @@ -40,7 +40,7 @@ d="M15 19l-7-7 7-7" /> -