From a3a10639f89a7229f439e2a3395b2cdbf5fc892d Mon Sep 17 00:00:00 2001
From: Piotr Roslaniec
Date: Fri, 28 Jun 2024 12:02:01 +0200
Subject: [PATCH] feat(auth): validate user-provided auth signature
---
packages/shared/package.json | 3 ++-
packages/shared/src/index.ts | 1 +
packages/shared/src/schemas.ts | 4 ++++
packages/taco-auth/package.json | 3 ++-
packages/taco-auth/src/auth-sig.ts | 18 ++++++++++++++++++
packages/taco-auth/src/providers/eip4361.ts | 5 ++++-
packages/taco/package.json | 2 +-
packages/taco/src/conditions/const.ts | 3 ---
packages/taco/src/conditions/shared.ts | 6 +-----
pnpm-lock.yaml | 8 +++++++-
10 files changed, 40 insertions(+), 13 deletions(-)
create mode 100644 packages/shared/src/schemas.ts
create mode 100644 packages/taco-auth/src/auth-sig.ts
diff --git a/packages/shared/package.json b/packages/shared/package.json
index 33b60369d..e0163869b 100644
--- a/packages/shared/package.json
+++ b/packages/shared/package.json
@@ -47,7 +47,8 @@
"axios": "^1.6.8",
"deep-equal": "^2.2.3",
"ethers": "*",
- "qs": "^6.12.1"
+ "qs": "^6.12.1",
+ "zod": "*"
},
"devDependencies": {
"@typechain/ethers-v5": "^11.1.2",
diff --git a/packages/shared/src/index.ts b/packages/shared/src/index.ts
index 63f08aa5a..0ca14e2b0 100644
--- a/packages/shared/src/index.ts
+++ b/packages/shared/src/index.ts
@@ -3,6 +3,7 @@ export * from './porter';
export type * from './types';
export * from './utils';
export * from './web3';
+export * from './schemas';
// Re-exports
export {
diff --git a/packages/shared/src/schemas.ts b/packages/shared/src/schemas.ts
new file mode 100644
index 000000000..0f083c130
--- /dev/null
+++ b/packages/shared/src/schemas.ts
@@ -0,0 +1,4 @@
+import { z } from 'zod';
+
+export const ETH_ADDRESS_REGEXP = new RegExp('^0x[a-fA-F0-9]{40}$');
+export const EthAddressSchema = z.string().regex(ETH_ADDRESS_REGEXP);
diff --git a/packages/taco-auth/package.json b/packages/taco-auth/package.json
index 0e821b87c..639c80f8c 100644
--- a/packages/taco-auth/package.json
+++ b/packages/taco-auth/package.json
@@ -41,7 +41,8 @@
"dependencies": {
"@ethersproject/abstract-signer": "^5.7.0",
"@nucypher/shared": "workspace:*",
- "siwe": "^2.3.2"
+ "siwe": "^2.3.2",
+ "zod": "^3.22.4"
},
"devDependencies": {
"@nucypher/test-utils": "workspace:*"
diff --git a/packages/taco-auth/src/auth-sig.ts b/packages/taco-auth/src/auth-sig.ts
new file mode 100644
index 000000000..749c1b1ec
--- /dev/null
+++ b/packages/taco-auth/src/auth-sig.ts
@@ -0,0 +1,18 @@
+import { EthAddressSchema } from '@nucypher/shared';
+import { z } from 'zod';
+
+import { EIP4361TypedDataSchema } from './providers/eip4361';
+import { EIP4361_AUTH_METHOD, EIP712_AUTH_METHOD } from './types';
+
+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
+ z.unknown()
+ ])
+});
+
+export type AuthSignature = z.infer;
diff --git a/packages/taco-auth/src/providers/eip4361.ts b/packages/taco-auth/src/providers/eip4361.ts
index 48c3fc1a0..0a5ab1362 100644
--- a/packages/taco-auth/src/providers/eip4361.ts
+++ b/packages/taco-auth/src/providers/eip4361.ts
@@ -1,10 +1,13 @@
import { ethers } from 'ethers';
import { generateNonce, SiweMessage } from 'siwe';
+import { z } from 'zod';
import { LocalStorage } from '../storage';
import { AuthSignature, EIP4361_AUTH_METHOD } from '../types';
-export type EIP4361TypedData = string;
+export const EIP4361TypedDataSchema = z.string();
+
+export type EIP4361TypedData = z.infer;
export type EIP4361AuthProviderParams = {
domain: string;
diff --git a/packages/taco/package.json b/packages/taco/package.json
index fb9f58ca4..90dffe9c4 100644
--- a/packages/taco/package.json
+++ b/packages/taco/package.json
@@ -44,7 +44,7 @@
"@nucypher/taco-auth": "workspace:*",
"ethers": "*",
"semver": "^7.5.2",
- "zod": "^3.22.4"
+ "zod": "*"
},
"devDependencies": {
"@nucypher/test-utils": "workspace:*",
diff --git a/packages/taco/src/conditions/const.ts b/packages/taco/src/conditions/const.ts
index 601888c31..45f25c44c 100644
--- a/packages/taco/src/conditions/const.ts
+++ b/packages/taco/src/conditions/const.ts
@@ -8,8 +8,6 @@ import {
export const USER_ADDRESS_PARAM_EXTERNAL_EIP4361 =
':userAddressExternalEIP4361';
-export const ETH_ADDRESS_REGEXP = new RegExp('^0x[a-fA-F0-9]{40}$');
-
// Only allow alphanumeric characters and underscores
export const CONTEXT_PARAM_REGEXP = new RegExp('^:[a-zA-Z_][a-zA-Z0-9_]*$');
@@ -35,5 +33,4 @@ export const RESERVED_CONTEXT_PARAMS = [
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
- // USER_ADDRESS_PARAM_EXTERNAL_EIP4361
];
diff --git a/packages/taco/src/conditions/shared.ts b/packages/taco/src/conditions/shared.ts
index 720fa5038..7f4a63e77 100644
--- a/packages/taco/src/conditions/shared.ts
+++ b/packages/taco/src/conditions/shared.ts
@@ -1,3 +1,4 @@
+import { EthAddressSchema } from '@nucypher/shared';
import {
USER_ADDRESS_PARAM_DEFAULT,
USER_ADDRESS_PARAM_EIP4361,
@@ -8,9 +9,6 @@ import { z } from 'zod';
import {
CONTEXT_PARAM_PREFIX,
CONTEXT_PARAM_REGEXP,
- ETH_ADDRESS_REGEXP,
-
-
} from './const';
export const contextParamSchema = z.string().regex(CONTEXT_PARAM_REGEXP);
@@ -41,8 +39,6 @@ export const returnValueTestSchema = z.object({
export type ReturnValueTestProps = z.infer;
-const EthAddressSchema = z.string().regex(ETH_ADDRESS_REGEXP);
-
const UserAddressSchema = z.enum([
USER_ADDRESS_PARAM_EIP712,
USER_ADDRESS_PARAM_EIP4361,
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index 3d109aaf3..940db4893 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -512,6 +512,9 @@ importers:
qs:
specifier: ^6.12.1
version: 6.12.1
+ zod:
+ specifier: '*'
+ version: 3.23.8
devDependencies:
'@typechain/ethers-v5':
specifier: ^11.1.2
@@ -553,7 +556,7 @@ importers:
specifier: ^7.5.2
version: 7.6.2
zod:
- specifier: ^3.22.4
+ specifier: '*'
version: 3.23.8
devDependencies:
'@nucypher/test-utils':
@@ -574,6 +577,9 @@ importers:
siwe:
specifier: ^2.3.2
version: 2.3.2(ethers@5.7.2)
+ zod:
+ specifier: ^3.22.4
+ version: 3.23.8
devDependencies:
'@nucypher/test-utils':
specifier: workspace:*