Closed45

はじめまして、NextAuthさん、Rainbowkitさん

hajimismhajimism

色々見たけど結局このリポジトリを探検するのが良さそう
https://github.com/rainbow-me/rainbowkit/tree/main/examples/with-next-siwe-next-auth

hajimismhajimism

unstable_getServerSessionも想定してくれてる。完璧じゃない?

hajimismhajimism

Providersがこいつでラップされてる
https://next-auth.js.org/providers/credentials

翻訳

Credentialsプロバイダは、ユーザー名とパスワード、ドメイン、二要素認証やハードウェアデバイス(YubiKey U2F / FIDOなど)など、任意の資格情報を使ってサインインすることを可能にします。

これは、ユーザーを認証する必要がある既存のシステムがある場合の使用をサポートすることを目的としています。

この方法で認証されたユーザはデータベースに保存されないため、JSON Web Tokens がセッションで有効な場合にのみ Credentials プロバイダを使用できるという制約があります。

hajimismhajimism

ユーザー名とパスワードがDBに保存されないなら誰がデータ保存するの?

hajimismhajimism

とりあえずこいつが本丸

 const providers = [
    CredentialsProvider({
      async authorize(credentials) {
        try {
          const siwe = new SiweMessage(
            JSON.parse(credentials?.message || '{}')
          );

          const nextAuthUrl =
            process.env.NEXTAUTH_URL ||
            (process.env.VERCEL_URL
              ? `https://${process.env.VERCEL_URL}`
              : null);
          if (!nextAuthUrl) {
            return null;
          }

          const nextAuthHost = new URL(nextAuthUrl).host;
          if (siwe.domain !== nextAuthHost) {
            return null;
          }

          if (siwe.nonce !== (await getCsrfToken({ req }))) {
            return null;
          }

          await siwe.validate(credentials?.signature || '');
          return {
            id: siwe.address,
          };
        } catch (e) {
          return null;
        }
      },
      credentials: {
        message: {
          label: 'Message',
          placeholder: '0x0',
          type: 'text',
        },
        signature: {
          label: 'Signature',
          placeholder: '0x0',
          type: 'text',
        },
      },
      name: 'Ethereum',
    }),
  ];
hajimismhajimism

下のここらへんはForm定義っぽい

    credentials: {
        message: {
          label: 'Message',
          placeholder: '0x0',
          type: 'text',
        },
        signature: {
          label: 'Signature',
          placeholder: '0x0',
          type: 'text',
        },
      },
      name: 'Ethereum',
hajimismhajimism

ゆーて認証部分これだけか

         await siwe.validate(credentials?.signature || '');
          return {
            id: siwe.address,
          };
hajimismhajimism

signatureが妥当であればidを発行する
signature, siwe.addressってなんなんだろ

hajimismhajimism
  // Hide Sign-In with Ethereum from default sign page
  if (isDefaultSigninPage) {
    authOptions.providers.pop();
  }

siweの公式によれば

We're going to now add the provider that will handle the message validation. Since it's not possible to sign in using the default page, the original provider should be removed from the list of providers before rendering. Modify pages/api/auth/[...nextauth].ts with the following:

とのこと

hajimismhajimism

電子署名とは、文書やメッセージなどのデータの真正性を証明するために付加される、短い暗号データ。作成者を証明し、改竄やすり替えが行われていないことを保証する。欧米で紙の文書に記されるサイン(signature)に似た働きをするためこのように呼ばれる。

https://e-words.jp/w/電子署名.html

hajimismhajimism

tokenはかなり抽象的だ

トークンは、プログラミングコード上でコードを構成する最小単位の要素であり、変数名、予約語、演算子、定数などが該当します。

またトークンが持つ「意味を持つ最小単位、証拠」という意味を起点に、近年は複数の意味を持つ多義語となりました。まず、情報セキュリティの認証で一度だけ使える「ワンタイムパスワード」を生成するための機器やソフトウェアなどのツール全般がトークンと呼ばれます。こちらは混同を避けるために「セキュリティトークン」と呼ばれることもありますが、意味は同じです。

