SIWE aids DApp identification to create a secure and reliable user system.

SIWE: A more powerful method of identification for your DApp

SIWE(Sign-In with Ethereum) is a method for verifying user identification on Ethereum, similar to initiating a transaction to prove the user's control over the wallet. Currently, most wallet plugins support this simple authentication method, requiring only a signature of the information within the plugin. This article primarily discusses the signing scenarios on Ethereum and does not cover other public chains.

SIWE User Manual: How to Make Your DApp More Powerful?

Does the project need SIWE?

If your DApp has the following requirements, you may consider using SIWE:

  • Have your own user system
  • Need to query information related to user privacy

But if your DApp mainly serves as a query function, like applications such as etherscan, then SIWE may not be necessary.

Although connecting a wallet on a DApp represents ownership of the wallet, this is only valid for the front end. For interface calls that require back-end support, simply passing the address cannot prove identification, as the address is public information.

The Principle and Process of SIWE

The SIWE process can be summarized in three steps: connect wallet - sign - obtain identification.

SIWE User Manual: How to Make Your DApp More Powerful?

Connect Wallet

This is a common Web3 operation to connect the wallet in the DApp through the wallet plugin.

signature

The signing steps include obtaining the Nonce value, wallet signing, and backend signature verification.

First, call the backend interface to obtain the Nonce value. The backend will generate a random Nonce and associate it with the address. After obtaining the Nonce, the front end constructs the signature content, including Nonce, domain name, chain ID, etc., uses the method provided by the wallet to sign, and then sends the signature to the backend.

obtain identification

After the backend verification of the signature passes, it will return the user's identification, such as JWT. The frontend should include the address and identification in subsequent requests to prove ownership of the wallet.

SIWE User Manual: How to Make Your DApp More Powerful?

Practice SIWE

We will develop a DApp that supports SIWE using Next.js, with the goal of returning a JWT for identification verification.

preparation work

  1. Install Next.js:

npx create-next-app@14

  1. Install SIWE related dependencies:

npm install antd @ant-design/web3 @ant-design/web3-wagmi wagmi viem @tanstack/react-query --save

Introduce Wagmi

Import WagmiProvider in layout.tsx:

typescript "use client"; import { getNonce, verifyMessage } from "@/app/api"; import { Mainnet, MetaMask, OkxWallet, TokenPocket, WagmiWeb3ConfigProvider, WalletConnect, } from "@ant-design/web3-wagmi"; import { QueryClient } from "@tanstack/react-query"; import React from "react"; import { createSiweMessage } from "viem/siwe"; import { http } from "wagmi"; import { JwtProvider } from "./JwtProvider";

const YOUR_WALLET_CONNECT_PROJECT_ID = "c07c0051c2055890eade3556618e38a6"; const queryClient = new QueryClient();

const WagmiProvider: React.FC = ({ children }) => { const [jwt, setJwt] = React.useState(()null());

return ( <wagmiweb3configprovider siwe="{{" getnonce:="" async="" (address)=""> (await getNonce(address)).data, createMessage: (props) => { return createSiweMessage({ ...props, statement: "Ant Design Web3" }); }, verifyMessage: async (message, signature) => { const jwt = (await verifyMessage(message, signature)).data; setJwt(jwt); return !!jwt; }, }} chains={[Mainnet]} transports={{ [Mainnet.id]: http(), }} walletConnect={{ projectId: YOUR_WALLET_CONNECT_PROJECT_ID, }} wallets={[ MetaMask(), WalletConnect(), TokenPocket({ group: "Popular", }), OkxWallet(), ]} queryClient={queryClient} > <jwtprovider.provider value="{jwt}">{children}</jwtprovider.provider> ); };

export default WagmiProvider;

SIWE User Manual: How to Make Your DApp More Powerful?

add connection button

typescript "use client"; import type { Account } from "@ant-design/web3"; import { ConnectButton, Connector } from "@ant-design/web3"; import { Flex, Space } from "antd"; import React from "react"; import { JwtProvider } from "./JwtProvider";

