Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: Wallet & Portal Bugs #745

Merged
merged 5 commits into from
Sep 13, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -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';
Expand Down Expand Up @@ -115,11 +115,11 @@ export default function IssueSection() {
<span> Authentication Method</span>
</div>
</div>
<Dropdown
values={AuthenticationMethods}
selected={selectedAuthenticationMethod}
setSelected={setSelectedAuthenticationMethod}
/>
<Dropdown
values={AuthenticationMethods}
selected={selectedAuthenticationMethod}
setSelected={setSelectedAuthenticationMethod}
/>
</div>
<div className="mt-3 flex flex-col sm:flex-row justify-between">
<div className="">
Expand Down Expand Up @@ -155,16 +155,16 @@ export default function IssueSection() {
</div>

<div className="mt-1 flex flex-col sm:flex-row justify-between">
<div className="">
<div className="">
<Checkbox value={requireVpProfile} onChange={setRequireVpProfile}>
VP Token Requested Profile
</Checkbox>
</div>
<Dropdown
values={VpProfiles}
selected={selectedVpProfile}
setSelected={setSelectedVpProfile}
/>
<Dropdown
values={VpProfiles}
selected={selectedVpProfile}
setSelected={setSelectedVpProfile}
/>
</div>

<hr className="my-5" />
Expand All @@ -173,7 +173,11 @@ export default function IssueSection() {
Cancel
</Button>
<Button
disabled={!(credentialsToIssue.length > 0 && (credentialsToIssue.length < 2 || credentialsToIssue.filter((cred) => cred.selectedFormat === "SD-JWT + VCDM").length === 0))}
disabled={!(credentialsToIssue.length > 0 && (
credentialsToIssue.length < 2 ||
credentialsToIssue.filter((cred) => cred.selectedFormat === "SD-JWT + W3C VC" || cred.selectedFormat === "SD-JWT + IETF SD-JWT VC").length === credentialsToIssue.length ||
credentialsToIssue.filter((cred) => !cred.selectedFormat || cred.selectedFormat === "JWT + W3C VC").length === credentialsToIssue.length
))}
onClick={handleIssue}>Issue</Button>
</div>
<div className="flex flex-col items-center mt-12">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down
124 changes: 47 additions & 77 deletions waltid-applications/waltid-web-portal/utils/getOfferUrl.tsx
Original file line number Diff line number Diff line change
@@ -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<AvailableCredential>, NEXT_PUBLIC_VC_REPO: string, NEXT_PUBLIC_ISSUER: string, authenticationMethod?: string, vpRequestValue?: string, vpProfile?: string) => {
const getOfferUrl = async (credentials: Array<AvailableCredential>, 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 },
Expand All @@ -35,27 +29,13 @@ const getOfferUrl = async (credentials: Array<AvailableCredential>, 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: "<uuid>",
iat: "<timestamp-seconds>",
nbf: "<timestamp-seconds>",
exp: "<timestamp-in-seconds:365d>"
};

// Hack - remove the following fields as they used for w3c only
delete payload.credentialData["@context"];
Expand All @@ -66,80 +46,70 @@ const getOfferUrl = async (credentials: Array<AvailableCredential>, 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: "<uuid>",
iat: "<timestamp-seconds>",
nbf: "<timestamp-seconds>",
exp: "<timestamp-in-seconds:365d>"
};

payload.credentialConfigurationId = Object.keys(credential_configurations_supported).find(key => key === c.id + "_vc+sd-jwt") as string;

interface SelectiveDisclosureField {
sd: boolean;
children: {
fields: Record<string, any>;
};
}

const selectiveDisclosure: {
fields: Record<string, SelectiveDisclosureField>;
} = {
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]);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@
d="M15 19l-7-7 7-7" />
</svg>
</button>
<VerifiableCredentialCard :credential="{
<VerifiableCredentialCard :key="index" :credential="{
parsedDocument: {
type: [credentialTypes[index]],
issuer: {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -175,7 +175,7 @@ export default defineNuxtConfig({
projectId: process.env.ProjectId,
issuerCallbackUrl: "http://localhost:7100",
credentialsRepositoryUrl: "http://localhost:3000",
devWalletUrl: "https://wallet-dev.walt.id",
demoWalletUrl: "https://wallet-dev.walt.id",
}
},

Expand Down
7 changes: 4 additions & 3 deletions waltid-services/waltid-wallet-api/k8s/deployment-dev.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -164,7 +164,7 @@ spec:
- name: NUXT_PUBLIC_DEMO_WALLET_URL
value: "https://wallet.walt-test.cloud"
ports:
- containerPort: 7101
- containerPort: 7104
name: http-api
---
kind: Deployment
Expand All @@ -190,7 +190,7 @@ spec:
env:
- name: NUXT_PUBLIC_ISSUER_CALLBACK_URL
value: "https://wallet.walt-test.cloud"
- name: NUXT_PUBLIC_DEMO_WALLET_URL
- name: NUXT_PUBLIC_DEV_WALLET_URL
value: "https://wallet-dev.walt-test.cloud"
- name: NUXT_PUBLIC_CREDENTIALS_REPOSITORY_URL
value: "https://vc-repo.walt-test.cloud"
Expand Down Expand Up @@ -239,9 +239,10 @@ spec:
tls:
- hosts:
- wallet.walt-test.cloud
secretName: test-wallet-demo-tls-secret
- hosts:
- wallet-dev.walt-test.cloud
secretName: wallet-tls-secret
secretName: test-wallet-dev-tls-secret
rules:
- host: wallet-dev.walt-test.cloud
http:
Expand Down
4 changes: 2 additions & 2 deletions waltid-services/waltid-wallet-api/k8s/deployment-prod.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -162,7 +162,7 @@ spec:
- name: NUXT_PUBLIC_DEMO_WALLET_URL
value: "https://wallet.walt.id"
ports:
- containerPort: 7101
- containerPort: 7104
name: http-api
---
kind: Service
Expand Down Expand Up @@ -200,7 +200,7 @@ spec:
env:
- name: NUXT_PUBLIC_ISSUER_CALLBACK_URL
value: "https://wallet.walt.id"
- name: NUXT_PUBLIC_DEMO_WALLET_URL
- name: NUXT_PUBLIC_DEV_WALLET_URL
value: "https://wallet-dev.walt.id"
- name: NUXT_PUBLIC_CREDENTIALS_REPOSITORY_URL
value: "https://credentials.walt.id"
Expand Down
Loading