Skip to content

Commit 0936d5d

Browse files
committed
feat: OID4VCI Rest API session improvements and delete endpoint
1 parent 5194986 commit 0936d5d

35 files changed

+535
-457
lines changed

packages/client/lib/AuthorizationCodeClient.ts

Lines changed: 30 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -26,11 +26,11 @@ import {
2626
PKCEOpts,
2727
PushedAuthorizationResponse,
2828
RequestObjectOpts,
29-
ResponseType
30-
} from '@sphereon/oid4vci-common'
29+
ResponseType,
30+
} from '@sphereon/oid4vci-common';
3131
import Debug from 'debug';
3232

33-
import { MetadataClient } from './MetadataClient'
33+
import { MetadataClient } from './MetadataClient';
3434
import { ProofOfPossessionBuilder } from './ProofOfPossessionBuilder';
3535

3636
const debug = Debug('sphereon:oid4vci');
@@ -280,62 +280,51 @@ const handleLocations = (endpointMetadata: EndpointMetadataResultV1_0_13, author
280280
return authorizationDetails;
281281
};
282282

283-
export const acquireAuthorizationChallengeAuthCode = async (opts: AuthorizationChallengeRequestOpts): Promise<OpenIDResponse<AuthorizationChallengeCodeResponse>> => {
284-
const { metadata } = opts
283+
export const acquireAuthorizationChallengeAuthCode = async (
284+
opts: AuthorizationChallengeRequestOpts,
285+
): Promise<OpenIDResponse<AuthorizationChallengeCodeResponse>> => {
286+
const { metadata } = opts;
285287

286-
const issuer = opts.credentialIssuer ?? opts?.metadata?.issuer as string
288+
const issuer = opts.credentialIssuer ?? (opts?.metadata?.issuer as string);
287289
if (!issuer) {
288290
throw Error('Issuer required at this point');
289291
}
290292

291293
const issuerOpts = {
292294
issuer,
293-
}
295+
};
294296

295297
return await acquireAuthorizationChallengeAuthCodeUsingRequest({
296298
authorizationChallengeRequest: await createAuthorizationChallengeRequest(opts),
297299
metadata,
298-
issuerOpts
300+
issuerOpts,
299301
});
300-
}
302+
};
301303

302-
export const acquireAuthorizationChallengeAuthCodeUsingRequest = async (
303-
opts: {
304-
authorizationChallengeRequest: CommonAuthorizationChallengeRequest,
305-
metadata?: EndpointMetadata,
306-
issuerOpts?: IssuerOpts
307-
}
308-
): Promise<OpenIDResponse<AuthorizationChallengeCodeResponse>> => {
309-
const { authorizationChallengeRequest, issuerOpts } = opts
304+
export const acquireAuthorizationChallengeAuthCodeUsingRequest = async (opts: {
305+
authorizationChallengeRequest: CommonAuthorizationChallengeRequest;
306+
metadata?: EndpointMetadata;
307+
issuerOpts?: IssuerOpts;
308+
}): Promise<OpenIDResponse<AuthorizationChallengeCodeResponse>> => {
309+
const { authorizationChallengeRequest, issuerOpts } = opts;
310310
const metadata = opts?.metadata
311311
? opts?.metadata
312312
: issuerOpts?.fetchMetadata
313313
? await MetadataClient.retrieveAllMetadata(issuerOpts.issuer, { errorOnNotFound: false })
314-
: undefined
315-
const authorizationChallengeCodeUrl = metadata?.authorization_challenge_endpoint
314+
: undefined;
315+
const authorizationChallengeCodeUrl = metadata?.authorization_challenge_endpoint;
316316

317317
if (!authorizationChallengeCodeUrl) {
318-
return Promise.reject(Error('Cannot determine authorization challenge endpoint URL'))
318+
return Promise.reject(Error('Cannot determine authorization challenge endpoint URL'));
319319
}
320320

321-
const response = await sendAuthorizationChallengeRequest(
322-
authorizationChallengeCodeUrl,
323-
authorizationChallengeRequest
324-
);
321+
const response = await sendAuthorizationChallengeRequest(authorizationChallengeCodeUrl, authorizationChallengeRequest);
325322

326-
return response
327-
}
323+
return response;
324+
};
328325

