🍆

【supabase-auth-helpers】Next.js等でSupabaseを使うときに活用したい認証ヘルパー

2022/05/16に公開

2023年9月28日追記-->

Next.jsのApp Routerが追加されたので実装方法やルールがガラッと変わっています。
この記事の情報は古いので、下記の2つの記事を参考するにようにしてください。

◆ローカル(localhost)でTwitterなどのoAuthを行うには?
https://zenn.dev/ttskch/articles/44ef674d6e3b73

◆ローカル(localhost)でTwitter認証をクライアントサイドで行う詳しい流れ
https://zenn.dev/masa5714/articles/db582fce8f3fd9

◆App RouterでのoAuthの書き方は?
https://zenn.dev/otaki0413/articles/supabase-auth-with-app-router

<--追記終了

ここから下は古い情報です。上記の追記を必ずご覧ください。

2022年8月11日追記: 情報鮮度が落ちたため下記にまとめ直しました。
https://zenn.dev/masa5714/articles/2d773224129f13


Supabaseの公式ドキュメントは度々見ていましたが、今さっき認証ヘルパーの存在に気づくことができました。認証ヘルパーの存在に気づいていない人も多いと思いますので、日本語で情報を残しておきます。

注意!

名前に @ や _ が入っているとログインできない事象を確認しました。
issuesにて報告済みですが、解決されるまで使い物にならないと考えた方が良いかもしれません。

とはいえ、活発に最新バージョンがリリースされているので、重大な問題と思われるこの問題もすぐに解決されるものと思われます。

https://github.com/supabase-community/supabase-auth-helpers/issues/99

v1.4.2で問題が解決されました!

supabase-auth-helper

詳しくはこちらを初めに読みましょう。

https://www.npmjs.com/package/@supabase/supabase-auth-helpers

Supabase公式ドキュメントのNext.jsのクイックスタートでは、 utils/supabaseClient.js を用意することを指示されますが、この辺りの処理もsupabase-auth-helperがやってくれるようです。 .env ファイルに NEXT_PUBLIC_SUPABASE_URLNEXT_PUBLIC_SUPABASE_ANON_KEY を用意しておけばOKです。

※記述の引用は supabase-community/supabase-auth-helpersをベースにしていますが、 nextjs-with-supabase-authのほうがシンプルで分かりやすいかもしれません。

しかし、直近でゴリゴリに変更を加えている様子でして、supabase-community/supabase-auth-helpers のほうが信憑性が高いかもしれません。(例えば、nextjs-with-supabase-authのサンプルでは withAuthRequired() というものがありますが、この関数は非推奨という扱いになっているようです。現時点<supabase-auth-helpers v1.4.1>)

/pages/_app.tsx

https://github.com/supabase-community/supabase-auth-helpers/blob/main/examples/nextjs/pages/_app.tsx

UserProvider で囲むことで全てのページでヘルパーを使えるようになります。なお、公式サンプルに記述されている <a href="/api/auth/logout">Logout</a> は認証状況に関係なく表示される雑な記述なので、この記述は無視してOKです。

/pages/api/auth/[...supabase].ts

https://github.com/supabase-community/supabase-auth-helpers/blob/main/examples/nextjs/pages/api/auth/[...supabase].ts

シンプルな記述はこちら


以上の準備でとりあえずは動く状態になるかと思います。

どうやって使っていくか

公式ドキュメント上では import { supabase } from '../utils/supabaseClient' で supabase を使いながらリクエストを投げていく例が書かれていますが、

supabase-auth-helper を使う場合は、 import { supabaseClient } from '@supabase/supabase-auth-helpers/nextjs'supabaseClient を使って色々やっていくようです。(参考

example
const { data } = await supabaseClient.from('test').select('*')

ログインしていない場合はリダイレクトさせることもできます!

https://github.com/supabase-community/supabase-auth-helpers/blob/main/examples/nextjs/pages/protected-page.tsx

ログインが絡む感じのやつでよくある動きで「ログインしてなければアクセスさせない」という処理もヘルパーの力で楽できるようです。

import { withPageAuth } from '@supabase/supabase-auth-helpers/nextjs';

~

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

この場合、ログインしてなければ /login にリダイレクトされます。


フロント側でログイン中、非ログインを判定

const { isLoading, user } = useUser()

isLoading では、ログイン判定の完了したかどうかを取得できます。
user には、ログイン中であれば認証情報が入っています。

ちなみに、useUser() はタブの切り替えを行ったときにも都度処理がされるようです。そのため、 react-transition-group などのパッケージを使って isLoading の状態を見て要素アニメーションさせようと思っている場合は、若干調整が必要になります。(ただし、supabase-auth-helpers側が必要と考えて実装している内容だと思いますので、これをハードコーディングによって封じ込めるのは果たして正解かどうかはご自身でご判断ください。)

例えば、初回アクセスかどうかを判定する状態をRecoilなどで管理しておき、初回アクセスでの認証後にその状態をtrueとして記録、trueの場合は表示・非表示のステータスが変化しないように調整するなど?(表示用のステータスとsupabase-auth-helpersの内部的な判定結果と矛盾が生じるケースがあるかもしれません。この辺りは全く詳しくないので、各自で検証の上ご判断ください。)

SSRでもログイン判定もできるので、SSRしたほうがシンプルに実装できるかも?

リファレンス

https://supabase-community.github.io/auth-helpers/index.html

公式サンプル

◆ゴリゴリに更新されてて信頼度高め(?)
https://github.com/supabase-community/supabase-auth-helpers

◆更新頻度は低い(?)がシンプルな記述でおおよその動きを知るなら良い感じ
https://github.com/supabase/supabase/tree/master/examples/nextjs-with-supabase-auth

Discussion