@sphereon/ssi-sdk.oid4vci-issuer 0.36.1-feature.SSISDK.82.and.SSISDK.70.37 → 0.36.1-feature.SSISDK.97.branding.incremental.sync.128

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,31 +1,39 @@
1
+ import {retrieveWellknown} from '@sphereon/oid4vci-client'
1
2
  import {
2
- AccessTokenResponse,
3
- AuthorizationServerMetadata,
4
- CredentialResponse,
5
- IssuerMetadata,
6
- OpenIDResponse,
7
- WellKnownEndpoints,
3
+ AccessTokenResponse,
4
+ AuthorizationServerMetadata,
5
+ CredentialResponse,
6
+ IssuerMetadata,
7
+ OpenIDResponse,
8
+ WellKnownEndpoints,
8
9
  } from '@sphereon/oid4vci-common'
9
- import { assertValidAccessTokenRequest, createAccessTokenResponse, VcIssuer } from '@sphereon/oid4vci-issuer'
10
- import { retrieveWellknown } from '@sphereon/oid4vci-client'
11
- import { getAgentResolver } from '@sphereon/ssi-sdk-ext.did-utils'
12
- import { IMetadataOptions } from '@sphereon/ssi-sdk.oid4vci-issuer-store'
13
- import { IAgentPlugin } from '@veramo/core'
14
- import { getAccessTokenSignerCallback } from '../functions'
10
+ import {assertValidAccessTokenRequest, createAccessTokenResponse, VcIssuer} from '@sphereon/oid4vci-issuer'
11
+ import {getAgentResolver} from '@sphereon/ssi-sdk-ext.did-utils'
12
+ import {IMetadataOptions} from '@sphereon/ssi-sdk.oid4vci-issuer-store'
13
+ import {IAgentPlugin} from '@veramo/core'
14
+ import {getAccessTokenSignerCallback} from '../functions'
15
15
  import {
16
- IAssertValidAccessTokenArgs,
17
- ICreateCredentialOfferURIResult,
18
- ICreateOfferArgs,
19
- IIssueCredentialArgs,
20
- IIssuerInstanceArgs,
21
- IIssuerOptions,
22
- IOID4VCIIssuerOpts,
23
- IRequiredContext,
24
- schema,
16
+ IAssertValidAccessTokenArgs,
17
+ ICreateCredentialOfferURIResult,
18
+ ICreateOfferArgs,
19
+ IIssueCredentialArgs,
20
+ IIssuerInstanceArgs,
21
+ IIssuerOptions,
22
+ IOID4VCIIssuerOpts,
23
+ IRefreshInstanceMetadata,
24
+ IRequiredContext,
25
+ schema,
25
26
  } from '../index'
26
- import { IssuerInstance } from '../IssuerInstance'
27
+ import {IssuerInstance} from '../IssuerInstance'
28
+ import {IOID4VCIIssuer} from '../types/IOID4VCIIssuer'
27
29
 
28
- import { IOID4VCIIssuer } from '../types/IOID4VCIIssuer'
30
+ export const oid4vciIssuerMethods: Array<string> = [
31
+ 'oid4vciCreateOfferURI',
32
+ 'oid4vciIssueCredential',
33
+ 'oid4vciCreateAccessTokenResponse',
34
+ 'oid4vciGetInstance',
35
+ 'oid4vciRefreshInstanceMetadata',
36
+ ]
29
37
 
