匿名認証 1 Supabase 匿名認証メモ #認証 - Qiita
匿名認証 2 Next.js 14 のServer Actions を利用した、Supabaseの匿名認証の最低限な実装 #ServerActions - Qiita
匿名認証の参考URL
Anonymous Sign-Ins | Supabase Docs
https://supabase.com/docs/guides/auth/auth-anonymous
Supabaseの匿名認証は、ユーザーに対してメールアドレスもパスワードも、GoogleやGitHub、Apple等のOAuth認証も必要とせず、何のユーザー情報も必要とせずにユーザーをログインさせて、そのウェブサイトの機能を試してもらうための認証方式です。
※30日間で自動削除されます。(公式:予定)
(現在はまだ手動で削除する必要があります。)
通常のユーザーと同じようにログイン出来ます。
同じような操作も可能になりますが、RLSやフラグ(is_anonymous)を使用することで差別化できます。
匿名認証でログインした後、ログアウトしてしまうとアカウント情報が引き継がれません。
前提
Next.js 14 のインストール済み
Supabaseのローカル開発環境を構築済み
Dockerを使うとローカルでSupabaseを使えます。
※Supabase CLIをインストールしておく必要があります。
Next.jsとSupabaseの基本的な使い方の参考
Use Supabase with Next.js | Supabase Docs
https://supabase.com/docs/guides/getting-started/quickstarts/nextjs
👆 Next.jsでのSupabaseの基礎的な使用方法です。
例
npx create-next-app -e with-supabase [アプリ名]
supabase init
supabase start
supabase status
scoop update supabase <<Supabase CLI更新コマンド
npm run dev
止める時
supabase stop
環境変数の設定
NEXT_PUBLIC_SUPABASE_URL=your-project-url
NEXT_PUBLIC_SUPABASE_ANON_KEY=your-anon-key
👆 Supabaseの環境変数を入力します。
.gitignoreファイルの変更
# local env files
.env
RLSとは (参考)
データベース内のどの行へのアクセスを許可するかのポリシー(=ルール)です。
public.usersテーブルがあるとして、今ログインしているのは「ユーザーA」だとします。
そのテーブルには
ユーザーA 個人データ メールアドレス等
ユーザーB 個人データ メールアドレス等
ユーザーC 個人データ メールアドレス等
の3人が登録されているとして
RLSで現在ログインしているユーザーを許可と設定すると
ユーザーAへアクセスできますが、
ユーザーB、ユーザーCにはアクセスできません。
だから RLS(row 行 level 水平 security 安心、安全)
行単位のセキュリティと名付けられています。
匿名認証
ローカル環境での匿名認証の許可
開発環境がローカル環境の場合
# Allow/disallow anonymous sign-ins to your project.
enable_anonymous_sign_ins = true
この設定をtrueにする必要があります。
この設定ファイルを編集した場合、
DockerのローカルSupabaseを再起動させます。
supabase stop
supabase start
サーバー環境での匿名認証の許可
開発環境がサーバー環境の場合
サーバーのSupabaseダッシュボードから
左サイドメニューの Project Settingsを選択します。
Settingsメニューが表示されます。
そのCONFIGURATION>>Authenticationを選択します。
User Signupsの
Allow anonymous sign-ins
Enable anonymous sign-ins for your project.
を有効化します。
ここまでが下準備、ここから実際の匿名認証の超基礎的なコード。
匿名認証のコード
DBに匿名ユーザーを登録するまでの最低限です。
import Link from 'next/link';
export default async function Index() {
return (
<div className="">
{/* SignInページへのリンク */}
<Link href="/signin">SignInページへのリンク</Link>
</div>
);
}
import { anonymousSignIn } from './actions';
export default async function SignIn() {
return (
<form action={anonymousSignIn}>
<button type="submit">SignIn</button>
</form>
);
}
※React19 Next.js14のサーバーアクションで匿名認証の関数を実行しています。
サーバー関数は👇 app\signin\actions.tsに書かれています。
'use server';
import { createClient } from '@/utils/supabase/server';
// ページのキャッシュを再検証するための関数です。これにより、ページのデータが最新の状態に保たれます
import { revalidatePath } from 'next/cache';
import { redirect } from 'next/navigation';
export async function anonymousSignIn() {
const supabase = createClient();
const { data, error } = await supabase.auth.signInAnonymously();
console.log('data:', data);
if (error) {
// エラー時の処理
}
// サインイン後にページのデータを最新の状態に更新するために使用されます。
revalidatePath('/', 'layout');
redirect('/');
}
匿名認証部分のコード
👇一部
const supabase = createClient();
const { data, error } = await supabase.auth.signInAnonymously();
console.log('data:', data);
Supabaseのクライアントを作り、 匿名認証用の関数を実行して、
console.logでデータを出力させています。
👇出力結果
GET /favicon.ico 200 in 4737ms
data: {
user: {
id: 'c4c21c05-b510-4503-9f8d-430ec67f7f32',
aud: 'authenticated',
role: 'authenticated',
email: '',
phone: '',
last_sign_in_at: '2024-07-06T19:41:29.122365579Z',
app_metadata: {},
user_metadata: {},
identities: [],
created_at: '2024-07-06T19:41:29.11744Z',
updated_at: '2024-07-06T19:41:29.12594Z',
is_anonymous: true
},
session: {
access_token: 'ey*****10',
token_type: 'bearer',
expires_in: 3600,
expires_at: 1720298489,
refresh_token: 'fr*****Gg',
user: {
id: 'c4c21c05-b510-4503-9f8d-430ec67f7f32',
aud: 'authenticated',
role: 'authenticated',
email: '',
phone: '',
last_sign_in_at: '2024-07-06T19:41:29.122365579Z',
app_metadata: {},
user_metadata: {},
identities: [],
created_at: '2024-07-06T19:41:29.11744Z',
updated_at: '2024-07-06T19:41:29.12594Z',
is_anonymous: true
}
}
}
POST /signin 303 in 146ms
ローカルのSupabase ダッシュボードから
左サイドメニューのAuthentication
もしくは
左サイドメニューのTable Editor でauthスキーマのusersテーブルを確認すると
匿名のユーザーが一人追加されています。
is_anonymous: が 「TRUE」で匿名認証であることが分かります。
revalidatePath('/', 'layout');
を実行することで、最新の状態に更新されます。
revalidatePath関数
revalidatePath()
👆この関数は状態管理の負担を減らしてくれます。
例えば、いいねボタンを押して、別の遠いい場所のコンポーネントでいいねボタン総カウント数を保存している場所がある場合、これまでは状態管理をする必要がありましたが、
revalidatePathを利用することで、状態管理をせずとも最新の状態になります。
※例えば、孫>>子>>親>>子>>孫のコンポーネント間でpropsを渡してバケツリレーをしたり、Reduxなどのライブラリを使いストアをグローバル変数のように使って離れたコンポーネント間で状態の同期を取れるようにしたりします。
なので、サインインをした後に、レイアウト(ログイン情報を表示しているはずの、別の遠いコンポーネント)コンポーネントではまだログインしていない状態のはずですが、revalidatePathを利用することで、指定した場所で最新の情報を読み取りログインした状態になっています。
状態管理は、うまく使えばいいですが、バグの温床にもなる所なので、revalidatePathを使うことで負担が減ります。
このコードでは最終的に
POST /signin 303 in 146ms
が出力され、ステータスコード303に対応する必要があります。(対応方法は未勉強)
その他
RLSは有効にしていません。
匿名認証を使用する場合、
hCaptcha
や
Turnstile by Cloudflare
を利用することを公式では強く推奨しています。
ユーザーのセッション(ログイン中)確認は、
getUserメソッドを使います。
const { data: { user } } = await supabase.auth.getUser()
サーバ上でユーザの認可をチェックする場合は、常にこのgetUserメソッドを使用する必要があります。クライアントでは、getSession().session.user を使用することで、より高速な結果を得ることができます。
機械的にユーザーを作成するようなBOTなどを弾くセキュリティ機能です。
応用として、メール認証やOAuth認証でも認証した場合、匿名認証の時の入力データを引き継がせるような設定も可能です。
※自身でコードを書く必要があります。
参考
Supabase 匿名認証メモ #認証 - Qiita
Supabase公式の匿名認証
【Supabase】Flutter + Supabase Authentication のAnonymous Sign-insを使って匿名サインインのサンプルを作ってみた - 狐好きぷろぐらまー
👆設定の説明が画像付き解説
※ 以下、未調査
匿名認証したユーザーがOAuth認証(GoogleやGitHub、Facebook、Slack等)に切り替える方法
Anonymous Sign-Ins | Supabase Docs
https://supabase.com/docs/guides/auth/auth-anonymous#sign-in-anonymously
自動
複数のOAuth認証をした場合、メールが同じだと自動でLinkされる。
匿名認証の場合は不明。
手動
手動の設定をONにします。
const { data, error } = await supabase.auth.linkIdentity({ provider: 'google' })
このコードを実行すると匿名認証していても、Google認証画面が立ち上がり、認証の手続きが開始されるようだ。