diff --git a/packages/client/lib/AccessTokenClient.ts b/packages/client/lib/AccessTokenClient.ts index d085089d..6e3f2c1f 100644 --- a/packages/client/lib/AccessTokenClient.ts +++ b/packages/client/lib/AccessTokenClient.ts @@ -176,14 +176,6 @@ export class AccessTokenClient { throw new Error('Authorization flow requires the code to be present'); } } - - private assertNonEmptyRedirectUri(accessTokenRequest: AccessTokenRequest): void { - if (!accessTokenRequest.redirect_uri) { - debug('No redirect_uri present, whilst it is required'); - throw new Error('Authorization flow requires the redirect_uri to be present'); - } - } - private validate(accessTokenRequest: AccessTokenRequest, isPinRequired?: boolean): void { if (accessTokenRequest.grant_type === GrantTypes.PRE_AUTHORIZED_CODE) { this.assertPreAuthorizedGrantType(accessTokenRequest.grant_type); @@ -193,7 +185,6 @@ export class AccessTokenClient { this.assertAuthorizationGrantType(accessTokenRequest.grant_type); this.assertNonEmptyCodeVerifier(accessTokenRequest); this.assertNonEmptyCode(accessTokenRequest); - this.assertNonEmptyRedirectUri(accessTokenRequest); } else { this.throwNotSupportedFlow(); } @@ -236,11 +227,14 @@ export class AccessTokenClient { private static creatTokenURLFromURL(url: string, allowInsecureEndpoints?: boolean, tokenEndpoint?: string): string { if (allowInsecureEndpoints !== true && url.startsWith('http:')) { - throw Error(`Unprotected token endpoints are not allowed ${url}. Adjust settings if you really need this (dev/test settings only!!)`); + throw Error( + `Unprotected token endpoints are not allowed ${url}. Use the 'allowInsecureEndpoints' param if you really need this for dev/testing!`, + ); } const hostname = url.replace(/https?:\/\//, '').replace(/\/$/, ''); const endpoint = tokenEndpoint ? (tokenEndpoint.startsWith('/') ? tokenEndpoint : tokenEndpoint.substring(1)) : '/token'; const scheme = url.split('://')[0]; + console.log(`scheme: ${scheme}, hostname: ${hostname}, endpoint: ${endpoint}`); return `${scheme ? scheme + '://' : 'https://'}${hostname}${endpoint}`; } diff --git a/packages/client/lib/AuthorizationCodeClient.ts b/packages/client/lib/AuthorizationCodeClient.ts index e47e22d3..1d68335a 100644 --- a/packages/client/lib/AuthorizationCodeClient.ts +++ b/packages/client/lib/AuthorizationCodeClient.ts @@ -104,7 +104,7 @@ export const createAuthorizationRequestUrl = async ({ console.log(`QUERY obj: ` + JSON.stringify(queryObj, null, 2)); const url = convertJsonToURI(queryObj, { baseUrl: endpointMetadata.authorization_endpoint, - uriTypeProperties: ['client_id', 'request_uri', 'redirect_uri', 'scope', 'authorization_details', 'issuer_state'], + uriTypeProperties: ['client_id', 'request_uri', 'redirect_uri', 'scope', 'authorization_details', 'issuer_state'], // arrayTypeProperties: ['authorization_details'], mode: JsonURIMode.X_FORM_WWW_URLENCODED, // We do not add the version here, as this always needs to be form encoded diff --git a/packages/client/lib/OpenID4VCIClient.ts b/packages/client/lib/OpenID4VCIClient.ts index 4dbf6c46..b8f4a015 100644 --- a/packages/client/lib/OpenID4VCIClient.ts +++ b/packages/client/lib/OpenID4VCIClient.ts @@ -20,44 +20,44 @@ import { OpenId4VCIVersion, PKCEOpts, ProofOfPossessionCallbacks, - toAuthorizationResponsePayload -} from '@sphereon/oid4vci-common' -import { CredentialFormat } from '@sphereon/ssi-types' -import Debug from 'debug' + toAuthorizationResponsePayload, +} from '@sphereon/oid4vci-common'; +import { CredentialFormat } from '@sphereon/ssi-types'; +import Debug from 'debug'; -import { AccessTokenClient } from './AccessTokenClient' -import { createAuthorizationRequestUrl } from './AuthorizationCodeClient' -import { CredentialOfferClient } from './CredentialOfferClient' -import { CredentialRequestClientBuilder } from './CredentialRequestClientBuilder' -import { MetadataClient } from './MetadataClient' -import { ProofOfPossessionBuilder } from './ProofOfPossessionBuilder' -import { generateMissingPKCEOpts } from './functions/AuthorizationUtil' +import { AccessTokenClient } from './AccessTokenClient'; +import { createAuthorizationRequestUrl } from './AuthorizationCodeClient'; +import { CredentialOfferClient } from './CredentialOfferClient'; +import { CredentialRequestClientBuilder } from './CredentialRequestClientBuilder'; +import { MetadataClient } from './MetadataClient'; +import { ProofOfPossessionBuilder } from './ProofOfPossessionBuilder'; +import { generateMissingPKCEOpts } from './functions/AuthorizationUtil'; -const debug = Debug('sphereon:oid4vci') +const debug = Debug('sphereon:oid4vci'); export class OpenID4VCIClient { - private readonly _credentialOffer?: CredentialOfferRequestWithBaseUrl - private readonly _credentialIssuer: string - private _clientId?: string - private _kid: string | undefined - private _jwk: JWK | undefined - private _alg: Alg | string | undefined - private _endpointMetadata: EndpointMetadataResult | undefined - private _accessTokenResponse: AccessTokenResponse | undefined - private _pkce: PKCEOpts = { disabled: false, codeChallengeMethod: CodeChallengeMethod.S256 } - private _authorizationRequestOpts?: AuthorizationRequestOpts - - private _authorizationURL?: string + private readonly _credentialOffer?: CredentialOfferRequestWithBaseUrl; + private readonly _credentialIssuer: string; + private _clientId?: string; + private _kid: string | undefined; + private _jwk: JWK | undefined; + private _alg: Alg | string | undefined; + private _endpointMetadata: EndpointMetadataResult | undefined; + private _accessTokenResponse: AccessTokenResponse | undefined; + private _pkce: PKCEOpts = { disabled: false, codeChallengeMethod: CodeChallengeMethod.S256 }; + private _authorizationRequestOpts?: AuthorizationRequestOpts; + + private _authorizationURL?: string; private constructor({ - credentialOffer, - clientId, - kid, - alg, - credentialIssuer, - pkce, - authorizationRequest - }: { + credentialOffer, + clientId, + kid, + alg, + credentialIssuer, + pkce, + authorizationRequest, + }: { credentialOffer?: CredentialOfferRequestWithBaseUrl; kid?: string; alg?: Alg | string; @@ -66,30 +66,30 @@ export class OpenID4VCIClient { pkce?: PKCEOpts; authorizationRequest?: AuthorizationRequestOpts; // Can be provided here, or when manually calling createAuthorizationUrl }) { - this._credentialOffer = credentialOffer - const issuer = credentialIssuer ?? (credentialOffer ? getIssuerFromCredentialOfferPayload(credentialOffer.credential_offer) : undefined) + this._credentialOffer = credentialOffer; + const issuer = credentialIssuer ?? (credentialOffer ? getIssuerFromCredentialOfferPayload(credentialOffer.credential_offer) : undefined); if (!issuer) { - throw Error('No credential issuer supplied or deduced from offer') + throw Error('No credential issuer supplied or deduced from offer'); } - this._credentialIssuer = issuer - this._kid = kid - this._alg = alg - this._clientId = clientId ?? (credentialOffer ? getClientIdFromCredentialOfferPayload(credentialOffer.credential_offer) : undefined) - this._pkce = { ...this._pkce, ...pkce } - this._authorizationRequestOpts = this.syncAuthorizationRequestOpts(authorizationRequest) - console.log(`Authorization req options: ${JSON.stringify(this._authorizationRequestOpts, null, 2)}`) + this._credentialIssuer = issuer; + this._kid = kid; + this._alg = alg; + this._clientId = clientId ?? (credentialOffer ? getClientIdFromCredentialOfferPayload(credentialOffer.credential_offer) : undefined); + this._pkce = { ...this._pkce, ...pkce }; + this._authorizationRequestOpts = this.syncAuthorizationRequestOpts(authorizationRequest); + console.log(`Authorization req options: ${JSON.stringify(this._authorizationRequestOpts, null, 2)}`); } public static async fromCredentialIssuer({ - kid, - alg, - retrieveServerMetadata, - clientId, - credentialIssuer, - pkce, - authorizationRequest, - createAuthorizationRequestURL - }: { + kid, + alg, + retrieveServerMetadata, + clientId, + credentialIssuer, + pkce, + authorizationRequest, + createAuthorizationRequestURL, + }: { credentialIssuer: string; kid?: string; alg?: Alg | string; @@ -105,28 +105,28 @@ export class OpenID4VCIClient { clientId: clientId ?? authorizationRequest?.clientId, credentialIssuer, pkce, - authorizationRequest - }) + authorizationRequest, + }); if (retrieveServerMetadata === undefined || retrieveServerMetadata) { - await client.retrieveServerMetadata() + await client.retrieveServerMetadata(); } if (createAuthorizationRequestURL === undefined || createAuthorizationRequestURL) { - await client.createAuthorizationRequestUrl({ authorizationRequest, pkce }) + await client.createAuthorizationRequestUrl({ authorizationRequest, pkce }); } - return client + return client; } public static async fromURI({ - uri, - kid, - alg, - retrieveServerMetadata, - clientId, - pkce, - createAuthorizationRequestURL, - authorizationRequest, - resolveOfferUri - }: { + uri, + kid, + alg, + retrieveServerMetadata, + clientId, + pkce, + createAuthorizationRequestURL, + authorizationRequest, + resolveOfferUri, + }: { uri: string; kid?: string; alg?: Alg | string; @@ -137,29 +137,29 @@ export class OpenID4VCIClient { clientId?: string; authorizationRequest?: AuthorizationRequestOpts; // Can be provided here, or when manually calling createAuthorizationUrl }): Promise { - const credentialOfferClient = await CredentialOfferClient.fromURI(uri, { resolve: resolveOfferUri }) + const credentialOfferClient = await CredentialOfferClient.fromURI(uri, { resolve: resolveOfferUri }); const client = new OpenID4VCIClient({ credentialOffer: credentialOfferClient, kid, alg, clientId: clientId ?? authorizationRequest?.clientId ?? credentialOfferClient.clientId, pkce, - authorizationRequest - }) + authorizationRequest, + }); if (retrieveServerMetadata === undefined || retrieveServerMetadata) { - await client.retrieveServerMetadata() + await client.retrieveServerMetadata(); } if ( credentialOfferClient.supportedFlows.includes(AuthzFlowType.AUTHORIZATION_CODE_FLOW) && (createAuthorizationRequestURL === undefined || createAuthorizationRequestURL) ) { - console.log(`AUTH REQ`) - await client.createAuthorizationRequestUrl({ authorizationRequest, pkce }) - console.log(`AUTH REQ URL: ${client._authorizationURL}`) + console.log(`AUTH REQ`); + await client.createAuthorizationRequestUrl({ authorizationRequest, pkce }); + console.log(`AUTH REQ URL: ${client._authorizationURL}`); } - return client + return client; } /** @@ -170,44 +170,44 @@ export class OpenID4VCIClient { */ public async createAuthorizationRequestUrl(opts?: { authorizationRequest?: AuthorizationRequestOpts; pkce?: PKCEOpts }): Promise { if (!this._authorizationURL) { - this.calculatePKCEOpts(opts?.pkce) - this._authorizationRequestOpts = this.syncAuthorizationRequestOpts(opts?.authorizationRequest) + this.calculatePKCEOpts(opts?.pkce); + this._authorizationRequestOpts = this.syncAuthorizationRequestOpts(opts?.authorizationRequest); if (!this._authorizationRequestOpts) { - throw Error(`No Authorization Request options present or provided in this call`) + throw Error(`No Authorization Request options present or provided in this call`); } // todo: Probably can go with current logic in MetadataClient who will always set the authorization_endpoint when found // handling this because of the support for v1_0-08 if (this._endpointMetadata?.credentialIssuerMetadata && 'authorization_endpoint' in this._endpointMetadata.credentialIssuerMetadata) { - this._endpointMetadata.authorization_endpoint = this._endpointMetadata.credentialIssuerMetadata.authorization_endpoint as string + this._endpointMetadata.authorization_endpoint = this._endpointMetadata.credentialIssuerMetadata.authorization_endpoint as string; } this._authorizationURL = await createAuthorizationRequestUrl({ pkce: this._pkce, endpointMetadata: this.endpointMetadata, authorizationRequest: this._authorizationRequestOpts, credentialOffer: this.credentialOffer, - credentialsSupported: this.getCredentialsSupported(true) - }) + credentialsSupported: this.getCredentialsSupported(true), + }); } - return this._authorizationURL + return this._authorizationURL; } public async retrieveServerMetadata(): Promise { - this.assertIssuerData() + this.assertIssuerData(); if (!this._endpointMetadata) { if (this.credentialOffer) { - this._endpointMetadata = await MetadataClient.retrieveAllMetadataFromCredentialOffer(this.credentialOffer) + this._endpointMetadata = await MetadataClient.retrieveAllMetadataFromCredentialOffer(this.credentialOffer); } else if (this._credentialIssuer) { - this._endpointMetadata = await MetadataClient.retrieveAllMetadata(this._credentialIssuer) + this._endpointMetadata = await MetadataClient.retrieveAllMetadata(this._credentialIssuer); } else { - throw Error(`Cannot retrieve issuer metadata without either a credential offer, or issuer value`) + throw Error(`Cannot retrieve issuer metadata without either a credential offer, or issuer value`); } } - return this.endpointMetadata + return this.endpointMetadata; } private calculatePKCEOpts(pkce?: PKCEOpts) { - this._pkce = generateMissingPKCEOpts({ ...this._pkce, ...pkce }) + this._pkce = generateMissingPKCEOpts({ ...this._pkce, ...pkce }); } public async acquireAccessToken(opts?: { @@ -218,19 +218,29 @@ export class OpenID4VCIClient { code?: string; // Directly pass in a code from an auth response redirectUri?: string; }): Promise { - const { pin, clientId, redirectUri } = opts ?? {} - const code = opts?.code ?? (opts?.authorizationResponse ? toAuthorizationResponsePayload(opts.authorizationResponse).code : undefined) + const { pin, clientId } = opts ?? {}; + let { redirectUri } = opts ?? {}; + const code = opts?.code ?? (opts?.authorizationResponse ? toAuthorizationResponsePayload(opts.authorizationResponse).code : undefined); if (opts?.codeVerifier) { - this._pkce.codeVerifier = opts.codeVerifier + this._pkce.codeVerifier = opts.codeVerifier; } - this.assertIssuerData() + this.assertIssuerData(); if (clientId) { - this._clientId = clientId + this._clientId = clientId; } if (!this._accessTokenResponse) { - const accessTokenClient = new AccessTokenClient() + const accessTokenClient = new AccessTokenClient(); + + if (redirectUri && redirectUri !== this._authorizationRequestOpts?.redirectUri) { + console.log( + `Redirect URI mismatch between access-token (${redirectUri}) and authorization request (${this._authorizationRequestOpts?.redirectUri}). According to the specification that is not allowed.`, + ); + } + if (this._authorizationRequestOpts?.redirectUri && !redirectUri) { + redirectUri = this._authorizationRequestOpts.redirectUri; + } const response = await accessTokenClient.acquireAccessToken({ credentialOffer: this.credentialOffer, @@ -240,40 +250,40 @@ export class OpenID4VCIClient { ...(!this._pkce.disabled && { codeVerifier: this._pkce.codeVerifier }), code, redirectUri, - asOpts: { clientId } - }) + asOpts: { clientId }, + }); if (response.errorBody) { - debug(`Access token error:\r\n${response.errorBody}`) + debug(`Access token error:\r\n${response.errorBody}`); throw Error( `Retrieving an access token from ${this._endpointMetadata?.token_endpoint} for issuer ${this.getIssuer()} failed with status: ${ response.origResponse.status - }` - ) + }`, + ); } else if (!response.successBody) { - debug(`Access token error. No success body`) + debug(`Access token error. No success body`); throw Error( `Retrieving an access token from ${this._endpointMetadata - ?.token_endpoint} for issuer ${this.getIssuer()} failed as there was no success response body` - ) + ?.token_endpoint} for issuer ${this.getIssuer()} failed as there was no success response body`, + ); } - this._accessTokenResponse = response.successBody + this._accessTokenResponse = response.successBody; } - return this.accessTokenResponse + return this.accessTokenResponse; } public async acquireCredentials({ - credentialTypes, - proofCallbacks, - format, - kid, - jwk, - alg, - jti, - deferredCredentialAwait, - deferredCredentialIntervalInMS - }: { + credentialTypes, + proofCallbacks, + format, + kid, + jwk, + alg, + jti, + deferredCredentialAwait, + deferredCredentialIntervalInMS, + }: { credentialTypes: string | string[]; proofCallbacks: ProofOfPossessionCallbacks; format?: CredentialFormat | OID4VCICredentialFormat; @@ -285,98 +295,98 @@ export class OpenID4VCIClient { deferredCredentialIntervalInMS?: number; }): Promise { if ([jwk, kid].filter((v) => v !== undefined).length > 1) { - throw new Error(KID_JWK_X5C_ERROR + `. jwk: ${jwk !== undefined}, kid: ${kid !== undefined}`) + throw new Error(KID_JWK_X5C_ERROR + `. jwk: ${jwk !== undefined}, kid: ${kid !== undefined}`); } - if (alg) this._alg = alg - if (jwk) this._jwk = jwk - if (kid) this._kid = kid + if (alg) this._alg = alg; + if (jwk) this._jwk = jwk; + if (kid) this._kid = kid; const requestBuilder = this.credentialOffer ? CredentialRequestClientBuilder.fromCredentialOffer({ - credentialOffer: this.credentialOffer, - metadata: this.endpointMetadata - }) + credentialOffer: this.credentialOffer, + metadata: this.endpointMetadata, + }) : CredentialRequestClientBuilder.fromCredentialIssuer({ - credentialIssuer: this.getIssuer(), - credentialTypes, - metadata: this.endpointMetadata, - version: this.version() - }) - - requestBuilder.withTokenFromResponse(this.accessTokenResponse) - requestBuilder.withDeferredCredentialAwait(deferredCredentialAwait ?? false, deferredCredentialIntervalInMS) + credentialIssuer: this.getIssuer(), + credentialTypes, + metadata: this.endpointMetadata, + version: this.version(), + }); + + requestBuilder.withTokenFromResponse(this.accessTokenResponse); + requestBuilder.withDeferredCredentialAwait(deferredCredentialAwait ?? false, deferredCredentialIntervalInMS); if (this.endpointMetadata?.credentialIssuerMetadata) { - const metadata = this.endpointMetadata.credentialIssuerMetadata - const types = Array.isArray(credentialTypes) ? [...credentialTypes].sort() : [credentialTypes] + const metadata = this.endpointMetadata.credentialIssuerMetadata; + const types = Array.isArray(credentialTypes) ? [...credentialTypes].sort() : [credentialTypes]; if (metadata.credentials_supported && Array.isArray(metadata.credentials_supported)) { - let typeSupported = false + let typeSupported = false; metadata.credentials_supported.forEach((supportedCredential) => { - const subTypes = getTypesFromCredentialSupported(supportedCredential) + const subTypes = getTypesFromCredentialSupported(supportedCredential); if ( subTypes.sort().every((t, i) => types[i] === t) || (types.length === 1 && (types[0] === supportedCredential.id || subTypes.includes(types[0]))) ) { - typeSupported = true + typeSupported = true; } - }) + }); if (!typeSupported) { - console.log(`Not all credential types ${JSON.stringify(credentialTypes)} are present in metadata for ${this.getIssuer()}`) + console.log(`Not all credential types ${JSON.stringify(credentialTypes)} are present in metadata for ${this.getIssuer()}`); // throw Error(`Not all credential types ${JSON.stringify(credentialTypes)} are supported by issuer ${this.getIssuer()}`); } } else if (metadata.credentials_supported && !Array.isArray(metadata.credentials_supported)) { - const credentialsSupported = metadata.credentials_supported + const credentialsSupported = metadata.credentials_supported; if (types.some((type) => !metadata.credentials_supported || !credentialsSupported[type])) { - throw Error(`Not all credential types ${JSON.stringify(credentialTypes)} are supported by issuer ${this.getIssuer()}`) + throw Error(`Not all credential types ${JSON.stringify(credentialTypes)} are supported by issuer ${this.getIssuer()}`); } } // todo: Format check? We might end up with some disjoint type / format combinations supported by the server } - const credentialRequestClient = requestBuilder.build() + const credentialRequestClient = requestBuilder.build(); const proofBuilder = ProofOfPossessionBuilder.fromAccessTokenResponse({ accessTokenResponse: this.accessTokenResponse, callbacks: proofCallbacks, - version: this.version() + version: this.version(), }) .withIssuer(this.getIssuer()) - .withAlg(this.alg) + .withAlg(this.alg); if (this._jwk) { - proofBuilder.withJWK(this._jwk) + proofBuilder.withJWK(this._jwk); } if (this._kid) { - proofBuilder.withKid(this._kid) + proofBuilder.withKid(this._kid); } if (this.clientId) { - proofBuilder.withClientId(this.clientId) + proofBuilder.withClientId(this.clientId); } if (jti) { - proofBuilder.withJti(jti) + proofBuilder.withJti(jti); } const response = await credentialRequestClient.acquireCredentialsUsingProof({ proofInput: proofBuilder, credentialTypes: credentialTypes, - format - }) + format, + }); if (response.errorBody) { - debug(`Credential request error:\r\n${JSON.stringify(response.errorBody)}`) + debug(`Credential request error:\r\n${JSON.stringify(response.errorBody)}`); throw Error( `Retrieving a credential from ${this._endpointMetadata?.credential_endpoint} for issuer ${this.getIssuer()} failed with status: ${ response.origResponse.status - }` - ) + }`, + ); } else if (!response.successBody) { - debug(`Credential request error. No success body`) + debug(`Credential request error. No success body`); throw Error( `Retrieving a credential from ${this._endpointMetadata - ?.credential_endpoint} for issuer ${this.getIssuer()} failed as there was no success response body` - ) + ?.credential_endpoint} for issuer ${this.getIssuer()} failed as there was no success response body`, + ); } - return response.successBody + return response.successBody; } // FIXME: We really should convert { if (typeof c === 'string') { - return [c] + return [c]; } else if ('types' in c) { - return c.types + return c.types; } else if ('vct' in c) { - return [c.vct] + return [c.vct]; } else { - return c.credential_definition.types + return c.credential_definition.types; } - }) + }); } } @@ -423,123 +433,123 @@ export class OpenID4VCIClient { return ( this.credentialOffer?.supportedFlows ?? (this._endpointMetadata?.credentialIssuerMetadata?.authorization_endpoint ? [AuthzFlowType.AUTHORIZATION_CODE_FLOW] : []) - ) + ); } isFlowTypeSupported(flowType: AuthzFlowType): boolean { - return this.issuerSupportedFlowTypes().includes(flowType) + return this.issuerSupportedFlowTypes().includes(flowType); } get authorizationURL(): string | undefined { - return this._authorizationURL + return this._authorizationURL; } public hasAuthorizationURL(): boolean { - return !!this.authorizationURL + return !!this.authorizationURL; } get credentialOffer(): CredentialOfferRequestWithBaseUrl | undefined { - return this._credentialOffer + return this._credentialOffer; } public version(): OpenId4VCIVersion { - return this.credentialOffer?.version ?? OpenId4VCIVersion.VER_1_0_11 + return this.credentialOffer?.version ?? OpenId4VCIVersion.VER_1_0_11; } public get endpointMetadata(): EndpointMetadataResult { - this.assertServerMetadata() + this.assertServerMetadata(); // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - return this._endpointMetadata! + return this._endpointMetadata!; } get kid(): string { - this.assertIssuerData() + this.assertIssuerData(); if (!this._kid) { - throw new Error('No value for kid is supplied') + throw new Error('No value for kid is supplied'); } - return this._kid + return this._kid; } get alg(): string { - this.assertIssuerData() + this.assertIssuerData(); if (!this._alg) { - throw new Error('No value for alg is supplied') + throw new Error('No value for alg is supplied'); } - return this._alg + return this._alg; } get clientId(): string | undefined { - return this._clientId + return this._clientId; } public hasAccessTokenResponse(): boolean { - return !!this._accessTokenResponse + return !!this._accessTokenResponse; } get accessTokenResponse(): AccessTokenResponse { - this.assertAccessToken() + this.assertAccessToken(); // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - return this._accessTokenResponse! + return this._accessTokenResponse!; } public getIssuer(): string { - this.assertIssuerData() - return this._credentialIssuer + this.assertIssuerData(); + return this._credentialIssuer; } public getAccessTokenEndpoint(): string { - this.assertIssuerData() + this.assertIssuerData(); return this.endpointMetadata ? this.endpointMetadata.token_endpoint - : AccessTokenClient.determineTokenURL({ issuerOpts: { issuer: this.getIssuer() } }) + : AccessTokenClient.determineTokenURL({ issuerOpts: { issuer: this.getIssuer() } }); } public getCredentialEndpoint(): string { - this.assertIssuerData() - return this.endpointMetadata ? this.endpointMetadata.credential_endpoint : `${this.getIssuer()}/credential` + this.assertIssuerData(); + return this.endpointMetadata ? this.endpointMetadata.credential_endpoint : `${this.getIssuer()}/credential`; } public hasDeferredCredentialEndpoint(): boolean { - return !!this.getAccessTokenEndpoint() + return !!this.getAccessTokenEndpoint(); } public getDeferredCredentialEndpoint(): string { - this.assertIssuerData() - return this.endpointMetadata ? this.endpointMetadata.credential_endpoint : `${this.getIssuer()}/credential` + this.assertIssuerData(); + return this.endpointMetadata ? this.endpointMetadata.credential_endpoint : `${this.getIssuer()}/credential`; } private assertIssuerData(): void { if (!this._credentialIssuer) { - throw Error(`No credential issuer value present`) + throw Error(`No credential issuer value present`); } else if (!this._credentialOffer && this._endpointMetadata && this.issuerSupportedFlowTypes().length === 0) { - throw Error(`No issuance initiation or credential offer present`) + throw Error(`No issuance initiation or credential offer present`); } } private assertServerMetadata(): void { if (!this._endpointMetadata) { - throw Error('No server metadata') + throw Error('No server metadata'); } } private assertAccessToken(): void { if (!this._accessTokenResponse) { - throw Error(`No access token present`) + throw Error(`No access token present`); } } private syncAuthorizationRequestOpts(opts?: AuthorizationRequestOpts): AuthorizationRequestOpts { - let authorizationRequestOpts = { ...this._authorizationRequestOpts, ...opts } as AuthorizationRequestOpts + let authorizationRequestOpts = { ...this._authorizationRequestOpts, ...opts } as AuthorizationRequestOpts; if (!authorizationRequestOpts) { - authorizationRequestOpts = { redirectUri: 'openid4vc%3A' } + authorizationRequestOpts = { redirectUri: 'openid4vc://' }; } - const clientId = authorizationRequestOpts.clientId ?? this._clientId - this._clientId = clientId - authorizationRequestOpts.clientId = clientId + const clientId = authorizationRequestOpts.clientId ?? this._clientId; + this._clientId = clientId; + authorizationRequestOpts.clientId = clientId; if (!authorizationRequestOpts.redirectUri) { - authorizationRequestOpts.redirectUri = 'openid4vc%3A' + authorizationRequestOpts.redirectUri = 'openid4vc://'; } - return authorizationRequestOpts + return authorizationRequestOpts; } }