🍆

【Supabase】パスワード再設定(recovery)で届いたメールのURLをクリックした先がおかしいバグを解決する

2024/12/13に公開

Supabaseにはメールアドレス認証の救済措置としてパスワード再設定機能が備わっています。

▼公式ドキュメント▼
https://supabase.com/docs/guides/auth/passwords?queryGroups=language&language=js&queryGroups=flow&flow=pkce&queryGroups=framework&framework=nextjs

基本的にドキュメント通りに実装していけばいいのですが、届いたメールをクリックした先で問題がありましたのでメモを残しておきます。

どんな問題が起きるのか?

メールテンプレートでは href="{{ .SiteURL }}/auth/confirm?token_hash={{ .TokenHash }}&type=email&next={{ .RedirectTo }}" という形でリンクを貼っています。

このメールが届いた後、リンクをクリックすると 404ページ が表示されてしまうという問題が発生します。

confirm/route.ts を一部修正する必要がある

症状からリダイレクトURLに問題があると見受けられます。

console.log(redirectTo) で確認してみると、

hrefの値が http://localhost:3000/http://localhost:3000/reset-password/update?token_hash=pkce_60 という形でホスト名が重複してしまっている状態です。

同様の問題が既に報告されているので内部的な問題によるものと思われます。
https://github.com/supabase/supabase/issues/27442

URLとして不適切ということで、これを無理やり置換で解決していく必要があります。( http://localhost:3000/reset-password/update?token_hash=pkce_60 という形が正しいURL )

無理やり置換で解決する

.env.development
NEXT_PUBLIC_HOSTNAME=http://localhost:3000
export function escapeForRegex(str: string) {
  return str.replace(/[.*+?^${}()|[\]\\\/]/g, "\\$&");
}
auth/confirm/route.ts
...省略

if (!error) {
  // Supabaseのバグでホスト名が重複してしまうのでここで調整している
  const escapedRegexString = escapeForRegex(`${process.env.NEXT_PUBLIC_HOSTNAME}/`);
  const regex = new RegExp(`^${escapedRegexString}`);
  const fixedRedirectTo = redirectTo.href.replace(regex, "");
  return NextResponse.redirect(fixedRedirectTo);
}

...省略

ホスト名をエスケープして置換するだけの簡単なコードで解決できます。

Discussion