export default function App() { const jwt = React.useContext(JwtProvider);

const renderSignBtnText = ( defaultDom: React.ReactNode, account?: Account ) => { const { address } = account ?? {}; const ellipsisAddress = address ? ${address.slice(0, 6)}...${address.slice(-6)} : ""; return Sign in as ${ellipsisAddress}; };

return ( <>

JWT: {jwt}
); }

SIWE User Manual: How to Make Your DApp More Powerful?

implement interface

Nonce interface

typescript import { randomBytes } from "crypto"; import { addressMap } from "../cache";

export async function GET(request: Request) { const { searchParams } = new URL(request.url); const address = searchParams.get("address");

if (!address) { throw new Error("Invalid address"); } const nonce = randomBytes(16).toString(("hex")); addressMap.set(address, nonce); return Response.json({ data: nonce, }); }

verification message interface

typescript import { createPublicClient, http } from "viem"; import { mainnet } from "viem/chains"; import jwt from "jsonwebtoken"; import { parseSiweMessage } from "viem/siwe"; import { addressMap } from "../cache";

const JWT_SECRET = "your-secret-key";

const publicClient = createPublicClient({ chain: mainnet, transport: http(), });

export async function POST(request: Request) { const { signature, message } = await request.json();

const { nonce, address = "0x" } = parseSiweMessage(message);

if (!nonce || nonce !== addressMap.get(address)) { throw new Error("Invalid nonce"); }

const valid = await publicClient.verifySiweMessage({ message, address, signature, });

if (!valid) { throw new Error("Invalid signature"); }

const token = jwt.sign({ address }, JWT_SECRET, { expiresIn: "1h" }); return Response.json({ data: token, }); }

SIWE User Manual: How to Make Your DApp More Powerful?

Optimization Suggestions

To improve the response speed of SIWE login, it is recommended to use a dedicated node service instead of the default RPC node. Taking the ZAN node service as an example, after obtaining the Ethereum mainnet HTTPS RPC connection, replace the default RPC of publicClient:

typescript const publicClient = createPublicClient({ chain: mainnet, transport: http('), //ZAN node service RPC });

This can significantly reduce verification time and improve interface speed.

SIWE User Manual: How to Make Your DApp More Powerful?

DAPP1.84%
View Original
This page may contain third-party content, which is provided for information purposes only (not representations/warranties) and should not be considered as an endorsement of its views by Gate, nor as financial or professional advice. See Disclaimer for details.
  • Reward
  • 10
  • Repost
  • Share
Comment
0/400
BearMarketSagevip
· 07-25 10:31
This verification has to be so fancy.
View OriginalReply0
Rekt_Recoveryvip
· 07-25 09:31
lost too much on leverage but still here to teach...identity is all we got fr fr
Reply0
RugPullAlertBotvip
· 07-24 00:17
Buddha again an identification verification
View OriginalReply0
FrogInTheWellvip
· 07-22 16:13
It is clearly necessary to implement important permissions identification.
View OriginalReply0
LiquidationWatchervip
· 07-22 16:11
been rekt by wallet exploits before... siwe better not fail us this time
Reply0
LayerZeroHerovip
· 07-22 16:11
Another mixed verification solution is here.
View OriginalReply0
ser_we_are_earlyvip
· 07-22 16:03
Really good, using this is much more reliable than a handwritten signature.
View OriginalReply0
wagmi_eventuallyvip
· 07-22 16:02
Just sign it and it's done, why worry about anything else?
View OriginalReply0
WalletDivorcervip
· 07-22 16:00
Ah, this thing is indeed more advanced than Google log in.
View OriginalReply0
ForkTonguevip
· 07-22 15:52
Is simple verification safe? Hehe
View OriginalReply0
View More
Trade Crypto Anywhere Anytime
qrCode
Scan to download Gate App
Community
English
  • 简体中文
  • English
  • Tiếng Việt
  • 繁體中文
  • Español
  • Русский
  • Français (Afrique)
  • Português (Portugal)
  • Bahasa Indonesia
  • 日本語
  • بالعربية
  • Українська
  • Português (Brasil)