|
| 1 | +--- |
| 2 | +"@rainbow-me/rainbowkit": minor |
| 3 | +--- |
| 4 | + |
| 5 | +The Authentication API now supports ERC-1271 and ERC-6492 for smart contract signature verification to enable Sign-in with Ethereum for Smart Contract Wallets, including Coinbase Smart Wallet and Argent. |
| 6 | + |
| 7 | +We have also deprecated the `siwe` and `ethers` peer dependencies in favor of `viem/siwe` to make RainbowKit even more seamless. |
| 8 | + |
| 9 | +Follow the appropriate steps below to migrate. |
| 10 | + |
| 11 | +** NextAuth Authentication ** |
| 12 | + |
| 13 | +1. Remove `siwe` and `ethers` |
| 14 | + |
| 15 | +```bash |
| 16 | +npm uninstall siwe ethers |
| 17 | +``` |
| 18 | + |
| 19 | +2. Upgrade RainbowKit, `rainbowkit-siwe-next-auth`, and `viem` |
| 20 | + |
| 21 | +```bash |
| 22 | +npm i @rainbow-me/rainbowkit@^2.2.0 rainbow-me/rainbowkit-siwe-next-auth@^0.5.0 viem@^2.12.0 |
| 23 | +``` |
| 24 | + |
| 25 | +3. Create a Public Client |
| 26 | + |
| 27 | +This allows `viem` to verify smart contract signatures. |
| 28 | + |
| 29 | +```diff |
| 30 | +const config = getDefaultConfig({ |
| 31 | + /* your config */ |
| 32 | +}); |
| 33 | + |
| 34 | ++ const publicClient = config.getClient().extend(publicActions); |
| 35 | +``` |
| 36 | + |
| 37 | +4. Adjust your `authorize` implementation in `/api/auth/[...nextauth].ts` |
| 38 | + |
| 39 | +```diff |
| 40 | +- import { SiweMessage } from 'siwe'; |
| 41 | ++ import { |
| 42 | ++ type SiweMessage, |
| 43 | ++ parseSiweMessage, |
| 44 | ++ validateSiweMessage, |
| 45 | ++ } from 'viem/siwe'; |
| 46 | + |
| 47 | +export function getAuthOptions(req: IncomingMessage): NextAuthOptions { |
| 48 | + const providers = [ |
| 49 | + CredentialsProvider({ |
| 50 | + async authorize(credentials: any) { |
| 51 | + |
| 52 | +- const siwe = new SiweMessage( |
| 53 | +- JSON.parse(credentials?.message || '{}'), |
| 54 | +- ); |
| 55 | ++ const siweMessage = parseSiweMessage( |
| 56 | ++ credentials?.message, |
| 57 | ++ ) as SiweMessage; |
| 58 | + |
| 59 | ++ if (!validateSiweMessage({ |
| 60 | ++ address: siweMessage?.address, |
| 61 | ++ message: siweMessage, |
| 62 | ++ })) { |
| 63 | ++ return null; |
| 64 | ++ } |
| 65 | + |
| 66 | + /* ... */ |
| 67 | + |
| 68 | +- await siwe.verify({ signature: credentials?.signature || '' }); |
| 69 | ++ const valid = await publicClient.verifyMessage({ |
| 70 | ++ address: siweMessage?.address, |
| 71 | ++ message: credentials?.message, |
| 72 | ++ signature: credentials?.signature, |
| 73 | ++ }); |
| 74 | + |
| 75 | ++ if (!valid) { |
| 76 | ++ return null; |
| 77 | ++ } |
| 78 | + }, |
| 79 | + /* ... */ |
| 80 | + }) |
| 81 | + ] |
| 82 | +} |
| 83 | +``` |
| 84 | + |
| 85 | +Reference the [with-next-siwe-next-auth](https://github.com/rainbow-me/rainbowkit/tree/main/examples/with-next-siwe-next-auth) example for more guidance. |
| 86 | + |
| 87 | +** Custom Authentication ** |
| 88 | + |
| 89 | +1. Remove `siwe` and `ethers` |
| 90 | + |
| 91 | +```bash |
| 92 | +npm uninstall siwe ethers |
| 93 | +``` |
| 94 | + |
| 95 | +2. Upgrade RainbowKit and `viem` |
| 96 | + |
| 97 | +```bash |
| 98 | +npm i @rainbow-me/rainbowkit@^2.2.0 viem@^2.12.0 |
| 99 | +``` |
| 100 | + |
| 101 | +3. Create a Public Client |
| 102 | + |
| 103 | +This allows `viem` to verify smart contract signatures. |
| 104 | + |
| 105 | +```diff |
| 106 | +const config = getDefaultConfig({ |
| 107 | + /* your config */ |
| 108 | +}); |
| 109 | + |
| 110 | ++ const publicClient = config.getClient().extend(publicActions); |
| 111 | +``` |
| 112 | + |
| 113 | +4. Adjust your `createAuthenticationAdapter` implementation |
| 114 | + |
| 115 | +```diff |
| 116 | +- import { SiweMessage } from 'siwe'; |
| 117 | ++ import { createSiweMessage } from 'viem/siwe'; |
| 118 | + |
| 119 | +createAuthenticationAdapter({ |
| 120 | + getNonce: async () => { |
| 121 | + const response = await fetch('/api/nonce'); |
| 122 | + return await response.text(); |
| 123 | + }, |
| 124 | + |
| 125 | + createMessage: ({ nonce, address, chainId }) => { |
| 126 | +- return new SiweMessage({ |
| 127 | ++ return createSiweMessage({ |
| 128 | + domain: window.location.host, |
| 129 | + address, |
| 130 | + statement: 'Sign in with Ethereum to the app.', |
| 131 | + uri: window.location.origin, |
| 132 | + version: '1', |
| 133 | + chainId, |
| 134 | + nonce, |
| 135 | + }); |
| 136 | + }, |
| 137 | + |
| 138 | +- getMessageBody: ({ message }) => { |
| 139 | +- return message.prepareMessage(); |
| 140 | +- }, |
| 141 | + |
| 142 | + /* ... */ |
| 143 | +}) |
| 144 | +``` |
| 145 | + |
| 146 | +5. Adopt `generateSiweNonce` |
| 147 | + |
| 148 | +```diff |
| 149 | +- import { generateNonce } from 'siwe'; |
| 150 | ++ import { generateSiweNonce } from 'viem/siwe'; |
| 151 | + |
| 152 | +- req.session.nonce = generateNonce(); |
| 153 | ++ req.session.nonce = generateSiweNonce(); |
| 154 | +``` |
| 155 | + |
| 156 | +6. Adopt `parseSiweMessage` and `verifyMessage` if your Verify handler |
| 157 | + |
| 158 | +```diff |
| 159 | +- import { SiweMessage } from 'siwe'; |
| 160 | ++ import { parseSiweMessage, type SiweMessage } from 'viem/siwe'; |
| 161 | + |
| 162 | +const { message, signature } = req.body; |
| 163 | +- const siweMessage = new SiweMessage(message); |
| 164 | +- const { success, error, data } = await siweMessage.verify({ |
| 165 | +- signature, |
| 166 | +- }); |
| 167 | ++ const siweMessage = parseSiweMessage(message) as SiweMessage; |
| 168 | ++ const success = await publicClient.verifyMessage({ |
| 169 | ++ address: siweMessage.address, |
| 170 | ++ message, |
| 171 | ++ signature, |
| 172 | ++ }); |
| 173 | + |
| 174 | +- if (!success) throw error; |
| 175 | ++ if (!success) throw new Error('Invalid signature.'); |
| 176 | + |
| 177 | +- if (data.nonce !== req.session.nonce) |
| 178 | ++ if (siweMessage.nonce !== req.session.nonce) |
| 179 | ++ return res.status(422).json({ message: 'Invalid nonce.' }); |
| 180 | +``` |
| 181 | + |
| 182 | +Reference the [with-next-siwe-iron-session](https://github.com/rainbow-me/rainbowkit/tree/main/examples/with-next-siwe-iron-session) example for more guidance. |
0 commit comments