🔥

NextAuth.js × PrismaでGoogle Accountで認証機能を実装しよう

2023/08/12に公開

はじめに

どうも、どすこいです。
勉強で、Nextjsで認証機能付きのをブログを作ってみたいと思いこの記事を作成した次第であります。
今回は、タイトルにもありますように、Next.jsとNextAuth.jsとPrismaでGoogle Accountで認証機能を作ります。
私が実際に作った手順をアウトプットするための記事になっています。
初心者の記事ですので間違いなどありましたら、指摘してください。

対象読者

・NextAuthで認証機能を作ってみたい方
・Prismaを使ってみたい方
・自作のポートフォリオに認証機能をつけたい方

使用する機能

・Next.js
https://nextjs.org/

・Prisma
https://www.prisma.io/

・NextAuth.js
https://next-auth.js.org/

・Docker

・Postgresql

Next.jsのプロジェクトを用意する

今回はTypeScriptを使用します。

terminal
npx create-next-app@latest

データベースの設定

postresqlの設定
今回はDockerを使用します。

docker-compose.yml
version: '3.9'
services:
  postgres:
    image: postgres:12-alpine
    container_name: postgres
    environment:
      - POSTGRES_USER=root
      - POSTGRES_PASSWORD=password
      - POSTGRES_DB=mydb

    volumes:
      - postgres:/var/lib/postgresql/data
    ports:
      - 5432:5432
volumes:
  postgres:

prismaのインストール

terminal
npm install prisma -D
npx prisma init

.envファイルの変更

.env
DATABASE_URL="postgresql://root:password@localhost:5432/mydb"

schema.prismaにテーブルを記入する。以下を参照しました。

https://authjs.dev/reference/adapter/prisma

schema
//Auth.jsの設定
model Account {
  id                 Int     @id @default(autoincrement())
  userId             Int     @map("user_id")
  type               String
  provider           String
  providerAccountId  String  @map("provider_account_id")
  refresh_token      String?
  access_token       String?
  expires_at         Int?
  token_type         String?
  scope              String?
  id_token           String?
  session_state      String?
  oauth_token_secret String?
  oauth_token        String?

  user User @relation(fields: [userId], references: [id], onDelete: Cascade)

  @@unique([provider, providerAccountId])
  @@map("accounts")
}

model Session {
  id           Int      @id @default(autoincrement())
  sessionToken String   @unique @map("session_token")
  userId       Int      @map("user_id")
  expires      DateTime
  user         User     @relation(fields: [userId], references: [id], onDelete: Cascade)

  @@map("sessions")
}

model User {
  id            Int       @id @default(autoincrement())
  name          String?
  email         String    @unique
  emailVerified DateTime? @map("email_verified")
  image         String?
  createdAt     DateTime  @default(now()) @map(name: "created_at")
  updatedAt     DateTime  @updatedAt @map(name: "updated_at")
  bookmarks     Article[]
  accounts      Account[]
  sessions      Session[]

  @@map(name: "users")
}

model VerificationToken {
  identifier String
  token      String   @unique
  expires    DateTime

  @@unique([identifier, token])
  @@map("verificationtokens")
}

//自分の作りたいアプリのデータベース
model Article {
  id        Int     @id @default(autoincrement())
  title     String
  content   String
  users     User[]
}

migrateを行う。

terminal
npx prisma migrate dev --name init

NextAuthの設定

npmでnextauthのインストール

terminal
npm install next-auth

page/api/auth/[...nextauth].tsxを作成する。ここに設定を書いていく。
今回はGoogleアカウントでの認証をしたいので、providersにはGoogleProvider記入する。
また、NextAuthではGithubなども認証として使用できるので詳しくはDoccumentを参照してください。
今回はPrismaを使用しているのでadapterには、PrismaAdapterを使用しています。

page/api/auth/[...nextauth].tsx
import NextAuth from "next-auth";
import GoogleProvider from "next-auth/providers/google";
import { PrismaAdapter } from "@auth/prisma-adapter";
import { PrismaClient } from "@prisma/client";

