Skip to content

Commit

Permalink
Merge pull request #280 from Sphereon-Opensource/feature/SDK-41_oidf-…
Browse files Browse the repository at this point in the history
…support

feature/SDK-41_oidf-support
  • Loading branch information
sanderPostma authored Nov 22, 2024
2 parents 8b55c43 + c5101c0 commit d8b119e
Show file tree
Hide file tree
Showing 52 changed files with 1,937 additions and 541 deletions.
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

0 comments on commit d8b119e

Please sign in to comment.