Supabaseのauth helperによってNext.jsプロジェクトの認証周りを楽にする

2022.07.31

こんにちは。データアナリティクス事業本部 サービスソリューション部の北川です。

Supabaseは、firebaseの大替サービスと言われるBaasです。

Supabase auth-helperについて

Supabaseでは、認証ヘルパーライブラリとして@supabase/supabase-auth-helpersを提供しています。

少し前に、@supabase/supabase-auth-helpersから、パッケージを分割し無駄を省いた@supabase/auth-helpersに変更できるようになりました。 丸ごと提供していた以前のライブラリに対し、使用するフレームワークの機能のみ提供するライブラリになっています。

使ってみる

Supabase側のAPIの取得については、以下のエントリーで紹介しています。

Next.jsプロジェクトを作成し、移動します。

$ yarn create next-app --ts

$ cd <appName>

auth-helpersをインストールします。この時に、今回はNext.jsなのでauth-helpers-next.jsを指定してインストールします。

$ yarn add @supabase/auth-helpers-nextjs @supabase/auth-helpers-react

.env.localファイルを作成し、キーとURLを環境変数に保存します。 キーとURLはsupabaseの「Settings」→「API」から確認することができます。

.env.local

NEXT_PUBLIC_SUPABASE_URL=YOUR_SUPABASE_URL
NEXT_PUBLIC_SUPABASE_ANON_KEY=YOUR_SUPABASE_ANON_KEY

/pages/api配下にauth/[...supabase].tsを作成し、以下のように記述します。

handleAuthを使用することで、/api/auth/userでユーザー情報の取得、/api/auth/logoutでログアウトし、リダイレクトすることができます。

import { handleAuth } from "@supabase/auth-helpers-nextjs";

export default handleAuth({ logout: { returnTo: "/" } });

次に_app.tsxでComponentをuseProviderでラッピングします。

// pages/_app.js
import React from 'react';
import { UserProvider } from '@supabase/auth-helpers-react';
import { supabaseClient } from '@supabase/auth-helpers-nextjs';

export default function App({ Component, pageProps }) {
  return (
    <UserProvider supabaseClient={supabaseClient}>
      <Component {...pageProps} />
    </UserProvider>
  );
}

認証情報の取得

次にindex.tsxを以下のように変更します。useUserを使用して、認証情報を取得します。

import { Auth } from "@supabase/ui";
import { useUser } from "@supabase/auth-helpers-react";
import { supabaseClient } from "@supabase/auth-helpers-nextjs";
import Link from "next/link";
import { NextPage } from "next";

const Home: NextPage = () => {
  const { user, error } = useUser();

  console.log("user", user);
  if (!user)
    return (
      <>
        <Auth supabaseClient={supabaseClient} />
        {error && <p>{error.message}</p>}
      </>
    );

  return (
    <>
      <button onClick={() => supabaseClient.auth.signOut()}>Sign out</button>
      <p>user: {user ? user.id : null}</p>
    </>
  );
};

export default Home;

認証前

認証後

ページのリダイレクト

withPageAuth

withPageAuthを使用することで、ユーザーが認証していない場合、ログインページにリダイレクトさせることができます。Next.jsではgetServerSidePropsを使用して実装します。

/pages配下にabout.tsxを作成し、以下のように記述します。今回は、ログインページの代わりにルートページにリダイレクトさせます。

import { supabaseClient, withPageAuth } from "@supabase/auth-helpers-nextjs";
import Link from "next/link";

export const getServerSideProps = withPageAuth({ redirectTo: "/" });

const AboutPage = () => {
  return (
    <>
      <button onClick={() => supabaseClient.auth.signOut()}>Sign out</button>
      <h2>AboutPage</h2>
      <Link href="/">Home</Link>
    </>
  );
};

export default AboutPage;

動作確認のため、一度サインアウトしてからaboutページにアクセスします。

localhost:3000に遷移していることが確認できます。

getUser

getServerSideProps内でgetUserを使用することで、ユーザー情報を取得し、propsに渡すことができます。

export const getServerSideProps = withPageAuth({
  redirectTo: "/",
  async getServerSideProps(ctx) {
    const { user } = await getUser(ctx);
    return { props: { email: user?.email } };
  },
});

また、Next.jsのミドルウェアを利用することで、個々のページではなく、指定のフォルダ配下全体にリダイレクト機能を実装できるようです。

まとめ

今回は、Supbaseのauth-helpersを使ったユーザー情報の取得を行なってみました。@supabase/supabase-auth-helpersからの置き換え方法について、Githubでわかりやすく紹介されています。認証周りの手間を減らすことができるので、Supabaseを使用する際は是非使ってみてください。