2024Reactチュートリアル、学習記録アプリのユーザー認証実装、後編です。Supabaseの認証機能を利用したユーザー認証の仕組みを実装します。前編でユーザーサインアップ機能の開発まで行いました。後編では、ログイン、ログアウト、パスワードリセットの機能を実装していきます。学習記録アプリ、3回目です。前回まででSupabaseを活用したDBデータの読み込み・編集・削除を実装しました。今回は、Supabaseの認証機能を利用してユーザー認証の仕組みを設けてみたいと思います。内容が長くなってしまったので、前編・後編と2回に分けてお届けします。今回は前編となります。前編ではSupabaseの設定、環境構築、サインアップ機能の開発までを解説します。後編では、ログイン・ログアウト、パスワードリセット機能の実装を解説します。1回目、2回目の記事は以下となります。GitHub、Firebase連携はじめに本記事は、Reactの初学者向けのチュートリアルコンテンツです。Service)であるSupabaseを利用したものとなっており、バックエンド処理も入ってきてますので、難易度はやや高いかも知れません。Reactコードの記述、Supabaseの認証処理の実装、及び実際にアプリケーションをデプロイしてユーザーが使えるリリースまでを行えます。IconsBaaSとしてSupabase、ホスティングサービスはGoogleのFirebaseを利用しています。本記事で以下のような対応が可能です。作成するアプリの構造は下図のイメージとなります。Supabaseのユーザー認証の実装にあたって、参考にしたサイトは以下となります。Qiitahttps://qiita.com/kaho_eng/items/cb8d735b5b6ca1b3a6c5はじめにこんにちは!かほです♪現在、本業では技術広報業務やエンジニア業務などに従事しています。今回の記事では、Next.js×Supabaseを用いたアプリ開発における簡易的な認証機能の実装方...Next.jsを前提にした記事ですが、内容はReactコードですので、十分に参考になります。その他、補足として下記のサイトとSupabaseのドキュメントを参考にしています。後編と言うことで、4章から始めます。前編でサインアップ機能が出来上がり、実際にログイン可能なユーザー作成できましたので、ここではログイン機能を開発していきます。開発の前にひとつ確認します。前編のサインアップ機能でユーザー登録を行った際、Supabase上のユーザー情報ではログイン(サインイン)済となっていました。Supabaseはこのログインしている状態=セッション状態をどのように管理しているかです。Supabaseではセッション管理に、JWTを利用しています。Tokenの略語です。JWTはトークンベースの認証の仕組みで、トークンベースの認証では、アプリケーションはユーザーのログイン状態を保持しません。サーバはクライアントに対して「ログイン済」という情報を含んだトークンを生成することができ、そのトークンをセッションで利用・確認することで、ログイン状態を把握します。このトークンは、ローカルストレージに保管されます。ローカルストレージと選択して、中身を確認してみましょう(これはChromeでの操作です。他のブラウザでは違うかも知れませんが似たような操作・構造だと思います)。名前で情報が保管されていることが分かります。これがSupabaseのJWTです。ログイン処理では、この情報も利用して制御を行います。ログインコンポーネントの作成ログインコンポーネントのファイルを作成します。pagesフォルダ配下に、Login.tsxと言うファイルを作成してください。Login.tsxに、以下のコードを記載します(下記はコード全文です)。setError('サーバーエラーが発生しました。後でもう一度お試しください。Login;Login.tsxの内容について解説していきます。useNavigate();冒頭のインポートは、それぞれ必要なものをインポートしていきます。Routerの機能であるuseNavigate、個別で作成した、Supabase接続処理用のsupabaseClientをインポートします。App.tsxよりPropsで受け取りますので、その型定義です。コンポーネント関数の定義は、先のtypeの箇所で設定した型定義Propsを定義します。React.FC<Props>です。state関連は、パスワード用のpassword、そしてerrorはApp.tsxから受け取るのではなく、(errorのステート管理が複雑になるので)ローカルのものとして定義してます。ログイン状態を判定するstate、loginStateを設けています。RouterのuseNavigateを使用しています。};次に、getItemSupabaseSessionです。これは、先述したローカルストレージに保管されたSupabaseのセッション情報の取得処理です。キーが存在する場合は、その情報の中のuser.emailを取得しています。user.emailはセッションユーザーのemailアドレスです。setError('サーバーエラーが発生しました。後でもう一度お試しください。};続いて、onLoginです。こちらが、Supabaseへのログイン処理となります。formイベントをサブミットした際に実行されます。非同期通信のasync/awaitを用いています。ローディング状態をtrueにセットします。次に、Supabase処理機能として作成したsupabaseClient.tsにより、supabase.auth.signInWithPasswordを実行しています。emailとpassword情報で認証します。認証に成功した場合は、認証されたユーザーのemailアドレス(data.session.user.email)をsetEmailでemailステートにセットしています。エラーが発生した場合は、エラーメッセージをセット。最終的に、ローディング状態を解除(false)しています。次に、useEffectによる処理についてです。[setEmail]);useEffectにより、コンポーネントマウント時、及び、setEmail動作時に、処理を実行しています。これらは、ログイン操作以外に、ページのリロードや、ブラウザウィンドウを閉じたあとに再度表示した際などに、セッション状態の維持とセッションemail情報の維持の為に実装しています。loggedInEmailで、getItemSupabaseSession(‘sb-YourSupabaseInfo-auth-token’)を実行しています。これは先に挙げたローカルストレージからのSupabaseのセッションemail情報の取得処理です。引数、sb-YourSupabaseInfo-auth-tokenの「YourSupabaseInfo」の箇所はご自身の環境でローカルストレージに保管されているキー名を参照して記載してください。ローカルストレージから値が取得出来れば、setEmailでemailをセット、setLoginStateでloginState(ログイン状態)をtrueにしています。リアルタイムのセッション状態変移のチェックを行っています。いずれもtrueであればローカルストレージデータ読み込み時と同じ処理を実行しています。これは、例えば、別のウィンドウから別のアカウントでログインした場合等への対処の為です。}次の処理ですが、loginStateがtrue、つまりログイン状態であると認識されれば、useNavigateを利用したnavigate(‘/home’)で、Home.tsxのリダイレクトしています。ログイン状態である場合は、ログイン画面から自動で/homeに遷移する仕組みです。この処理は少し間を持たせたかった為、setTimeoutで0.5秒後に遷移するようにしています。後述するHome.tsxからのリダイレクト処理との兼ね合いもあります。最後にJSX箇所です。</>内容は、Register.tsxと似たような感じです。ログイン用のformを設置しています。その中にメールアドレス、パスワードのinputフィールドを設けています。それぞれのinputフィールドは、onChangeイベントで、mail、passwordをset関数でstate変更を実施しています。color=’red’>{error}</Box>}でエラー表示します。エラー発生した場合、各inputフィールドに再フォーカス(カーソルを移動)することでエラー表示を消す処理をしています。「ログイン」ボタンクリックで、formがサブミットされ、先のSupabaseログイン処理のonSubmitが実行されます。その他のページ遷移メニューとして、useNavigateによるnavigate()にて、新規登録は、先に作成したRegister.tsxへのリンク(‘/register’)を設定しています。パスワードリセット用に、’/sendReset’を設定しています。ここはまだ未作成なので、今時点は「みつかりません」の404に遷移することになります。パスワードリセット機能は後ほど実装します。Home.tsxの変更ログイン画面、Login.tsxが出来ましたので、これをApp.tsxとHome.tsxに反映します。"./pages/Login";//Login.tsxのインポート追加まずは、冒頭のインポート文です。Loginコンポーネントを新たに追加してます。続いて、emailステートについて、初期値として固定値を設定してましたが、”の空値をセットします。/>最後にJSXの箇所です。ルートとしてLoginをルート直下’/’に設定します。setLoadingを渡しています。現時点のApp.tsxのコード全体は以下となります。App次は、Home.tsxです。変更は以下内容となります。}新たに、useNavigateを導入、インポートしています。useEffectの中に、useNavigateによるnavigate(‘/’)を追加しています。email情報が空の場合は、’/’つまりログイン画面に遷移させています。これはHome画面を表示中にリロード等した場合に、emailステート情報が空になる為、ログイン画面に遷移し、セッション情報の取得を行っています。これにより、セッション維持中であれば、自動でまたHomeに遷移します。現時点のHome.tsxのコード全体は以下なります。ログイン機能の確認それでは作成したログイン機能が動作するか確認します。ローカルストレージに格納されている、Supabaseのセッション情報を一度削除します(sb-xxxxxxxxxx-auth-tokenのキー情報)。ログイン画面が表示されますので、Supabaseにユーザー登録したメールアドレスとパスワードでログインします。ログインが完了すると、自動でHome画面に遷移し、メールアドレスとマッチした学習記録データが表示されれば成功です。サインアップ機能で作成したサインアップ画面に遷移するのも確認出来ると思います。次にログイン状態からログアウトする機能を作成していきます。本機能はHomeコンポーネントに実装します。ログアウトボタンを設け、モーダルでログアウトコンポーネントを表示させる形です。ログアウトコンポーネントの作成ログアウトコンポーネントのファイルを作成します。pagesフォルダ配下に、Logout.tsxと言うファイルを作成してください。Logout.tsxに、以下のコードを記載します(下記はコード全文です)。Logout;Logout.tsxの内容について解説していきます。useDisclosure()冒頭のインポートは、それぞれ必要なものをインポートしていきます。UIの利用コンポーネント、個別で作成した、Supabase接続処理用のsupabaseClientをインポートします。App.tsxよりPropsで受け取りますので、その型定義です。コンポーネント関数の定義は、先のtypeの箇所で設定した型定義Propsを定義します。React.FC<Props>です。RouterのuseNavigateを使用しています。UIのModalコンポーネントで利用するものです。続いて、ログアウト処理についてです。}onLogoutとしてSupabaseからのログアウト処理を定義しています。formイベントをサブミットした際に実行されます。非同期通信のasync/awaitを用いています。これまでと同様ですが、まず、ローディング状態をtrueにセットします。次に、Supabase処理機能として作成したsupabaseClient.tsにより、supabase.auth.signOutを実行しログアウト処理をしています。’/’(ログイン画面)に遷移、エラーが発生した場合は、アラートでエラー表示の内容です。最終的に、ローディング状態を解除(false)しています。最後にJSXの箇所です。UIのModalコンポーネントを利用し、モーダル形式の処理としています。冒頭の<Button.../>の箇所は、Homeコンポーネントに表示される、ログアウトボタン部分。それをクリックすると、モーダルがオープンする仕組みです。モーダル箇所は、「ログアウト」と「Cansel」のボタン配置。「ログアウト」をクリックすると、onLogoutが実行され、ログアウト処理を実行、正常終了すれば、ログイン画面に遷移の動きとなります。Home.tsxの変更Logout.tsxが完了しましたので、続いて、ログアウトコンポーネントを実装するHome.tsxに変更を加えます。"../studyData"まず、冒頭のインポートの箇所です。UIのStackをインポートしてます。Logoutコンポーネントのインポートを追加しています。</Card>続いて、JSXの箇所です。NewEntryコンポーネント(新規データ登録)の下にLogoutコンポーネントを配置しています。現時点でのHome.tsxのコード全体は以下の通りです。ログアウト機能の確認ログアウト関連のコードの実装が完了したので、実際に動きを確認していきます。ログイン機能確認時と同様、一度ローカルストレージにSupabaseのセッション情報を一度します(sb-xxxxxxxxxx-auth-tokenのキー情報)。アクセスし、ログイン→Homeに遷移→ログアウトを実施してみましょう。ログアウト処理が正常に行われ、ログイン画面に遷移出来ればOKです。ブラウザの検証ツールでローカルストレージのセッション情報保管状況も確認してみましょう。ログアウトすれば自動的にセッション情報も削除されます。