0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

supabase+Next.jsでパスワードリセットで「Auth session missing」というエラーが出た

Posted at

supabaseでパスワードのリセットを実装しようとしましたがドキュメントのコピペだけではうまく動作しませんでした。

以下のようなエラーに遭遇しました。

 [Error [AuthSessionMissingError]: Auth session missing!] {
 __isAuthError: true,
 status: 400,
code: undefined

パスワードリセット用のトークンを適切に処理できていないことに起因していると思われます。本記事ではその解決法を記載します。

パスワードリセットメールを送る機能の実装

まず、Next.js側で以下のようにpage.tsxとactions.tsを作成します。MUIを使用して記載していますが、適宜form、input、buttonに変更します。

app/
|
└reset-password/
    └actions.ts
    └page.tsx
app/reset-password/page.tsx
  <Paper
    component="form"
  >
    <InputLabel sx={{ mt: 2 }}>メールアドレス</InputLabel>
    <TextField
      id="email"
      variant="standard"
      fullWidth
      name="email"
      type="email"
    />

    <Box>
      <Button formAction={sendResetPasswordEmail}>送信</Button>
    </Box>
  </Paper>

app/reset-password/actions.ts

"use server";

import { redirect } from "next/navigation";
import { createClient } from "@/utils/supabase/server";

export async function sendResetPasswordEmail(formData: FormData) {
  const supabase = await createClient();

  const { error } = await supabase.auth.resetPasswordForEmail(
    formData.get("email") as string,
    {
      redirectTo: `${getURL()}set-password`,
    }
  );

  if (error) {
    console.error("Reset password error:", error);
    redirect("/error");
  }
}

const getURL = () => {
  let url =
    process?.env?.NEXT_PUBLIC_SITE_URL ?? // Set this to your site URL in production env.
    process?.env?.NEXT_PUBLIC_VERCEL_URL ?? // Automatically set by Vercel.
    "http://localhost:3000/";
  // Make sure to include `https://` when not localhost.
  url = url.startsWith("http") ? url : `https://${url}`;
  // Make sure to include a trailing `/`.
  url = url.endsWith("/") ? url : `${url}/`;
  return url;
};

上記コード中の「utils/supabase/server」については以下のドキュメントに記載のとおりです。

次に、SupabaseでAuthentication
→EmailsのReset Passwordのメールテンプレートを以下のように変更します。

<h2>Reset Password</h2>

<p>Follow this link to reset the password for your user:</p>
<!-- <p><a href="{{ .ConfirmationURL }}">Reset Password</a></p> -->
<p><a href="{{ .RedirectTo }}?code={{ .TokenHash }}">Reset Password</a></p>

新しいパスワードの設定の実装

これまでの方法でパスワードリセットメールを送るまでを実装しました。続いてはメールに記載のリンク先のページの作成、新しいパスワードの設定について記載していきます。

app/
|
└reset-password/
    └actions.ts
    └page.tsx
└set-password/
    └actions.ts
    └page.tsx
app/set-password/page.tsx
export default async function SetPassword({
  searchParams,
}: {
  searchParams: Promise<{ code?: string }>;
}) {
  // ✅ searchParams を await してから使う
  const { code } = await searchParams;
  return (
    <>
      <Paper component="form">
        <Grid
          container
          direction="column"
          justifyContent="flex-start"
          alignItems="center"
        >
          <Typography variant={"h5"} sx={{ m: "30px" }}>
            新しいパスワード
          </Typography>
        </Grid>

        <input type="hidden" name="code" value={code} />
        <TextField
          type="password"
          variant="standard"
          fullWidth
          name="password"
        />
        <Box>
          <Button
            type="submit"
            variant="outlined"
            fullWidth
            formAction={setPassword}
          >
            パスワードをセット
          </Button>
        </Box>
      </Paper>
    </>
  );
}
app/set-password/actions.ts
export async function setPassword(formData: FormData) {
  const supabase = await createClient();

  // type-casting here for convenience
  // in practice, you should validate your inputs
  const code = formData.get("code") as string;



  // 🔁 再度 verifyOtp でセッション復元
  const { error: verifyError } = await supabase.auth.verifyOtp({
    token_hash: code,
    type: "recovery",
  });

  if (verifyError) {
    console.error("Failed to verify OTP:", verifyError);
    redirect("/error");
  }

  const { error } = await supabase.auth.updateUser({
    password: formData.get("password") as string,
  });
  if (error) {
    console.error("Login error:", error);
    redirect("/error");
  }

  revalidatePath("/", "layout");
  redirect("/");
}

参考

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?