const prisma = new PrismaClient();

export default NextAuth({
  adapter: PrismaAdapter(prisma),
  providers: [
    GoogleProvider({
      clientId: process.env.GOOGLE_CLIENT_ID,
      clientSecret: process.env.GOOGLE_CLIENT_SECRET,
    }),
  ],
  secret: 'secret',
});

Session Providerの設定

以下をすることでuseSession()を通じて全てのページでSession情報を共有できます。

src/_app.tsx
import type { AppProps } from 'next/app';
import { SessionProvider } from 'next-auth/react';

function MyApp({ Component, pageProps }: AppProps) {
  return (
  <SessionProvider session={pageProps.session}>
      <Component {...pageProps} />
  </SessionProvider>
  );
}

export default MyApp;

Google Cloud Platfom(GCP)の設定

1.https://console.cloud.google.com/ にアクセスするとGCPのログイン画面が表示されるのでログインを行ってください。

  1. Oauth の設定は認証に関する設定なので左側のサイドバーメニューから API とサービスを選択して認証情報を選択します。

  2. 認証情報の画面が表示されるのでプロジェクトを作成するために画面右側にある"プロジェクトを作成"をクリックしてください。

4.プロジェクトには名前をつける必要があります。自動で名前が表示されるのでそのまま利用することができますし、任意の名前をつけることができます。

5.プロジェクト名を変更して”作成”ボタンをクリックします。

  1. OAuth2.0 のクライアント ID を設定するため上部にある"認証情報を作成"をクリックしてください。

  2. 画面上には”必ず、アプリケーションに関する情報を使用して OAuth 同意画面を構成してくださ”と表示されているので気になるところですが OAuth2.0 のクライアント ID を設定するため上部にある"認証情報を作成"をクリックしてください。

  3. OAuth 同意画面が表示されるので User Type では外部を選択します。

  4. 次にスコープの画面が表示されます。今回は何も設定せずそのまま進むため”保存して次へ”ボタンをクリックします。今回は、テストユーザーなどは作りません。

  5. 同意画面の作成が完了したのでダッシュボードに戻り再度認証情報を作成するため OAuth クライアント ID を選択します。

  6. 同意画面の作成が完了している場合は OAuth クライアント ID の作成画面が表示されます。開発サーバの URL(http://localhost:3000)を入力。承認済みのリダイレクト URL には http://localhost:3000/api/auth/providers に対して GET リクエストを送信した際に取得した callbackUrl(http://localhost:3000/api/auth/callback/google)を入力します。

  7. 入力が完了したら”生成”ボタンをクリックしてください。生成すると、作成が完了すると画面上にクライアント ID とクライアントシークレットの情報が表示されます。この2つをコピーします。

.envファイルの追加

.env
GOOGLE_CLIENT_ID={コピーしたもの}
GOOGLE_CLIENT_SECRET={コピーしたもの}
NEXTAUTH_URL="http://localhost:3000/"

認証をかけたいページでUseSessionをつかう

自分が使いたい認証ページでuseSessionを使い認証機能を使います。以下は公式Doccumentからの参照です。

https://next-auth.js.org/getting-started/client


import { useSession, signIn, signOut } from "next-auth/react"
export default function Component() {
  const { data: session } = useSession()
  if (session) {
    return (
      <>
        Signed in as {session.user} <br />
        <button onClick={() => signOut()}>Sign out</button>
      </>
    )
  }
  return (
    <>
      Not signed in <br />
      <button onClick={() => signIn()}>Sign in</button>
    </>
  )
}

終わりに

今回はNextAuth.jsで認証機能を作ることができました。最後のuseSessionのところがまだ完璧に理科できていませんが、引き続き勉強していきます。

以下は今回の参照したサイトです。ありがとうございました。

https://zenn.dev/hayato94087/articles/91179fbbe1cad4

https://reffect.co.jp/react/next-auth/

https://zenn.dev/farstep/books/7a6eb67dd3bf1f

Discussion