Prisma

【NextAuth.js】ソーシャルログインの実装。

GoogleやTwitter、FacebookなどのSNSアカウントを使ってログインできる「ソーシャルログイン」の実装方法をまとめていきたいと思います。

使用するパッケージをインストールする

「next-auth」をインストール

$ npm install next-auth

プロバイダ側(SNSサービス側)の設定をする

ソーシャルログインを使うためには、GoogleやTwitterなど認証機能を使いたいサービスごとに「⑴ clientId」と「⑵ clientSecret」を事前に取得する必要があります。

Googleアカウントでログインしたい場合

Google Cloud Platform(GCP)で「clientId」と「clientSecret」の2つを取得します。

こちらは下記記事がとても参考になりました 。

Twitterアカウントでログインしたい場合

※分かり次第更新します。

Next.js側の設定をする

「.env」ファイル

プロバイダ側の設定で取得した「clientId」と「clientSecret」を.envファイル内記載します。

(もしトップディレクトリに.envファイルがない場合は作成してください。)

GOOGLE_CLIENT_ID=[取得したクライアントID]
GOOGLE_CLIENT_SECRET=[取得したクライアントシークレット]

「pages/api/[…nextauth].js」ファイル

pages/apiディレクトリ内に[...nextauth].jsを作成します。

[…nextauth].jsでは「使用するプロバイダの指定」をします。

import NextAuth from 'next-auth';
import GoogleProvider from 'next-auth/providers/google';

export default NextAuth({
    // 1: ログインに使用するプロバイダを指定
    providers: [
        GoogleProvider({
            clientId: process.env.GOOGLE_CLIENT_ID,
            clientSecret: process.env.GOOGLE_CLIENT_SECRET,
        }),
    ],
    secret: 'secret',
});

プロバイダごとに記載方法が異なるので、こちらの記事を参考に選んで記載してみてください。

「_app.js」ファイル

_app.jsのComponentをSessionProviderで囲います。

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

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

ログインボタンを作る

NextAuthでは、signIn()でログイン、signOut()でログアウトの処理を実装することができます。

import { useSession, signIn, signOut } from "next-auth/react"

export default function LoginButton(props) {
    // セッション情報を取得
    const { data: session } = useSession()

    return (
        {session ?  // ログイン判定
            <button onClick={() => signOut()}>ログアウト</button>:
            <button onClick={() => signIn()}>ログイン</button>
        }
    );
};

ログインユーザー情報をデータベースに保存する

ログインしたユーザー情報をデータベースへ保存したい場合は、「Prisma」を利用すると比較的簡単に実装することができます。

詳しくはこちらの記事を参考にしてみてください。

【NextAuth.js + Prisma】ログインしたユーザー情報をDBに保存する

NextAuth.jsとPrismaを使って、ログインしたユーザー情報をデータベースに保存する方法をまとめておきます。

今回は主に「Prismaの設定」に関する内容になります。NextAuth.jsの設定は完了している前提で書いているので、まだ設定できていない場合は先にNextAuth.jsの設定が必要になります。

後半にMySQLの場合の設定方法も詳しく記載しています。

⑴ 使用するパッケージをインストールする

$ npm install @prisma/client @next-auth/prisma-adapter
$ npm install prisma --save-dev

⑵ 接続先のデータベースを設定する

.envファイルの作成

Prismaで使用するデータベースの情報(URL等)を記載する.envファイルを作成します。

[project]
 ├ 〇〇
 ├ 〇〇
 └ .env  # 新規作成

.envファイルに接続先のデータベース情報を記載

接続先データベースの「URL」や「ユーザー名」などを.envファイル内に記載していきます。

PostgreSQLややMySQL、SQLiteなどのデータベースの種類によって記載方法が異なることがあるので確認してみてください。

DATABASE_URL=[データベースURL等]

⑶ データベース構造(スキーマ)等の設定する

$ npx prisma init

「prisma」フォルダを作成

[project]
 ├ 〇〇
 ├ 〇〇
 ├ .env
 └ prisma  # 新規作成

「schema.prisma」ファイルを作成

先ほど作成した「prisma」フォルダ内に「schema.prisma」作成します。

この「schema.prisma」は、データベースの構造を指定するファイルです。

[project]
 ├ 〇〇
 ├ 〇〇
 ├ .env
 └ prisma
   └ schema.prisma  # 新規作成

「schema.prisma」を編集

// =====================================
// 1_接続するデータベースの設定
// =====================================
datasource db {
    provider = "mysql"
    url      = [DATABASE_URL]
}


// =====================================
// 2_「npx prisma generate」で生成するものを指定
// =====================================
generator client {
    provider = "prisma-client-js"
}


// =====================================
// 3_作成するモデルを指定
// =====================================
// Accountモデル
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])
}

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

    @@map("sessions")
}

// Userモデル
model User {
    id            String    @id @default(cuid())
    name          String?
    email         String?   @unique
    emailVerified DateTime? @map("email_verified")
    image         String?
    accounts      Account[]
    sessions      Session[]

    @@map("users")
}

❶ 接続するデータベースの設定

「⑴データベースの種類(SQLite, progresql, MySQL, …)」と「⑵その接続先URL」を設定します。

// =====================================
// 1_接続するデータベースの設定
// =====================================

datasource db {
    provider = "mysql"
    url      = [DATABASE_URL]  # MySQLの接続先URLの書き方は後述
}

❷ 生成するクライアントの指定(Prisma Client)

// =====================================
// 2_「npx prisma generate」で生成するものを指定
// =====================================

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

ここで生成するClientは、アプリ内で使用できるようになります。

const { PrismaClient } = require('@prisma/client')

const prisma = new PrismaClient()

❸ 作成するデータベースのモデルを指定

今回のデータベースには、「NextAuth.js」が基本としているモデルをそのまま使用しています。

// =====================================
// 3_作成するモデルを指定
// =====================================

// Accountモデル
model Account {
    ...
}

// Sessionモデル
model Session {
    ...
}

// Userモデル
model User {
    ...
}

[おまけ] MySQLの接続先URLの書き方

参照:Prisma 公式ドキュメント
// 基本の書き方
mysql://[USER]:[PASSWORD]@[HOST]:[PORT]/[DATABASE]

// 例
mysql://root:mypw@127.0.0.1:8889/project_databese
USERデータベースのユーザー名。
PASSWORDデータベースのパスワード。
HOSTホスト。
PORTポート。
DATABASEデータベースの名前。

[おまけ] NextAuth.jsで使用する基本モデル

NextAuth.jsでは基本となるデータベース構造を教えてくれています。

⑷ マイグレートを実行する

マイグレートを実行して、schema.prismaで指定したモデルのテーブルをデータベースに作成します。

$ npx prisma migrate dev

--nameを付けることでマイグレーションファイルに名前を付けることができます。

$ npx prisma migrate dev --name [マイグレーションファイル名]

$ npx prisma migrate dev --name first-migration  # 例
$ npx prisma migrate dev --name added_job_title  # 例

⑸ Pricma Clientを作成する

$ npx prisma generate