UNPKG

@sphereon/ssi-sdk.ebsi-authorization-client

Version:

<!--suppress HtmlDeprecatedAttribute --> <h1 align="center"> <br> <a href="https://www.sphereon.com"><img src="https://sphereon.com/content/themes/sphereon/assets/img/logo.svg" alt="Sphereon" width="400"></a> <br>EBSI Authorization Client (Typescrip

105 lines 5.16 kB
import { OpenID4VCIClient } from '@sphereon/oid4vci-client'; import { AuthzFlowType, getJson, getTypesFromCredentialSupported, } from '@sphereon/oid4vci-common'; import { getIdentifier } from '@sphereon/ssi-sdk-ext.did-utils'; import { calculateJwkThumbprintForKey } from '@sphereon/ssi-sdk-ext.key-utils'; import { getAuthenticationKey, signCallback, SupportedDidMethodEnum } from '@sphereon/ssi-sdk.oid4vci-holder'; /** * Method to generate an authz url for getting attestation credentials from a (R)TAO on EBSI using a cloud/service wallet * * This method can be used standalone. But it can also be used as input for the `oid4vciHolderStart` agent method, * to start a OID4VCI holder flow. * * @param opts * @param context */ export const ebsiCreateAttestationAuthRequestURL = async (opts, context) => { const { credentialIssuer, credentialType, idOpts, redirectUri, requestObjectOpts, formats = ['jwt_vc', 'jwt_vc_json'] } = opts; const identifier = await getIdentifier(idOpts, context); if (identifier.provider !== 'did:ebsi' && identifier.provider !== 'did:key') { throw Error(`EBSI only supports did:key for natural persons and did:ebsi for legal persons. Provider: ${identifier.provider}, did: ${identifier.did}`); } // This only works if the DID is actually registered, otherwise use our internal KMS; // that is why the offline argument is passed in when type is Verifiable Auth to Onboard, as no DID is present at that point yet const authKey = await getAuthenticationKey({ identifier, offlineWhenNoDIDRegistered: credentialType === 'VerifiableAuthorisationToOnboard', noVerificationMethodFallback: true, context, }); const kid = authKey.meta.jwkThumbprint ?? calculateJwkThumbprintForKey({ key: authKey }); const clientId = opts.clientId ?? identifier.did; const vciClient = await OpenID4VCIClient.fromCredentialIssuer({ credentialIssuer: credentialIssuer, kid, clientId, createAuthorizationRequestURL: false, // We will do that down below retrieveServerMetadata: true, }); const allMatches = vciClient.getCredentialsSupported(false); let arrayMatches; if (Array.isArray(allMatches)) { arrayMatches = allMatches; } else { arrayMatches = Object.entries(allMatches).map(([id, supported]) => { supported.id = id; return supported; }); } const supportedConfigurations = arrayMatches .filter((supported) => getTypesFromCredentialSupported(supported, { filterVerifiableCredential: false }).includes(credentialType)) .filter((supported) => (supported.format === 'jwt_vc' || supported.format === 'jwt_vc_json') && formats.includes(supported.format)); if (supportedConfigurations.length === 0) { throw Error(`Could not find '${credentialType}' with format(s) '${formats.join(',')}' in list of supported types for issuer: ${credentialIssuer}`); } const authorizationDetails = supportedConfigurations.map((supported) => { return { type: 'openid_credential', format: supported.format, types: getTypesFromCredentialSupported(supported), }; }); const signCallbacks = requestObjectOpts.signCallbacks ?? { signCallback: await signCallback(vciClient, idOpts, context), }; const authorizationRequestOpts = { redirectUri, clientId, authorizationDetails, requestObjectOpts: { ...requestObjectOpts, signCallbacks, kid: requestObjectOpts.kid ?? kid, }, }; // todo: Do we really need to do this, or can we just set the create option to true at this point? We are passing in the authzReq opts const authorizationCodeURL = await vciClient.createAuthorizationRequestUrl({ authorizationRequest: authorizationRequestOpts, }); return { requestData: { createAuthorizationRequestURL: false, flowType: AuthzFlowType.AUTHORIZATION_CODE_FLOW, uri: credentialIssuer, existingClientState: JSON.parse(await vciClient.exportState()), }, authorizationRequestOpts, authorizationCodeURL, identifier, authKey, didMethodPreferences: [SupportedDidMethodEnum.DID_EBSI, SupportedDidMethodEnum.DID_KEY], }; }; /** * Normally you would use the browser to let the user make this call in the front channel, * however EBSI mainly uses mocks at present, and we want to be able to test as well */ export const ebsiAuthRequestExecution = async (authRequestResult, opts) => { const { requestData, authorizationCodeURL } = authRequestResult; const vciClient = await OpenID4VCIClient.fromState({ state: requestData?.existingClientState }); console.log(`URL: ${authorizationCodeURL}, according to client: ${vciClient.authorizationURL}`); const authResponse = await getJson(authorizationCodeURL); const location = authResponse.origResponse.headers.get('location'); console.log(`LOCATION: ${location}`); }; //# sourceMappingURL=Attestation.js.map