Skip to content

Commit

Permalink
feat: single use credentials for BLE and DCQL (#237)
Browse files Browse the repository at this point in the history
Signed-off-by: Timo Glastra <[email protected]>
  • Loading branch information
TimoGlastra authored Nov 26, 2024
1 parent 9278f84 commit 8c855ce
Show file tree
Hide file tree
Showing 4 changed files with 36 additions and 12 deletions.
21 changes: 16 additions & 5 deletions apps/easypid/src/features/proximity/mdocProximity.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import {
import { TypedArrayEncoder } from '@credo-ts/core'
import { getMdocContext } from '@credo-ts/core/build/modules/mdoc/MdocContext'
import type { EasyPIDAppAgent, FormattedSubmission, MdocRecord } from '@package/agent'
import { handleBatchCredential } from '@package/agent/src/batch'
import { type Permission, PermissionsAndroid, Platform } from 'react-native'

const requireMdocDataTransfer = () =>
Expand Down Expand Up @@ -83,12 +84,22 @@ export const shareDeviceResponse = async (options: ShareDeviceResponseOptions) =
throw new Error('Not all requirements are satisfied')
}

const issuerSignedDocuments = options.submission.entries.map((e) => {
if (!e.isSatisfied) throw new Error(`Requirement for doctype ${e.inputDescriptorId} not satisfied`)
if (options.submission.entries.length > 1) {
throw new Error('Only one mdoc supported at the moment due to only being able to sign with one device key')
}

const issuerSignedDocuments = await Promise.all(
options.submission.entries.map(async (e) => {
if (!e.isSatisfied) throw new Error(`Requirement for doctype ${e.inputDescriptorId} not satisfied`)

const credential = e.credentials[0].credential.record as MdocRecord

// Optionally handle batch issuance
const credentialRecord = await handleBatchCredential(options.agent, credential)

const credential = e.credentials[0].credential.record as MdocRecord
return parseIssuerSigned(TypedArrayEncoder.fromBase64(credential.base64Url), credential.getTags().docType)
})
return parseIssuerSigned(TypedArrayEncoder.fromBase64(credentialRecord.base64Url), credential.getTags().docType)
})
)

const mdoc = new MDoc(issuerSignedDocuments)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,8 @@ export function FunkeCredentialNotificationScreen() {
credentialConfigurationIdsToRequest: [configurationId],
accessToken: tokenResponse,
clientId: resolvedAuthorizationRequest ? authorization.clientId : undefined,
// Always request batch for non pid credentials
requestBatch: true,
})

const credentialRecord = credentialResponses[0].credential
Expand Down
12 changes: 6 additions & 6 deletions packages/agent/src/batch.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,10 @@ import { updateCredential } from './storage'
*
* @todo: what if batch is gone?
*/
export async function handleBatchCredential(
export async function handleBatchCredential<CredentialRecord extends W3cCredentialRecord | SdJwtVcRecord | MdocRecord>(
agent: EitherAgent,
credentialRecord: W3cCredentialRecord | SdJwtVcRecord | MdocRecord
) {
credentialRecord: CredentialRecord
): Promise<CredentialRecord> {
const batchMetadata = getBatchCredentialMetadata(credentialRecord)

if (batchMetadata) {
Expand All @@ -26,18 +26,18 @@ export async function handleBatchCredential(
if (credentialRecord instanceof MdocRecord) {
return new MdocRecord({
mdoc: Mdoc.fromBase64Url(batchCredential as string),
})
}) as CredentialRecord
}
if (credentialRecord instanceof SdJwtVcRecord) {
return new SdJwtVcRecord({
compactSdJwtVc: batchCredential as string,
})
}) as CredentialRecord
}
if (credentialRecord instanceof W3cCredentialRecord) {
return new W3cCredentialRecord({
tags: { expandedTypes: [] },
credential: decodeW3cCredential(batchCredential),
})
}) as CredentialRecord
}
}
}
Expand Down
13 changes: 12 additions & 1 deletion packages/agent/src/invitation/handler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -578,7 +578,18 @@ export const shareProof = async ({

// TODO: support credential selection for DCQL
const dcqlCredentials = resolvedRequest.queryResult
? agent.modules.openId4VcHolder.selectCredentialsForDcqlRequest(resolvedRequest.queryResult)
? Object.fromEntries(
await Promise.all(
Object.entries(
agent.modules.openId4VcHolder.selectCredentialsForDcqlRequest(resolvedRequest.queryResult)
).map(async ([queryCredentialId, credential]) => {
// Optionally use a batch credential
const credentialRecord = await handleBatchCredential(agent, credential.credentialRecord)

return [queryCredentialId, { ...credential, credentialRecord }]
})
)
)
: undefined

try {
Expand Down

0 comments on commit 8c855ce

Please sign in to comment.