@sphereon/oid4vci-client
Version:
OpenID for Verifiable Credential Issuance (OpenID4VCI) client
209 lines (179 loc) • 7 kB
text/typescript
import {
AccessTokenResponse,
CredentialIssuerMetadata,
CredentialIssuerMetadataV1_0_13,
CredentialOfferRequestWithBaseUrl,
determineSpecVersionFromOffer,
EndpointMetadata,
ExperimentalSubjectIssuance,
OID4VCICredentialFormat,
OpenId4VCIVersion,
UniformCredentialOfferRequest,
} from '@sphereon/oid4vci-common';
import { CredentialFormat } from '@sphereon/ssi-types';
import { CredentialOfferClient } from './CredentialOfferClient';
import { CredentialRequestClientBuilderV1_0_11 } from './CredentialRequestClientBuilderV1_0_11';
import { CredentialRequestClientBuilderV1_0_13 } from './CredentialRequestClientBuilderV1_0_13';
type CredentialRequestClientBuilderVersionSpecific = CredentialRequestClientBuilderV1_0_11 | CredentialRequestClientBuilderV1_0_13;
function isV1_0_13(builder: CredentialRequestClientBuilderVersionSpecific): builder is CredentialRequestClientBuilderV1_0_13 {
return (builder as CredentialRequestClientBuilderV1_0_13).withCredentialIdentifier !== undefined;
}
export class CredentialRequestClientBuilder {
private _builder: CredentialRequestClientBuilderVersionSpecific;
private constructor(builder: CredentialRequestClientBuilderVersionSpecific) {
this._builder = builder;
}
public static fromCredentialIssuer({
credentialIssuer,
metadata,
version,
credentialIdentifier,
credentialTypes,
}: {
credentialIssuer: string;
metadata?: EndpointMetadata;
version?: OpenId4VCIVersion;
credentialIdentifier?: string;
credentialTypes?: string | string[];
}): CredentialRequestClientBuilder {
const specVersion = version ?? OpenId4VCIVersion.VER_1_0_13;
let builder;
if (specVersion >= OpenId4VCIVersion.VER_1_0_13) {
builder = CredentialRequestClientBuilderV1_0_13.fromCredentialIssuer({
credentialIssuer,
metadata,
version,
credentialIdentifier,
credentialTypes,
});
} else {
if (!credentialTypes || credentialTypes.length === 0) {
throw new Error('CredentialTypes must be provided for v1_0_11');
}
builder = CredentialRequestClientBuilderV1_0_11.fromCredentialIssuer({
credentialIssuer,
metadata,
version,
credentialTypes,
});
}
return new CredentialRequestClientBuilder(builder);
}
public static async fromURI({ uri, metadata }: { uri: string; metadata?: EndpointMetadata }): Promise<CredentialRequestClientBuilder> {
const offer = await CredentialOfferClient.fromURI(uri);
return CredentialRequestClientBuilder.fromCredentialOfferRequest({
request: offer,
...offer,
metadata,
version: offer.version,
});
}
public static fromCredentialOfferRequest(opts: {
request: UniformCredentialOfferRequest;
scheme?: string;
baseUrl?: string;
version?: OpenId4VCIVersion;
metadata?: EndpointMetadata;
}): CredentialRequestClientBuilder {
const { request } = opts;
const version = opts.version ?? request.version ?? determineSpecVersionFromOffer(request.original_credential_offer);
let builder;
if (version < OpenId4VCIVersion.VER_1_0_13) {
builder = CredentialRequestClientBuilderV1_0_11.fromCredentialOfferRequest(opts);
} else {
builder = CredentialRequestClientBuilderV1_0_13.fromCredentialOfferRequest(opts);
}
return new CredentialRequestClientBuilder(builder);
}
public static fromCredentialOffer({
credentialOffer,
metadata,
}: {
credentialOffer: CredentialOfferRequestWithBaseUrl;
metadata?: EndpointMetadata;
}): CredentialRequestClientBuilder {
const version = determineSpecVersionFromOffer(credentialOffer.credential_offer);
let builder;
if (version < OpenId4VCIVersion.VER_1_0_13) {
builder = CredentialRequestClientBuilderV1_0_11.fromCredentialOffer({
credentialOffer,
metadata,
});
} else {
builder = CredentialRequestClientBuilderV1_0_13.fromCredentialOffer({
credentialOffer,
metadata,
});
}
return new CredentialRequestClientBuilder(builder);
}
public getVersion(): OpenId4VCIVersion | undefined {
return this._builder.version;
}
public withCredentialEndpointFromMetadata(metadata: CredentialIssuerMetadata | CredentialIssuerMetadataV1_0_13): this {
if (isV1_0_13(this._builder)) {
this._builder.withCredentialEndpointFromMetadata(metadata as CredentialIssuerMetadataV1_0_13);
} else {
this._builder.withCredentialEndpointFromMetadata(metadata as CredentialIssuerMetadata);
}
return this;
}
public withCredentialEndpoint(credentialEndpoint: string): this {
this._builder.withCredentialEndpoint(credentialEndpoint);
return this;
}
public withDeferredCredentialEndpointFromMetadata(metadata: CredentialIssuerMetadata | CredentialIssuerMetadataV1_0_13): this {
if (isV1_0_13(this._builder)) {
this._builder.withDeferredCredentialEndpointFromMetadata(metadata as CredentialIssuerMetadataV1_0_13);
} else {
this._builder.withDeferredCredentialEndpointFromMetadata(metadata as CredentialIssuerMetadata);
}
return this;
}
public withDeferredCredentialEndpoint(deferredCredentialEndpoint: string): this {
this._builder.withDeferredCredentialEndpoint(deferredCredentialEndpoint);
return this;
}
public withDeferredCredentialAwait(deferredCredentialAwait: boolean, deferredCredentialIntervalInMS?: number): this {
this._builder.withDeferredCredentialAwait(deferredCredentialAwait, deferredCredentialIntervalInMS);
return this;
}
public withCredentialIdentifier(credentialIdentifier: string): this {
if (this._builder.version === undefined || this._builder.version < OpenId4VCIVersion.VER_1_0_13) {
throw new Error('Version of spec should be equal or higher than v1_0_13');
}
(this._builder as CredentialRequestClientBuilderV1_0_13).withCredentialIdentifier(credentialIdentifier);
return this;
}
public withIssuerState(issuerState?: string): this {
this._builder.withIssuerState(issuerState);
return this;
}
public withCredentialType(credentialTypes: string | string[]): this {
this._builder.withCredentialType(credentialTypes);
return this;
}
public withFormat(format: CredentialFormat | OID4VCICredentialFormat): this {
this._builder.withFormat(format);
return this;
}
public withSubjectIssuance(subjectIssuance: ExperimentalSubjectIssuance): this {
this._builder.withSubjectIssuance(subjectIssuance);
return this;
}
public withToken(accessToken: string): this {
this._builder.withToken(accessToken);
return this;
}
public withTokenFromResponse(response: AccessTokenResponse): this {
this._builder.withTokenFromResponse(response);
return this;
}
public withVersion(version: OpenId4VCIVersion): this {
this._builder.withVersion(version);
return this;
}
public build() {
return this._builder.build();
}
}