🐽

next.js supabase prisma next-authでgoogleログイン

2024/09/10に公開

本記事ではnext.js supabase prisma next-authを連携させて
認証処理を実現します。

  • next.js 14.2.8
  • next-auth 4.24.7
  • prisma 5.19.1

next.js、ライブラリインストール

公式ドキュメントにならってセットアップを進めます。

npx create-next-app@latest

What is your project named? my-app
Would you like to use TypeScript? Yes
Would you like to use ESLint? Yes
Would you like to use Tailwind CSS? Yes
Would you like your code inside a `src/` directory?  Yes
Would you like to use App Router? (recommended) Yes
Would you like to use Turbopack for `next dev`?Yes
Would you like to customize the import alias (`@/*` by default)?  Yes
What import alias would you like configured? @/*

npm i next-auth
npm i prisma
npm i @next-auth/prisma-adapter
npx prisma init  

supabaseセットアップ

ログイン画面から
github認証でログインをしてください。

newProjectよりデータベースを作成してください。

projectURLとproject API keysのanon keyを保存しておきましょう。
SUPABASE_URL
SUPABASE_ANON_KEY
として使用します。

次にDATABASE_URLを取得します。
左下のProject Settigns->Database->URL->Mode Sessionにして
.envのDATABASE_URLを更新します。パスワードの部分はDB作ったものに変えてください。

prismaディレクトリの中のschemma.prismaを以下の様に編集します。

generator client {
  provider = "prisma-client-js"
}

datasource db {
  provider = "postgresql"
  url      = env("DATABASE_URL")
}

model Account {
  id                 String  @id @default(cuid())
  userId             String
  type               String
  provider           String
  providerAccountId  String
  refresh_token      String?
  access_token       String?
  expires_at         Int?
  token_type         String?
  scope              String?
  id_token           String?
  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[]
}


その後に以下のコマンドでsupabaseにデータを反映させます。

npx prisma db push

supabaseのtable editorに反映されていればOKです。

next-auth設定

.env.localに以下を追記
NEXTAUTH_URL=http://localhost:5000
NEXTAUTH_SECRET=hogheohgeogea

次にapp配下にapiディレクトリを作成。その下にauth/[...nextauth]ディレクトリを作成後に
authOptions.tsとroute.tsを作成します。

import { NextAuthOptions } from "next-auth";
import GoogleProvider from "next-auth/providers/google";
import { PrismaAdapter } from "@next-auth/prisma-adapter";
import { PrismaClient } from "@prisma/client";

const prisma = new PrismaClient();

export const authOptions: NextAuthOptions = {
  providers: [
    GoogleProvider({
      clientId: process.env.GOOGLE_CLIENT_ID!,
      clientSecret: process.env.GOOGLE_CLIENT_SECRET!,
    }),
  ],
  adapter: PrismaAdapter(prisma),
};


import NextAuth from "next-auth/next";
import { authOptions } from "./authOptions";

const handler = NextAuth(authOptions);

export { handler as GET, handler as POST };


次にlibディレクトリを作成し、provider.tsxを作成します。

"use client";

import { SessionProvider } from "next-auth/react";

export function SessionProviders({ children }: { children: React.ReactNode }) {
  return <SessionProvider>{children}</SessionProvider>;
}


このコンポーネントをlayout.tsxでラップします。

import type { Metadata } from 'next';
import './globals.css';
import { SessionProviders } from './lib/provider';

export const metadata: Metadata = {
  title: 'Create Next App',
  description: 'Generated by create next app',
};

export default function RootLayout({
  children,
}: Readonly<{
  children: React.ReactNode;
}>) {
  return (
    <html lang="ja">
      <body>
        <SessionProviders>{children}</SessionProviders>
      </body>
    </html>
  );
}


google auth設定

gcpコンソール画面からプロジェクトを作成します。

APIとサービス->OAuth同意画面
UserType->外部->必要情報を入力

認証情報->認証情報を作成->OAuth クライアント ID->承認済みのリダイレクトURI
http://localhost:5000/api/auth/callback/google
クライアントIDとクライアントシークレットが出るので
GOOGLE_CLIENT_IDとGOOGLE_CLIENT_SECRETとして.env.localに保存しましょう。

ログイン

page.tsxに以下を追記

"use client";
import { signIn, signOut, useSession } from "next-auth/react";
export default function Home() {
  const { data: session } = useSession();

  if (session) {
    return (
      <>
        Signed in as {session.user?.email} <br />
        <button onClick={() => signOut()}>Sign out</button>
      </>
    );
  }
  return (
    <>
      Not signed in <br />
      <button onClick={() => signIn("google")}>Sign in with Google</button>
    </>
  );
}


これでログインボタンを押すとGoogle認証が走りログインに成功すると
googleのメールアドレスが表示されます。
supbaseにも反映されていればOKです。

サーバサイドの取得方法

import { getServerSession } from "next-auth";
import { authOptions } from "../api/auth/[...nextauth]/authOptions";

export default async function Home() {
  const session = await getServerSession(authOptions);

  console.log(session);

  return <div>hoge</div>;
}


まとめ

今回はnext.jsとsupabaseを使用したgoogleログインの方法を紹介しました。
他のプロバイダーでも簡単にできるので積極的に試していこうと思います!!

Discussion