From 5af7c3da29c0dca2b5f62b885640e4bc0afe32f9 Mon Sep 17 00:00:00 2001 From: Jesse van Muijden Date: Wed, 4 Jun 2025 06:01:29 -0400 Subject: [PATCH 1/2] feat(display): hardcoded display of AcademicEnrollmentCredential name and issuer --- src/components/Credentials/CredentialInfo.js | 4 +++- src/context/ContainerContext.tsx | 1 + 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/src/components/Credentials/CredentialInfo.js b/src/components/Credentials/CredentialInfo.js index df0361a2b..be69682b4 100644 --- a/src/components/Credentials/CredentialInfo.js +++ b/src/components/Credentials/CredentialInfo.js @@ -60,6 +60,7 @@ const CredentialInfo = ({ credential, mainClassName = "text-sm lg:text-base w-fu const { isOnline } = useContext(StatusContext); const [parsedCredential, setParsedCredential] = useState(null); const [credentialFormat, setCredentialFormat] = useState(''); + const [issuerName, setIssuerName] = useState(''); const [credentialSubjectRows, setCredentialSubjectRows] = useState([]); const container = useContext(ContainerContext); const { api } = useContext(SessionContext); @@ -84,6 +85,7 @@ const CredentialInfo = ({ credential, mainClassName = "text-sm lg:text-base w-fu } setParsedCredential(c.beautifiedForm); + setIssuerName(c.beautifiedForm.issuer?.name || ''); let iss = c.beautifiedForm.iss; @@ -212,7 +214,7 @@ const CredentialInfo = ({ credential, mainClassName = "text-sm lg:text-base w-fu {!credentialSubjectRows.some(row => row.name === 'institution') && renderRow('institution', 'Institution', parsedCredential?.vc?.credentialSubject?.institution, screenType)} {!credentialSubjectRows.some(row => row.name === 'valid_from') && renderRow('valid_from', 'Valid from', parsedCredential?.vc?.credentialSubject?.valid_from, screenType)} {!credentialSubjectRows.some(row => row.name === 'valid_until') && renderRow('valid_until', 'Valid until', parsedCredential?.vc?.credentialSubject?.valid_until, screenType)} - {!credentialSubjectRows.some(row => row.name === 'issuer') && renderRow('issuer', 'Issuer', parsedCredential?.vc?.credentialSubject?.issuer, screenType)} + {!credentialSubjectRows.some(row => row.name === 'issuer') && renderRow('issuer', 'Issuer', parsedCredential?.vc?.credentialSubject?.issuer || issuerName, screenType)} ) } diff --git a/src/context/ContainerContext.tsx b/src/context/ContainerContext.tsx index 7e9b2e8be..a183e486c 100644 --- a/src/context/ContainerContext.tsx +++ b/src/context/ContainerContext.tsx @@ -269,6 +269,7 @@ export const ContainerContextProvider = ({ children }) => { if (isOpenBadgeCredential) return beautifiedForm.credentialSubject.achievement.name; if (t.includes('SupportCredential') || t.includes('ExamEnrollmentCredential')) return beautifiedForm.credentialSubject.title; + if (t.includes('AcademicEnrollmentCredential')) return beautifiedForm.credentialSubject.name; if (storedCredentialConfigurationId === 'EduID') return 'eduID' return result.beautifiedForm.name || credentialConfiguration?.display?.[0]?.name || 'Credential'; From fb9a5c2a880e2cc9f18a6b45c3674055c0cad021 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C3=A8r=20Kessels?= Date: Fri, 6 Jun 2025 15:59:35 +0200 Subject: [PATCH 2/2] feat: Make the token exchange in pre-authorized-code-flow with a form-encoded request The spec https://www.rfc-editor.org/rfc/rfc6749.html#section-4.1.3 explicitly mentions it must be a form-encoded request. One of our issuers - veramo-core - only handles form-encoded token requests in the pre-authorized-code-flow when done with such a form-encoded body and header. --- .../services/pre-authorized-code-flow.service.ts | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/src/lib/services/pre-authorized-code-flow.service.ts b/src/lib/services/pre-authorized-code-flow.service.ts index 3ab34409a..c20b9ccc6 100644 --- a/src/lib/services/pre-authorized-code-flow.service.ts +++ b/src/lib/services/pre-authorized-code-flow.service.ts @@ -19,15 +19,17 @@ export const getToken = async ( preAuthorizedCode: string, pin: string = '', ): Promise => { + const bodyFormEncoded = new URLSearchParams({ + grant_type: FIELD_PRE_AUTHORIZED_CODE_GRANT_TYPE, + 'pre-authorized_code': preAuthorizedCode, + user_pin: pin || undefined, + }).toString(); + const response = await ProxyClient.post( `${credentialIssuer}${PATH_TOKEN}`, + bodyFormEncoded, { - grant_type: FIELD_PRE_AUTHORIZED_CODE_GRANT_TYPE, - 'pre-authorized_code': preAuthorizedCode, - user_pin: pin || undefined, - }, - { - 'Content-Type': 'application/json', + 'Content-Type': 'application/x-www-form-urlencoded', }, ) as ProxyResponseData;