@sphereon/oid4vci-client
Version:
OpenID for Verifiable Credential Issuance (OpenID4VCI) client
170 lines (148 loc) • 6.18 kB
text/typescript
import {
AccessTokenResponse,
CredentialIssuerMetadata,
CredentialOfferPayloadV1_0_08,
CredentialOfferPayloadV1_0_11,
CredentialOfferRequestWithBaseUrl,
determineSpecVersionFromOffer,
EndpointMetadata,
ExperimentalSubjectIssuance,
getIssuerFromCredentialOfferPayload,
getTypesFromOfferV1_0_11,
OID4VCICredentialFormat,
OpenId4VCIVersion,
UniformCredentialOfferRequest,
} from '@sphereon/oid4vci-common';
import { CredentialFormat } from '@sphereon/ssi-types';
import { CredentialOfferClientV1_0_11 } from './CredentialOfferClientV1_0_11';
import { CredentialRequestClientV1_0_11 } from './CredentialRequestClientV1_0_11';
export class CredentialRequestClientBuilderV1_0_11 {
credentialEndpoint?: string;
deferredCredentialEndpoint?: string;
deferredCredentialAwait = false;
deferredCredentialIntervalInMS = 5000;
credentialTypes: string[] = [];
format?: CredentialFormat | OID4VCICredentialFormat;
token?: string;
version?: OpenId4VCIVersion;
subjectIssuance?: ExperimentalSubjectIssuance;
issuerState?: string;
public static fromCredentialIssuer({
credentialIssuer,
metadata,
version,
credentialTypes,
}: {
credentialIssuer: string;
metadata?: EndpointMetadata;
version?: OpenId4VCIVersion;
credentialTypes: string | string[];
}): CredentialRequestClientBuilderV1_0_11 {
const issuer = credentialIssuer;
const builder = new CredentialRequestClientBuilderV1_0_11();
builder.withVersion(version ?? OpenId4VCIVersion.VER_1_0_11);
builder.withCredentialEndpoint(metadata?.credential_endpoint ?? (issuer.endsWith('/') ? `${issuer}credential` : `${issuer}/credential`));
if (metadata?.deferred_credential_endpoint) {
builder.withDeferredCredentialEndpoint(metadata.deferred_credential_endpoint);
}
builder.withCredentialType(credentialTypes);
return builder;
}
public static async fromURI({ uri, metadata }: { uri: string; metadata?: EndpointMetadata }): Promise<CredentialRequestClientBuilderV1_0_11> {
const offer = await CredentialOfferClientV1_0_11.fromURI(uri);
return CredentialRequestClientBuilderV1_0_11.fromCredentialOfferRequest({ request: offer, ...offer, metadata, version: offer.version });
}
public static fromCredentialOfferRequest(opts: {
request: UniformCredentialOfferRequest;
scheme?: string;
baseUrl?: string;
version?: OpenId4VCIVersion;
metadata?: EndpointMetadata;
}): CredentialRequestClientBuilderV1_0_11 {
const { request, metadata } = opts;
const version = opts.version ?? request.version ?? determineSpecVersionFromOffer(request.original_credential_offer);
const builder = new CredentialRequestClientBuilderV1_0_11();
const issuer = getIssuerFromCredentialOfferPayload(request.credential_offer) ?? (metadata?.issuer as string);
builder.withVersion(version);
builder.withCredentialEndpoint(metadata?.credential_endpoint ?? (issuer.endsWith('/') ? `${issuer}credential` : `${issuer}/credential`));
if (metadata?.deferred_credential_endpoint) {
builder.withDeferredCredentialEndpoint(metadata.deferred_credential_endpoint);
}
if (version <= OpenId4VCIVersion.VER_1_0_08) {
//todo: This basically sets all types available during initiation. Probably the user only wants a subset. So do we want to do this?
builder.withCredentialType((request.original_credential_offer as CredentialOfferPayloadV1_0_08).credential_type);
} else if (version <= OpenId4VCIVersion.VER_1_0_11) {
// todo: look whether this is correct
builder.withCredentialType(getTypesFromOfferV1_0_11(request.credential_offer as CredentialOfferPayloadV1_0_11));
}
return builder;
}
public static fromCredentialOffer({
credentialOffer,
metadata,
}: {
credentialOffer: CredentialOfferRequestWithBaseUrl;
metadata?: EndpointMetadata;
}): CredentialRequestClientBuilderV1_0_11 {
return CredentialRequestClientBuilderV1_0_11.fromCredentialOfferRequest({
request: credentialOffer,
metadata,
version: credentialOffer.version,
});
}
public withIssuerState(issuerState?: string): this {
this.issuerState = issuerState;
return this;
}
public withCredentialEndpointFromMetadata(metadata: CredentialIssuerMetadata): this {
this.credentialEndpoint = metadata.credential_endpoint;
return this;
}
public withCredentialEndpoint(credentialEndpoint: string): this {
this.credentialEndpoint = credentialEndpoint;
return this;
}
public withDeferredCredentialEndpointFromMetadata(metadata: CredentialIssuerMetadata): this {
this.deferredCredentialEndpoint = metadata.deferred_credential_endpoint;
return this;
}
public withDeferredCredentialEndpoint(deferredCredentialEndpoint: string): this {
this.deferredCredentialEndpoint = deferredCredentialEndpoint;
return this;
}
public withDeferredCredentialAwait(deferredCredentialAwait: boolean, deferredCredentialIntervalInMS?: number): this {
this.deferredCredentialAwait = deferredCredentialAwait;
this.deferredCredentialIntervalInMS = deferredCredentialIntervalInMS ?? 5000;
return this;
}
public withCredentialType(credentialTypes: string | string[]): this {
this.credentialTypes = Array.isArray(credentialTypes) ? credentialTypes : [credentialTypes];
return this;
}
public withFormat(format: CredentialFormat | OID4VCICredentialFormat): this {
this.format = format;
return this;
}
public withSubjectIssuance(subjectIssuance: ExperimentalSubjectIssuance): this {
this.subjectIssuance = subjectIssuance;
return this;
}
public withToken(accessToken: string): this {
this.token = accessToken;
return this;
}
public withTokenFromResponse(response: AccessTokenResponse): this {
this.token = response.access_token;
return this;
}
public withVersion(version: OpenId4VCIVersion): this {
this.version = version;
return this;
}
public build(): CredentialRequestClientV1_0_11 {
if (!this.version) {
this.withVersion(OpenId4VCIVersion.VER_1_0_11);
}
return new CredentialRequestClientV1_0_11(this);
}
}