【個人開発入門】Nextjs+supabaseでログイン機能を構築したい

Next.js

はじめに

今回は、Nextjs+supabaseを用いて匿名ログイン機能を作成していきます。

以下の動画を参考に進めていきます。

わかりやすく説明してくれているので、その部分についても触れながら進めたいと思います!

nino+さんの動画は初学者にも理解しやすいと思いますのでおすすめです!

作業の流れ

  • server-onlyをインストールする
  • server actionsを設定する
    • /project/actions/auth.tsを作成してuser serverを使用する
  • 匿名ログインを有効化する
    • supabaseの設定ファイルを変更する
    • supabaseを一旦stopする
  • ログインフォームの作成する
    • ログアウトを追加する

server-onlyをインストール

以下のコマンドでserver-onlyをインストールします。

% bun add server-only
[0.55ms] ".env.local"
bun add v1.1.6 (e58d67b4)

 installed server-only@0.0.1

 1 package installed [1372.00ms]
Data Fetching: Server Actions and Mutations | Next.js
Learn how to handle form submissions and data mutations with Next.js.

/app/data/auth.tsは以下のように記述しておきます。

import 'server-only'

import { createClient } from "@/lib/supabase/server"
import { cache } from "react";

export const currentUser = cache(async () => {
  const supabase = createClient();
  const {
    data:{user},
  } = await supabase.auth.getUser();

  return user;
});

server actionsを設定する

Server Actionsを設定していきます。

/projectname/actions/auth.tsを作成します。

以下の通り、記述します。

'use server';

import { createClient } from "@/lib/supabase/server";

export const signIn = async () => {
  const supabase = createClient();
  await supabase.auth.signInAnonymously(); # 匿名サインイン機能
  };

export const signOut = async () => {
    const supabase = createClient();
    await supabase.auth.signOut();
    };
  

匿名ログインを有効化

匿名ログインはデフォルトで無効化されています。

匿名ログインの用途は以下のようなケースがあるようです。

  • デバッグ用に画面を確認するため
  • 一部の機能だけ利用してもらい、サービスが良ければアカウント作成してもらう
    • 作成した後にアカウントと匿名ユーザーを紐づけてもらう

supabaseの設定ファイルを変更する

設定ファイル/projectname/supabase/config.tomlを開きます。

以下の設定箇所を検索してfalsetrue として保存します。

# Allow/disallow anonymous sign-ins to your project.
enable_anonymous_sign_ins = false
Supabase Auth now supports Anonymous Sign-ins
Sign in as an anonymous user to authenticate with Supabase

supabaseを一旦stop/startする

(前回の記事の続きのため)supabaseを実行していましたが、設定を反映させるために一度stopします。

$ bunx supabase stop
Stopped supabase local development setup.
Local data are backed up to docker volume. Use docker to show them: docker volume ls --filter label=com.supabase.cli.project=supabase-app

再度スタートさせましょう。

$ bunx supabase start
supabase start is already running.
Run supabase status to show status of local Supabase containers.

DocerDesktopを起動させておく必要があります。

ログインフォームの作成

/project-name/app/login/page.tsxについて、以下の通り更新します。

formタグ内にButtonをおくことで、type=”button”以外のものはデフォルトで、action=’’’の内容を実行します。

サーバーコンポーネント(サーバー側の記述をしている)ファイルですが、ユーザー側の操作も受け付けられるようになります。

import { signIn } from "@/actions/auth";
import { Button } from "@/components/ui/button";
import { currentUser } from "@/app/data/auth";

export default async function Page() {
  const user = await currentUser();

  return (
    <div className="p-6">
      <h1>LOGIN</h1>

      {user && <p>{JSON.stringify(user)}</p>} {/* ユーザーが存在する場合にはそのユーザーの情報を表示する */}

      <form action={signIn}> {/* #サーバーコンポーネントでありながらユーザーの操作を受け付ける */}
        <Button>ログイン</Button>
      </form>
    </div>
  );
}

bun devを実行してサーバーを起動済みであれば、ブラウザからhttp://localhost:3000/loginにアクセスして、ログインボタンを押してみます。

その後、ブラウザの別タブでhttp://127.0.0.1:54323/project/default/auth/usersにアクセスします。

するとログインボタンを押した時間で、匿名ユーザーのログイン情報が確認できると思います。

ログアウトも作成

以下の通り更新します。

ログイン済みのユーザーならログアウトボタンを表示、未ログインならログインボタンを表示するようにします。

import { signIn, signOut } from "@/actions/auth";
import { Button } from "@/components/ui/button";
import { currentUser } from "@/app/data/auth";

export default async function Page() {
  const user = await currentUser();

  return (
    <div className="p-6">
      <h1>LOGIN</h1>

      {user && <p>{JSON.stringify(user)}</p>}

      {user ? (
        <form action={signOut}>{/* ログイン済みのユーザーならログアウトボタンを表示 */}
          <Button>ログアウト</Button>
        </form>
      ) : (
        <form action={signIn}>{/* ユーザーが存在しなければログインボタンを表示 */}
            <Button>ログイン</Button>
        </form>
      )}
    </div>
  );
}

通常、ログイン状態だけを示すログアウト画面があることは珍しく、マイページやヘッダーのメニューにあることがほとんどです。なので以下のように変更していきます。

import { signIn, signOut } from "@/actions/auth";
import { Button } from "@/components/ui/button";
import { currentUser } from "@/app/data/auth";
import { redirect } from "next/navigation";

export default async function Page() {
  const user = await currentUser();

  if (user) {
    redirect('/mypage') // ログイン済みであればマイページにリダイレクトする
  }

  return (
    <div className="p-6">
      <h1>LOGIN</h1>

      {user && <p>{JSON.stringify(user)}</p>}

      <form action={signIn}>
        <Button>ログイン</Button>
      </form>
    </div>
  );
}

これで、ログイン済みであればマイページへリダイレクトされて、ログインしていなければ、ログインボタンが表示されるようになりました。

まとめ

今回は、Nextjsとsupabaseでログイン機能を作成しました。

まだまだ先は長いですが、地道に進めていきます!

コメント

タイトルとURLをコピーしました