Skip to content

Commit e73157f

Browse files
committed
Fix server side verification example
1 parent aa9a5f6 commit e73157f

File tree

5 files changed

+139
-34
lines changed

5 files changed

+139
-34
lines changed

other/server-side-verification-example/app/App.tsx

Lines changed: 31 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import { SwitchChain } from "../components/switchNetwork";
99
import { useEffect } from "react";
1010

1111
function App() {
12-
const { connect, isConnected, loading: connectLoading, error: connectError } = useWeb3AuthConnect();
12+
const { connect, isConnected, loading: connectLoading, error: connectError, connectorName } = useWeb3AuthConnect();
1313
const { disconnect, loading: disconnectLoading, error: disconnectError } = useWeb3AuthDisconnect();
1414
const { userInfo } = useWeb3AuthUser();
1515
const { token, getIdentityToken, loading: idTokenLoading, error: idTokenError } = useIdentityToken();
@@ -25,26 +25,43 @@ function App() {
2525
}
2626

2727
const validateIdToken = async () => {
28-
await getIdentityToken();
29-
const pubKey = await web3Auth?.provider?.request({ method: "public_key" });
28+
const idToken = await getIdentityToken();
29+
30+
let res;
31+
if (connectorName === "auth") {
32+
// Social login: send public key
33+
const pubKey = await web3Auth?.provider?.request({ method: "public_key" });
34+
console.log("pubKey:", pubKey);
35+
res = await fetch("/api/login", {
36+
method: "POST",
37+
headers: {
38+
"Content-Type": "application/json",
39+
Authorization: `Bearer ${idToken}`,
40+
},
41+
body: JSON.stringify({ appPubKey: pubKey }),
42+
});
43+
} else {
44+
// External wallet: send address
45+
const address = await web3Auth?.provider?.request({ method: "eth_accounts" });
46+
res = await fetch("/api/login-external", {
47+
method: "POST",
48+
headers: {
49+
"Content-Type": "application/json",
50+
Authorization: `Bearer ${idToken}`,
51+
},
52+
body: JSON.stringify({ address }),
53+
});
54+
}
3055

31-
// Validate idToken with server
32-
const res = await fetch("/api/login", {
33-
method: "POST",
34-
headers: {
35-
"Content-Type": "application/json",
36-
Authorization: `Bearer ${token}`,
37-
},
38-
body: JSON.stringify({ appPubKey: pubKey }),
39-
});
56+
// Handle response
4057
if (res.status === 200) {
4158
toast.success("JWT Verification Successful");
4259
uiConsole(`Logged in Successfully!`, userInfo);
4360
} else {
4461
toast.error("JWT Verification Failed");
45-
console.log("JWT Verification Failed");
4662
await disconnect();
4763
}
64+
4865
return res.status;
4966
};
5067

@@ -60,7 +77,7 @@ function App() {
6077
};
6178

6279
init();
63-
}, [isConnected, validateIdToken]);
80+
}, [isConnected]);
6481

