diff --git a/packages/taco-auth/src/providers/encryptor/self-delegate.ts b/packages/taco-auth/src/providers/encryptor/self-delegate.ts index 2f2cc11b..e2a9f614 100644 --- a/packages/taco-auth/src/providers/encryptor/self-delegate.ts +++ b/packages/taco-auth/src/providers/encryptor/self-delegate.ts @@ -1,6 +1,8 @@ -import { ethers } from 'ethers'; +import { ethers, Wallet } from 'ethers'; import { z } from 'zod'; +// import { Bytes } from "@ethersproject/bytes"; + import { AuthSignature } from '../../auth-sig'; import { LocalStorage } from '../../storage'; @@ -8,6 +10,29 @@ export const ENCRYPTOR_SELF_DELEGATE_AUTH_METHOD = 'EncryptorSelfDelegate' export const SelfDelegateTypedDataSchema = z.string(); + +// TODO: Create generic EncryptorSigner class/interface, which can be +// instantiated with ethers' Signers and Wallets, but also with our custom +// classes +export class DelegatedSigner extends Wallet { // TODO: extend from generic Signer + + authSignature?: AuthSignature; + + async authenticate(selfDelegateProvider: SelfDelegateProvider){ + const appSideSignerAddress = await this.getAddress(); + this.authSignature = await selfDelegateProvider.getOrCreateAuthSignature(appSideSignerAddress); + } + + override async signMessage(message: any): Promise { // TODO: Restrict input type to Bytes | string + if (typeof this.authSignature === 'undefined'){ + throw new Error('Encryptor must authenticate app signer first'); + } + const appSignature = await super.signMessage(message); + return appSignature.concat(this.authSignature.signature) + } +} + + export class SelfDelegateProvider { private readonly storage: LocalStorage; @@ -15,6 +40,14 @@ export class SelfDelegateProvider { this.storage = new LocalStorage(); } + public async createSelfDelegatedAppSideSigner( + ephemeralPrivateKey: any // TODO: Find a stricter type + ): Promise { + const appSideSigner = new DelegatedSigner(ephemeralPrivateKey); + await appSideSigner.authenticate(this); + return appSideSigner; + } + public async getOrCreateAuthSignature( ephemeralPublicKeyOrAddress: string ): Promise { diff --git a/packages/taco-auth/test/auth-provider.test.ts b/packages/taco-auth/test/auth-provider.test.ts index 2b84b17b..2329f373 100644 --- a/packages/taco-auth/test/auth-provider.test.ts +++ b/packages/taco-auth/test/auth-provider.test.ts @@ -140,11 +140,18 @@ describe('encryptor self-delegate provider authorization', () => { const provider = fakeProvider(bobSecretKeyBytes); const signer = provider.getSigner(); const selfDelegateProvider = new SelfDelegateProvider(signer); + + it('creates a new self-delegated app signer', async () => { + const appSideSignerAddress = await applicationSideSigner.getAddress(); + const [newSigner, newAuthSignature] = await selfDelegateProvider.createSelfDelegatedAppSideSigner(aliceSecretKeyBytes); + expect(await newSigner.getAddress()).toEqual(appSideSignerAddress); + expect(newAuthSignature.typedData).toEqual(appSideSignerAddress); + }); const applicationSideProvider = fakeProvider(aliceSecretKeyBytes); const applicationSideSigner = applicationSideProvider.getSigner(); - it('creates a new message', async () => { + it('creates a new auth signature', async () => { const appSideSignerAddress = await applicationSideSigner.getAddress(); const typedSignature = await selfDelegateProvider.getOrCreateAuthSignature(appSideSignerAddress); expect(typedSignature.signature).toBeDefined();