@sphereon/openid4vci-client
Version:
OpenID for Verifiable Credential Issuance (OpenID4VCI) client
144 lines • 12 kB
JavaScript
;
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.MetadataClient = void 0;
const debug_1 = __importDefault(require("debug"));
const functions_1 = require("./functions");
const types_1 = require("./types");
const debug = (0, debug_1.default)('sphereon:openid4vci:metadata');
class MetadataClient {
/**
* Retrieve metadata using the Initiation obtained from a previous step
*
* @param initiation
*/
static retrieveAllMetadataFromInitiation(initiation) {
return __awaiter(this, void 0, void 0, function* () {
return MetadataClient.retrieveAllMetadataFromInitiationRequest(initiation.issuanceInitiationRequest);
});
}
/**
* Retrieve the metada using the initiation request obtained from a previous step
* @param initiationRequest
*/
static retrieveAllMetadataFromInitiationRequest(initiationRequest) {
return __awaiter(this, void 0, void 0, function* () {
return MetadataClient.retrieveAllMetadata(initiationRequest.issuer);
});
}
/**
* Retrieve all metadata from an issuer
* @param issuer The issuer URL
*/
static retrieveAllMetadata(issuer, opts) {
var _a;
return __awaiter(this, void 0, void 0, function* () {
let token_endpoint;
let credential_endpoint;
const response = yield MetadataClient.retrieveOpenID4VCIServerMetadata(issuer);
let oid4vciMetadata = response.successBody ? response.successBody : undefined;
if (oid4vciMetadata) {
debug(`Issuer ${issuer} OID4VCI well-known server metadata\r\n${oid4vciMetadata}`);
credential_endpoint = oid4vciMetadata.credential_endpoint;
token_endpoint = oid4vciMetadata.token_endpoint;
if (!token_endpoint && oid4vciMetadata.authorization_server) {
debug(`Issuer ${issuer} OID4VCI metadata has separate authorization_server ${oid4vciMetadata.authorization_server} that contains the token endpoint`);
// Crossword uses this to separate the AS metadata. We fail when not found, since we now have no way of getting the token endpoint
const response = yield this.retrieveWellknown(oid4vciMetadata.authorization_server, types_1.WellKnownEndpoints.OAUTH_AS, {
errorOnNotFound: true,
});
token_endpoint = (_a = response.successBody) === null || _a === void 0 ? void 0 : _a.token_endpoint;
}
}
else {
// No specific OID4VCI endpoint. Either can be an OAuth2 AS or an OpenID IDP. Let's start with OIDC first
let response = yield MetadataClient.retrieveWellknown(issuer, types_1.WellKnownEndpoints.OPENID_CONFIGURATION, {
errorOnNotFound: false,
});
let asConfig = response.successBody;
if (asConfig) {
debug(`Issuer ${issuer} has OpenID Connect Server metadata in well-known location`);
}
else {
// Now oAuth2
response = yield MetadataClient.retrieveWellknown(issuer, types_1.WellKnownEndpoints.OAUTH_AS, { errorOnNotFound: false });
asConfig = response.successBody;
}
if (asConfig) {
debug(`Issuer ${issuer} has oAuth2 Server metadata in well-known location`);
oid4vciMetadata = asConfig;
credential_endpoint = oid4vciMetadata.credential_endpoint;
token_endpoint = oid4vciMetadata.token_endpoint;
}
}
if (!token_endpoint) {
debug(`Issuer ${issuer} does not have a token_endpoint listed in well-known locations!`);
if (opts === null || opts === void 0 ? void 0 : opts.errorOnNotFound) {
throw new Error(`Could not deduce the token endpoint for ${issuer}`);
}
else {
token_endpoint = `${issuer}${issuer.endsWith('/') ? '' : '/'}token`;
}
}
if (!credential_endpoint) {
debug(`Issuer ${issuer} does not have a credential_endpoint listed in well-known locations!`);
if (opts === null || opts === void 0 ? void 0 : opts.errorOnNotFound) {
throw new Error(`Could not deduce the credential endpoint for ${issuer}`);
}
else {
credential_endpoint = `${issuer}${issuer.endsWith('/') ? '' : '/'}credential`;
}
}
debug(`Issuer ${issuer} token endpoint ${token_endpoint}, credential endpoint ${credential_endpoint}`);
return {
issuer,
token_endpoint,
credential_endpoint,
openid4vci_metadata: oid4vciMetadata,
};
});
}
/**
* Retrieve only the OID4VCI metadata for the issuer. So no OIDC/OAuth2 metadata
*
* @param issuerHost The issuer hostname
*/
static retrieveOpenID4VCIServerMetadata(issuerHost) {
return __awaiter(this, void 0, void 0, function* () {
// Since the server metadata endpoint is optional we are not going to throw an error.
return MetadataClient.retrieveWellknown(issuerHost, types_1.WellKnownEndpoints.OPENID4VCI_ISSUER, { errorOnNotFound: false });
});
}
/**
* Allows to retrieve information from a well-known location
*
* @param host The host
* @param endpointType The endpoint type, currently supports OID4VCI, OIDC and OAuth2 endpoint types
* @param opts Options, like for instance whether an error should be thrown in case the endpoint doesn't exist
*/
static retrieveWellknown(host, endpointType, opts) {
return __awaiter(this, void 0, void 0, function* () {
const result = yield (0, functions_1.getJson)(`${host.endsWith('/') ? host.slice(0, -1) : host}${endpointType}`, {
exceptionOnHttpErrorStatus: opts === null || opts === void 0 ? void 0 : opts.errorOnNotFound,
});
if (result.origResponse.status === 404) {
// We only get here when error on not found is false
debug(`host ${host} with endpoint type ${endpointType} was not found (404)`);
}
return result;
});
}
}
exports.MetadataClient = MetadataClient;
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiTWV0YWRhdGFDbGllbnQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi9saWIvTWV0YWRhdGFDbGllbnQudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7Ozs7Ozs7O0FBQUEsa0RBQTBCO0FBRTFCLDJDQUFzQztBQUN0QyxtQ0FTaUI7QUFFakIsTUFBTSxLQUFLLEdBQUcsSUFBQSxlQUFLLEVBQUMsOEJBQThCLENBQUMsQ0FBQztBQUVwRCxNQUFhLGNBQWM7SUFHekI7Ozs7T0FJRztJQUNJLE1BQU0sQ0FBTyxpQ0FBaUMsQ0FBQyxVQUF5Qzs7WUFDN0YsT0FBTyxjQUFjLENBQUMsd0NBQXdDLENBQUMsVUFBVSxDQUFDLHlCQUF5QixDQUFDLENBQUM7UUFDdkcsQ0FBQztLQUFBO0lBRUQ7OztPQUdHO0lBQ0ksTUFBTSxDQUFPLHdDQUF3QyxDQUFDLGlCQUFtRDs7WUFDOUcsT0FBTyxjQUFjLENBQUMsbUJBQW1CLENBQUMsaUJBQWlCLENBQUMsTUFBTSxDQUFDLENBQUM7UUFDdEUsQ0FBQztLQUFBO0lBRUQ7OztPQUdHO0lBQ0ksTUFBTSxDQUFPLG1CQUFtQixDQUFDLE1BQWMsRUFBRSxJQUFtQzs7O1lBQ3pGLElBQUksY0FBYyxDQUFDO1lBQ25CLElBQUksbUJBQW1CLENBQUM7WUFDeEIsTUFBTSxRQUFRLEdBQUcsTUFBTSxjQUFjLENBQUMsZ0NBQWdDLENBQUMsTUFBTSxDQUFDLENBQUM7WUFDL0UsSUFBSSxlQUFlLEdBQUcsUUFBUSxDQUFDLFdBQVcsQ0FBQyxDQUFDLENBQUMsUUFBUSxDQUFDLFdBQVcsQ0FBQyxDQUFDLENBQUMsU0FBUyxDQUFDO1lBQzlFLElBQUksZUFBZSxFQUFFO2dCQUNuQixLQUFLLENBQUMsVUFBVSxNQUFNLDBDQUEwQyxlQUFlLEVBQUUsQ0FBQyxDQUFDO2dCQUNuRixtQkFBbUIsR0FBRyxlQUFlLENBQUMsbUJBQW1CLENBQUM7Z0JBQzFELGNBQWMsR0FBRyxlQUFlLENBQUMsY0FBYyxDQUFD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