329326
export const createAuthorizationChallengeRequest = async (opts: AuthorizationChallengeRequestOpts): Promise<CommonAuthorizationChallengeRequest> => {
330-
const {
331-
clientId,
332-
issuerState,
333-
authSession,
334-
scope,
335-
codeChallenge,
336-
codeChallengeMethod,
337-
presentationDuringIssuanceSession
338-
} = opts;
327+
const { clientId, issuerState, authSession, scope, codeChallenge, codeChallengeMethod, presentationDuringIssuanceSession } = opts;
339328

340329
const request: CommonAuthorizationChallengeRequest = {
341330
client_id: clientId,
@@ -344,18 +333,18 @@ export const createAuthorizationChallengeRequest = async (opts: AuthorizationCha
344333
scope,
345334
code_challenge: codeChallenge,
346335
code_challenge_method: codeChallengeMethod,
347-
presentation_during_issuance_session: presentationDuringIssuanceSession
348-
}
336+
presentation_during_issuance_session: presentationDuringIssuanceSession,
337+
};
349338

350-
return request
351-
}
339+
return request;
340+
};
352341

353342
export const sendAuthorizationChallengeRequest = async (
354343
authorizationChallengeCodeUrl: string,
355344
authorizationChallengeRequest: CommonAuthorizationChallengeRequest,
356-
opts?: { headers?: Record<string, string> }
345+
opts?: { headers?: Record<string, string> },
357346
): Promise<OpenIDResponse<AuthorizationChallengeCodeResponse>> => {
358347
return await formPost(authorizationChallengeCodeUrl, convertJsonToURI(authorizationChallengeRequest, { mode: JsonURIMode.X_FORM_WWW_URLENCODED }), {
359348
customHeaders: opts?.headers ? opts.headers : undefined,
360349
});
361-
}
350+
};

