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

feature/SDK-41_oidf-support #280

Merged
merged 30 commits into from
Nov 22, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
80f5431
chore: saving work
sanderPostma Nov 7, 2024
8a30e70
chore: oidf-metadata-server complete
sanderPostma Nov 7, 2024
787ca3c
Merge remote-tracking branch 'origin/develop' into feature/SPRIND-93_…
sanderPostma Nov 7, 2024
b574e31
chore: cleanup
sanderPostma Nov 7, 2024
bc575b1
chore: switch oid4vc lib
sanderPostma Nov 7, 2024
ed712c9
chore: kv fixes
sanderPostma Nov 7, 2024
39f3da0
chore: unit test fix
sanderPostma Nov 7, 2024
1850eb2
chore: reverted metadataType for persistence filtering
sanderPostma Nov 8, 2024
ec15211
chore: global MetadataType & oidfStoreImportMetadatas
sanderPostma Nov 8, 2024
a07c5ce
chore: finetuning interfaces
sanderPostma Nov 8, 2024
6918c9d
chore: unit test fix
sanderPostma Nov 8, 2024
fb1f616
chore: subjectBaseUrl -> baseUrl
sanderPostma Nov 8, 2024
c032ccd
chore: test fixes
sanderPostma Nov 8, 2024
acd6b23
chore: cleanup
sanderPostma Nov 8, 2024
201f1e6
Merge remote-tracking branch 'origin/develop' into feature/SPRIND-93_…
sanderPostma Nov 11, 2024
be621c6
chore: lockfile
sanderPostma Nov 11, 2024
139be68
Merge remote-tracking branch 'origin/develop' into feature/SDK-41_oid…
sanderPostma Nov 12, 2024
74a01ec
Merge remote-tracking branch 'origin/feature/SDK-44' into feature/SDK…
sanderPostma Nov 18, 2024
d0a95e5
chore: merged in SDK-44
sanderPostma Nov 18, 2024
a281066
chore: use oidfOpts when present
sanderPostma Nov 20, 2024
ae3ec05
Merge remote-tracking branch 'origin/develop' into feature/SDK-41_oid…
sanderPostma Nov 20, 2024
d9a06ec
Merge remote-tracking branch 'origin/develop' into feature/SDK-41_oid…
sanderPostma Nov 20, 2024
1b8cc06
chore: OIDF fixes
sanderPostma Nov 20, 2024
08b9458
chore: mdoc fix in countVCsInAllVPs
sanderPostma Nov 20, 2024
e57ecaa
chore: PR feedback
sanderPostma Nov 21, 2024
9cc0060
chore: PR feedback
sanderPostma Nov 22, 2024
9e05b86
Merge branch 'feature/SDK-44' into feature/SDK-41_oidf-support
sanderPostma Nov 22, 2024
f359d5a
Merge remote-tracking branch 'origin/develop' into feature/SDK-41_oid…
sanderPostma Nov 22, 2024
2e66e40
Merge remote-tracking branch 'origin/develop' into feature/SDK-41_oid…
sanderPostma Nov 22, 2024
c5101c0
chore: fixed lockfile
sanderPostma Nov 22, 2024
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
4 changes: 2 additions & 2 deletions packages/contact-manager-rest-api/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@
},
"dependencies": {
"@sphereon/ssi-express-support": "workspace:*",
"@sphereon/ssi-sdk-ext.key-manager": "0.25.0",
"@sphereon/ssi-sdk-ext.key-utils": "0.25.0",
"@sphereon/ssi-sdk-ext.key-manager": "0.25.1-feature.SDK.41.oidf.support.20",
"@sphereon/ssi-sdk-ext.key-utils": "0.25.1-feature.SDK.41.oidf.support.20",
"@sphereon/ssi-sdk.contact-manager": "workspace:*",
"@sphereon/ssi-sdk.core": "workspace:*",
"@sphereon/ssi-sdk.data-store": "workspace:*",
Expand Down
4 changes: 2 additions & 2 deletions packages/data-store/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,8 @@
"dependencies": {
"@sphereon/kmp-mdl-mdoc": "0.2.0-SNAPSHOT.22",
"@sphereon/pex": "5.0.0-unstable.27",
"@sphereon/ssi-sdk-ext.did-utils": "0.25.0",
"@sphereon/ssi-sdk-ext.identifier-resolution": "0.25.0",
"@sphereon/ssi-sdk-ext.did-utils": "0.25.1-feature.SDK.41.oidf.support.20",
"@sphereon/ssi-sdk-ext.identifier-resolution": "0.25.1-feature.SDK.41.oidf.support.20",
"@sphereon/ssi-sdk.agent-config": "workspace:*",
"@sphereon/ssi-sdk.core": "workspace:*",
"@sphereon/ssi-types": "workspace:*",
Expand Down
22 changes: 11 additions & 11 deletions packages/ebsi-support/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,15 +15,15 @@
},
"dependencies": {
"@ethersproject/random": "^5.7.0",
"@sphereon/did-auth-siop": "0.16.1-next.187",
"@sphereon/did-auth-siop-adapter": "0.16.1-next.187",
"@sphereon/did-auth-siop": "0.16.1-next.224",
"@sphereon/did-auth-siop-adapter": "0.16.1-next.224",
"@sphereon/pex": "5.0.0-unstable.27",
"@sphereon/pex-models": "^2.3.1",
"@sphereon/ssi-sdk-ext.did-resolver-ebsi": "0.25.0",
"@sphereon/ssi-sdk-ext.did-utils": "0.25.0",
"@sphereon/ssi-sdk-ext.identifier-resolution": "0.25.0",
"@sphereon/ssi-sdk-ext.jwt-service": "0.25.0",
"@sphereon/ssi-sdk-ext.key-utils": "0.25.0",
"@sphereon/ssi-sdk-ext.did-resolver-ebsi": "0.25.1-feature.SDK.41.oidf.support.20",
"@sphereon/ssi-sdk-ext.did-utils": "0.25.1-feature.SDK.41.oidf.support.20",
"@sphereon/ssi-sdk-ext.identifier-resolution": "0.25.1-feature.SDK.41.oidf.support.20",
"@sphereon/ssi-sdk-ext.jwt-service": "0.25.1-feature.SDK.41.oidf.support.20",
"@sphereon/ssi-sdk-ext.key-utils": "0.25.1-feature.SDK.41.oidf.support.20",
"@sphereon/ssi-sdk.contact-manager": "workspace:*",
"@sphereon/ssi-sdk.core": "workspace:*",
"@sphereon/ssi-sdk.oid4vci-holder": "workspace:*",
Expand All @@ -44,11 +44,11 @@
"xstate": "^4.38.3"
},
"devDependencies": {
"@sphereon/oid4vci-client": "0.16.1-next.187",
"@sphereon/oid4vci-common": "0.16.1-next.187",
"@sphereon/oid4vci-client": "0.16.1-next.224",
"@sphereon/oid4vci-common": "0.16.1-next.224",
"@sphereon/ssi-express-support": "workspace:*",
"@sphereon/ssi-sdk-ext.key-manager": "0.25.0",
"@sphereon/ssi-sdk-ext.kms-local": "0.25.0",
"@sphereon/ssi-sdk-ext.key-manager": "0.25.1-feature.SDK.41.oidf.support.20",
"@sphereon/ssi-sdk-ext.kms-local": "0.25.1-feature.SDK.41.oidf.support.20",
"@sphereon/ssi-sdk.agent-config": "workspace:*",
"@sphereon/ssi-sdk.data-store": "workspace:*",
"@sphereon/ssi-sdk.public-key-hosting": "workspace:*",
Expand Down
3 changes: 2 additions & 1 deletion packages/kv-store/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@
"main": "dist/index.js",
"types": "dist/index.d.ts",
"scripts": {
"build": "tsc"
"build": "tsc",
"build:clean": "tsc --build --clean && tsc --build"
},
"dependencies": {
"@veramo/utils": "4.2.0",
Expand Down
32 changes: 27 additions & 5 deletions packages/kv-store/src/keyv/keyv.ts
Original file line number Diff line number Diff line change
Expand Up @@ -126,8 +126,11 @@ export class Keyv<Value = any> extends EventEmitter implements KeyvStore<Value>
const keyPrefixed = this._getKeyPrefixArray(keys)
let promise: Promise<Array<KeyvStoredData<Value>>>
if (this.store.getMany !== undefined) {
promise = this.store.getMany(keyPrefixed, options) as Promise<KeyvStoredData<Value>[]> //.then(value => !!value ? value.values() : undefined)
// todo: Probably wise to check expired ValueData here, if the getMany does not implement this feature itself!
promise = this.store.getMany(keyPrefixed, options) as Promise<KeyvStoredData<Value>[]>
} else if (this.isMapWithEntries(this.store)) {
// Handle Map-based stores with prefix matching
promise = this.getFromMapWithPrefix(keyPrefixed)
} else {
promise = Promise.all(keyPrefixed.map((k) => this.store.get(k, options) as Promise<KeyvStoredData<Value>>))
}
Expand All @@ -136,13 +139,12 @@ export class Keyv<Value = any> extends EventEmitter implements KeyvStore<Value>

return Promise.resolve(allValues)
.then((all) => {
keys.forEach((key, index) => {
const data = all[index]

const entries = Array.isArray(all) ? all : [all]
entries.forEach((data, index) => {
let result = typeof data === 'string' ? this.deserialize(data) : !!data && this.opts.compression ? this.deserialize(data) : data

if (result && typeof result === 'object' && 'expires' in result && typeof result.expires === 'number' && Date.now() > result.expires) {
this.delete(key)
this.delete(keys[index])
result = undefined
}

Expand All @@ -156,6 +158,26 @@ export class Keyv<Value = any> extends EventEmitter implements KeyvStore<Value>
.then(() => Promise.all(results))
}

private isMapWithEntries(store: any): store is Map<string, Value> {
return store instanceof Map && typeof store.entries === 'function'
}

private async getFromMapWithPrefix(prefixes: string[]): Promise<Array<KeyvStoredData<Value> | undefined>> {
if (!this.isMapWithEntries(this.store)) {
return []
}

const map = this.store as Map<string, Value>

return prefixes.flatMap((prefix) => {
const matchedValues = Array.from(map.entries())
.filter(([key]) => key.startsWith(prefix))
.map(([, value]) => value as KeyvStoredData<Value>)

return matchedValues.length > 0 ? matchedValues : [undefined]
})
}

async get(
key: string | string[],
options?: { raw?: boolean },
Expand Down
16 changes: 8 additions & 8 deletions packages/mdl-mdoc/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,13 @@
"build:clean": "tsc --build --clean && tsc --build"
},
"dependencies": {
"@sphereon/did-auth-siop": "0.16.1-next.187",
"@sphereon/did-auth-siop": "0.16.1-next.224",
"@sphereon/kmp-mdl-mdoc": "0.2.0-SNAPSHOT.22",
"@sphereon/pex": "5.0.0-unstable.27",
"@sphereon/pex-models": "^2.3.1",
"@sphereon/ssi-sdk-ext.did-utils": "0.25.0",
"@sphereon/ssi-sdk-ext.key-utils": "0.25.0",
"@sphereon/ssi-sdk-ext.x509-utils": "0.25.0",
"@sphereon/ssi-sdk-ext.did-utils": "0.25.1-feature.SDK.41.oidf.support.20",
"@sphereon/ssi-sdk-ext.key-utils": "0.25.1-feature.SDK.41.oidf.support.20",
"@sphereon/ssi-sdk-ext.x509-utils": "0.25.1-feature.SDK.41.oidf.support.20",
"@sphereon/ssi-sdk.core": "workspace:*",
"@sphereon/ssi-types": "workspace:*",
"@veramo/core": "4.2.0",
Expand All @@ -35,11 +35,11 @@
"uuid": "^9.0.1"
},
"devDependencies": {
"@sphereon/oid4vci-client": "0.16.1-next.187",
"@sphereon/oid4vci-common": "0.16.1-next.187",
"@sphereon/oid4vci-client": "0.16.1-next.224",
"@sphereon/oid4vci-common": "0.16.1-next.224",
"@sphereon/ssi-express-support": "workspace:*",
"@sphereon/ssi-sdk-ext.key-manager": "0.25.0",
"@sphereon/ssi-sdk-ext.kms-local": "0.25.0",
"@sphereon/ssi-sdk-ext.key-manager": "0.25.1-feature.SDK.41.oidf.support.20",
"@sphereon/ssi-sdk-ext.kms-local": "0.25.1-feature.SDK.41.oidf.support.20",
"@sphereon/ssi-sdk.agent-config": "workspace:*",
"@sphereon/ssi-sdk.data-store": "workspace:*",
"@sphereon/ssi-sdk.public-key-hosting": "workspace:*",
Expand Down
14 changes: 7 additions & 7 deletions packages/oid4vci-holder/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,12 @@
},
"dependencies": {
"@sphereon/kmp-mdl-mdoc": "0.2.0-SNAPSHOT.22",
"@sphereon/oid4vci-client": "0.16.1-next.187",
"@sphereon/oid4vci-common": "0.16.1-next.187",
"@sphereon/ssi-sdk-ext.did-utils": "0.25.0",
"@sphereon/ssi-sdk-ext.identifier-resolution": "0.25.0",
"@sphereon/ssi-sdk-ext.jwt-service": "0.25.0",
"@sphereon/ssi-sdk-ext.key-utils": "0.25.0",
"@sphereon/oid4vci-client": "0.16.1-next.224",
"@sphereon/oid4vci-common": "0.16.1-next.224",
"@sphereon/ssi-sdk-ext.did-utils": "0.25.1-feature.SDK.41.oidf.support.20",
"@sphereon/ssi-sdk-ext.identifier-resolution": "0.25.1-feature.SDK.41.oidf.support.20",
"@sphereon/ssi-sdk-ext.jwt-service": "0.25.1-feature.SDK.41.oidf.support.20",
"@sphereon/ssi-sdk-ext.key-utils": "0.25.1-feature.SDK.41.oidf.support.20",
"@sphereon/ssi-sdk.contact-manager": "workspace:*",
"@sphereon/ssi-sdk.core": "workspace:*",
"@sphereon/ssi-sdk.credential-store": "workspace:*",
Expand All @@ -44,7 +44,7 @@
},
"devDependencies": {
"@sphereon/oid4vc-common": "0.16.1-next.187",
"@sphereon/ssi-sdk-ext.did-resolver-jwk": "0.25.0",
"@sphereon/ssi-sdk-ext.did-resolver-jwk": "0.25.1-feature.SDK.41.oidf.support.20",
"@types/i18n-js": "^3.8.9",
"@types/lodash.memoize": "^4.1.9",
"@types/uuid": "^9.0.8",
Expand Down
51 changes: 27 additions & 24 deletions packages/oid4vci-holder/src/agent/OID4VCIHolder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ import {
IdentityOrigin,
IIssuerLocaleBranding,
NonPersistedIdentity,
Party
Party,
} from '@sphereon/ssi-sdk.data-store'
import {
CredentialMapper,
Expand Down Expand Up @@ -72,7 +72,6 @@ import { v4 as uuidv4 } from 'uuid'
import { OID4VCIMachine } from '../machine/oid4vciMachine'
import {
AddContactIdentityArgs,
StoreIssuerBrandingArgs,
AssertValidCredentialsArgs,
Attribute,
createCredentialsToSelectFromArgs,
Expand All @@ -81,9 +80,10 @@ import {
GetContactArgs,
GetCredentialArgs,
GetCredentialsArgs,
GetFederationTrustArgs,
GetIssuerBrandingArgs,
GetIssuerMetadataArgs,
IOID4VCIHolder,
GetFederationTrustArgs,
IssuanceOpts,
MappedCredentialToAccept,
OID4VCIHolderEvent,
Expand All @@ -100,10 +100,10 @@ import {
StartResult,
StoreCredentialBrandingArgs,
StoreCredentialsArgs,
StoreIssuerBrandingArgs,
VerificationResult,
VerifyEBSICredentialIssuerArgs,
VerifyEBSICredentialIssuerResult,
GetIssuerBrandingArgs
} from '../types/IOID4VCIHolder'
import {
getBasicIssuerLocaleBranding,
Expand All @@ -117,6 +117,7 @@ import {
} from './OID4VCIHolderService'

import 'cross-fetch/polyfill'

/**
* {@inheritDoc IOID4VCIHolder}
*/
Expand Down Expand Up @@ -258,7 +259,7 @@ export class OID4VCIHolder implements IAgentPlugin {
didMethodPreferences,
jwtCryptographicSuitePreferences,
defaultAuthorizationRequestOptions,
hasher
hasher,
} = { ...options }

this.hasher = hasher
Expand Down Expand Up @@ -315,15 +316,16 @@ export class OID4VCIHolder implements IAgentPlugin {
),
createCredentialsToSelectFrom: (args: createCredentialsToSelectFromArgs) => this.oid4vciHoldercreateCredentialsToSelectFrom(args, context),
getContact: (args: GetContactArgs) => this.oid4vciHolderGetContact(args, context),
getCredentials: (args: GetCredentialsArgs) => this.oid4vciHolderGetCredentials({ accessTokenOpts: args.accessTokenOpts ?? opts.accessTokenOpts, ...args }, context),
getCredentials: (args: GetCredentialsArgs) =>
this.oid4vciHolderGetCredentials({ accessTokenOpts: args.accessTokenOpts ?? opts.accessTokenOpts, ...args }, context),
addContactIdentity: (args: AddContactIdentityArgs) => this.oid4vciHolderAddContactIdentity(args, context),
getIssuerBranding: (args: GetIssuerBrandingArgs) => this.oid4vciHolderGetIssuerBranding(args, context),
storeIssuerBranding: (args: StoreIssuerBrandingArgs) => this.oid4vciHolderStoreIssuerBranding(args, context),
assertValidCredentials: (args: AssertValidCredentialsArgs) => this.oid4vciHolderAssertValidCredentials(args, context),
storeCredentialBranding: (args: StoreCredentialBrandingArgs) => this.oid4vciHolderStoreCredentialBranding(args, context),
storeCredentials: (args: StoreCredentialsArgs) => this.oid4vciHolderStoreCredentials(args, context),
sendNotification: (args: SendNotificationArgs) => this.oid4vciHolderSendNotification(args, context),
getFederationTrust: (args: GetFederationTrustArgs) => this.getFederationTrust(args, context)
getFederationTrust: (args: GetFederationTrustArgs) => this.getFederationTrust(args, context),
}

const oid4vciMachineInstanceArgs: OID4VCIMachineInstanceOpts = {
Expand Down Expand Up @@ -458,7 +460,10 @@ export class OID4VCIHolder implements IAgentPlugin {
}
}

private async oid4vciHoldercreateCredentialsToSelectFrom(args: createCredentialsToSelectFromArgs, context: RequiredContext): Promise<Array<CredentialToSelectFromResult>> {
private async oid4vciHoldercreateCredentialsToSelectFrom(
args: createCredentialsToSelectFromArgs,
context: RequiredContext,
): Promise<Array<CredentialToSelectFromResult>> {
const { credentialBranding, locale, selectedCredentials /*, openID4VCIClientState*/, credentialsSupported } = args

// const client = await OpenID4VCIClient.fromState({ state: openID4VCIClientState! }) // TODO see if we need the check openID4VCIClientState defined
Expand Down Expand Up @@ -730,7 +735,10 @@ export class OID4VCIHolder implements IAgentPlugin {
return context.agent.cmAddIdentity({ contactId: contact.id, identity })
}

private async oid4vciHolderGetIssuerBranding(args: GetIssuerBrandingArgs, context: RequiredContext): Promise<Array<IIssuerLocaleBranding | IBasicIssuerLocaleBranding>> {
private async oid4vciHolderGetIssuerBranding(
args: GetIssuerBrandingArgs,
context: RequiredContext,
): Promise<Array<IIssuerLocaleBranding | IBasicIssuerLocaleBranding>> {
const { serverMetadata, contact } = args

// Here we are fetching issuer branding for a contact. If no contact is found that means we encounter this contact for the first time. This also means we do not have any branding for the contact.
Expand All @@ -747,7 +755,7 @@ export class OID4VCIHolder implements IAgentPlugin {

// We should have serverMetadata in the context else something went wrong
if (!serverMetadata) {
return Promise.reject(Error('Missing serverMetadata in context'));
return Promise.reject(Error('Missing serverMetadata in context'))
}

return getBasicIssuerLocaleBranding({
Expand All @@ -759,12 +767,13 @@ export class OID4VCIHolder implements IAgentPlugin {

private async oid4vciHolderStoreIssuerBranding(args: StoreIssuerBrandingArgs, context: RequiredContext): Promise<void> {
const { issuerBranding, contact } = args
if (!issuerBranding || issuerBranding.length === 0 || (<Array<IIssuerLocaleBranding>>issuerBranding)[0].id) { // FIXME we need better separation between a contact(issuer) we encountered before and it's branding vs a new contact and it's branding
if (!issuerBranding || issuerBranding.length === 0 || (<Array<IIssuerLocaleBranding>>issuerBranding)[0].id) {
// FIXME we need better separation between a contact(issuer) we encountered before and it's branding vs a new contact and it's branding
return
}

if (!contact) {
return Promise.reject(Error('Missing contact in context'));
return Promise.reject(Error('Missing contact in context'))
}

const issuerCorrelationId = contact?.identities
Expand Down Expand Up @@ -1051,19 +1060,13 @@ export class OID4VCIHolder implements IAgentPlugin {
const openidFederation = params.get('openid_federation')
const entityIdentifier = openidFederation ?? serverMetadata.issuer

const trustedAnchors = []
for (const trustAnchor of trustAnchors) {
const resolveResult = await context.agent.resolveTrustChain({
entityIdentifier,
trustAnchors: [trustAnchor]
})

if (!resolveResult.error) {
trustedAnchors.push(trustAnchor)
}
}
const result = await context.agent.identifierExternalResolveByOIDFEntityId({
method: 'entity_id',
trustAnchors: trustAnchors,
identifier: entityIdentifier,
})

return trustedAnchors
return Object.keys(result.trustedAnchors)
}

private async oid4vciHolderGetIssuerMetadata(args: GetIssuerMetadataArgs, context: RequiredContext): Promise<EndpointMetadataResult> {
Expand Down
Loading