@credo-ts/openid4vc 0.6.0-pr-2088-20241109180557 → 0.6.0-pr-2088-20241116152443
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/build/openid4vc-holder/OpenId4VcHolderApi.d.ts +24 -6
- package/build/openid4vc-holder/OpenId4VcHolderApi.js +11 -2
- package/build/openid4vc-holder/OpenId4VcHolderApi.js.map +1 -1
- package/build/openid4vc-holder/OpenId4VciHolderService.js +20 -17
- package/build/openid4vc-holder/OpenId4VciHolderService.js.map +1 -1
- package/build/openid4vc-holder/OpenId4VciHolderServiceOptions.d.ts +16 -2
- package/build/openid4vc-holder/OpenId4vcSiopHolderService.d.ts +16 -4
- package/build/openid4vc-holder/OpenId4vcSiopHolderService.js +25 -12
- package/build/openid4vc-holder/OpenId4vcSiopHolderService.js.map +1 -1
- package/build/openid4vc-holder/OpenId4vcSiopHolderServiceOptions.d.ts +1 -6
- package/build/openid4vc-issuer/OpenId4VcIssuerApi.d.ts +40 -6
- package/build/openid4vc-issuer/OpenId4VcIssuerApi.js +14 -8
- package/build/openid4vc-issuer/OpenId4VcIssuerApi.js.map +1 -1
- package/build/openid4vc-issuer/OpenId4VcIssuerModule.js +0 -1
- package/build/openid4vc-issuer/OpenId4VcIssuerModule.js.map +1 -1
- package/build/openid4vc-issuer/OpenId4VcIssuerModuleConfig.d.ts +48 -6
- package/build/openid4vc-issuer/OpenId4VcIssuerModuleConfig.js +31 -4
- package/build/openid4vc-issuer/OpenId4VcIssuerModuleConfig.js.map +1 -1
- package/build/openid4vc-issuer/OpenId4VcIssuerService.d.ts +35 -1
- package/build/openid4vc-issuer/OpenId4VcIssuerService.js +69 -23
- package/build/openid4vc-issuer/OpenId4VcIssuerService.js.map +1 -1
- package/build/openid4vc-issuer/OpenId4VcIssuerServiceOptions.d.ts +44 -11
- package/build/openid4vc-issuer/repository/OpenId4VcIssuanceSessionRecord.d.ts +14 -3
- package/build/openid4vc-issuer/repository/OpenId4VcIssuanceSessionRecord.js +19 -3
- package/build/openid4vc-issuer/repository/OpenId4VcIssuanceSessionRecord.js.map +1 -1
- package/build/openid4vc-issuer/repository/OpenId4VcIssuerRecord.d.ts +13 -3
- package/build/openid4vc-issuer/repository/OpenId4VcIssuerRecord.js +51 -1
- package/build/openid4vc-issuer/repository/OpenId4VcIssuerRecord.js.map +1 -1
- package/build/openid4vc-issuer/router/accessTokenEndpoint.js +27 -16
- package/build/openid4vc-issuer/router/accessTokenEndpoint.js.map +1 -1
- package/build/openid4vc-issuer/router/authorizationChallengeEndpoint.js +31 -13
- package/build/openid4vc-issuer/router/authorizationChallengeEndpoint.js.map +1 -1
- package/build/openid4vc-issuer/router/credentialEndpoint.js +75 -24
- package/build/openid4vc-issuer/router/credentialEndpoint.js.map +1 -1
- package/build/openid4vc-verifier/OpenId4VcSiopVerifierService.js +24 -10
- package/build/openid4vc-verifier/OpenId4VcSiopVerifierService.js.map +1 -1
- package/build/openid4vc-verifier/OpenId4VcSiopVerifierServiceOptions.d.ts +8 -6
- package/build/openid4vc-verifier/repository/OpenId4VcVerificationSessionRecord.d.ts +10 -0
- package/build/openid4vc-verifier/repository/OpenId4VcVerificationSessionRecord.js +1 -0
- package/build/openid4vc-verifier/repository/OpenId4VcVerificationSessionRecord.js.map +1 -1
- package/build/openid4vc-verifier/router/authorizationEndpoint.js +4 -1
- package/build/openid4vc-verifier/router/authorizationEndpoint.js.map +1 -1
- package/package.json +5 -5
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { OpenId4VcIssuanceSessionRecord, OpenId4VcIssuerRecordProps } from './repository';
|
|
2
|
-
import type { OpenId4VcSiopCreateAuthorizationRequestReturn,
|
|
2
|
+
import type { OpenId4VcSiopCreateAuthorizationRequestReturn, OpenId4VcSiopVerifiedAuthorizationResponsePresentationExchange, OpenId4VcVerificationSessionRecord } from '../openid4vc-verifier';
|
|
3
3
|
import type { OpenId4VcCredentialHolderBindingWithKey, OpenId4VciCredentialConfigurationsSupportedWithFormats, OpenId4VciCredentialOfferPayload, OpenId4VciCredentialRequest, OpenId4VciCredentialRequestFormatSpecific, OpenId4VciCredentialIssuerMetadataDisplay, OpenId4VciTxCode } from '../shared';
|
|
4
4
|
import type { OpenId4VciAuthorizationServerConfig } from '../shared/models/OpenId4VciAuthorizationServerConfig';
|
|
5
5
|
import type { AccessTokenProfileJwtPayload, TokenIntrospectionResponse } from '@animo-id/oauth2';
|
|
@@ -51,13 +51,29 @@ export interface OpenId4VciAuthorizationCodeFlowConfig {
|
|
|
51
51
|
*/
|
|
52
52
|
requirePresentationDuringIssuance?: boolean;
|
|
53
53
|
}
|
|
54
|
-
|
|
54
|
+
interface OpenId4VciCreateCredentialOfferOptionsBase {
|
|
55
55
|
offeredCredentials: string[];
|
|
56
56
|
/**
|
|
57
57
|
* baseUri for the credential offer uri. By default `openid-credential-offer://` will be used
|
|
58
58
|
* if no value is provided. If a value is provided, make sure it contains the scheme as well as `://`.
|
|
59
59
|
*/
|
|
60
60
|
baseUri?: string;
|
|
61
|
+
/**
|
|
62
|
+
* @default v1.draft11-13
|
|
63
|
+
*/
|
|
64
|
+
version?: 'v1.draft11-13' | 'v1.draft13';
|
|
65
|
+
}
|
|
66
|
+
export interface OpenId4VciCreateStatelessCredentialOfferOptions extends OpenId4VciCreateCredentialOfferOptionsBase {
|
|
67
|
+
authorizationCodeFlowConfig: Required<Pick<OpenId4VciAuthorizationCodeFlowConfig, 'authorizationServerUrl'>>;
|
|
68
|
+
/**
|
|
69
|
+
* For stateless credential offers we need an external authorization server, which also means we need to
|
|
70
|
+
* support `authorization_servers`, therefore only draft 13 offers are supported
|
|
71
|
+
*
|
|
72
|
+
* @default v1.draft13
|
|
73
|
+
*/
|
|
74
|
+
version?: 'v1.draft13';
|
|
75
|
+
}
|
|
76
|
+
export interface OpenId4VciCreateCredentialOfferOptions extends OpenId4VciCreateCredentialOfferOptionsBase {
|
|
61
77
|
preAuthorizedCodeFlowConfig?: OpenId4VciPreAuthorizedCodeFlowConfig;
|
|
62
78
|
authorizationCodeFlowConfig?: OpenId4VciAuthorizationCodeFlowConfig;
|
|
63
79
|
/**
|
|
@@ -67,10 +83,6 @@ export interface OpenId4VciCreateCredentialOfferOptions {
|
|
|
67
83
|
* data.
|
|
68
84
|
*/
|
|
69
85
|
issuanceMetadata?: Record<string, unknown>;
|
|
70
|
-
/**
|
|
71
|
-
* @default v1.draft11-13
|
|
72
|
-
*/
|
|
73
|
-
version?: 'v1.draft11-13' | 'v1.draft13';
|
|
74
86
|
}
|
|
75
87
|
export interface OpenId4VciCreateCredentialResponseOptions {
|
|
76
88
|
credentialRequest: OpenId4VciCredentialRequest;
|
|
@@ -104,8 +116,17 @@ export type OpenId4VciGetVerificationSessionForIssuanceSessionAuthorization = (o
|
|
|
104
116
|
* parameter
|
|
105
117
|
*/
|
|
106
118
|
scopes: string[];
|
|
107
|
-
}) => Promise<OpenId4VcSiopCreateAuthorizationRequestReturn
|
|
108
|
-
|
|
119
|
+
}) => Promise<OpenId4VcSiopCreateAuthorizationRequestReturn & {
|
|
120
|
+
/**
|
|
121
|
+
* The scopes which will be granted by successfully completing the verification
|
|
122
|
+
* session.
|
|
123
|
+
*
|
|
124
|
+
* @todo do we need more granular support? I.e. every input descriptor can satisfy a
|
|
125
|
+
* different scope?
|
|
126
|
+
*/
|
|
127
|
+
scopes: string[];
|
|
128
|
+
}>;
|
|
129
|
+
export interface OpenId4VciCredentialRequestToCredentialMapperOptions {
|
|
109
130
|
agentContext: AgentContext;
|
|
110
131
|
/**
|
|
111
132
|
* Authorization associated with the credential request
|
|
@@ -118,7 +139,7 @@ export type OpenId4VciCredentialRequestToCredentialMapper = (options: {
|
|
|
118
139
|
*/
|
|
119
140
|
verification?: {
|
|
120
141
|
session: OpenId4VcVerificationSessionRecord;
|
|
121
|
-
|
|
142
|
+
presentationExchange: OpenId4VcSiopVerifiedAuthorizationResponsePresentationExchange;
|
|
122
143
|
};
|
|
123
144
|
/**
|
|
124
145
|
* The issuance session associated with the credential request. You can extract the
|
|
@@ -157,7 +178,8 @@ export type OpenId4VciCredentialRequestToCredentialMapper = (options: {
|
|
|
157
178
|
* NOTE: This will probably become a single entry, as it will be matched on id
|
|
158
179
|
*/
|
|
159
180
|
credentialConfigurationIds: [string, ...string[]];
|
|
160
|
-
}
|
|
181
|
+
}
|
|
182
|
+
export type OpenId4VciCredentialRequestToCredentialMapper = (options: OpenId4VciCredentialRequestToCredentialMapperOptions) => Promise<OpenId4VciSignCredentials> | OpenId4VciSignCredentials;
|
|
161
183
|
export type OpenId4VciSignCredentials = OpenId4VciSignSdJwtCredentials | OpenId4VciSignW3cCredentials | OpenId4VciSignMdocCredentials;
|
|
162
184
|
export interface OpenId4VciSignSdJwtCredentials {
|
|
163
185
|
credentialConfigurationId: string;
|
|
@@ -177,6 +199,12 @@ export interface OpenId4VciSignW3cCredentials {
|
|
|
177
199
|
credential: W3cCredential;
|
|
178
200
|
}>;
|
|
179
201
|
}
|
|
202
|
+
export interface OpenId4VciBatchCredentialIssuanceOptions {
|
|
203
|
+
/**
|
|
204
|
+
* The maximum batch size
|
|
205
|
+
*/
|
|
206
|
+
batchSize: number;
|
|
207
|
+
}
|
|
180
208
|
export type OpenId4VciCreateIssuerOptions = {
|
|
181
209
|
/**
|
|
182
210
|
* Id of the issuer, not the id of the issuer record. Will be exposed publicly
|
|
@@ -192,5 +220,10 @@ export type OpenId4VciCreateIssuerOptions = {
|
|
|
192
220
|
authorizationServerConfigs?: OpenId4VciAuthorizationServerConfig[];
|
|
193
221
|
dpopSigningAlgValuesSupported?: [JwaSignatureAlgorithm, ...JwaSignatureAlgorithm[]];
|
|
194
222
|
credentialConfigurationsSupported: OpenId4VciCredentialConfigurationsSupportedWithFormats;
|
|
223
|
+
/**
|
|
224
|
+
* Indicate support for batch issuane of credentials
|
|
225
|
+
*/
|
|
226
|
+
batchCredentialIssuance?: OpenId4VciBatchCredentialIssuanceOptions;
|
|
195
227
|
};
|
|
196
|
-
export type OpenId4VcUpdateIssuerRecordOptions = Pick<OpenId4VcIssuerRecordProps, 'issuerId' | 'display' | 'dpopSigningAlgValuesSupported' | 'credentialConfigurationsSupported'>;
|
|
228
|
+
export type OpenId4VcUpdateIssuerRecordOptions = Pick<OpenId4VcIssuerRecordProps, 'issuerId' | 'display' | 'dpopSigningAlgValuesSupported' | 'credentialConfigurationsSupported' | 'batchCredentialIssuance'>;
|
|
229
|
+
export {};
|
|
@@ -17,6 +17,16 @@ export interface OpenId4VcIssuanceSessionAuthorization {
|
|
|
17
17
|
* is used to bind the subsequent Authorization Request with the Credential Issuer to a context set up during previous steps.
|
|
18
18
|
*/
|
|
19
19
|
issuerState?: string;
|
|
20
|
+
/**
|
|
21
|
+
* Scopes that are granted when the authorization is complete.
|
|
22
|
+
*/
|
|
23
|
+
scopes?: string[];
|
|
24
|
+
/**
|
|
25
|
+
* Subject the issuance session is bound to. For internal authorization this will be defined
|
|
26
|
+
* from the moment the token is issued. For external authorization this will be defined after
|
|
27
|
+
* the first time the credential endpoint has been called.
|
|
28
|
+
*/
|
|
29
|
+
subject?: string;
|
|
20
30
|
}
|
|
21
31
|
export interface OpenId4VcIssuanceSessionPresentation {
|
|
22
32
|
/**
|
|
@@ -25,7 +35,6 @@ export interface OpenId4VcIssuanceSessionPresentation {
|
|
|
25
35
|
required: true;
|
|
26
36
|
/**
|
|
27
37
|
* Auth session for the presentation during issuance flow
|
|
28
|
-
* @todo can't we use some other param for this, or maybe a JWT so it's stateless?
|
|
29
38
|
*/
|
|
30
39
|
authSession?: string;
|
|
31
40
|
/**
|
|
@@ -41,6 +50,8 @@ export type DefaultOpenId4VcIssuanceSessionRecordTags = {
|
|
|
41
50
|
preAuthorizedCode?: string;
|
|
42
51
|
authorizationCode?: string;
|
|
43
52
|
issuerState?: string;
|
|
53
|
+
authorizationSubject?: string;
|
|
54
|
+
presentationAuthSession?: string;
|
|
44
55
|
};
|
|
45
56
|
export interface OpenId4VcIssuanceSessionRecordProps {
|
|
46
57
|
id?: string;
|
|
@@ -48,7 +59,6 @@ export interface OpenId4VcIssuanceSessionRecordProps {
|
|
|
48
59
|
tags?: TagsBase;
|
|
49
60
|
state: OpenId4VcIssuanceSessionState;
|
|
50
61
|
issuerId: string;
|
|
51
|
-
dpopRequired?: boolean;
|
|
52
62
|
/**
|
|
53
63
|
* Client id will mostly be used when doing auth flow
|
|
54
64
|
*/
|
|
@@ -108,7 +118,6 @@ export declare class OpenId4VcIssuanceSessionRecord extends BaseRecord<DefaultOp
|
|
|
108
118
|
codeChallengeMethod: PkceCodeChallengeMethod;
|
|
109
119
|
codeChallenge: string;
|
|
110
120
|
};
|
|
111
|
-
dpopRequired?: boolean;
|
|
112
121
|
/**
|
|
113
122
|
* Authorization code flow specific metadata values
|
|
114
123
|
*/
|
|
@@ -145,5 +154,7 @@ export declare class OpenId4VcIssuanceSessionRecord extends BaseRecord<DefaultOp
|
|
|
145
154
|
preAuthorizedCode: string | undefined;
|
|
146
155
|
issuerState: string | undefined;
|
|
147
156
|
authorizationCode: string | undefined;
|
|
157
|
+
authorizationSubject: string | undefined;
|
|
158
|
+
presentationAuthSession: string | undefined;
|
|
148
159
|
};
|
|
149
160
|
}
|
|
@@ -31,7 +31,6 @@ class OpenId4VcIssuanceSessionRecord extends core_1.BaseRecord {
|
|
|
31
31
|
this.userPin = props.userPin;
|
|
32
32
|
this.preAuthorizedCode = props.preAuthorizedCode;
|
|
33
33
|
this.pkce = props.pkce;
|
|
34
|
-
this.dpopRequired = props.dpopRequired;
|
|
35
34
|
this.authorization = props.authorization;
|
|
36
35
|
this.credentialOfferUri = props.credentialOfferUri;
|
|
37
36
|
this.credentialOfferPayload = props.credentialOfferPayload;
|
|
@@ -49,12 +48,14 @@ class OpenId4VcIssuanceSessionRecord extends core_1.BaseRecord {
|
|
|
49
48
|
}
|
|
50
49
|
}
|
|
51
50
|
getTags() {
|
|
52
|
-
var _a, _b;
|
|
51
|
+
var _a, _b, _c, _d;
|
|
53
52
|
return Object.assign(Object.assign({}, this._tags), { issuerId: this.issuerId, credentialOfferUri: this.credentialOfferUri, state: this.state,
|
|
54
53
|
// Pre-auth flow
|
|
55
54
|
preAuthorizedCode: this.preAuthorizedCode,
|
|
56
55
|
// Auth flow
|
|
57
|
-
issuerState: (_a = this.authorization) === null || _a === void 0 ? void 0 : _a.issuerState, authorizationCode: (_b = this.authorization) === null || _b === void 0 ? void 0 : _b.code
|
|
56
|
+
issuerState: (_a = this.authorization) === null || _a === void 0 ? void 0 : _a.issuerState, authorizationCode: (_b = this.authorization) === null || _b === void 0 ? void 0 : _b.code, authorizationSubject: (_c = this.authorization) === null || _c === void 0 ? void 0 : _c.subject,
|
|
57
|
+
// Presentation during issuance
|
|
58
|
+
presentationAuthSession: (_d = this.presentation) === null || _d === void 0 ? void 0 : _d.authSession });
|
|
58
59
|
}
|
|
59
60
|
}
|
|
60
61
|
exports.OpenId4VcIssuanceSessionRecord = OpenId4VcIssuanceSessionRecord;
|
|
@@ -69,4 +70,19 @@ __decorate([
|
|
|
69
70
|
}),
|
|
70
71
|
__metadata("design:type", String)
|
|
71
72
|
], OpenId4VcIssuanceSessionRecord.prototype, "state", void 0);
|
|
73
|
+
__decorate([
|
|
74
|
+
(0, class_transformer_1.Transform)(({ type, value }) => {
|
|
75
|
+
if (type === class_transformer_1.TransformationType.PLAIN_TO_CLASS && (0, core_1.isJsonObject)(value) && typeof value.codeExpiresAt === 'string') {
|
|
76
|
+
return Object.assign(Object.assign({}, value), { codeExpiresAt: new Date(value.codeExpiresAt) });
|
|
77
|
+
}
|
|
78
|
+
if (type === class_transformer_1.TransformationType.CLASS_TO_CLASS && (0, core_1.isJsonObject)(value) && value.codeExpiresAt instanceof Date) {
|
|
79
|
+
return Object.assign(Object.assign({}, value), { codeExpiresAt: new Date(value.codeExpiresAt.getTime()) });
|
|
80
|
+
}
|
|
81
|
+
if (type === class_transformer_1.TransformationType.CLASS_TO_PLAIN && (0, core_1.isJsonObject)(value) && value.codeExpiresAt instanceof Date) {
|
|
82
|
+
return Object.assign(Object.assign({}, value), { codeExpiresAt: value.codeExpiresAt.toISOString() });
|
|
83
|
+
}
|
|
84
|
+
return value;
|
|
85
|
+
}),
|
|
86
|
+
__metadata("design:type", Object)
|
|
87
|
+
], OpenId4VcIssuanceSessionRecord.prototype, "authorization", void 0);
|
|
72
88
|
//# sourceMappingURL=OpenId4VcIssuanceSessionRecord.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"OpenId4VcIssuanceSessionRecord.js","sourceRoot":"","sources":["../../../src/openid4vc-issuer/repository/OpenId4VcIssuanceSessionRecord.ts"],"names":[],"mappings":";;;;;;;;;;;;AAIA,
|
|
1
|
+
{"version":3,"file":"OpenId4VcIssuanceSessionRecord.js","sourceRoot":"","sources":["../../../src/openid4vc-issuer/repository/OpenId4VcIssuanceSessionRecord.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { OpenId4VciAuthorizationServerConfig, OpenId4VciCredentialConfigurationsSupportedWithFormats, OpenId4VciCredentialIssuerMetadataDisplay } from '../../shared';
|
|
2
|
+
import type { OpenId4VciBatchCredentialIssuanceOptions } from '../OpenId4VcIssuerServiceOptions';
|
|
2
3
|
import type { JwaSignatureAlgorithm, RecordTags, TagsBase } from '@credo-ts/core';
|
|
3
4
|
import { BaseRecord } from '@credo-ts/core';
|
|
4
5
|
export type OpenId4VcIssuerRecordTags = RecordTags<OpenId4VcIssuerRecord>;
|
|
@@ -23,9 +24,13 @@ export type OpenId4VcIssuerRecordProps = {
|
|
|
23
24
|
display?: OpenId4VciCredentialIssuerMetadataDisplay[];
|
|
24
25
|
authorizationServerConfigs?: OpenId4VciAuthorizationServerConfig[];
|
|
25
26
|
credentialConfigurationsSupported: OpenId4VciCredentialConfigurationsSupportedWithFormats;
|
|
27
|
+
/**
|
|
28
|
+
* Indicate support for batch issuane of credentials
|
|
29
|
+
*/
|
|
30
|
+
batchCredentialIssuance?: OpenId4VciBatchCredentialIssuanceOptions;
|
|
26
31
|
};
|
|
27
32
|
/**
|
|
28
|
-
* For OID4VC you need to
|
|
33
|
+
* For OID4VC you need to expose metadata files. Each issuer needs to host this metadata. This is not the case for DIDComm where we can just have one /didcomm endpoint.
|
|
29
34
|
* So we create a record per openid issuer/verifier that you want, and each tenant can create multiple issuers/verifiers which have different endpoints
|
|
30
35
|
* and metadata files
|
|
31
36
|
* */
|
|
@@ -34,11 +39,16 @@ export declare class OpenId4VcIssuerRecord extends BaseRecord<DefaultOpenId4VcIs
|
|
|
34
39
|
readonly type = "OpenId4VcIssuerRecord";
|
|
35
40
|
issuerId: string;
|
|
36
41
|
accessTokenPublicKeyFingerprint: string;
|
|
37
|
-
|
|
38
|
-
|
|
42
|
+
/**
|
|
43
|
+
* Only here for class transformation. If credentialsSupported is set we transform
|
|
44
|
+
* it to the new credentialConfigurationsSupported format
|
|
45
|
+
*/
|
|
46
|
+
private set credentialsSupported(value);
|
|
47
|
+
credentialConfigurationsSupported: OpenId4VciCredentialConfigurationsSupportedWithFormats;
|
|
39
48
|
display?: OpenId4VciCredentialIssuerMetadataDisplay[];
|
|
40
49
|
authorizationServerConfigs?: OpenId4VciAuthorizationServerConfig[];
|
|
41
50
|
dpopSigningAlgValuesSupported?: [JwaSignatureAlgorithm, ...JwaSignatureAlgorithm[]];
|
|
51
|
+
batchCredentialIssuance?: OpenId4VciBatchCredentialIssuanceOptions;
|
|
42
52
|
constructor(props: OpenId4VcIssuerRecordProps);
|
|
43
53
|
getTags(): {
|
|
44
54
|
issuerId: string;
|
|
@@ -1,13 +1,46 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
3
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
4
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
5
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
6
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
7
|
+
};
|
|
8
|
+
var __metadata = (this && this.__metadata) || function (k, v) {
|
|
9
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
10
|
+
};
|
|
11
|
+
var __rest = (this && this.__rest) || function (s, e) {
|
|
12
|
+
var t = {};
|
|
13
|
+
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
|
|
14
|
+
t[p] = s[p];
|
|
15
|
+
if (s != null && typeof Object.getOwnPropertySymbols === "function")
|
|
16
|
+
for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
|
|
17
|
+
if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
|
|
18
|
+
t[p[i]] = s[p[i]];
|
|
19
|
+
}
|
|
20
|
+
return t;
|
|
21
|
+
};
|
|
2
22
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
23
|
exports.OpenId4VcIssuerRecord = void 0;
|
|
24
|
+
const oid4vci_1 = require("@animo-id/oid4vci");
|
|
4
25
|
const core_1 = require("@credo-ts/core");
|
|
26
|
+
const class_transformer_1 = require("class-transformer");
|
|
5
27
|
/**
|
|
6
|
-
* For OID4VC you need to
|
|
28
|
+
* For OID4VC you need to expose metadata files. Each issuer needs to host this metadata. This is not the case for DIDComm where we can just have one /didcomm endpoint.
|
|
7
29
|
* So we create a record per openid issuer/verifier that you want, and each tenant can create multiple issuers/verifiers which have different endpoints
|
|
8
30
|
* and metadata files
|
|
9
31
|
* */
|
|
10
32
|
class OpenId4VcIssuerRecord extends core_1.BaseRecord {
|
|
33
|
+
/**
|
|
34
|
+
* Only here for class transformation. If credentialsSupported is set we transform
|
|
35
|
+
* it to the new credentialConfigurationsSupported format
|
|
36
|
+
*/
|
|
37
|
+
set credentialsSupported(credentialsSupported) {
|
|
38
|
+
if (this.credentialConfigurationsSupported)
|
|
39
|
+
return;
|
|
40
|
+
this.credentialConfigurationsSupported =
|
|
41
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
42
|
+
(0, oid4vci_1.credentialsSupportedToCredentialConfigurationsSupported)(credentialsSupported);
|
|
43
|
+
}
|
|
11
44
|
constructor(props) {
|
|
12
45
|
var _a, _b, _c;
|
|
13
46
|
super();
|
|
@@ -22,6 +55,7 @@ class OpenId4VcIssuerRecord extends core_1.BaseRecord {
|
|
|
22
55
|
this.dpopSigningAlgValuesSupported = props.dpopSigningAlgValuesSupported;
|
|
23
56
|
this.display = props.display;
|
|
24
57
|
this.authorizationServerConfigs = props.authorizationServerConfigs;
|
|
58
|
+
this.batchCredentialIssuance = props.batchCredentialIssuance;
|
|
25
59
|
}
|
|
26
60
|
}
|
|
27
61
|
getTags() {
|
|
@@ -30,4 +64,20 @@ class OpenId4VcIssuerRecord extends core_1.BaseRecord {
|
|
|
30
64
|
}
|
|
31
65
|
exports.OpenId4VcIssuerRecord = OpenId4VcIssuerRecord;
|
|
32
66
|
OpenId4VcIssuerRecord.type = 'OpenId4VcIssuerRecord';
|
|
67
|
+
__decorate([
|
|
68
|
+
(0, class_transformer_1.Transform)(({ type, value }) => {
|
|
69
|
+
if (type === class_transformer_1.TransformationType.PLAIN_TO_CLASS && Array.isArray(value)) {
|
|
70
|
+
return value.map((display) => {
|
|
71
|
+
var _a, _b;
|
|
72
|
+
if ((_a = display.logo) === null || _a === void 0 ? void 0 : _a.uri)
|
|
73
|
+
return display;
|
|
74
|
+
const _c = (_b = display.logo) !== null && _b !== void 0 ? _b : {}, { url } = _c, logoRest = __rest(_c, ["url"]);
|
|
75
|
+
return Object.assign(Object.assign({}, display), { logo: url
|
|
76
|
+
? Object.assign(Object.assign({}, logoRest), { uri: url }) : undefined });
|
|
77
|
+
});
|
|
78
|
+
}
|
|
79
|
+
return value;
|
|
80
|
+
}),
|
|
81
|
+
__metadata("design:type", Array)
|
|
82
|
+
], OpenId4VcIssuerRecord.prototype, "display", void 0);
|
|
33
83
|
//# sourceMappingURL=OpenId4VcIssuerRecord.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"OpenId4VcIssuerRecord.js","sourceRoot":"","sources":["../../../src/openid4vc-issuer/repository/OpenId4VcIssuerRecord.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"OpenId4VcIssuerRecord.js","sourceRoot":"","sources":["../../../src/openid4vc-issuer/repository/OpenId4VcIssuerRecord.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;AAQA,+CAA2F;AAC3F,yCAAkD;AAClD,yDAAiE;AAsCjE;;;;KAIK;AACL,MAAa,qBAAsB,SAAQ,iBAA4C;IAOrF;;;OAGG;IACH,IAAY,oBAAoB,CAAC,oBAAoC;QACnE,IAAI,IAAI,CAAC,iCAAiC;YAAE,OAAM;QAElD,IAAI,CAAC,iCAAiC;YACpC,8DAA8D;YAC9D,IAAA,iEAAuD,EAAC,oBAA2B,CAAQ,CAAA;IAC/F,CAAC;IA8BD,YAAmB,KAAiC;;QAClD,KAAK,EAAE,CAAA;QA9CO,SAAI,GAAG,qBAAqB,CAAC,IAAI,CAAA;QAgD/C,IAAI,KAAK,EAAE,CAAC;YACV,IAAI,CAAC,EAAE,GAAG,MAAA,KAAK,CAAC,EAAE,mCAAI,YAAK,CAAC,IAAI,EAAE,CAAA;YAClC,IAAI,CAAC,SAAS,GAAG,MAAA,KAAK,CAAC,SAAS,mCAAI,IAAI,IAAI,EAAE,CAAA;YAC9C,IAAI,CAAC,KAAK,GAAG,MAAA,KAAK,CAAC,IAAI,mCAAI,EAAE,CAAA;YAE7B,IAAI,CAAC,QAAQ,GAAG,KAAK,CAAC,QAAQ,CAAA;YAC9B,IAAI,CAAC,+BAA+B,GAAG,KAAK,CAAC,+BAA+B,CAAA;YAC5E,IAAI,CAAC,iCAAiC,GAAG,KAAK,CAAC,iCAAiC,CAAA;YAChF,IAAI,CAAC,6BAA6B,GAAG,KAAK,CAAC,6BAA6B,CAAA;YACxE,IAAI,CAAC,OAAO,GAAG,KAAK,CAAC,OAAO,CAAA;YAC5B,IAAI,CAAC,0BAA0B,GAAG,KAAK,CAAC,0BAA0B,CAAA;YAClE,IAAI,CAAC,uBAAuB,GAAG,KAAK,CAAC,uBAAuB,CAAA;QAC9D,CAAC;IACH,CAAC;IAEM,OAAO;QACZ,uCACK,IAAI,CAAC,KAAK,KACb,QAAQ,EAAE,IAAI,CAAC,QAAQ,IACxB;IACH,CAAC;;AAtEH,sDAuEC;AAtEwB,0BAAI,GAAG,uBAAuB,AAA1B,CAA0B;AAyC9C;IApBN,IAAA,6BAAS,EAAC,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,EAAE,EAAE;QAC7B,IAAI,IAAI,KAAK,sCAAkB,CAAC,cAAc,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;YACvE,OAAO,KAAK,CAAC,GAAG,CAAC,CAAC,OAAO,EAAE,EAAE;;gBAC3B,IAAI,MAAA,OAAO,CAAC,IAAI,0CAAE,GAAG;oBAAE,OAAO,OAAO,CAAA;gBAErC,MAAM,KAAuB,MAAA,OAAO,CAAC,IAAI,mCAAI,EAAE,EAAzC,EAAE,GAAG,OAAoC,EAA/B,QAAQ,cAAlB,OAAoB,CAAqB,CAAA;gBAC/C,uCACK,OAAO,KACV,IAAI,EAAE,GAAG;wBACP,CAAC,iCACM,QAAQ,KACX,GAAG,EAAE,GAAG,IAEZ,CAAC,CAAC,SAAS,IACd;YACH,CAAC,CAAC,CAAA;QACJ,CAAC;QAED,OAAO,KAAK,CAAA;IACd,CAAC,CAAC;;sDAC0D"}
|
|
@@ -3,7 +3,6 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.configureAccessTokenEndpoint = configureAccessTokenEndpoint;
|
|
4
4
|
exports.handleTokenRequest = handleTokenRequest;
|
|
5
5
|
const oauth2_1 = require("@animo-id/oauth2");
|
|
6
|
-
const oid4vci_1 = require("@animo-id/oid4vci");
|
|
7
6
|
const core_1 = require("@credo-ts/core");
|
|
8
7
|
const router_1 = require("../../shared/router");
|
|
9
8
|
const utils_1 = require("../../shared/utils");
|
|
@@ -15,7 +14,7 @@ function configureAccessTokenEndpoint(router, config) {
|
|
|
15
14
|
}
|
|
16
15
|
function handleTokenRequest(config) {
|
|
17
16
|
return async (request, response, next) => {
|
|
18
|
-
var _a, _b, _c;
|
|
17
|
+
var _a, _b, _c, _d;
|
|
19
18
|
response.set({ 'Cache-Control': 'no-store', Pragma: 'no-cache' });
|
|
20
19
|
const requestContext = (0, router_1.getRequestContext)(request);
|
|
21
20
|
const { agentContext, issuer } = requestContext;
|
|
@@ -32,7 +31,6 @@ function handleTokenRequest(config) {
|
|
|
32
31
|
method: request.method,
|
|
33
32
|
url: fullRequestUrl,
|
|
34
33
|
};
|
|
35
|
-
// What error does this throw?
|
|
36
34
|
const { accessTokenRequest, grant, dpopJwt, pkceCodeVerifier } = oauth2AuthorizationServer.parseAccessTokenRequest({
|
|
37
35
|
accessTokenRequest: request.body,
|
|
38
36
|
request: requestLike,
|
|
@@ -50,6 +48,16 @@ function handleTokenRequest(config) {
|
|
|
50
48
|
error_description: 'Invalid authorization code',
|
|
51
49
|
});
|
|
52
50
|
}
|
|
51
|
+
if (Date.now() >
|
|
52
|
+
(0, utils_1.addSecondsToDate)(issuanceSession.createdAt, config.statefullCredentialOfferExpirationInSeconds).getTime()) {
|
|
53
|
+
issuanceSession.errorMessage = 'Credential offer has expired';
|
|
54
|
+
await openId4VcIssuerService.updateState(agentContext, issuanceSession, OpenId4VcIssuanceSessionState_1.OpenId4VcIssuanceSessionState.Error);
|
|
55
|
+
throw new oauth2_1.Oauth2ServerErrorResponseError({
|
|
56
|
+
// What is the best error here?
|
|
57
|
+
error: oauth2_1.Oauth2ErrorCodes.InvalidGrant,
|
|
58
|
+
error_description: 'Session expired',
|
|
59
|
+
});
|
|
60
|
+
}
|
|
53
61
|
let verificationResult;
|
|
54
62
|
try {
|
|
55
63
|
if (grant.grantType === oauth2_1.preAuthorizedCodeGrantIdentifier) {
|
|
@@ -68,10 +76,12 @@ function handleTokenRequest(config) {
|
|
|
68
76
|
request: requestLike,
|
|
69
77
|
dpop: {
|
|
70
78
|
jwt: dpopJwt,
|
|
71
|
-
|
|
79
|
+
// This will only have effect when DPoP is not present.
|
|
80
|
+
// If it is present it will always be verified
|
|
81
|
+
required: config.dpopRequired,
|
|
72
82
|
},
|
|
73
83
|
expectedTxCode: issuanceSession.userPin,
|
|
74
|
-
preAuthorizedCodeExpiresAt: (0, utils_1.addSecondsToDate)(issuanceSession.createdAt, config.
|
|
84
|
+
preAuthorizedCodeExpiresAt: (0, utils_1.addSecondsToDate)(issuanceSession.createdAt, config.statefullCredentialOfferExpirationInSeconds),
|
|
75
85
|
});
|
|
76
86
|
}
|
|
77
87
|
else if (grant.grantType === oauth2_1.authorizationCodeGrantIdentifier) {
|
|
@@ -91,7 +101,9 @@ function handleTokenRequest(config) {
|
|
|
91
101
|
request: requestLike,
|
|
92
102
|
dpop: {
|
|
93
103
|
jwt: dpopJwt,
|
|
94
|
-
|
|
104
|
+
// This will only have effect when DPoP is not present.
|
|
105
|
+
// If it is present it will always be verified
|
|
106
|
+
required: config.dpopRequired,
|
|
95
107
|
},
|
|
96
108
|
pkce: issuanceSession.pkce
|
|
97
109
|
? {
|
|
@@ -110,35 +122,34 @@ function handleTokenRequest(config) {
|
|
|
110
122
|
}
|
|
111
123
|
await openId4VcIssuerService.updateState(agentContext, issuanceSession, OpenId4VcIssuanceSessionState_1.OpenId4VcIssuanceSessionState.AccessTokenRequested);
|
|
112
124
|
const { cNonce, cNonceExpiresInSeconds } = await openId4VcIssuerService.createNonce(agentContext, issuer);
|
|
113
|
-
//
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
});
|
|
125
|
+
// for authorization code flow we take the authorization scopes. For pre-auth we don't use scopes (we just
|
|
126
|
+
// use the offered credential configuration ids so a scope is not required)
|
|
127
|
+
const scopes = grant.grantType === oauth2_1.authorizationCodeGrantIdentifier ? (_c = issuanceSession.authorization) === null || _c === void 0 ? void 0 : _c.scopes : undefined;
|
|
128
|
+
const subject = `credo:${core_1.utils.uuid()}`;
|
|
118
129
|
const signerJwk = (0, core_1.getJwkFromKey)(accessTokenSigningKey);
|
|
119
130
|
const accessTokenResponse = await oauth2AuthorizationServer.createAccessTokenResponse({
|
|
120
131
|
audience: issuerMetadata.credentialIssuer.credential_issuer,
|
|
121
132
|
authorizationServer: issuerMetadata.credentialIssuer.credential_issuer,
|
|
122
133
|
expiresInSeconds: config.accessTokenExpiresInSeconds,
|
|
123
|
-
// TODO: we need to include kid and also host the jwks?
|
|
124
|
-
// Or we should somehow bypass the jwks_uri resolving if we verify our own token (only we will verify the token)
|
|
125
134
|
signer: {
|
|
126
135
|
method: 'jwk',
|
|
127
136
|
alg: signerJwk.supportedSignatureAlgorithms[0],
|
|
128
137
|
publicJwk: signerJwk.toJson(),
|
|
129
138
|
},
|
|
130
139
|
dpopJwk: verificationResult.dpopJwk,
|
|
131
|
-
scope: scopes === null || scopes === void 0 ? void 0 : scopes.join('
|
|
140
|
+
scope: scopes === null || scopes === void 0 ? void 0 : scopes.join(' '),
|
|
132
141
|
clientId: issuanceSession.clientId,
|
|
133
142
|
additionalAccessTokenPayload: {
|
|
134
143
|
'pre-authorized_code': grant.grantType === oauth2_1.preAuthorizedCodeGrantIdentifier ? grant.preAuthorizedCode : undefined,
|
|
135
|
-
issuer_state: (
|
|
144
|
+
issuer_state: (_d = issuanceSession.authorization) === null || _d === void 0 ? void 0 : _d.issuerState,
|
|
136
145
|
},
|
|
137
|
-
subject
|
|
146
|
+
// We generate a random subject for each access token and bind the issuance session to this.
|
|
147
|
+
subject,
|
|
138
148
|
// NOTE: these have been removed in newer drafts. Keeping them in for now
|
|
139
149
|
cNonce,
|
|
140
150
|
cNonceExpiresIn: cNonceExpiresInSeconds,
|
|
141
151
|
});
|
|
152
|
+
issuanceSession.authorization = Object.assign(Object.assign({}, issuanceSession.authorization), { subject });
|
|
142
153
|
await openId4VcIssuerService.updateState(agentContext, issuanceSession, OpenId4VcIssuanceSessionState_1.OpenId4VcIssuanceSessionState.AccessTokenCreated);
|
|
143
154
|
return (0, router_1.sendJsonResponse)(response, next, accessTokenResponse);
|
|
144
155
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"accessTokenEndpoint.js","sourceRoot":"","sources":["../../../src/openid4vc-issuer/router/accessTokenEndpoint.ts"],"names":[],"mappings":";;
|
|
1
|
+
{"version":3,"file":"accessTokenEndpoint.js","sourceRoot":"","sources":["../../../src/openid4vc-issuer/router/accessTokenEndpoint.ts"],"names":[],"mappings":"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"}
|
|
@@ -72,6 +72,16 @@ async function handleAuthorizationChallengeNoAuthSession(options) {
|
|
|
72
72
|
error_description: `Missing required 'issuer_state' parameter. Only requests initiated by a credential offer are supported for authorization challenge.`,
|
|
73
73
|
});
|
|
74
74
|
}
|
|
75
|
+
// FIXME: we need to authenticate the client. Could be either using client_id/client_secret
|
|
76
|
+
// but that doesn't make sense for wallets. So for now we just allow any client_id and we will
|
|
77
|
+
// need OAuth2 Attestation Based Client Auth and dynamically allow client_ids based on wallet providers
|
|
78
|
+
// we trust. Will add this in a follow up PR (basically we do no client authentication at the moment)
|
|
79
|
+
// if (!authorizationChallengeRequest.client_id) {
|
|
80
|
+
// throw new Oauth2ServerErrorResponseError({
|
|
81
|
+
// error: Oauth2ErrorCodes.InvalidRequest,
|
|
82
|
+
// error_description: `Missing required 'client_id' parameter..`,
|
|
83
|
+
// })
|
|
84
|
+
// }
|
|
75
85
|
const issuanceSession = await openId4VcIssuerService.findSingleIssuancSessionByQuery(agentContext, {
|
|
76
86
|
issuerId: issuer.issuerId,
|
|
77
87
|
issuerState: authorizationChallengeRequest.issuer_state,
|
|
@@ -88,8 +98,6 @@ async function handleAuthorizationChallengeNoAuthSession(options) {
|
|
|
88
98
|
});
|
|
89
99
|
}
|
|
90
100
|
const offeredCredentialConfigurations = (0, shared_1.getOfferedCredentials)(issuanceSession.credentialOfferPayload.credential_configuration_ids, issuerMetadata.credentialIssuer.credential_configurations_supported);
|
|
91
|
-
// NOTE: for now we assume all credential configurations that were offered have a scope (should
|
|
92
|
-
// be checked when creating offer that requires presentation)
|
|
93
101
|
const allowedScopes = (0, shared_1.getScopesFromCredentialConfigurationsSupported)(offeredCredentialConfigurations);
|
|
94
102
|
const requestedScopes = (0, shared_1.getAllowedAndRequestedScopeValues)({
|
|
95
103
|
allowedScopes,
|
|
@@ -102,18 +110,26 @@ async function handleAuthorizationChallengeNoAuthSession(options) {
|
|
|
102
110
|
error_description: `No requested 'scope' values match with offered credential configurations.`,
|
|
103
111
|
});
|
|
104
112
|
}
|
|
105
|
-
const { authorizationRequest, verificationSession } = await config.getVerificationSessionForIssuanceSessionAuthorization({
|
|
113
|
+
const { authorizationRequest, verificationSession, scopes: presentationScopes, } = await config.getVerificationSessionForIssuanceSessionAuthorization({
|
|
106
114
|
agentContext,
|
|
107
115
|
issuanceSession,
|
|
108
116
|
requestedCredentialConfigurations,
|
|
109
117
|
scopes: requestedScopes,
|
|
110
118
|
});
|
|
119
|
+
// Store presentation during issuance session on the record
|
|
120
|
+
verificationSession.presentationDuringIssuanceSession = core_1.TypedArrayEncoder.toBase64URL(agentContext.wallet.getRandomValues(32));
|
|
121
|
+
await agentContext.dependencyManager
|
|
122
|
+
.resolve(openid4vc_verifier_1.OpenId4VcVerificationSessionRepository)
|
|
123
|
+
.update(agentContext, verificationSession);
|
|
111
124
|
const authSession = core_1.TypedArrayEncoder.toBase64URL(agentContext.wallet.getRandomValues(32));
|
|
125
|
+
issuanceSession.authorization = Object.assign(Object.assign({}, issuanceSession.authorization), { scopes: presentationScopes });
|
|
112
126
|
issuanceSession.presentation = {
|
|
113
127
|
required: true,
|
|
114
128
|
authSession,
|
|
115
129
|
openId4VcVerificationSessionId: verificationSession.id,
|
|
116
130
|
};
|
|
131
|
+
// NOTE: should only allow authenticated clients in the future.
|
|
132
|
+
issuanceSession.clientId = authorizationChallengeRequest.client_id;
|
|
117
133
|
await openId4VcIssuerService.updateState(agentContext, issuanceSession, OpenId4VcIssuanceSessionState_1.OpenId4VcIssuanceSessionState.AuthorizationInitiated);
|
|
118
134
|
const authorizationChallengeErrorResponse = authorizationServer.createAuthorizationChallengePresentationErrorResponse({
|
|
119
135
|
authSession,
|
|
@@ -132,14 +148,13 @@ async function handleAuthorizationChallengeWithAuthSession(options) {
|
|
|
132
148
|
// should we validate that these are not in the request? I'm not sure what best practive would be here
|
|
133
149
|
const issuanceSession = await openId4VcIssuerService.findSingleIssuancSessionByQuery(agentContext, {
|
|
134
150
|
issuerId: issuer.issuerId,
|
|
135
|
-
|
|
151
|
+
presentationAuthSession: authorizationChallengeRequest.auth_session,
|
|
136
152
|
});
|
|
137
153
|
const allowedStates = [OpenId4VcIssuanceSessionState_1.OpenId4VcIssuanceSessionState.AuthorizationInitiated];
|
|
138
|
-
if (!issuanceSession ||
|
|
139
|
-
!issuanceSession.presentation ||
|
|
154
|
+
if (!(issuanceSession === null || issuanceSession === void 0 ? void 0 : issuanceSession.presentation) ||
|
|
140
155
|
!issuanceSession.presentation.openId4VcVerificationSessionId ||
|
|
141
156
|
!issuanceSession.presentation.authSession ||
|
|
142
|
-
allowedStates.includes(issuanceSession.state)) {
|
|
157
|
+
!allowedStates.includes(issuanceSession.state)) {
|
|
143
158
|
throw new oauth2_1.Oauth2ServerErrorResponseError({
|
|
144
159
|
error: oauth2_1.Oauth2ErrorCodes.InvalidSession,
|
|
145
160
|
error_description: `Invalid 'auth_session'`,
|
|
@@ -168,16 +183,19 @@ async function handleAuthorizationChallengeWithAuthSession(options) {
|
|
|
168
183
|
.then(async (verificationSession) => {
|
|
169
184
|
// Issuance session cannot be used anymore
|
|
170
185
|
if (verificationSession.state === openid4vc_verifier_1.OpenId4VcVerificationSessionState.Error) {
|
|
171
|
-
issuanceSession.errorMessage = `Associated
|
|
186
|
+
issuanceSession.errorMessage = `Associated openId4VcVerificationSessionRecord with id '${openId4VcVerificationSessionId}' has error state`;
|
|
172
187
|
await openId4VcIssuerService.updateState(agentContext, issuanceSession, OpenId4VcIssuanceSessionState_1.OpenId4VcIssuanceSessionState.Error);
|
|
173
188
|
}
|
|
174
|
-
if (verificationSession.state !== openid4vc_verifier_1.OpenId4VcVerificationSessionState.ResponseVerified
|
|
189
|
+
if (verificationSession.state !== openid4vc_verifier_1.OpenId4VcVerificationSessionState.ResponseVerified ||
|
|
190
|
+
authorizationChallengeRequest.presentation_during_issuance_session !==
|
|
191
|
+
verificationSession.presentationDuringIssuanceSession) {
|
|
175
192
|
throw new oauth2_1.Oauth2ServerErrorResponseError({
|
|
176
|
-
// InsufficentAuthorization?
|
|
177
193
|
error: oauth2_1.Oauth2ErrorCodes.InvalidSession,
|
|
178
|
-
error_description: `Invalid 'auth_session'`,
|
|
194
|
+
error_description: `Invalid presentation for 'auth_session'`,
|
|
179
195
|
}, {
|
|
180
|
-
internalMessage:
|
|
196
|
+
internalMessage: verificationSession.state !== openid4vc_verifier_1.OpenId4VcVerificationSessionState.ResponseVerified
|
|
197
|
+
? `Openid4vc verification session with id '${openId4VcVerificationSessionId}' has state '${verificationSession.state}', while '${openid4vc_verifier_1.OpenId4VcVerificationSessionState.ResponseVerified}' was expected.`
|
|
198
|
+
: `Openid4vc verification session with id '${openId4VcVerificationSessionId}' has 'presentation_during_issuance_session' '${verificationSession.presentationDuringIssuanceSession}', but authorization challenge request provided value '${authorizationChallengeRequest.presentation_during_issuance_session}'.`,
|
|
181
199
|
});
|
|
182
200
|
}
|
|
183
201
|
});
|
|
@@ -187,7 +205,7 @@ async function handleAuthorizationChallengeWithAuthSession(options) {
|
|
|
187
205
|
issuanceSession.authorization = Object.assign(Object.assign({}, issuanceSession.authorization), { code: authorizationCode, codeExpiresAt: authorizationCodeExpiresAt });
|
|
188
206
|
// TODO: we need to start using locks so we can't get corrupted state
|
|
189
207
|
await openId4VcIssuerService.updateState(agentContext, issuanceSession, OpenId4VcIssuanceSessionState_1.OpenId4VcIssuanceSessionState.AuthorizationGranted);
|
|
190
|
-
const authorizationChallengeResponse = authorizationServer.createAuthorizationChallengeResponse({
|
|
208
|
+
const { authorizationChallengeResponse } = authorizationServer.createAuthorizationChallengeResponse({
|
|
191
209
|
authorizationCode,
|
|
192
210
|
});
|
|
193
211
|
return (0, router_1.sendJsonResponse)(response, next, authorizationChallengeResponse);
|