30
38
  export class OID4VCIIssuer implements IAgentPlugin {
31
39
  private static readonly _DEFAULT_OPTS_KEY = '_default'
@@ -37,6 +45,7 @@ export class OID4VCIIssuer implements IAgentPlugin {
37
45
  oid4vciIssueCredential: this.oid4vciIssueCredential.bind(this),
38
46
  oid4vciCreateAccessTokenResponse: this.oid4vciCreateAccessTokenResponse.bind(this),
39
47
  oid4vciGetInstance: this.oid4vciGetInstance.bind(this),
48
+ oid4vciRefreshInstanceMetadata: this.oid4vciRefreshInstanceMetadata.bind(this),
40
49
  }
41
50
  private _opts: IOID4VCIIssuerOpts
42
51
 
@@ -132,6 +141,7 @@ export class OID4VCIIssuer implements IAgentPlugin {
132
141
  if (!issuerOpts.resolveOpts?.resolver) {
133
142
  issuerOpts.resolveOpts.resolver = getAgentResolver(context)
134
143
  }
144
+
135
145
  this.instances.set(
136
146
  credentialIssuer,
137
147
  new IssuerInstance({
@@ -141,9 +151,20 @@ export class OID4VCIIssuer implements IAgentPlugin {
141
151
  authorizationServerMetadata,
142
152
  }),
143
153
  )
154
+
144
155
  return this.oid4vciGetInstance(args, context)
145
156
  }
146
157
 
158
+ // TODO SSISDK-87 create proper solution to update issuer metadata
159
+ public async oid4vciRefreshInstanceMetadata(args: IRefreshInstanceMetadata, context: IRequiredContext): Promise<boolean> {
160
+ const instance = this.instances.get(args.credentialIssuer)
161
+ if (instance) {
162
+ instance.issuerMetadata = await this.getIssuerMetadata({ ...args }, context)
163
+ return true
164
+ }
165
+ return false
166
+ }
167
+
147
168
  public async oid4vciGetInstance(args: IIssuerInstanceArgs, context: IRequiredContext): Promise<IssuerInstance> {
148
169
  const credentialIssuer = args.credentialIssuer ?? OID4VCIIssuer._DEFAULT_OPTS_KEY
149
170
  //todo: prob doesn't make sense as credentialIssuer is mandatory anyway
package/src/functions.ts CHANGED
@@ -12,7 +12,7 @@ import {
12
12
  } from '@sphereon/oid4vci-common'
13
13
  import { CredentialDataSupplier, CredentialIssuanceInput, CredentialSignerCallback, VcIssuer, VcIssuerBuilder } from '@sphereon/oid4vci-issuer'
14
14
  import { getAgentResolver, IDIDOptions } from '@sphereon/ssi-sdk-ext.did-utils'
15
- import { legacyKeyRefsToIdentifierOpts, ManagedIdentifierOptsOrResult } from '@sphereon/ssi-sdk-ext.identifier-resolution'
15
+ import { legacyKeyRefsToIdentifierOpts, ManagedIdentifierOptsOrResult, ManagedIdentifierResult } from '@sphereon/ssi-sdk-ext.identifier-resolution'
16
16
  import { contextHasPlugin } from '@sphereon/ssi-sdk.agent-config'
17
17
  import { SdJwtVcPayload } from '@sphereon/ssi-sdk.sd-jwt'
18
18
  import { IStatusListPlugin } from '@sphereon/ssi-sdk.vc-status-list'
@@ -25,6 +25,8 @@ import { Resolvable } from 'did-resolver'
25
25
  import { jwtDecode } from 'jwt-decode'
26
26
  import { IIssuerOptions, IRequiredContext } from './types/IOID4VCIIssuer'
27
27
 
28
+ const CLOCK_SKEW_ISSUANCE = 2 // Clock drift on Android is typically up to 2000ms, so we issue 2 seconds in the past
29
+
28
30
  export function getJwtVerifyCallback({ verifyOpts }: { verifyOpts?: JWTVerifyOptions }, _context: IRequiredContext) {
29
31
  return async (args: { jwt: string; kid?: string }): Promise<JwtVerifyResult> => {
30
32
  const resolver = getAgentResolver(_context, {
@@ -141,14 +143,20 @@ export async function getAccessTokenSignerCallback(
141
143
  },
142
144
  context: IRequiredContext,
143
145
  ) {
146
+ const resolution = legacyKeyRefsToIdentifierOpts(opts)
147
+ const identifier = await context.agent.identifierManagedGet({
148
+ identifier: resolution.identifier as string,
149
+ vmRelationship: 'authentication',
150
+ })
151
+
152
+ const keyRef = identifier.kmsKeyRef
153
+ if (!keyRef) {
154
+ throw Error('Cannot sign access tokens without a key ref')
155
+ }
156
+
144
157
  const signer = async (data: string | Uint8Array) => {
145
158
  let dataString, encoding: 'base64' | undefined
146
159
 
147
- const resolution = await legacyKeyRefsToIdentifierOpts(opts)
148
- const keyRef = resolution.kmsKeyRef
149
- if (!keyRef) {
150
- throw Error('Cannot sign access tokens without a key ref')
151
- }
152
160
  if (typeof data === 'string') {
153
161
  dataString = data
154
162
  encoding = undefined
@@ -168,6 +176,9 @@ export async function getAccessTokenSignerCallback(
168
176
  }
169
177
 
170
178
  let kidHeader: string | undefined = jwt?.header?.kid ?? kid
179
+ if (!kidHeader && identifier.kid) {
180
+ kidHeader = identifier.kid
181
+ }
171
182
  if (!kidHeader) {
172
183
  if (
173
184
  opts.idOpts?.method === 'did' ||
@@ -178,7 +189,13 @@ export async function getAccessTokenSignerCallback(
178
189
  kidHeader = opts.idOpts?.kid ?? opts.didOpts?.idOpts?.kid ?? opts?.didOpts?.identifierOpts?.kid
179
190
  }
180
191
  }
181
- return await createJWT(jwt.payload, { signer, issuer }, { ...jwt.header, ...(kidHeader && { kid: kidHeader }), typ: 'JWT' })
192
+
193
+ const alg = identifier.jwk?.alg
194
+ if (!alg) {
195
+ return Promise.reject(Error('No algorithm found in identifier JWK'))
196
+ }
197
+
198
+ return await createJWT(jwt.payload, { signer, issuer }, { ...jwt.header, ...(kidHeader && { kid: kidHeader }), typ: 'JWT', alg })
182
199
  }
183
200
 
184
201
  return accessTokenSignerCallback
@@ -201,7 +218,15 @@ export async function getCredentialSignerCallback(
201
218
  const credential = args.credential as ICredential // TODO: SDJWT
202
219
  let proofFormat: ProofFormat
203
220
 
204
- const resolution = await context.agent.identifierManagedGet(idOpts)
221
+ let resolution: ManagedIdentifierResult
222
+ if (typeof idOpts.identifier !== 'string') {
223
+ resolution = idOpts as ManagedIdentifierResult
224
+ } else {
225
+ resolution = await context.agent.identifierManagedGet({
226
+ identifier: idOpts.identifier,
227
+ vmRelationship: 'assertionMethod',
228
+ })
229
+ }
205
230
  proofFormat = format?.includes('ld') ? 'lds' : 'jwt'
206
231
  const issuer = resolution.issuer ?? resolution.kmsKeyRef
207
232
 
@@ -245,7 +270,7 @@ export async function getCredentialSignerCallback(
245
270
  sdJwtPayload.iss = issuer
246
271
  }
247
272
  if (sdJwtPayload.iat === undefined) {
248
- sdJwtPayload.iat = Math.floor(new Date().getTime() / 1000)
273
+ sdJwtPayload.iat = Math.floor(new Date().getTime() / 1000) - CLOCK_SKEW_ISSUANCE
249
274
  }
250
275
 
251
276
  let disclosureFrame
package/src/index.ts CHANGED
@@ -3,7 +3,7 @@
3
3
  */
4
4
  const schema = require('../plugin.schema.json')
5
5
  export { schema }
6
- export { OID4VCIIssuer } from './agent/OID4VCIIssuer'
6
+ export { OID4VCIIssuer, oid4vciIssuerMethods } from './agent/OID4VCIIssuer'
7
7
  export * from './functions'
8
8
  export * from './IssuerInstance'
9
9
  export * from './types/IOID4VCIIssuer'
@@ -30,6 +30,7 @@ export interface IOID4VCIIssuer extends IPluginMethodMap {
30
30
  oid4vciIssueCredential(issueArgs: IIssueCredentialArgs, context: IRequiredContext): Promise<CredentialResponse>
31
31
  oid4vciCreateAccessTokenResponse(accessTokenArgs: IAssertValidAccessTokenArgs, context: IRequiredContext): Promise<AccessTokenResponse>
32
32
  oid4vciGetInstance(args: IIssuerInstanceArgs, context: IRequiredContext): Promise<IssuerInstance>
33
+ oid4vciRefreshInstanceMetadata(args: IRefreshInstanceMetadata, context: IRequiredContext): Promise<boolean>
33
34
  }
34
35
 
35
36
  export interface IOID4VCIIssuerOpts {
@@ -45,7 +46,6 @@ export interface ICreateOfferArgs extends IIssuerInstanceArgs {
45
46
  credentialDefinition?: IssuerCredentialDefinition
46
47
  credentialOfferUri?: string
47
48
  credentialDataSupplierInput?: CredentialDataSupplierInput // Optional storage that can help the credential Data Supplier. For instance to store credential input data during offer creation, if no additional data can be supplied later on
48
-
49
49
  redirectUri?: string
50
50
  // auth_session?: string; Would be a nice extension to support, to allow external systems to determine what the auth_session value should be
51
51
  // @Deprecated use tx_code in the grant object
@@ -83,6 +83,10 @@ export interface IIssuerInstanceArgs {
83
83
  namespace?: string
84
84
  }
85
85
 
86
+ export interface IRefreshInstanceMetadata {
87
+ credentialIssuer: string
88
+ }
89
+
86
90
  export interface IIssuerInstanceOptions extends IMetadataOptions {
87
91
  issuerOpts?: IIssuerOptions
88
92
  metadataOpts?: CredentialIssuerMetadataOpts