Skip to content

Commit e8db7d1

Browse files
authored
Merge pull request #744 from inblockio/fix/siwe-session-eoa-local-recovery
fix: recover EOA signatures locally in /session verification
2 parents 50c965f + b28b2ca commit e8db7d1

1 file changed

Lines changed: 19 additions & 3 deletions

File tree

api/src/utils/auth_utils.ts

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import { SiweMessage } from "siwe";
22
import { createPublicClient, http } from 'viem';
3+
import { ethers } from 'ethers';
34

45
const alchemyKey = process.env.ALCHEMY_API_KEY;
56

@@ -57,16 +58,31 @@ export async function verifySiweMessage(message: string, signature: string) {
5758
// console.log('Chain ID:', chainId);
5859
// console.log('Nonce:', nonce);
5960

61+
// Fast path: try local ECDSA recovery first. For standard EOA signatures
62+
// this avoids any RPC call, so verification can't be broken by upstream
63+
// RPC failures, rate limits, or missing API keys.
64+
try {
65+
const recovered = ethers.verifyMessage(message, signature);
66+
if (recovered.toLowerCase() === address.toLowerCase()) {
67+
return {
68+
isValid: true,
69+
address,
70+
expirationTime,
71+
nonce,
72+
};
73+
}
74+
} catch {
75+
// Not a standard 65-byte ECDSA signature (e.g. smart wallet) — fall
76+
// through to the on-chain verification path below.
77+
}
78+
6079
// Use Alchemy or publicnode instead of WalletConnect RPC
6180
const rpcUrl = getRpcUrl(chainId);
62-
// console.log('RPC URL:', rpcUrl);
6381

6482
const publicClient = createPublicClient({
6583
transport: http(rpcUrl)
6684
});
6785

68-
// console.log('Calling publicClient.verifyMessage...');
69-
7086
// Check if the address is a contract (smart wallet) by checking bytecode
7187
const bytecode = await publicClient.getBytecode({ address: address as `0x${string}` });
7288
const isContract = bytecode && bytecode !== '0x';

0 commit comments

Comments
 (0)