以前の記事
またも以前の記事に関連していますが、
Tursoの場合、認証基盤がないのでAuth.js(旧NextAuth)で作ろうと書いていたのですが、
Turso公式がClerkを推していました。
こちらも実装が非常に楽ではあったのですが、
authMiddlewareがdeprecatedになりClaude3.7では知識がインプットされていなかったため、
新しい方のclerkMiddlewareによる実装を記載します。
Clerkの認証設定
srcディレクトリがあれば、その直下にmiddleware.ts
なければ、プロジェクトルートにmiddleware.tsを作成します。
src/middleware.ts
import { clerkMiddleware } from '@clerk/nextjs/server'
export default clerkMiddleware()
// 認証したい
import { clerkMiddleware, createRouteMatcher } from "@clerk/nextjs/server";
// パブリックルートの定義
const isPublicRoute = createRouteMatcher([
"/",
"/public"
]);
export default clerkMiddleware(async (auth, request) => {
if (!isPublicRoute(request)) {
await auth.protect()
}
})
export const config = {
matcher: ["/((?!.+\\.[\\w]+$|_next).*)", "/", "/(api|trpc)(.*)"],
};
ログイン画面の例
/sign-in/page.tsx
'use client';
import { SignIn } from '@clerk/nextjs';
import { useRouter } from 'next/navigation';
import { useEffect } from 'react';
import { useClerk } from '@clerk/nextjs';
export default function SignInPage() {
const router = useRouter();
const { session } = useClerk();
// ユーザーが既にログインしている場合はマイページにリダイレクト
useEffect(() => {
if (session) {
router.push('/mypage');
}
}, [session, router]);
return (
<div className="flex min-h-screen flex-col items-center justify-center p-4">
<div className="w-full max-w-md">
<h1 className="mb-8 text-center text-3xl font-bold text-white">ログイン</h1>
<div className="rounded-lg bg-white/90 p-6 shadow-lg">
<SignIn
appearance={{
elements: {
formButtonPrimary: 'bg-blue-500 hover:bg-blue-600 text-sm normal-case',
card: 'bg-transparent shadow-none',
},
}}
routing="path"
path="/sign-in"
redirectUrl="/mypage"
/>
</div>
</div>
</div>
);
}
アカウント登録画面の例
/sign-up/page.tsx
'use client';
import { SignUp } from '@clerk/nextjs';
import { useRouter } from 'next/navigation';
import { useEffect } from 'react';
import { useClerk } from '@clerk/nextjs';
export default function SignUpPage() {
const router = useRouter();
const { session } = useClerk();
// ユーザーが既にログインしている場合はマップページにリダイレクト
useEffect(() => {
if (session) {
router.push('/mypage');
}
}, [session, router]);
return (
<div className="flex min-h-screen flex-col items-center justify-center p-4">
<div className="w-full max-w-md">
<h1 className="mb-8 text-center text-3xl font-bold text-white">アカウント登録</h1>
<div className="rounded-lg bg-white/90 p-6 shadow-lg">
<SignUp
appearance={{
elements: {
formButtonPrimary: 'bg-blue-500 hover:bg-blue-600 text-sm normal-case',
card: 'bg-transparent shadow-none',
},
}}
routing="path"
path="/sign-up"
redirectUrl="/mypage"
/>
</div>
<div className="mt-4 text-center">
<button
onClick={() => router.push('/sign-in')}
className="text-white underline hover:text-blue-300"
>
既にアカウントをお持ちの方はこちら
</button>
</div>
</div>
</div>
);
}