From e6c4e1b48630605b929eef8e5ae17339e92ffa5b Mon Sep 17 00:00:00 2001 From: Piotr Roslaniec Date: Tue, 9 Jul 2024 16:59:52 +0200 Subject: [PATCH] feat!(auth): remove eip712 --- packages/taco-auth/src/auth-provider.ts | 12 +- packages/taco-auth/src/auth-sig.ts | 12 +- packages/taco-auth/src/helper.ts | 19 --- packages/taco-auth/src/index.ts | 1 - packages/taco-auth/src/providers/eip712.ts | 155 ------------------ packages/taco-auth/src/providers/index.ts | 1 - packages/taco-auth/test/auth-provider.test.ts | 32 +--- packages/taco-auth/test/auth-sig.test.ts | 74 +-------- packages/taco/src/conditions/const.ts | 12 +- packages/taco/src/conditions/shared.ts | 8 +- .../test/conditions/base/contract.test.ts | 4 +- packages/taco/test/conditions/context.test.ts | 58 +------ packages/test-utils/src/utils.ts | 28 ++-- 13 files changed, 33 insertions(+), 383 deletions(-) delete mode 100644 packages/taco-auth/src/helper.ts delete mode 100644 packages/taco-auth/src/providers/eip712.ts diff --git a/packages/taco-auth/src/auth-provider.ts b/packages/taco-auth/src/auth-provider.ts index 18e83d5e6..fbb8d4c64 100644 --- a/packages/taco-auth/src/auth-provider.ts +++ b/packages/taco-auth/src/auth-provider.ts @@ -1,30 +1,20 @@ import { AuthSignature } from './auth-sig'; -import { EIP4361AuthProvider, EIP712AuthProvider } from './providers'; +import { EIP4361AuthProvider } from './providers'; -/** - * @deprecated Use EIP4361_AUTH_METHOD instead. - */ -export const EIP712_AUTH_METHOD = 'EIP712'; export const EIP4361_AUTH_METHOD = 'EIP4361'; - export interface AuthProvider { getOrCreateAuthSignature(): Promise; } export type AuthProviders = { - [EIP712_AUTH_METHOD]?: EIP712AuthProvider; [EIP4361_AUTH_METHOD]?: EIP4361AuthProvider; // Fallback to satisfy type checking [key: string]: AuthProvider | undefined; }; export const USER_ADDRESS_PARAM_DEFAULT = ':userAddress'; -export const USER_ADDRESS_PARAM_EIP712 = `:userAddress${EIP712_AUTH_METHOD}`; -export const USER_ADDRESS_PARAM_EIP4361 = `:userAddress${EIP4361_AUTH_METHOD}`; export const AUTH_METHOD_FOR_PARAM: Record = { [USER_ADDRESS_PARAM_DEFAULT]: EIP4361_AUTH_METHOD, - [USER_ADDRESS_PARAM_EIP712]: EIP712_AUTH_METHOD, - [USER_ADDRESS_PARAM_EIP4361]: EIP4361_AUTH_METHOD, }; diff --git a/packages/taco-auth/src/auth-sig.ts b/packages/taco-auth/src/auth-sig.ts index 4e21677b0..5d51d7491 100644 --- a/packages/taco-auth/src/auth-sig.ts +++ b/packages/taco-auth/src/auth-sig.ts @@ -1,19 +1,15 @@ import { EthAddressSchema } from '@nucypher/shared'; import { z } from 'zod'; -import { EIP4361_AUTH_METHOD, EIP712_AUTH_METHOD } from './auth-provider'; -import { EIP4361TypedDataSchema, EIP712TypedDataSchema } from './providers'; +import { EIP4361_AUTH_METHOD } from './auth-provider'; +import { EIP4361TypedDataSchema } from './providers'; export const authSignatureSchema = z.object({ signature: z.string(), address: EthAddressSchema, - scheme: z.enum([EIP712_AUTH_METHOD, EIP4361_AUTH_METHOD]), - typedData: z.union([ - EIP4361TypedDataSchema, - // TODO(#536): Remove post EIP712 deprecation - EIP712TypedDataSchema, - ]), + scheme: z.enum([EIP4361_AUTH_METHOD]), + typedData: EIP4361TypedDataSchema, }); export type AuthSignature = z.infer; diff --git a/packages/taco-auth/src/helper.ts b/packages/taco-auth/src/helper.ts deleted file mode 100644 index 894353afb..000000000 --- a/packages/taco-auth/src/helper.ts +++ /dev/null @@ -1,19 +0,0 @@ -import { ethers } from 'ethers'; - -import { AuthProviders, EIP4361_AUTH_METHOD, EIP712_AUTH_METHOD } from './auth-provider'; -import { - EIP4361AuthProvider, - EIP4361AuthProviderParams, - EIP712AuthProvider, -} from './providers'; - -export const makeAuthProviders = ( - provider: ethers.providers.Provider, - signer?: ethers.Signer, - siweDefaultParams?: EIP4361AuthProviderParams, -): AuthProviders => { - return { - [EIP712_AUTH_METHOD]: signer ? new EIP712AuthProvider(provider, signer) : undefined, - [EIP4361_AUTH_METHOD]: signer ? new EIP4361AuthProvider(provider, signer, siweDefaultParams) : undefined, - } as AuthProviders; -}; diff --git a/packages/taco-auth/src/index.ts b/packages/taco-auth/src/index.ts index a7cb7846a..48718042f 100644 --- a/packages/taco-auth/src/index.ts +++ b/packages/taco-auth/src/index.ts @@ -1,4 +1,3 @@ export * from './providers'; -export * from './helper'; export * from './auth-sig'; export * from './auth-provider'; diff --git a/packages/taco-auth/src/providers/eip712.ts b/packages/taco-auth/src/providers/eip712.ts deleted file mode 100644 index fb554f16a..000000000 --- a/packages/taco-auth/src/providers/eip712.ts +++ /dev/null @@ -1,155 +0,0 @@ -import type { TypedDataSigner } from '@ethersproject/abstract-signer'; -import { ethers } from 'ethers'; -import { utils as ethersUtils } from 'ethers/lib/ethers'; -import { z } from 'zod'; - -import { AuthProvider } from '../auth-provider'; -import { AuthSignature } from '../auth-sig'; -import { LocalStorage } from '../storage'; - - -const typeFieldSchema = z.object({ - name: z.string(), - type: z.string(), -}); - -const domain = z.object({ - salt: z.string(), - chainId: z.number(), - name: z.string(), - version: z.string(), -}); - -const messageSchema = z.object({ - blockHash: z.string(), - address: z.string(), - blockNumber: z.number(), - signatureText: z.string(), -}); - -export const EIP712TypedDataSchema = z.object({ - primaryType: z.literal('Wallet'), - types: z.object({ - EIP712Domain: z.array(typeFieldSchema), - Wallet: z.array(typeFieldSchema), - }), - domain: domain, - message: messageSchema, -}); - - -export type EIP712TypedData = z.infer; - -interface ChainData { - blockHash: string; - chainId: number; - blockNumber: number; -} - -const EIP712Domain = [ - { - name: 'name', - type: 'string', - }, - { - name: 'version', - type: 'string', - }, - { - name: 'chainId', - type: 'uint256', - }, - { - name: 'salt', - type: 'bytes32', - }, -]; - -/** - * @deprecated Use EIP4361AuthProvider instead. - */ -export class EIP712AuthProvider implements AuthProvider { - private readonly storage: LocalStorage; - - constructor( - // TODO: We only need the provider to fetch the chainId, consider removing it - private readonly provider: ethers.providers.Provider, - private readonly signer: ethers.Signer, - ) { - console.warn( - 'DeprecationWarning: The EIP712AuthProvider authentication provider is deprecated. ' + - 'Please use EIP4361AuthProvider instead. Refer to the documentation for more details.' - ); - this.storage = new LocalStorage(); - } - - public async getOrCreateAuthSignature(): Promise { - const address = await this.signer.getAddress(); - const storageKey = `eip712-signature-${address}`; - - // If we have a signature in localStorage, return it - const maybeSignature = this.storage.getAuthSignature(storageKey); - if (maybeSignature) { - return maybeSignature; - } - - // If at this point we didn't return, we need to create a new signature - const authSignature = await this.createAuthMessage(); - this.storage.setAuthSignature(storageKey, authSignature); - return authSignature; - } - - private async createAuthMessage(): Promise { - // Ensure freshness of the signature - const { blockNumber, blockHash, chainId } = await this.getChainData(); - const address = await this.signer.getAddress(); - const signatureText = `I'm the owner of address ${address} as of block number ${blockNumber}`; - const salt = ethersUtils.hexlify(ethersUtils.randomBytes(32)); - - const typedData = { - types: { - Wallet: [ - { name: 'address', type: 'address' }, - { name: 'signatureText', type: 'string' }, - { name: 'blockNumber', type: 'uint256' }, - { name: 'blockHash', type: 'bytes32' }, - ], - }, - domain: { - name: 'TACo', - version: '1', - chainId, - salt, - }, - message: { - address, - signatureText, - blockNumber, - blockHash, - }, - }; - // https://github.com/ethers-io/ethers.js/issues/1431#issuecomment-813950552 - const signature = await ( - this.signer as unknown as TypedDataSigner - )._signTypedData(typedData.domain, typedData.types, typedData.message); - - const formattedTypedData: EIP712TypedData = { - ...typedData, - primaryType: 'Wallet', - types: { - ...typedData.types, - EIP712Domain, - }, - }; - const scheme = 'EIP712'; - return { signature, address, scheme, typedData: formattedTypedData }; - } - - private async getChainData(): Promise { - const blockNumber = await this.provider.getBlockNumber(); - const block = await this.provider.getBlock(blockNumber); - const blockHash = block.hash; - const chainId = (await this.provider.getNetwork()).chainId; - return { blockNumber, blockHash, chainId }; - } -} diff --git a/packages/taco-auth/src/providers/index.ts b/packages/taco-auth/src/providers/index.ts index 6b5476af1..5bc7a7faf 100644 --- a/packages/taco-auth/src/providers/index.ts +++ b/packages/taco-auth/src/providers/index.ts @@ -1,2 +1 @@ -export * from './eip712'; export * from './eip4361'; diff --git a/packages/taco-auth/test/auth-provider.test.ts b/packages/taco-auth/test/auth-provider.test.ts index 1ced7495a..69b5636a1 100644 --- a/packages/taco-auth/test/auth-provider.test.ts +++ b/packages/taco-auth/test/auth-provider.test.ts @@ -7,39 +7,9 @@ import { import { SiweMessage } from 'siwe'; import { describe, expect, it } from 'vitest'; -import { - EIP4361AuthProvider, - EIP712AuthProvider, - EIP712TypedData, -} from '../src'; +import { EIP4361AuthProvider } from '../src'; describe('auth provider', () => { - it('creates a new EIP-712 message', async () => { - const provider = fakeProvider(bobSecretKeyBytes); - const signer = fakeSigner(bobSecretKeyBytes); - - const eip712Provider = new EIP712AuthProvider(provider, signer); - const eip712Message = await eip712Provider.getOrCreateAuthSignature(); - expect(eip712Message.signature).toBeDefined(); - expect(eip712Message.address).toEqual(await signer.getAddress()); - expect(eip712Message.scheme).toEqual('EIP712'); - - const typedData = eip712Message.typedData as EIP712TypedData; - expect(typedData).toBeDefined(); - expect(typedData.types.Wallet).toBeDefined(); - expect(typedData.domain.name).toEqual('TACo'); - expect(typedData.domain.version).toEqual('1'); - expect(typedData.domain.chainId).toEqual( - (await provider.getNetwork()).chainId, - ); - expect(typedData.domain.salt).toBeDefined(); - expect(typedData.message.address).toEqual(await signer.getAddress()); - expect(typedData.message.blockNumber).toEqual( - await provider.getBlockNumber(), - ); - expect(typedData.message['blockHash']).toBeDefined(); - }); - it('creates a new SIWE message', async () => { const provider = fakeProvider(bobSecretKeyBytes); const signer = fakeSigner(bobSecretKeyBytes); diff --git a/packages/taco-auth/test/auth-sig.test.ts b/packages/taco-auth/test/auth-sig.test.ts index 1eabf42fb..cc8eca343 100644 --- a/packages/taco-auth/test/auth-sig.test.ts +++ b/packages/taco-auth/test/auth-sig.test.ts @@ -1,67 +1,8 @@ import { describe, expect, it } from 'vitest'; -import { - authSignatureSchema, -} from '../src'; +import { authSignatureSchema } from '../src'; + -const eip712AuthSignature = { - 'signature': 'fake-typed-signature', - 'address': '0x0000000000000000000000000000000000000000', - 'scheme': 'EIP712', - 'typedData': { - 'types': { - 'Wallet': [ - { - 'name': 'address', - 'type': 'address', - }, - { - 'name': 'signatureText', - 'type': 'string', - }, - { - 'name': 'blockNumber', - 'type': 'uint256', - }, - { - 'name': 'blockHash', - 'type': 'bytes32', - }, - ], - 'EIP712Domain': [ - { - 'name': 'name', - 'type': 'string', - }, - { - 'name': 'version', - 'type': 'string', - }, - { - 'name': 'chainId', - 'type': 'uint256', - }, - { - 'name': 'salt', - 'type': 'bytes32', - }, - ], - }, - 'domain': { - 'name': 'TACo', - 'version': '1', - 'chainId': 1234, - 'salt': '0x55d90a3b041db6dda74671bc83a25d1508979b19a105be17f57f86fe08627dbd', - }, - 'message': { - 'address': '0x0000000000000000000000000000000000000000', - 'signatureText': 'I\'m the owner of address 0x0000000000000000000000000000000000000000 as of block number 1000', - 'blockNumber': 1000, - 'blockHash': '0x0000000000000000000000000000000000000000', - }, - 'primaryType': 'Wallet', - }, -}; const eip4361AuthSignature = { 'signature': 'fake-signature', 'address': '0x0000000000000000000000000000000000000000', @@ -70,17 +11,6 @@ const eip4361AuthSignature = { }; describe('auth signature', () => { - it('accepts a well-formed EIP172 auth signature', async () => { - authSignatureSchema.parse(eip712AuthSignature); - }); - - it('rejects an EIP712 auth signature with missing fields', async () => { - expect(() => authSignatureSchema.parse({ - ...eip712AuthSignature, - 'signature': undefined, - })).toThrow(); - }); - it('accepts a well-formed EIP4361 auth signature', async () => { authSignatureSchema.parse(eip4361AuthSignature); }); diff --git a/packages/taco/src/conditions/const.ts b/packages/taco/src/conditions/const.ts index 45f25c44c..3cfff3d09 100644 --- a/packages/taco/src/conditions/const.ts +++ b/packages/taco/src/conditions/const.ts @@ -1,9 +1,5 @@ -import {ChainId} from '@nucypher/shared'; -import { - USER_ADDRESS_PARAM_DEFAULT, - USER_ADDRESS_PARAM_EIP4361, - USER_ADDRESS_PARAM_EIP712 -} from "@nucypher/taco-auth"; +import { ChainId } from '@nucypher/shared'; +import { USER_ADDRESS_PARAM_DEFAULT } from "@nucypher/taco-auth"; export const USER_ADDRESS_PARAM_EXTERNAL_EIP4361 = ':userAddressExternalEIP4361'; @@ -21,8 +17,6 @@ export const SUPPORTED_CHAIN_IDS = [ ]; export const USER_ADDRESS_PARAMS = [ - USER_ADDRESS_PARAM_EIP712, - USER_ADDRESS_PARAM_EIP4361, USER_ADDRESS_PARAM_EXTERNAL_EIP4361, // Ordering matters, this should always be last USER_ADDRESS_PARAM_DEFAULT, @@ -30,7 +24,5 @@ export const USER_ADDRESS_PARAMS = [ export const RESERVED_CONTEXT_PARAMS = [ USER_ADDRESS_PARAM_DEFAULT, - USER_ADDRESS_PARAM_EIP712, - USER_ADDRESS_PARAM_EIP4361, // USER_ADDRESS_PARAM_EXTERNAL_EIP4361 is not reserved and can be used as a custom context parameter ]; diff --git a/packages/taco/src/conditions/shared.ts b/packages/taco/src/conditions/shared.ts index 7f4a63e77..025bbdf6b 100644 --- a/packages/taco/src/conditions/shared.ts +++ b/packages/taco/src/conditions/shared.ts @@ -1,9 +1,5 @@ import { EthAddressSchema } from '@nucypher/shared'; -import { - USER_ADDRESS_PARAM_DEFAULT, - USER_ADDRESS_PARAM_EIP4361, - USER_ADDRESS_PARAM_EIP712 -} from "@nucypher/taco-auth"; +import { USER_ADDRESS_PARAM_DEFAULT } from "@nucypher/taco-auth"; import { z } from 'zod'; import { @@ -40,8 +36,6 @@ export const returnValueTestSchema = z.object({ export type ReturnValueTestProps = z.infer; const UserAddressSchema = z.enum([ - USER_ADDRESS_PARAM_EIP712, - USER_ADDRESS_PARAM_EIP4361, USER_ADDRESS_PARAM_DEFAULT, ]); export const EthAddressOrUserAddressSchema = z.union([ diff --git a/packages/taco/test/conditions/base/contract.test.ts b/packages/taco/test/conditions/base/contract.test.ts index aec30a6dd..8ab390791 100644 --- a/packages/taco/test/conditions/base/contract.test.ts +++ b/packages/taco/test/conditions/base/contract.test.ts @@ -1,6 +1,6 @@ import { initialize } from '@nucypher/nucypher-core'; -import {USER_ADDRESS_PARAM_DEFAULT} from "@nucypher/taco-auth"; -import { fakeAuthProviders} from '@nucypher/test-utils'; +import { USER_ADDRESS_PARAM_DEFAULT } from '@nucypher/taco-auth'; +import { fakeAuthProviders } from '@nucypher/test-utils'; import { beforeAll, describe, expect, it } from 'vitest'; import { diff --git a/packages/taco/test/conditions/context.test.ts b/packages/taco/test/conditions/context.test.ts index 5120a8685..673ed3db3 100644 --- a/packages/taco/test/conditions/context.test.ts +++ b/packages/taco/test/conditions/context.test.ts @@ -4,16 +4,9 @@ import { AuthSignature, EIP4361_AUTH_METHOD, EIP4361AuthProvider, - EIP712AuthProvider, - EIP712TypedData, - makeAuthProviders, } from '@nucypher/taco-auth'; -import { - USER_ADDRESS_PARAM_DEFAULT, - USER_ADDRESS_PARAM_EIP4361, - USER_ADDRESS_PARAM_EIP712 -} from "@nucypher/taco-auth"; -import { fakeAuthProviders, fakeProvider, fakeSigner, TEST_SIWE_PARAMS } from '@nucypher/test-utils'; +import { USER_ADDRESS_PARAM_DEFAULT } from "@nucypher/taco-auth"; +import { fakeAuthProviders, fakeProvider, fakeSigner } from '@nucypher/test-utils'; import { ethers } from 'ethers'; import { beforeAll, describe, expect, it, vi } from 'vitest'; @@ -316,7 +309,7 @@ describe('No authentication provider', () => { await initialize(); provider = fakeProvider(); signer = fakeSigner(); - authProviders = makeAuthProviders(provider, signer, TEST_SIWE_PARAMS); + authProviders = fakeAuthProviders(); }); it('throws an error if there is no auth provider', () => { @@ -351,22 +344,6 @@ describe('No authentication provider', () => { ).not.toThrow(); }); - it('supports multiple providers when needed', () => { - const conditionObj = { - ...testContractConditionObj, - returnValueTest: { - ...testReturnValueTest, - // TODO: Is it supposed to work? Multiple providers at the same time? - value: [USER_ADDRESS_PARAM_EIP712, USER_ADDRESS_PARAM_EIP4361], - }, - }; - const condition = new ContractCondition(conditionObj); - const conditionExpr = new ConditionExpression(condition); - expect(() => - conditionExpr.buildContext( {}, authProviders), - ).not.toThrow(); - }); - async function makeAuthSignature(authMethod: string) { const conditionObj = { ...testContractConditionObj, @@ -386,25 +363,6 @@ describe('No authentication provider', () => { return authSignature; } - async function testEIP712AuthMethod(authMethod: string) { - const eip712Spy = vi.spyOn( - EIP712AuthProvider.prototype, - 'getOrCreateAuthSignature', - ); - - const authSignature = await makeAuthSignature(authMethod); - expect(authSignature).toBeDefined(); - expect(authSignature.signature).toBeDefined(); - expect(authSignature.scheme).toEqual('EIP712'); - expect(authSignature.address).toEqual(await signer.getAddress()); - - const typedData = authSignature.typedData as EIP712TypedData; - expect(typedData).toBeDefined(); - expect(typedData.domain.name).toEqual('TACo'); - expect(typedData.message.address).toEqual(await signer.getAddress()); - expect(eip712Spy).toHaveBeenCalledOnce(); - } - async function testEIP4361AuthMethod(authMethod: string) { const eip4361Spy = vi.spyOn( EIP4361AuthProvider.prototype, @@ -419,17 +377,9 @@ describe('No authentication provider', () => { await testEIP4361AuthMethod(USER_ADDRESS_PARAM_DEFAULT); }); - it('supports eip712', async () => { - await testEIP712AuthMethod(USER_ADDRESS_PARAM_EIP712); - }); - - it('supports eip4361', async () => { - await testEIP4361AuthMethod(USER_ADDRESS_PARAM_EIP4361); - }); - it('supports reusing external eip4361', async () => { // Because we are reusing an existing SIWE auth message, we have to pass it as a custom parameter - const authMessage = await makeAuthSignature(USER_ADDRESS_PARAM_EIP4361); + const authMessage = await makeAuthSignature(USER_ADDRESS_PARAM_DEFAULT); const customParams: Record = { [USER_ADDRESS_PARAM_EXTERNAL_EIP4361]: authMessage as CustomContextParam, }; diff --git a/packages/test-utils/src/utils.ts b/packages/test-utils/src/utils.ts index c72822466..b5d830a07 100644 --- a/packages/test-utils/src/utils.ts +++ b/packages/test-utils/src/utils.ts @@ -39,7 +39,7 @@ import { Ursula, zip, } from '@nucypher/shared'; -import {makeAuthProviders} from "@nucypher/taco-auth"; +import { EIP4361_AUTH_METHOD, EIP4361AuthProvider } from '@nucypher/taco-auth'; import axios from 'axios'; import { ethers, providers, Wallet } from 'ethers'; import { expect, SpyInstance, vi } from 'vitest'; @@ -58,7 +58,7 @@ export const fakePorterUri = 'https://_this_should_crash.com/'; const makeFakeProvider = ( timestamp: number, blockNumber: number, - blockHash: string + blockHash: string, ) => { const block = { timestamp, hash: blockHash }; return { @@ -86,7 +86,11 @@ export const fakeSigner = ( } as unknown as ethers.providers.JsonRpcSigner; }; -export const fakeAuthProviders = () => makeAuthProviders(fakeProvider(), fakeSigner(), TEST_SIWE_PARAMS); +export const fakeAuthProviders = () => { + return { + [EIP4361_AUTH_METHOD]: new EIP4361AuthProvider(fakeProvider(), fakeSigner(), TEST_SIWE_PARAMS), + }; +}; export const fakeProvider = ( secretKeyBytes = SecretKey.random().toBEBytes(), @@ -254,15 +258,15 @@ interface FakeDkgRitualFlow { } export const fakeTDecFlow = ({ - validators, - validatorKeypairs, - ritualId, - sharesNum, - threshold, - receivedMessages, - message, - thresholdMessageKit, -}: FakeDkgRitualFlow) => { + validators, + validatorKeypairs, + ritualId, + sharesNum, + threshold, + receivedMessages, + message, + thresholdMessageKit, + }: FakeDkgRitualFlow) => { // Having aggregated the transcripts, the validators can now create decryption shares const decryptionShares: DecryptionShareSimple[] = []; zip(validators, validatorKeypairs).forEach(([validator, keypair]) => {