mcpField
U
using-authentication

using-authentication

github.com/andrelandgrafセキュリティ2394 回インストール20 週間前に更新
リポジトリ

using-authentication について

Fullstack Recipes のスキルで、Better Auth を使ったクライアント側とサーバー側の認証方法を開発者向けに説明します。セッション、ルート保護、サインイン・サインアウト、ユーザーデータ取得を扱います。

主な機能

  1. 01クライアント側のセッションフック
  2. 02サーバー側のセッション取得
  3. 03保護対象ルートのパターン
  4. 04メールでのサインインと登録
  5. 05ユーザー別データの取得

活用シーン

  1. 01ログイン中のユーザーセッションの表示
  2. 02ページや API ルートの認証必須化
  3. 03サインインと登録フローの構築

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/andrelandgraf/fullstackrecipes --skill using-authentication

インストール後、Claude Code で/using-authenticationを入力して読み込まれたか確認します。

詳細

認証の操作

クライアント側とサーバー側の認証には Better Auth を使用します。セッションへのアクセス、保護されたルート、サインイン/サインアウト、ユーザーデータの取得について説明します。

認証の操作の実装

クライアント側とサーバー側の認証には Better Auth を使用します。セッションへのアクセス、保護されたルート、サインイン/サインアウト、ユーザーデータの取得について説明します。

参照:


クライアント側の認証

React コンポーネントで認証クライアントのフックを使用します。

"use client";

import { useSession, signOut } from "@/lib/auth/client";

export function UserMenu() {
  const { data: session, isPending } = useSession();

  if (isPending) return <div>Loading...</div>;
  if (!session) return <a href="/sign-in">Sign In</a>;

  return (
    <div>
      <span>{session.user.name}</span>
      <button onClick={() => signOut()}>Sign Out</button>
    </div>
  );
}
サーバー側でのセッションへのアクセス

Server Components と API ルートでセッションを取得します。

import { auth } from "@/lib/auth/server";
import { headers } from "next/headers";

// In a Server Component
export default async function Page() {
  const session = await auth.api.getSession({
    headers: await headers(),
  });

  if (!session) {
    return <div>Not signed in</div>;
  }

  return <div>Hello, {session.user.name}</div>;
}
// In an API route
export async function POST(request: Request) {
  const session = await auth.api.getSession({
    headers: await headers(),
  });

  if (!session) {
    return new Response("Unauthorized", { status: 401 });
  }

  // Use session.user.id for queries...
}
保護されたページのパターン

認証されていないユーザーをリダイレクトします。

import { redirect } from "next/navigation";
import { headers } from "next/headers";
import { auth } from "@/lib/auth/server";

export default async function ProtectedPage() {
  const session = await auth.api.getSession({
    headers: await headers(),
  });

  if (!session) {
    redirect("/sign-in");
  }

  return <Dashboard user={session.user} />;
}
認証ページのパターン

認証済みのユーザーが認証ページにアクセスしないようリダイレクトします。

import { redirect } from "next/navigation";
import { headers } from "next/headers";
import { auth } from "@/lib/auth/server";

export default async function SignInPage() {
  const session = await auth.api.getSession({
    headers: await headers(),
  });

  if (session) {
    redirect("/chats"); // Already signed in
  }

  return <SignIn />;
}
サインイン
import { signIn } from "@/lib/auth/client";

// Email/password
await signIn.email({
  email: "[email protected]",
  password: "password",
  callbackURL: "/chats",
});

// Social provider
await signIn.social({
  provider: "google",
  callbackURL: "/chats",
});
サインアップ
import { signUp } from "@/lib/auth/client";

await signUp.email({
  email: "[email protected]",
  password: "password",
  name: "John Doe",
  callbackURL: "/verify-email",
});
サインアウト
import { signOut } from "@/lib/auth/client";

await signOut({
  fetchOptions: {
    onSuccess: () => {
      router.push("/");
    },
  },
});
認証後のユーザーデータの取得

保護されたページでは、セッションを検証した後にユーザー固有のデータを取得します。

export default async function DashboardPage() {
  const session = await auth.api.getSession({
    headers: await headers(),
  });

  if (!session) {
    redirect("/sign-in");
  }

  const [chats, profile] = await Promise.all([
    getUserChats(session.user.id),
    getUserProfile(session.user.id),
  ]);

  return <Dashboard chats={chats} profile={profile} />;
}

参考資料

コメント