packages/client/lib/MetadataClient.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,7 @@ export class MetadataClient {
8585
if (credentialIssuerMetadata.token_endpoint) {
8686
token_endpoint = credentialIssuerMetadata.token_endpoint;
8787
}
88-
authorization_challenge_endpoint = credentialIssuerMetadata.authorization_challenge_endpoint
88+
authorization_challenge_endpoint = credentialIssuerMetadata.authorization_challenge_endpoint;
8989
if (credentialIssuerMetadata.authorization_servers) {
9090
authorization_servers = credentialIssuerMetadata.authorization_servers as string[];
9191
} else if (credentialIssuerMetadata.authorization_server) {

packages/client/lib/MetadataClientV1_0_11.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ export class MetadataClientV1_0_11 {
6262
if (credentialIssuerMetadata.token_endpoint) {
6363
token_endpoint = credentialIssuerMetadata.token_endpoint;
6464
}
65-
authorization_challenge_endpoint = credentialIssuerMetadata.authorization_challenge_endpoint
65+
authorization_challenge_endpoint = credentialIssuerMetadata.authorization_challenge_endpoint;
6666
if (credentialIssuerMetadata.authorization_server) {
6767
authorization_server = credentialIssuerMetadata.authorization_server;
6868
}

packages/client/lib/MetadataClientV1_0_13.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ export class MetadataClientV1_0_13 {
6262
if (credentialIssuerMetadata.token_endpoint) {
6363
token_endpoint = credentialIssuerMetadata.token_endpoint;
6464
}
65-
authorization_challenge_endpoint = credentialIssuerMetadata.authorization_challenge_endpoint
65+
authorization_challenge_endpoint = credentialIssuerMetadata.authorization_challenge_endpoint;
6666
if (credentialIssuerMetadata.authorization_servers) {
6767
authorization_servers = credentialIssuerMetadata.authorization_servers;
6868
}

packages/client/lib/OpenID4VCIClient.ts

Lines changed: 29 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -36,17 +36,14 @@ import {
3636
OpenId4VCIVersion,
3737
PKCEOpts,
3838
ProofOfPossessionCallbacks,
39-
toAuthorizationResponsePayload
40-
} from '@sphereon/oid4vci-common'
39+
toAuthorizationResponsePayload,
40+
} from '@sphereon/oid4vci-common';
4141
import { CredentialFormat } from '@sphereon/ssi-types';
4242
import Debug from 'debug';
4343

4444
import { AccessTokenClient } from './AccessTokenClient';
4545
import { AccessTokenClientV1_0_11 } from './AccessTokenClientV1_0_11';
46-
import {
47-
acquireAuthorizationChallengeAuthCode,
48-
createAuthorizationRequestUrl
49-
} from './AuthorizationCodeClient'
46+
import { acquireAuthorizationChallengeAuthCode, createAuthorizationRequestUrl } from './AuthorizationCodeClient';
5047
import { createAuthorizationRequestUrlV1_0_11 } from './AuthorizationCodeClientV1_0_11';
5148
import { CredentialOfferClient } from './CredentialOfferClient';
5249
import { CredentialRequestOpts } from './CredentialRequestClient';
@@ -136,7 +133,7 @@ export class OpenID4VCIClient {
136133
pkce,
137134
authorizationRequest,
138135
createAuthorizationRequestURL,
139-
endpointMetadata
136+
endpointMetadata,
140137
}: {
141138
credentialIssuer: string;
142139
kid?: string;
@@ -146,7 +143,7 @@ export class OpenID4VCIClient {
146143
createAuthorizationRequestURL?: boolean;
147144
authorizationRequest?: AuthorizationRequestOpts; // Can be provided here, or when manually calling createAuthorizationUrl
148145
pkce?: PKCEOpts;
149-
endpointMetadata?: EndpointMetadataResult
146+
endpointMetadata?: EndpointMetadataResult;
150147
}) {
151148
const client = new OpenID4VCIClient({
152149
kid,
@@ -155,7 +152,7 @@ export class OpenID4VCIClient {
155152
credentialIssuer,
156153
pkce,
157154
authorizationRequest,
158-
endpointMetadata
155+
endpointMetadata,
159156
});
160157
if (retrieveServerMetadata === undefined || retrieveServerMetadata) {
161158
await client.retrieveServerMetadata();
@@ -182,7 +179,7 @@ export class OpenID4VCIClient {
182179
createAuthorizationRequestURL,
183180
authorizationRequest,
184181
resolveOfferUri,
185-
endpointMetadata
182+
endpointMetadata,
186183
}: {
187184
uri: string;
188185
kid?: string;
@@ -193,7 +190,7 @@ export class OpenID4VCIClient {
193190
pkce?: PKCEOpts;
194191
clientId?: string;
195192
authorizationRequest?: AuthorizationRequestOpts; // Can be provided here, or when manually calling createAuthorizationUrl
196-
endpointMetadata?: EndpointMetadataResult
193+
endpointMetadata?: EndpointMetadataResult;
197194
}): Promise<OpenID4VCIClient> {
198195
const credentialOfferClient = await CredentialOfferClient.fromURI(uri, { resolve: resolveOfferUri });
199196
const client = new OpenID4VCIClient({
@@ -203,7 +200,7 @@ export class OpenID4VCIClient {
203200
clientId: clientId ?? authorizationRequest?.clientId ?? credentialOfferClient.clientId,
204201
pkce,
205202
authorizationRequest,
206-
endpointMetadata
203+
endpointMetadata,
207204
});
208205

209206
if (retrieveServerMetadata === undefined || retrieveServerMetadata) {
@@ -287,19 +284,23 @@ export class OpenID4VCIClient {
287284
metadata: this.endpointMetadata,
288285
credentialIssuer: this.getIssuer(),
289286
clientId: this._state.clientId ?? this._state.authorizationRequestOpts?.clientId,
290-
...opts
291-
})
287+
...opts,
288+
});
292289

293290
if (response.errorBody) {
294291
debug(`Authorization code error:\r\n${JSON.stringify(response.errorBody)}`);
295-
const error = response.errorBody as AuthorizationChallengeErrorResponse
296-
return Promise.reject(error)
292+
const error = response.errorBody as AuthorizationChallengeErrorResponse;
293+
return Promise.reject(error);
297294
} else if (!response.successBody) {
298295
debug(`Authorization code error. No success body`);
299-
return Promise.reject(Error(`Retrieving an authorization code token from ${this._state.endpointMetadata?.authorization_challenge_endpoint} for issuer ${this.getIssuer()} failed as there was no success response body`))
296+
return Promise.reject(
297+
Error(
298+
`Retrieving an authorization code token from ${this._state.endpointMetadata?.authorization_challenge_endpoint} for issuer ${this.getIssuer()} failed as there was no success response body`,
299+
),
300+
);
300301
}
301302

302-
return { ...response.successBody }
303+
return { ...response.successBody };
303304
}
304305

305306
public async acquireAccessToken(
@@ -312,7 +313,7 @@ export class OpenID4VCIClient {
312313
const { pin, clientId = this._state.clientId ?? this._state.authorizationRequestOpts?.clientId } = opts ?? {};
313314
let { redirectUri } = opts ?? {};
314315

315-
const code = this.getAuthorizationCode(opts?.authorizationResponse, opts?.code)
316+
const code = this.getAuthorizationCode(opts?.authorizationResponse, opts?.code);
316317

317318
if (opts?.codeVerifier) {
318319
this._state.pkce.codeVerifier = opts.codeVerifier;
@@ -765,13 +766,19 @@ export class OpenID4VCIClient {
765766
return authorizationRequestOpts;
766767
}
767768

768-
private getAuthorizationCode = (authorizationResponse?: string | AuthorizationResponse | AuthorizationChallengeCodeResponse, code?: string): string | undefined => {
769+
private getAuthorizationCode = (
770+
authorizationResponse?: string | AuthorizationResponse | AuthorizationChallengeCodeResponse,
771+
code?: string,
772+
): string | undefined => {
769773
if (authorizationResponse) {
770774
this._state.authorizationCodeResponse = { ...toAuthorizationResponsePayload(authorizationResponse) };
771775
} else if (code) {
772776
this._state.authorizationCodeResponse = { code };
773777
}
774778

775-
return (this._state.authorizationCodeResponse as AuthorizationResponse)?.code ?? (this._state.authorizationCodeResponse as AuthorizationChallengeCodeResponse)?.authorization_code;
776-
}
779+
return (
780+
(this._state.authorizationCodeResponse as AuthorizationResponse)?.code ??
781+
(this._state.authorizationCodeResponse as AuthorizationChallengeCodeResponse)?.authorization_code
782+
);
783+
};
777784
}

packages/client/lib/OpenID4VCIClientV1_0_11.ts

Lines changed: 23 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -30,13 +30,13 @@ import {
3030
OpenId4VCIVersion,
3131
PKCEOpts,
3232
ProofOfPossessionCallbacks,
33-
toAuthorizationResponsePayload
34-
} from '@sphereon/oid4vci-common'
33+
toAuthorizationResponsePayload,
34+
} from '@sphereon/oid4vci-common';
3535
import { CredentialFormat } from '@sphereon/ssi-types';
3636
import Debug from 'debug';
3737

3838
import { AccessTokenClientV1_0_11 } from './AccessTokenClientV1_0_11';
39-
import { acquireAuthorizationChallengeAuthCode } from './AuthorizationCodeClient'
39+
import { acquireAuthorizationChallengeAuthCode } from './AuthorizationCodeClient';
4040
import { createAuthorizationRequestUrlV1_0_11 } from './AuthorizationCodeClientV1_0_11';
4141
import { CredentialOfferClientV1_0_11 } from './CredentialOfferClientV1_0_11';
4242
import { CredentialRequestClientBuilderV1_0_11 } from './CredentialRequestClientBuilderV1_0_11';
@@ -265,19 +265,23 @@ export class OpenID4VCIClientV1_0_11 {
265265
metadata: this.endpointMetadata,
266266
credentialIssuer: this.getIssuer(),
267267
clientId: this._state.clientId ?? this._state.authorizationRequestOpts?.clientId,
268-
...opts
269-
})
268+
...opts,
269+
});
270270

271271
if (response.errorBody) {
272272
debug(`Authorization code error:\r\n${JSON.stringify(response.errorBody)}`);
273-
const error = response.errorBody as AuthorizationChallengeErrorResponse
274-
return Promise.reject(error)
273+
const error = response.errorBody as AuthorizationChallengeErrorResponse;
274+
return Promise.reject(error);
275275
} else if (!response.successBody) {
276276
debug(`Authorization code error. No success body`);
277-
return Promise.reject(Error(`Retrieving an authorization code token from ${this._state.endpointMetadata?.authorization_challenge_endpoint} for issuer ${this.getIssuer()} failed as there was no success response body`))
277+
return Promise.reject(
278+
Error(
279+
`Retrieving an authorization code token from ${this._state.endpointMetadata?.authorization_challenge_endpoint} for issuer ${this.getIssuer()} failed as there was no success response body`,
280+
),
281+
);
278282
}
279283

280-
return { ...response.successBody }
284+
return { ...response.successBody };
281285
}
282286

283287
public async acquireAccessToken(
@@ -290,7 +294,7 @@ export class OpenID4VCIClientV1_0_11 {
290294
const { pin, clientId = this._state.clientId ?? this._state.authorizationRequestOpts?.clientId } = opts ?? {};
291295
let { redirectUri } = opts ?? {};
292296

293-
const code = this.getAuthorizationCode(opts?.authorizationResponse, opts?.code)
297+
const code = this.getAuthorizationCode(opts?.authorizationResponse, opts?.code);
294298

295299
if (opts?.codeVerifier) {
296300
this._state.pkce.codeVerifier = opts.codeVerifier;
@@ -693,13 +697,19 @@ export class OpenID4VCIClientV1_0_11 {
693697
return authorizationRequestOpts;
694698
}
695699

696-
private getAuthorizationCode = (authorizationResponse?: string | AuthorizationResponse | AuthorizationChallengeCodeResponse, code?: string): string | undefined => {
700+
private getAuthorizationCode = (
701+
authorizationResponse?: string | AuthorizationResponse | AuthorizationChallengeCodeResponse,
702+
code?: string,
703+
): string | undefined => {
697704
if (authorizationResponse) {
698705
this._state.authorizationCodeResponse = { ...toAuthorizationResponsePayload(authorizationResponse) };
699706
} else if (code) {
700707
this._state.authorizationCodeResponse = { code };
701708
}
702709

703-
return (this._state.authorizationCodeResponse as AuthorizationResponse)?.code ?? (this._state.authorizationCodeResponse as AuthorizationChallengeCodeResponse)?.authorization_code;
704-
}
710+
return (
711+
(this._state.authorizationCodeResponse as AuthorizationResponse)?.code ??
712+
(this._state.authorizationCodeResponse as AuthorizationChallengeCodeResponse)?.authorization_code
713+
);
714+
};
705715
}

0 commit comments

Comments
 (0)