そして、ブロックチェーン技術を利用して発行された仮想通貨などのデータをトークンと呼ぶこともあります。また、ブロックチェーン技術が使われており、デジタルアートなどで活用が進んでいるNFT(非代替性トークン)もトークンの一種です。

https://www.softbank.jp/sbnews/entry/20220315_01

hajimismhajimism

要するにこれは、

  1. Ethの人かどうか確かめて
  2. そうであるならそのデータをアプリ上でもそのまま認証に使う

ってことかな

       await siwe.validate(credentials?.signature || '');
          return {
            id: siwe.address,
          };
hajimismhajimism

Google認証とかとはモノが違うと思うんだけどうまく説明できない

hajimismhajimism

これを使ってFirestoreにユーザーデータ登録したいんだけどな、多分

hajimismhajimism

_app.tsxの方はwagmiとRainbowKitがよしなにやってくれすぎてて追いきれない

import '../styles/global.css';
import '@rainbow-me/rainbowkit/styles.css';
import type { AppProps } from 'next/app';
import {
  RainbowKitProvider,
  getDefaultWallets,
  connectorsForWallets,
} from '@rainbow-me/rainbowkit';
import {
  argentWallet,
  trustWallet,
  ledgerWallet,
} from '@rainbow-me/rainbowkit/wallets';
import { configureChains, createClient, WagmiConfig } from 'wagmi';
import { mainnet, polygon, optimism, arbitrum, goerli } from 'wagmi/chains';
import { alchemyProvider } from 'wagmi/providers/alchemy';
import { publicProvider } from 'wagmi/providers/public';
import { SessionProvider } from 'next-auth/react';
import {
  RainbowKitSiweNextAuthProvider,
  GetSiweMessageOptions,
} from '@rainbow-me/rainbowkit-siwe-next-auth';

const { chains, provider, webSocketProvider } = configureChains(
  [
    mainnet,
    polygon,
    optimism,
    arbitrum,
    ...(process.env.NEXT_PUBLIC_ENABLE_TESTNETS === 'true' ? [goerli] : []),
  ],
  [
    alchemyProvider({ apiKey: '_gg7wSSi0KMBsdKnGVfHDueq6xMB9EkC' }),
    publicProvider(),
  ]
);

const { wallets } = getDefaultWallets({
  appName: 'RainbowKit demo',
  chains,
});

const demoAppInfo = {
  appName: 'Rainbowkit Demo',
};

const connectors = connectorsForWallets([
  ...wallets,
  {
    groupName: 'Other',
    wallets: [
      argentWallet({ chains }),
      trustWallet({ chains }),
      ledgerWallet({ chains }),
    ],
  },
]);

const wagmiClient = createClient({
  autoConnect: true,
  connectors,
  provider,
  webSocketProvider,
});

const getSiweMessageOptions: GetSiweMessageOptions = () => ({
  statement: 'Sign in to the RainbowKit + SIWE example app',
});

export default function App({ Component, pageProps }: AppProps) {
  return (
    <SessionProvider refetchInterval={0} session={pageProps.session}>
      <WagmiConfig client={wagmiClient}>
        <RainbowKitSiweNextAuthProvider
          getSiweMessageOptions={getSiweMessageOptions}
        >
          <RainbowKitProvider appInfo={demoAppInfo} chains={chains}>
            <Component {...pageProps} />
          </RainbowKitProvider>
        </RainbowKitSiweNextAuthProvider>
      </WagmiConfig>
    </SessionProvider>
  );
}

hajimismhajimism

consoleにはerror - uncaughtException: Error: unable to get local issuer certificateとあって、SSL証明書が見つからないらしい

hajimismhajimism


Connect Walletのボタンを押すとこのようなモーダルが出てくる

hajimismhajimism

ボタンはkitのものらしい import { ConnectButton } from '@rainbow-me/rainbowkit';

hajimismhajimism


MetaMaskを選択するとこんなかんじ。
なんかもう全部やってくれそう

hajimismhajimism

Send messageを押すとSignature requestの画面に。

Signボタンを押すも失敗しているみたい

このスクラップは2022/12/25にクローズされました