6582
const loggedInView = (
6683
<div className="grid">
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
import * as jose from "jose";
2+
import { NextRequest, NextResponse } from "next/server";
3+
4+
export async function POST(req: NextRequest) {
5+
try {
6+
// Extract JWT token from Authorization header
7+
const authHeader = req.headers.get("authorization");
8+
const idToken = authHeader?.split(" ")[1];
9+
10+
if (!idToken) {
11+
return NextResponse.json({ error: "No token provided" }, { status: 401 });
12+
}
13+
14+
// Get address from request body
15+
const { address } = await req.json();
16+
17+
if (!address) {
18+
return NextResponse.json({ error: "No address provided" }, { status: 400 });
19+
}
20+
21+
// Verify JWT using AuthJS JWKS
22+
const jwks = jose.createRemoteJWKSet(new URL("https://authjs.web3auth.io/jwks"));
23+
const { payload } = await jose.jwtVerify(idToken, jwks, { algorithms: ["ES256"] });
24+
25+
// Find matching wallet in JWT
26+
const wallets = (payload as any).wallets || [];
27+
const addressToCheck = Array.isArray(address) ? address[0] : address;
28+
const normalizedAddress = addressToCheck.toLowerCase();
29+
30+
const isValid = wallets.some((wallet: any) => {
31+
return wallet.type === "ethereum" &&
32+
wallet.address &&
33+
wallet.address.toLowerCase() === normalizedAddress;
34+
});
35+
36+
if (isValid) {
37+
return NextResponse.json({ name: "Verification Successful" }, { status: 200 });
38+
} else {
39+
return NextResponse.json({ name: "Verification Failed" }, { status: 400 });
40+
}
41+
} catch (error) {
42+
console.error("External wallet verification error:", error);
43+
return NextResponse.json({ error: "Verification error" }, { status: 500 });
44+
}
45+
}
Lines changed: 44 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,55 @@
11
import * as jose from "jose";
2-
import { NextResponse } from "next/server";
2+
import { NextRequest, NextResponse } from "next/server";
33

4-
export async function POST(request: Request) {
4+
export async function POST(req: NextRequest) {
55
try {
6-
const authHeader = request.headers.get("authorization");
7-
const idToken = authHeader?.split(" ")[1] || "";
6+
// Extract JWT token from Authorization header
7+
const authHeader = req.headers.get("authorization");
8+
const idToken = authHeader?.split(" ")[1];
89

9-
const body = await request.json();
10-
const app_pub_key = body.appPubKey;
10+
if (!idToken) {
11+
return NextResponse.json({ error: "No token provided" }, { status: 401 });
12+
}
1113

12-
const jwks = jose.createRemoteJWKSet(new URL("https://api.openlogin.com/jwks"));
13-
const jwtDecoded = await jose.jwtVerify(idToken, jwks, {
14-
algorithms: ["ES256"],
15-
});
14+
// Get public key from request body
15+
const { appPubKey } = await req.json();
16+
17+
if (!appPubKey) {
18+
return NextResponse.json({ error: "No appPubKey provided" }, { status: 400 });
19+
}
20+
21+
// Verify JWT using Web3Auth JWKS
22+
const jwks = jose.createRemoteJWKSet(new URL("https://api-auth.web3auth.io/jwks"));
23+
const { payload } = await jose.jwtVerify(idToken, jwks, { algorithms: ["ES256"] });
24+
25+
// Find matching wallet in JWT
26+
const wallets = (payload as any).wallets || [];
27+
const normalizedAppKey = appPubKey.toLowerCase().replace(/^0x/, '');
1628

17-
if (
18-
(jwtDecoded.payload as any).wallets.find((x: { type: string }) => x.type === "web3auth_app_key").public_key.toLowerCase() ===
19-
app_pub_key.toLowerCase()
20-
) {
21-
// Verified
22-
return NextResponse.json({ name: "Validation Success" }, { status: 200 });
29+
const isValid = wallets.some((wallet: any) => {
30+
if (wallet.type !== "web3auth_app_key") return false;
31+
32+
const walletKey = wallet.public_key.toLowerCase();
33+
34+
// Direct key comparison for ed25519 keys
35+
if (walletKey === normalizedAppKey) return true;
36+
37+
// Handle compressed secp256k1 keys
38+
if (wallet.curve === "secp256k1" && walletKey.length === 66 && normalizedAppKey.length === 128) {
39+
const compressedWithoutPrefix = walletKey.substring(2);
40+
return normalizedAppKey.startsWith(compressedWithoutPrefix);
41+
}
42+
43+
return false;
44+
});
45+
46+
if (isValid) {
47+
return NextResponse.json({ name: "Verification Successful" }, { status: 200 });
2348
} else {
24-
return NextResponse.json({ name: "Failed" }, { status: 400 });
49+
return NextResponse.json({ name: "Verification Failed" }, { status: 400 });
2550
}
2651
} catch (error) {
27-
return NextResponse.json({ error }, { status: 500 });
52+
console.error("Social login verification error:", error);
53+
return NextResponse.json({ error: "Verification error" }, { status: 500 });
2854
}
2955
}

other/server-side-verification-example/app/web3authContext.tsx

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
// IMP START - Quick Start
2-
import { WEB3AUTH_NETWORK, type Web3AuthOptions } from "@web3auth/modal";
2+
import { authConnector, WEB3AUTH_NETWORK, type Web3AuthOptions } from "@web3auth/modal";
33
// IMP END - Quick Start
44

55
// IMP START - Dashboard Registration
@@ -10,7 +10,6 @@ const clientId = "BPi5PB_UiIZ-cPz1GtV5i1I2iOSOHuimiXBI0e-Oe_u6X3oVAbCiAZOTEBtTXw
1010
const web3AuthOptions: Web3AuthOptions = {
1111
clientId,
1212
web3AuthNetwork: WEB3AUTH_NETWORK.SAPPHIRE_MAINNET,
13-
1413
};
1514
// IMP END - Instantiate SDK
1615

other/server-side-verification-example/next.config.js

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,24 @@
22
const nextConfig = {
33
reactStrictMode: true,
44
// swcMinify: true,
5+
webpack: (config) => {
6+
// Handle @react-native-async-storage/async-storage
7+
config.resolve.alias = {
8+
...config.resolve.alias,
9+
'@react-native-async-storage/async-storage': false,
10+
};
11+
12+
// Handle other potential React Native modules
13+
config.resolve.fallback = {
14+
...config.resolve.fallback,
15+
fs: false,
16+
net: false,
17+
tls: false,
18+
crypto: false,
19+
};
20+
21+
return config;
22+
},
523
}
624

725
module.exports = nextConfig

0 commit comments

Comments
 (0)