@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.
- package/dist/index.cjs +57 -10
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +9 -4
- package/dist/index.d.ts +9 -4
- package/dist/index.js +57 -10
- package/dist/index.js.map +1 -1
- package/package.json +20 -20
- package/src/IssuerInstance.ts +8 -0
- package/src/agent/OID4VCIIssuer.ts +44 -23
- package/src/functions.ts +34 -9
- package/src/index.ts +1 -1
- package/src/types/IOID4VCIIssuer.ts +5 -1
|
@@ -1,31 +1,39 @@
|
|
|
1
|
+
import {retrieveWellknown} from '@sphereon/oid4vci-client'
|
|
1
2
|
import {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
3
|
+
AccessTokenResponse,
|
|
4
|
+
AuthorizationServerMetadata,
|
|
5
|
+
CredentialResponse,
|
|
6
|
+
IssuerMetadata,
|
|
7
|
+
OpenIDResponse,
|
|
8
|
+
WellKnownEndpoints,
|
|
8
9
|
} from '@sphereon/oid4vci-common'
|
|
9
|
-
import {
|
|
10
|
-
import {
|
|
11
|
-
import {
|
|
12
|
-
import {
|
|
13
|
-
import {
|
|
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
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
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 {
|
|
27
|
+
import {IssuerInstance} from '../IssuerInstance'
|
|
28
|
+
import {IOID4VCIIssuer} from '../types/IOID4VCIIssuer'
|
|
27
29
|
|
|
28
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|