UNPKG

@sphereon/ssi-sdk.ebsi-support

Version:

229 lines • 12.2 kB
"use strict"; 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.siopDoneCallback = exports.reviewCredentialsCallback = exports.authorizationCodeUrlCallback = exports.selectCredentialsCallback = exports.handleErrorCallback = exports.addContactCallback = void 0; const did_auth_siop_1 = require("@sphereon/did-auth-siop"); const oid4vci_common_1 = require("@sphereon/oid4vci-common"); const ssi_sdk_data_store_1 = require("@sphereon/ssi-sdk.data-store"); const ssi_sdk_oid4vci_holder_1 = require("@sphereon/ssi-sdk.oid4vci-holder"); const cross_fetch_1 = __importDefault(require("cross-fetch")); const index_1 = require("../index"); const addContactCallback = (context) => { return (oid4vciMachine, state) => __awaiter(void 0, void 0, void 0, function* () { const { serverMetadata, hasContactConsent, contactAlias } = state.context; if (!serverMetadata) { return Promise.reject(Error('Missing serverMetadata in context')); } const issuerUrl = new URL(serverMetadata.issuer); const correlationId = `${issuerUrl.protocol}//${issuerUrl.hostname}`; let issuerName = (0, oid4vci_common_1.getIssuerName)(correlationId, serverMetadata.credentialIssuerMetadata); const party = { contact: { displayName: issuerName, legalName: issuerName, }, // FIXME maybe its nicer if we can also just use the id only // TODO using the predefined party type from the contact migrations here // TODO this is not used as the screen itself adds one, look at the params of the screen, this is not being passed in partyType: { id: '3875c12e-fdaa-4ef6-a340-c936e054b627', origin: ssi_sdk_data_store_1.PartyOrigin.EXTERNAL, type: ssi_sdk_data_store_1.PartyTypeType.ORGANIZATION, name: 'Sphereon_default_type', tenantId: '95e09cfc-c974-4174-86aa-7bf1d5251fb4', }, uri: correlationId, identities: [ { alias: correlationId, roles: [ssi_sdk_data_store_1.CredentialRole.ISSUER], origin: ssi_sdk_data_store_1.IdentityOrigin.EXTERNAL, identifier: { type: ssi_sdk_data_store_1.CorrelationIdentifierType.URL, correlationId: issuerUrl.hostname, }, // TODO WAL-476 add support for correct connection connection: { type: ssi_sdk_data_store_1.ConnectionType.OPENID_CONNECT, config: { clientId: '138d7bf8-c930-4c6e-b928-97d3a4928b01', clientSecret: '03b3955f-d020-4f2a-8a27-4e452d4e27a0', scopes: ['auth'], issuer: 'https://example.com/app-test', redirectUrl: 'app:/callback', dangerouslyAllowInsecureHttpRequests: true, clientAuthMethod: 'post', }, }, }, ], }; const onCreate = (_a) => __awaiter(void 0, [_a], void 0, function* ({ party, issuerUrl, issuerName, correlationId, }) { var _b, _c, _d; const displayName = (_b = party.contact.displayName) !== null && _b !== void 0 ? _b : issuerName; const contacts = yield context.agent.cmGetContacts({ filter: [ { contact: { // Searching on legalName as displayName is not unique, and we only support organizations for now legalName: displayName, }, }, ], }); if (contacts.length === 0 || !((_c = contacts[0]) === null || _c === void 0 ? void 0 : _c.contact)) { const contact = yield context.agent.cmAddContact(Object.assign(Object.assign({}, party), { displayName, legalName: displayName, contactType: { type: ssi_sdk_data_store_1.PartyTypeType.ORGANIZATION, name: displayName, origin: ssi_sdk_data_store_1.PartyOrigin.EXTERNAL, tenantId: (_d = party.tenantId) !== null && _d !== void 0 ? _d : '1', } })); oid4vciMachine.send({ type: ssi_sdk_oid4vci_holder_1.OID4VCIMachineEvents.CREATE_CONTACT, data: contact, }); } }); const onConsentChange = (hasConsent) => __awaiter(void 0, void 0, void 0, function* () { oid4vciMachine.send({ type: ssi_sdk_oid4vci_holder_1.OID4VCIMachineEvents.SET_CONTACT_CONSENT, data: hasConsent, }); }); const onAliasChange = (alias) => __awaiter(void 0, void 0, void 0, function* () { oid4vciMachine.send({ type: ssi_sdk_oid4vci_holder_1.OID4VCIMachineEvents.SET_CONTACT_ALIAS, data: alias, }); }); if (!issuerName) { issuerName = `EBSI unknown (${issuerUrl})`; } else if (issuerName.startsWith('http')) { issuerName = `EBSI ${issuerName.replace(/https?:\/\//, '')}`; } if (!contactAlias) { return yield onAliasChange(issuerName); } issuerName = contactAlias; if (!hasContactConsent) { return yield onConsentChange(true); } yield onCreate({ party, issuerName, issuerUrl: issuerUrl.toString(), correlationId }); }); }; exports.addContactCallback = addContactCallback; const handleErrorCallback = (context) => { return (oid4vciMachine, state) => __awaiter(void 0, void 0, void 0, function* () { console.error(`error callback event: ${state.event}`, state.context.error); index_1.logger.trace(state.event); }); }; exports.handleErrorCallback = handleErrorCallback; const selectCredentialsCallback = (context) => { return (oid4vciMachine, state) => __awaiter(void 0, void 0, void 0, function* () { const { contact, credentialToSelectFrom, selectedCredentials } = state.context; if (selectedCredentials && selectedCredentials.length > 0) { index_1.logger.info(`selected: ${selectedCredentials.join(', ')}`); oid4vciMachine.send({ type: ssi_sdk_oid4vci_holder_1.OID4VCIMachineEvents.NEXT, }); return; } else if (!contact) { return Promise.reject(Error('Missing contact in context')); } const onSelectType = (selectedCredentials) => __awaiter(void 0, void 0, void 0, function* () { console.log(`Selected credentials: ${selectedCredentials.join(', ')}`); oid4vciMachine.send({ type: ssi_sdk_oid4vci_holder_1.OID4VCIMachineEvents.SET_SELECTED_CREDENTIALS, data: selectedCredentials, }); }); yield onSelectType(credentialToSelectFrom.map((sel) => sel.credentialId)); }); }; exports.selectCredentialsCallback = selectCredentialsCallback; const authorizationCodeUrlCallback = ({ authReqResult, vpLinkHandler, }, context) => { return (oid4vciMachine, state) => __awaiter(void 0, void 0, void 0, function* () { const url = state.context.authorizationCodeURL; console.log('navigateAuthorizationCodeURL: ', url); if (!url) { return Promise.reject(Error('Missing authorization URL in context')); } const onOpenAuthorizationUrl = (url) => __awaiter(void 0, void 0, void 0, function* () { var _a; console.log('onOpenAuthorizationUrl being invoked: ', url); oid4vciMachine.send({ type: ssi_sdk_oid4vci_holder_1.OID4VCIMachineEvents.INVOKED_AUTHORIZATION_CODE_REQUEST, data: url, }); const response = yield (0, cross_fetch_1.default)(url, { redirect: 'manual' }); if (response.status < 301 || response.status > 302) { throw Error(`When doing a headless auth, we expect to be redirected on getting the authz URL`); } const openidUri = response.headers.get('location'); if (!openidUri || !openidUri.startsWith('openid://')) { let error = undefined; if (openidUri) { if (openidUri.includes('error')) { error = 'Authorization server error: '; const decoded = (0, did_auth_siop_1.decodeUriAsJson)(openidUri); if ('error' in decoded && decoded.error) { error += decoded.error + ', '; } if ('error_description' in decoded && decoded.error_description) { error += decoded.error_description; } } } throw Error(error !== null && error !== void 0 ? error : `Expected a openid:// URI to be returned from EBSI in headless mode. Returned: ${openidUri}, ${JSON.stringify(yield response.text())}`); } console.log(`onOpenAuthorizationUrl after openUrl: ${url}`); const kid = ((_a = authReqResult.authKey.meta) === null || _a === void 0 ? void 0 : _a.jwkThumbprint) ? `${authReqResult.identifier.did}#${authReqResult.authKey.meta.jwkThumbprint}` : authReqResult.identifier.kid; yield vpLinkHandler.handle(openidUri, { idOpts: Object.assign(Object.assign({}, authReqResult.identifier), { kmsKeyRef: kid }) }); }); yield onOpenAuthorizationUrl(url); }); }; exports.authorizationCodeUrlCallback = authorizationCodeUrlCallback; const reviewCredentialsCallback = (context) => { return (oid4vciMachine, state) => __awaiter(void 0, void 0, void 0, function* () { console.log(`# REVIEW CREDENTIALS:`); console.log(JSON.stringify(state.context.credentialsToAccept, null, 2)); oid4vciMachine.send({ type: ssi_sdk_oid4vci_holder_1.OID4VCIMachineEvents.NEXT, }); }); }; exports.reviewCredentialsCallback = reviewCredentialsCallback; const siopDoneCallback = ({ oid4vciMachine }, context) => { return (oid4vpMachine, state) => __awaiter(void 0, void 0, void 0, function* () { var _a, _b; // console.log('SIOP result:') // console.log(JSON.stringify(state.context, null , 2)) if (!((_b = (_a = state.context.authorizationResponseData) === null || _a === void 0 ? void 0 : _a.queryParams) === null || _b === void 0 ? void 0 : _b.code)) { throw Error(`No code was returned from the authorization step`); } oid4vciMachine.interpreter.send({ type: ssi_sdk_oid4vci_holder_1.OID4VCIMachineEvents.PROVIDE_AUTHORIZATION_CODE_RESPONSE, data: state.context.authorizationResponseData.url, }); console.log(`SIOP DONE!`); }); }; exports.siopDoneCallback = siopDoneCallback; //# sourceMappingURL=AttestationHeadlessCallbacks.js.map