【Next14(App Router)×Prism×Supabase Google,Github認証の実装メモ】
公式ドキュメントに殆ど書いてありますが自分用のメモ程度に書き起こしておきます
Next14構築
下記のコマンドを打ってnext14の環境を整えます
npx create-next-app@latest --ts
【Next14 必要実行環境】
現在のnodeバージョン確認
node -v
※足りていない場合はnodebrewかnvmからバージョンアップをしてください
√ What is your project named? ... zen1
√ Would you like to use ESLint? ... No / Yes
√ Would you like to use Tailwind CSS? ... No / Yes
√ Would you like to use `src/` directory? ... No / Yes
√ Would you like to use App Router? (recommended) ... No / Yes
√ Would you like to customize the default import alias (@/*)? ... No / Yes
Would you like to customize the default import alias (@/*)?以外すべてYes
必要なライブラリをインストールします
npm install next-auth @next-auth/prisma-adapter
src/app/page.tsxの中身を下記の通りに書き換えます
"use client"
import { signIn, signOut, useSession } from "next-auth/react"
const IndexPage = () => {
const { data: session } = useSession()
return (
<>
<div className="flex justify-center">
{!session && (
<button
onClick={() => signIn()}
className='flex w-full justify-center border-2 border-b border-red-300 hover:border-red-400 bg-red-200 hover:bg-red-300 pb-6 pt-8 backdrop-blur-2xl dark:border-red-800 dark:hover:border-red-900 dark:bg-red-800/50 dark:hover:bg-red-900/30 lg:static lg:w-auto lg:rounded-xl lg:p-4'
>
Sign In
</button>
)}
{session && (
<button
onClick={() => signOut()}
className='flex w-full justify-center border-2 border-b border-green-300 bg-green-200 pb-6 pt-8 backdrop-blur-2xl dark:border-green-800 dark:bg-green-800/30 lg:static lg:w-auto lg:rounded-xl lg:p-4 hover:border-green-400 hover:bg-green-300 dark:hover:border-green-900 dark:hover:bg-green-900/30'
>
Sign Out
</button>
)}
</div>
</>
)
}
export default IndexPage
src/app/globals.cssの不要箇所を削除し下記の通りに書き換えます
@tailwind base;
@tailwind components;
@tailwind utilities;
【認証の作成】
次にsrc/app/api/auth/[...nextauth]/route.tsを作成します
GoogleとGithubの認証Providerを設定します
import NextAuth from 'next-auth'
import GithubProvider from 'next-auth/providers/github'
import GoogleProvider from 'next-auth/providers/google'
export const authOptions = {
secret: process.env.NEXTAUTH_SECRET,
providers: [
GithubProvider({
clientId: process.env.GITHUB_CLIENT_ID ?? '',
clientSecret: process.env.GITHUB_CLIENT_SECRET ?? '',
}),
GoogleProvider({
clientId: process.env.Google_CLIENT_ID ?? '',
clientSecret: process.env.Google_CLIENT_SECRET ?? '',
}),
],
}
const handler = NextAuth(authOptions)
export { handler as GET, handler as POST }
ルートディレクトリにenvファイルを作成します
NEXTAUTH_SECRETは秘密鍵を作成し入力してください
下記のサイトは自動で秘密鍵を生成してくれます
NEXTAUTH_URL="http://localhost:3000"
NEXTAUTH_SECRET=""
GITHUB_CLIENT_ID=""
GITHUB_CLIENT_SECRET=""
GOOGLE_CLIENT_ID=""
GOOGLE_CLIENT_SECRET=""
DATABASE_URL=""
Github ID生成
Github公式
公式の手順が一番わかりやすいのでこちらを見て作成してみてください
Authorization callback UrlはURLの後ろに必ず/api/auth/callback/githubを付けます
例)http:localhost:3000/api/auth/callback/github
作成し終えると下記の画像の通りClientIDが表示されます
Client secretsの作成はGenerate a new client secretsから行って下さい
ClienIDとClient secretsは先ほど作成したenvファイルに記載します
Google ID生成
GoogleConsole
まずはGoogleConsoleに行きAPIとサービス→認証情報→プロジェクトを作成で作成してください
1.OAuth 同意画面で必要に応じて入力して下さい(メールアドレスとアプリ名だけで可能)
2.+認証情報を作成からOAuthクライアントIDを作成します
3.自身の作成するアプリケーションに選択して下さい
4.作成が完了すると下記のような画面が表示されIDとキーが取得できます
ClienIDとClient secretsは先ほど作成したenvファイルに記載します
【プロバイダーの作成】
クライアント側でAuthを使用できるようにするため
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
作成したNextAuthProviderをlayout.tsxに記述します
import type { Metadata } from 'next'
import { Inter } from 'next/font/google'
import NextAuthProvider from '@/providers/NextAuth'
import './globals.css'
const inter = Inter({ subsets: ['latin'] })
export const metadata: Metadata = {
title: 'Create Next App',
description: 'Generated by create next app',
}
export default function RootLayout({
children,
}: {
children: React.ReactNode
}) {
return (
<html lang="en">
<body className={inter.className}>
<NextAuthProvider>{children}</NextAuthProvider>
</body>
</html>
)
}
ここまでで一度ターミナルでnpm run devで実行すると下記のように認証が出来ます
npm run dev
ログイン前
認証
ログイン後
Prismaアダプターの連携
認証は完成しましたがDBにデータの格納が出来ていないためアダプターの連携をし
DBに認証データを保存します。今回はPrismaを使用しますが、それ以外のアダプターについても
NextAuthの公式ドキュメントに記述してあります。
必要なライブラリをインストールします
npm install @prisma/client @next-auth/prisma-adapter
npm install prisma --save-dev
src/app/api/auth/[...nextauth]/route.tsにインストールしたライブラリをimportし追加します
import NextAuth from 'next-auth'
import GithubProvider from 'next-auth/providers/github'
import GoogleProvider from 'next-auth/providers/google'
+ import { PrismaAdapter } from "@auth/prisma-adapter"
+ import { PrismaClient } from "@prisma/client"
+ const prisma = new PrismaClient()
export const authOptions = {
secret: process.env.NEXTAUTH_SECRET,
+ adapter: PrismaAdapter(prisma),
providers: [
GithubProvider({
clientId: process.env.GITHUB_CLIENT_ID ?? '',
clientSecret: process.env.GITHUB_CLIENT_SECRET ?? '',
}),
GoogleProvider({
clientId: process.env.Google_CLIENT_ID ?? '',
clientSecret: process.env.Google_CLIENT_SECRET ?? '',
}),
],
}
const handler = NextAuth(authOptions)
export { handler as GET, handler as POST }
Prismaスキーマの作成
続いてNextAuthのスキーマを作成していきます
npx prisma init
上記のコマンドを実行するとルートディレクトリにprisma/schema.prismaファイルが作成されます
prisma/schema.prismaファイルをNextAuthの公式ドキュメントにのっとって書き換えます
datasource db {
provider = "postgresql"
url = env("DATABASE_URL")
shadowDatabaseUrl = env("SHADOW_DATABASE_URL") // Only needed when using a cloud provider that doesn't support the creation of new databases, like Heroku. Learn more: https://pris.ly/d/migrate-shadow
}
generator client {
provider = "prisma-client-js"
previewFeatures = ["referentialActions"] // You won't need this in Prisma 3.X or higher.
}
model Account {
id String @id @default(cuid())
userId String
type String
provider String
providerAccountId String
refresh_token String? @db.Text
access_token String? @db.Text
expires_at Int?
token_type String?
scope String?
id_token String? @db.Text
session_state String?
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
@@unique([provider, providerAccountId])
}
model Session {
id String @id @default(cuid())
sessionToken String @unique
userId String
expires DateTime
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
}
model User {
id String @id @default(cuid())
name String?
email String? @unique
emailVerified DateTime?
image String?
accounts Account[]
sessions Session[]
}
model VerificationToken {
identifier String
token String @unique
expires DateTime
@@unique([identifier, token])
}
Supabaseにデータを格納
次に格納先のDBとしてSupabaseを使用します。
Supabase公式に飛びアカウントがない場合は作成してください
1.newProjectからプロジェクトを作成してください
※Databaseパスワードは後で使うのでメモしておいてください又、作成には数分かかる可能性があります
2.作成が完了したら左のメニューバーのProgectSetting(一番下)から2個目の左のメニュバーの中のDatabaseに行きます
URIをクリックし表示されたURIを.envのDETABASE_URLに記載してください
※[password]には1で作成したときに入力したpasswordに置き換えてください
supabaseのデータベースに追加します
npx prisma db push
【動作確認】
ログインしたときに実際にトークンや情報が入っているかを確認します
npm run dev
npm run devで実行しログインを行います
npx prisma studio
PrismaStudioでログインユーザーのデータが格納されている確認します
上記のようにデータがあれば以上で実装完了です
Discussion