57
40

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

【Next.js】App Router × NextAuth.jsでGoogleログイン機能を実装したい

Last updated at Posted at 2023-09-10

概要

おつかれさまです!
個人開発でログイン機能を実装するにあたり、NextAuth.jsを採用することにしたので今回はその方法についてまとめてみました!

NextAuth.jsとは

OAuthの仕組みをもとにNext.js向けに作られたライブラリです。
GoogleやGitHubなど、OAuthを使った認証サービスが簡単に利用できるように作られています。

OAuthについてはこの記事が大変わかりやすかったです!
https://qiita.com/TakahikoKawasaki/items/e37caf50776e00e733be

手順

手順としては以下のようになります!

  1. GoogleAPIの設定
  2. .envの設定
  3. Dynamic Routesの設定
  4. Session Providerの設定
  5. コンポーネントの作成
  6. 実装の確認

1. GoogleAPIの設定

下記記事を参考にAPIの設定を行います。
最終的にClientIdClientSecretが発行されるので、コピーして保存しておきましょう。

2. .envの設定

発行したAPIの情報を.envファイルに保存し参照できるようにしておきます。
この際、認証にアプリケーションのURLも必要になってくるため、NEXTAUTH_URLで設定をしておきます。

また、認証の際にNEXTAUTH_SECRETも必要になってくるため下記のコマンドで値を生成しておきます。

command
openssl rand -base64 32
.env
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と呼ばれ、ルート階層が深くなってもリクエストできるような仕組みを作ることができます。

src/app/api/auth/[...nextauth]/route.ts
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情報を各ページで使いたい為、設定をしておきます。

src/providers/NextAuth.tsx
'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で読み込んでおきます。

src/app/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. コンポーネントの作成

処理の実装ができたので、コンポーネントを作って実際に動作を確認していきます。

app/components/Login.tsx
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;
}
app/components/Logout.tsx
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.実装の確認

画面表示はこのようになります。
Image from Gyazo

Googleでログインをクリックすると、Googleログイン画面へ遷移し、アカウントを選択すると、画像のようにログイン処理とアカウント情報を取得することができました。

また、ログアウトを押しても正常にログアウトすることができます。
Image from Gyazo

まとめ

認証周りの知識がまだまだですが、改めて学ぶきっかけになりました!
最後まで読んで頂き、ありがとうございました!

57
40
1

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
57
40

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?