Next.jsのサイトにScratch認証機能を実装する
認証プロバイダーでは、Google, GitHub, Discord, Apple など有名なサービスが多いですが、一部のサービス(例えば Scratch)は公式な認証機能を提供していません。本記事では、Scratch のアカウント認証を実現するために、サードパーティのライブラリを用いた実装方法を解説します。
サイトを制作
サイトを制作していない場合は、サイトを制作してください。
開発環境
- Next.js v15.0.2, App router
インストール
npm install @scratch-auth/nextjs
環境変数を設定する
暗号化キー SCRATCH_AUTH_SECRET_KEY
を設定する必要があります。
このキーはセッションデータの暗号化と認証のために使用されます。
openssl rand -hex 32
SCRATCH_AUTH_SECRET_KEY=***************************************
パッケージ設定ファイル
項目 | 説明 |
---|---|
COOKIE_NAME | クッキーに保存される名前 |
redirect_url | セッション認証の処理を実行するエンドポイントを指定する |
title | サイト名, 外部サイトの認証ページでタイトルとして表示されます。 |
expiration | セッションの有効期限, 日数単位です。 |
cn | CN 関数, パッケージが提供するコンポーネントUIの構築に必要です。 |
debug | デバッグモード, ログをコンソールに出力したりします |
import { ScratchAuthConfig } from "@scratch-auth/nextjs/src/types";
import { type ClassValue, clsx } from "clsx";
import { twMerge } from "tailwind-merge";
const config: ScratchAuthConfig = {
COOKIE_NAME: "scratch-auth-session",
redirect_url: `http://localhost:3000/api/auth`,
title: `Scratch Auth`,
expiration: 30,
cn: function cn(...inputs: ClassValue[]) {
return twMerge(clsx(inputs));
},
debug: true,
};
export default config;
セッション検証ページの追加
このページはセッションをデコードし、アカウント情報を検証します。このファイルを scratch-auth.config.ts
で設定した redirect_url
のパスに追加する必要があります。リダイレクトの間、セッションは privateCode
パラメータに設定される。
setScratchAuthSession
にprivateCode
を渡すことでパッケージがコードの有効性を確認します。もし成功した場合はクッキーにセッションが保存されます。
このページでは、リダイレクト先が /
に固定されていますが、もし変更したい場合は、独自のリダイレクト機能を制作する必要があります。
"use client";
import React, { useEffect } from "react";
import { useRouter, useSearchParams } from "next/navigation";
import { setScratchAuthSession } from "@scratch-auth/nextjs";
export default function AuthPage() {
const router = useRouter();
const searchParams = useSearchParams();
const privateCode = searchParams.get("privateCode");
useEffect(() => {
async function auth() {
console.log(privateCode);
const check = await setScratchAuthSession(privateCode);
console.log("check", check);
if (check) {
console.log("認証に成功");
} else {
console.error("認証に失敗");
}
router.push("/");
}
auth();
}, [privateCode]);
return (
<div className="flex justify-center items-center w-full h-full min-h-[calc(100dvh-64px)]">
スクラッチアカウントの認証...
</div>
);
}
認証ボタンの追加
Scratch Authのビルド済みコンポーネントを使うことで、ログインしたユーザーとログアウトしたユーザーに表示されるコンテンツをコントロールすることができます。まず、ユーザーがログインまたはログアウトするためのヘッダーを作成します。これには以下を使用します:
-
<LogIned>
を使用します: このコンポーネントの子コンポーネントは、ユーザがログインしているときのみ表示されます。 -
<LogOuted>
: このコンポーネントの子コンポーネントは、ユーザがログアウトしたときのみ表示されます。 -
<UserButton />
: ログインしているユーザのアカウントのアバターを表示するためのスタイルがあらかじめ用意されたコンポーネントです。 -
<LogInButton />
: ログインページにリンクするスタイルのないコンポーネント。
import React from "react";
import {
LogInButton,
LogIned,
LogOuted,
UserButton,
} from "@scratch-auth/nextjs";
export default function Page() {
return (
<div>
<LogOuted>
<LogInButton />
</LogOuted>
<LogIned>
<UserButton />
</LogIned>
</div>
);
}
スクラッチアカウントの認証
以下のコマンドでプロジェクトを実行する:
npm run dev
http://localhost:3000 ↗ からウェブサイトにアクセスして、認証機能を確認してください。
リダイレクト機能の補足
Scratch Auth を利用してログイン後に希望のページにリダイレクトする機能を実装する方法を解説します。ScratchAuthLogin
関数を使用し、リダイレクト先をクッキーに保存するカスタムログイン関数を作成します。その後、認証ページでリダイレクト先の情報を取得し、指定のページに遷移させます。
カスタムログイン関数
以下のコードでは、ログイン前にリダイレクト先をクッキーに保存します。このクッキーは認証ページで読み取られます。
sah-sessionchange
イベントについて:
このイベントは、パッケージが提供するログイン状態を再検証するための仕組みです。例えば、ログイン失敗時にリトライやセッション更新をトリガーする用途があります。
import { setCookie } from "cookies-next/client";
import {
ScratchAuthLogin,
} from "@scratch-auth/nextjs";
const onScratchAuthLogin = async () => {
setCookie("scratch-auth-redirect", "/dashboard");
const success = await ScratchAuthLogin();
if (!success) eventDispatch(new Event("sah-sessionchange"));
};
カスタムリダイレクト先
カスタムログイン関数で設定した、scratch-auth-redirect
をクッキーから取得して、そのURLにリダイレクトするようにする。
"use client";
import React, { useEffect } from "react";
import { useRouter, useSearchParams } from "next/navigation";
import { setScratchAuthSession } from "@scratch-auth/nextjs";
import { deleteCookie, getCookie } from "cookies-next/client";
export default function AuthPage() {
const router = useRouter();
const searchParams = useSearchParams();
const privateCode = searchParams.get("privateCode");
useEffect(() => {
async function auth() {
console.log(privateCode);
const check = await setScratchAuthSession(privateCode);
console.log("check", check);
if (check) {
console.log("認証に成功しました");
} else {
console.error("認証に失敗しました");
}
const redirect = getCookie("scratch-auth-redirect");
deleteCookie("scratch-auth-redirect");
router.push(redirect || "/");
}
auth();
}, [privateCode]);
return (
<div className="flex justify-center items-center w-full h-full min-h-[calc(100dvh-64px)]">
Scratchアカウントを認証中...
</div>
);
}
Discussion