Skip to content

Commit 13ec00a

Browse files
committed
add eth rpc config
1 parent 9f3db12 commit 13ec00a

8 files changed

Lines changed: 58 additions & 20 deletions

File tree

nextjs-app/app/api/validate/route.ts

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { hasAccess } from "@/lib/access";
2-
import { getXnodeAddress } from "@/lib/xnode-address";
2+
import { verifyXnodeUserEthAddress as verifyXnodeUserEthAddress } from "@/lib/xnode-address";
33
import { cookies as getCookies } from "next/headers";
44
import { NextRequest } from "next/server";
55
import { isHex } from "viem";
@@ -41,8 +41,13 @@ export async function GET(req: NextRequest) {
4141
throw new Error();
4242
}
4343

44-
const address = await getXnodeAddress({ domain, timestamp, signature });
45-
if (requestedUser !== address) {
44+
const validSignature = await verifyXnodeUserEthAddress({
45+
user: requestedUser,
46+
domain,
47+
timestamp,
48+
signature,
49+
});
50+
if (!validSignature) {
4651
requestedUser = undefined;
4752
}
4853
} else {

nextjs-app/components/login.tsx

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
"use client";
22

33
import { getMessage } from "@/lib/message";
4-
import { getXnodeAddress } from "@/lib/xnode-address";
4+
import { toXnodeAddress } from "@/lib/xnode-address";
55
import sdk from "@farcaster/miniapp-sdk";
66
import { useRouter, useSearchParams } from "next/navigation";
77
import { useEffect, useState } from "react";
@@ -15,7 +15,7 @@ export function Login({ deniedForUser }: { deniedForUser?: string }) {
1515
}, [searchParams]);
1616
const { replace } = useRouter();
1717

18-
const { isConnected } = useAccount();
18+
const { address } = useAccount();
1919
const { signMessageAsync, isPending, error: signError } = useSignMessage();
2020

2121
const [loginError, setLoginError] = useState<string>("");
@@ -45,7 +45,7 @@ export function Login({ deniedForUser }: { deniedForUser?: string }) {
4545
: signError.message}
4646
</span>
4747
)}
48-
{isConnected &&
48+
{address &&
4949
(isPending ? (
5050
<div className="flex gap-2">
5151
<svg
@@ -94,11 +94,7 @@ export function Login({ deniedForUser }: { deniedForUser?: string }) {
9494
"Content-Type": "application/json",
9595
},
9696
body: JSON.stringify({
97-
user: await getXnodeAddress({
98-
domain,
99-
signature,
100-
timestamp: timestamp.toString(),
101-
}),
97+
user: toXnodeAddress({ address }),
10298
signature,
10399
timestamp: timestamp.toString(),
104100
}),

nextjs-app/lib/config.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
export const config = JSON.parse(
2+
process.env.XNODEAUTH_CONFIG ?? JSON.stringify({ eth: { rpc: "" } })
3+
) as {
4+
eth: {
5+
rpc: string;
6+
};
7+
};

nextjs-app/lib/xnode-address.ts

Lines changed: 20 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,36 @@
1-
import { Address, Hex, recoverMessageAddress } from "viem";
1+
import { Address, createPublicClient, Hex, http, verifyMessage } from "viem";
22
import { getMessage } from "./message";
3+
import { config } from "./config";
34

45
export function toXnodeAddress({ address }: { address: Address }): string {
56
return `eth:${address.replace("0x", "").toLowerCase()}`;
67
}
78

8-
export function getXnodeAddress({
9+
export async function verifyXnodeUserEthAddress({
10+
user,
911
domain,
1012
timestamp,
1113
signature,
1214
}: {
15+
user: string;
1316
domain: string;
1417
timestamp: string;
1518
signature: Hex;
16-
}): Promise<string> {
17-
return recoverMessageAddress({
19+
}): Promise<boolean> {
20+
if (config.eth.rpc) {
21+
const publicClient = createPublicClient({
22+
transport: http(config.eth.rpc),
23+
});
24+
return await publicClient.verifyMessage({
25+
address: `0x${user.replace("eth:", "")}`,
26+
message: getMessage({ domain, timestamp: Number(timestamp) }),
27+
signature,
28+
});
29+
}
30+
31+
return await verifyMessage({
32+
address: `0x${user.replace("eth:", "")}`,
1833
message: getMessage({ domain, timestamp: Number(timestamp) }),
1934
signature,
20-
}).then((address) => toXnodeAddress({ address }));
35+
});
2136
}

nextjs-app/package-lock.json

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

nextjs-app/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "xnode-auth",
3-
"version": "1.1.1",
3+
"version": "1.1.2",
44
"scripts": {
55
"dev": "next dev",
66
"build": "next build",

nix/nixos-module.nix

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ in
5050
};
5151
}
5252
);
53+
default = { };
5354
example = {
5455
"regex:^eth:*.$" = {
5556
paths = "^\/user\/profile(?:\?.*)?$";
@@ -207,6 +208,19 @@ in
207208
'';
208209
};
209210

211+
config = {
212+
eth = {
213+
rpc = lib.mkOption {
214+
type = lib.types.str;
215+
default = "";
216+
example = "https://mainnet.base.org";
217+
description = ''
218+
Use an RPC to validate smart account signatures.
219+
'';
220+
};
221+
};
222+
};
223+
210224
nginxConfig = {
211225
enable = lib.mkOption {
212226
type = lib.types.bool;
@@ -263,6 +277,7 @@ in
263277
) [ ] cfg.domains
264278
)
265279
);
280+
XNODEAUTH_CONFIG = builtins.toJSON cfg.config;
266281
};
267282
serviceConfig = {
268283
ExecStart = "${lib.getExe xnode-auth}";

nix/package.nix

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{ pkgs, lib }:
22
pkgs.buildNpmPackage {
33
pname = "xnode-auth";
4-
version = "1.1.1";
4+
version = "1.1.2";
55
src = ../nextjs-app;
66

77
npmDeps = pkgs.importNpmLock {

0 commit comments

Comments
 (0)