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

169 lines (157 loc) 6.77 kB
import { CheckLinkedDomain, PresentationDefinitionLocation, PresentationDefinitionWithLocation, SupportedVersion } from '@sphereon/did-auth-siop' import { CredentialMapper } from '@sphereon/ssi-types' import { IAgentPlugin } from '@veramo/core' import fetch from 'cross-fetch' import { ApiOpts, EBSIAuthAccessTokenGetArgs, EbsiEnvironment, EBSIOIDMetadata, GetPresentationDefinitionSuccessResponse, IRequiredContext, schema, } from '../index' import { ExceptionResponse, GetAccessTokenArgs, GetAccessTokenResponse, GetOIDProviderJwksResponse, GetOIDProviderMetadataResponse, GetPresentationDefinitionArgs, GetPresentationDefinitionResponse, IEBSIAuthorizationClient, } from '../types/IEBSIAuthorizationClient' //const encodeBase64url = (input: string): string => u8a.toString(u8a.fromString(input), 'base64url') export class EBSIAuthorizationClient implements IAgentPlugin { readonly schema = schema.IEBSIAuthorizationClient readonly methods: IEBSIAuthorizationClient = { ebsiAuthASDiscoveryMetadataGet: this.ebsiAuthASDiscoveryMetadataGet.bind(this), ebsiAuthASJwksGet: this.ebsiAuthASJwksGet.bind(this), ebsiAuthPresentationDefinitionGet: this.ebsiAuthPresentationDefinitionGet.bind(this), ebsiAuthAccessTokenGet: this.ebsiAuthAccessTokenGet.bind(this), } private async ebsiAuthASDiscoveryMetadataGet(args?: ApiOpts): Promise<GetOIDProviderMetadataResponse> { const url = await this.getDiscoveryEndpoint(args) return await ( await fetch(url, { method: 'GET', headers: { Accept: 'application/json', }, }) ).json() } private async ebsiAuthASJwksGet(args?: ApiOpts): Promise<GetOIDProviderJwksResponse | ExceptionResponse> { const discoveryMetadata: EBSIOIDMetadata = await this.ebsiAuthASDiscoveryMetadataGet(args) return await ( await fetch(`${discoveryMetadata.jwks_uri}`, { method: 'GET', headers: { Accept: 'application/jwk-set+json', }, }) ).json() } private async ebsiAuthPresentationDefinitionGet(args: GetPresentationDefinitionArgs): Promise<GetPresentationDefinitionResponse> { const { scope, apiOpts } = args const discoveryMetadata: EBSIOIDMetadata = await this.ebsiAuthASDiscoveryMetadataGet(apiOpts) return (await ( await fetch(`${discoveryMetadata.presentation_definition_endpoint}?scope=openid%20${scope}`, { method: 'GET', headers: { Accept: 'application/json', }, }) ).json()) satisfies GetPresentationDefinitionSuccessResponse } private async ebsiAuthAccessTokenGet(args: EBSIAuthAccessTokenGetArgs, context: IRequiredContext): Promise<GetAccessTokenResponse> { const { vc, scope, kid, did, definitionId, apiOpts } = args console.log(vc, scope, kid, did, definitionId) const metadataResponse = await this.ebsiAuthASDiscoveryMetadataGet(args.apiOpts) const definitionResponse = await this.ebsiAuthPresentationDefinitionGet(args) const pexResult = await context.agent.pexDefinitionFilterCredentials({ presentationDefinition: definitionResponse, credentialFilterOpts: { verifiableCredentials: [vc] }, }) const definition = { definition: definitionResponse, location: PresentationDefinitionLocation.TOPLEVEL_PRESENTATION_DEF, version: SupportedVersion.SIOPv2_D11, } satisfies PresentationDefinitionWithLocation const opSesssion = await context.agent.siopRegisterOPSession({ requestJwtOrUri: '', // Siop assumes we use an auth request, which we don't have in this case op: { checkLinkedDomains: CheckLinkedDomain.NEVER }, providedPresentationDefinitions: [definition], }) const oid4vp = await opSesssion.getOID4VP([did]) const vp = await oid4vp.createVerifiablePresentation( { definition, credentials: pexResult.filteredCredentials }, { proofOpts: { domain: metadataResponse.issuer, nonce: Date().toString() }, holderDID: did, identifierOpts: { identifier: did, kid }, skipDidResolution: scope === 'didr_invite', }, ) const accessToken = await this.getAccessTokenResponse({ grant_type: 'vp_token', vp_token: CredentialMapper.toCompactJWT(vp.verifiablePresentation), scope, presentation_submission: vp.presentationSubmission, apiOpts, }) //FIXME console.log(JSON.stringify(accessToken)) return accessToken // // // const metadataResponse = await this.ebsiAuthASDiscoveryMetadataGet() // if ('status' in metadataResponse) { // throw Error(JSON.stringify(metadataResponse)) // } // // const tokenResponse = await this.getAccessToken({ // grant_type: 'vp_token', // vp_token: vpJwt.verifiablePresentation as CompactJWT, // presentation_submission: vpJwt.presentationSubmission, // scope, // }) // if ('status' in tokenResponse) { // throw new Error(JSON.stringify(tokenResponse)) // } } private async getAccessTokenResponse(args: GetAccessTokenArgs): Promise<GetAccessTokenResponse> { const { grant_type = 'vp_token', scope, vp_token, presentation_submission, apiOpts } = args const discoveryMetadata: EBSIOIDMetadata = await this.ebsiAuthASDiscoveryMetadataGet(apiOpts) return await ( await fetch(`${discoveryMetadata.token_endpoint}`, { method: 'POST', headers: { ContentType: 'application/x-www-form-urlencoded', Accept: 'application/json', }, body: new URLSearchParams({ grant_type, scope: `openid ${scope}`, vp_token, presentation_submission: JSON.stringify(presentation_submission), }), }) ).json() } private async getUrl(args?: { environment?: EbsiEnvironment; version?: string }): Promise<string> { const { environment, version } = args ?? { environment: EbsiEnvironment.CONFORMANCE, version: 'v3' } if (environment === EbsiEnvironment.MOCK) { return `https://api-conformance.ebsi.eu/conformance/${version}/auth-mock` } else if (environment === EbsiEnvironment.ISSUER) { return `https://api-conformance.ebsi.eu/conformance/${version}/issuer-mock` } return `https://api-${environment}.ebsi.eu/authorisation/${version}` } private async getDiscoveryEndpoint(args?: ApiOpts): Promise<string> { const { environment, version } = { environment: EbsiEnvironment.CONFORMANCE, version: 'v4', ...args } if (environment === EbsiEnvironment.ISSUER) { return `${await this.getUrl({ environment, version })}/.well-known/openid-credential-issuer` } return `${await this.getUrl({ environment, version })}/.well-known/openid-configuration` } }