概要
おつかれさまです!
個人開発でログイン機能を実装するにあたり、NextAuth.jsを採用することにしたので今回はその方法についてまとめてみました!
NextAuth.jsとは
OAuthの仕組みをもとにNext.js向けに作られたライブラリです。
GoogleやGitHubなど、OAuthを使った認証サービスが簡単に利用できるように作られています。
OAuthについてはこの記事が大変わかりやすかったです!
https://qiita.com/TakahikoKawasaki/items/e37caf50776e00e733be
手順
手順としては以下のようになります!
- GoogleAPIの設定
- .envの設定
- Dynamic Routesの設定
- Session Providerの設定
- コンポーネントの作成
- 実装の確認
1. GoogleAPIの設定
下記記事を参考にAPIの設定を行います。
最終的にClientId
とClientSecret
が発行されるので、コピーして保存しておきましょう。
2. .envの設定
発行したAPIの情報を.envファイルに保存し参照できるようにしておきます。
この際、認証にアプリケーションのURLも必要になってくるため、NEXTAUTH_URL
で設定をしておきます。
また、認証の際にNEXTAUTH_SECRET
も必要になってくるため下記のコマンドで値を生成しておきます。
openssl rand -base64 32
GOOGLE_CLIENT_ID="xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
GOOGLE_CLIENT_SECRET="xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
NEXTAUTH_URL="http://localhost:3000"
NEXTAUTH_SECRET="xxxxxxxxxxxxxxxxxx"
3. Dynamic Routesの設定
まず、NextAuth
をnpmでインストールしておきます。
npm install next-auth
次にApp RouterでのDynamicRoutesを設定します。追加するルーティングはsrc/app/api/auth/[...nextauth]/route.ts
です。
[...nextauth]
は、Dynamic Segments
と呼ばれ、ルート階層が深くなってもリクエストできるような仕組みを作ることができます。
import NextAuth from 'next-auth';
import GoogleProvider from 'next-auth/providers/google';
const handler = NextAuth({
secret: process.env.NEXTAUTH_SECRET,
providers: [
GoogleProvider({
clientId: process.env.GOOGLE_CLIENT_ID ?? '',
clientSecret: process.env.GOOGLE_CLIENT_SECRET ?? '',
}),
]
});
export { handler as GET, handler as POST };
4. Session Providerの設定
ログイン後に、session情報を各ページで使いたい為、設定をしておきます。
'use client';
import { SessionProvider } from 'next-auth/react';
import { ReactNode } from 'react';
const NextAuthProvider = ({ children }: { children: ReactNode }) => {
return <SessionProvider>{children}</SessionProvider>;
};
export default NextAuthProvider;
SessionProviderはuseContextを含むのでuse client
を付ける必要があります。
後はグローバルに参照できるようにlayout.tsx
で読み込んでおきます。
import './globals.css';
import { Inter } from 'next/font/google';
import NextAuthProvider from '@/providers/NextAuth';
const inter = Inter({ subsets: ['latin'] });
export const metadata: Metadata = {
title: 'xxxxxxx',
description: 'xxxxxxx',
};
export default function RootLayout({
children,
}: {
children: React.ReactNode;
}) {
return (
<html lang="en">
<body className={inter.className}>
<NextAuthProvider>{children}</NextAuthProvider>
</body>
</html>
);
}
5. コンポーネントの作成
処理の実装ができたので、コンポーネントを作って実際に動作を確認していきます。
import React from 'react';
import { useSession, signIn } from 'next-auth/react';
export default function Login() {
const { data: session, status } = useSession();
if (status === 'loading') {
return <div>Loading...</div>;
}
if (status !== 'authenticated') {
return (
<div>
<p>あなたはログインしていません</p>
<button onClick={() => signIn('google', {}, { prompt: 'login' })}>
Googleでログイン
</button>
</div>
);
}
return null;
}
import React from 'react';
import { useSession, signOut } from 'next-auth/react';
export default function Logout() {
const { data: session, status } = useSession();
if (status === 'authenticated') {
return (
<div>
<button onClick={() => signOut()}>ログアウト</button>
</div>
);
}
return null;
}
useSession()
とsignIn()
、signOut()
はNextAuthが提供しているフックです。
useSession()
を使うことでsessionの状態を参照でき、signIn()
でログイン処理を実行させています。
'use client';
import { useSession } from 'next-auth/react';
import Login from './components/Login';
import Logout from './components/Logout';
export default function Home() {
const { data: session, status } = useSession();
return (
<div>
{status === 'authenticated' ? (
<div>
<p>セッションの期限:{session.expires}</p>
<p>ようこそ、{session.user?.name}さん</p>
<img
src={session.user?.image ?? ``}
alt=""
style={{ borderRadius: '50px' }}
/>
<div>
<Logout />
</div>
</div>
) : (
<Login />
)}
</div>
);
}
6.実装の確認
Googleでログイン
をクリックすると、Googleログイン画面へ遷移し、アカウントを選択すると、画像のようにログイン処理とアカウント情報を取得することができました。
また、ログアウト
を押しても正常にログアウトすることができます。
まとめ
認証周りの知識がまだまだですが、改めて学ぶきっかけになりました!
最後まで読んで頂き、ありがとうございました!