NextAuth

【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

NextAuth.jsのオプションまとめ。

NextAuth.jsを利用していて、セッションの有効期限を変更したりカスタマイズしたくなりました。

NextAuth.jsのオプション設定でどんなことができるかまとめてみました。

NextAuth.jsの基本コード

import NextAuth from "next-auth"

export default NextAuth({
    ...

})

NextAuth.jsのオプション早見表

オプション名内容デフォルト値必須?
providersプロバイダの指定
(ログインに使用できるSNSサービスの種類を指定)
[]Yes
secret・Cookieの署名/暗号化などに使う設定string(開発)
No(本番)
Yes
(本番)
session・セッションに関する設定objNo
jwt???objNo
pages???{}No
callbacks・signIn, signOutなどアクションが起きた時に実行される処理のカスタマイズ設定objNo
events???objNo
adapter・外部DBやバックエンドシステムに接続するための設定
(ユーザー情報等をDBに保存したい場合など)
noneNo
debug???falseNo
logger???consoleNo
theme???objNo

providers

ユーザー登録(サインイン)やログインに使用できるプロバイダの設定

Google, Facebook, Twitter, GitHub, Emailなどなど。

export default NextAuth({
    ...,
    providers: [
        ...,
    ],
});

【関連記事】 NextAuth.jsで使える主要なプロバイダ一覧まとめ。

secret

「トークンのハッシュ化」や「Cookieの署名/暗号化」、「暗号化キーの生成」のために必要な設定。

本番環境の場合、「⑴ “secret“を記載」または「⑵ 環境変数に”NEXTAUTH_SECRET”を設定」のどちらかをしないとエラーになります。

方法⑴ “secret”を記載する

export default NextAuth({
    ...,
    secret: 'secret',
});

方法⑵ 環境変数に”NEXTAUTH_SECRET”を設定

下記コマンドで乱数を生成します。

$ openssl rand -base64 32

生成された乱数を環境変数に追加します。

NEXTAUTH_SECRET=[生成した乱数]

session

セッションに関する設定。

strategyセッション情報の保存方法(「JWT」や「データベース」など)
デフォルト値は“jwt”
「adapter」の指定されている場合は、デフォルトが“database”になる。
maxAgeセッションの有効期限。「秒」単位。
updateAgeセッション延長のためのデータベース更新頻度。「秒」単位。

セッションの有効期限は「どのくらいの期間、ログインしたままの状態が保たれるか」。

export default NextAuth({
    ...,
    session: {
        strategy: "database",
        maxAge: 30 * 24 * 60 * 60,  // 30 days
        updateAge: 24 * 60 * 60,  // 24 hours
    }
});

jwt

今後追記する…かも。

pages

今後追記する…かも。

callbacks

今後追記する…かも。

events

今後追記する…かも。

adapter

外部DBやバックエンドシステムに接続するための設定。UserデータやSessionデータなどをDBに保存したい場合などに必要な設定です。

例えば、ユーザー情報等を「Prisma」を使ってDBに保存したい場合など。

// 例:Prisma
import NextAuth from "next-auth"
import { PrismaAdapter } from "@next-auth/prisma-adapter"
import { PrismaClient } from "@prisma/client"

const prisma = new PrismaClient()

export default NextAuth({
    adapter: PrismaAdapter(prisma),
})

debug

今後追記する…かも。

logger

今後追記する…かも。

theme

今後追記する…かも。

まとめ

ユーザーのログインした状態を保持する期間を「session」で指定できることがわかって嬉しい。

NextAuth.jsで使える主要なプロバイダ一覧まとめ。

NextAuth.jsで、よく使われそうな主要なプロバイダをまとめました。

これでいろいろなSNSやWEBサービスのアカウントでユーザー登録できるようになります。

NextAuth.js

プロバイダを指定で編集するファイル

/pages/api/auth/[…nextauth].js のprovidersの中に記載していきます。

import NextAuth from "next-auth"

export default NextAuth({
    providers: [
        // ここにプロバイダを追加していきます。
        ...,
    ],
})

主要なプロバイダ一覧

プロバイダ名公式ドキュメントNextAuthページ
Applehttps://developer.apple.com/sign-in-with-apple/get-started/https://next-auth.js.org/providers/apple
Discordhttps://discord.com/developers/docs/topics/oauth2https://next-auth.js.org/providers/discord
Facebookhttps://developers.facebook.com/docs/facebook-login/manually-build-a-login-flow/https://next-auth.js.org/providers/facebook
GitHubhttps://developer.github.com/apps/building-oauth-apps/authorizing-oauth-appshttps://next-auth.js.org/providers/github
Googlehttps://developers.google.com/identity/protocols/oauth2https://next-auth.js.org/providers/google
Instagramhttps://developers.facebook.com/docs/instagram-basic-display-api/getting-startedhttps://next-auth.js.org/providers/instagram
LINEhttps://developers.line.biz/en/docs/line-login/integrate-line-login/https://next-auth.js.org/providers/line
Twitchhttps://dev.twitch.tv/docs/authenticationhttps://next-auth.js.org/providers/twitch
Twitterhttps://developer.twitter.com/https://next-auth.js.org/providers/twitter

Apple

プロバイダの公式ドキュメントhttps://developer.apple.com/sign-in-with-apple/get-started/
NextAuth.jsの詳細ページhttps://next-auth.js.org/providers/apple
import AppleProvider from "next-auth/providers/apple";

...
providers: [
    AppleProvider({
        clientId: process.env.APPLE_ID,
        clientSecret: process.env.APPLE_SECRET
    }),
    ...,
],
...

Discord

プロバイダの公式ドキュメントhttps://discord.com/developers/docs/topics/oauth2
NextAuth.jsの詳細ページhttps://next-auth.js.org/providers/discord
import DiscordProvider from "next-auth/providers/discord";

...
providers: [
    DiscordProvider({
        clientId: process.env.DISCORD_CLIENT_ID,
        clientSecret: process.env.DISCORD_CLIENT_SECRET
    }),
],
...

Facebook

プロバイダの公式ドキュメントhttps://developers.facebook.com/docs/facebook-login/manually-build-a-login-flow/
NextAuth.jsの詳細ページhttps://next-auth.js.org/providers/facebook
import FacebookProvider from "next-auth/providers/facebook";

...
providers: [
    FacebookProvider({
        clientId: process.env.FACEBOOK_CLIENT_ID,
        clientSecret: process.env.FACEBOOK_CLIENT_SECRET
    }),
],
...

GitHub

プロバイダの公式ドキュメントhttps://developer.github.com/apps/building-oauth-apps/authorizing-oauth-apps
NextAuth.jsの詳細ページhttps://next-auth.js.org/providers/github
import GitHubProvider from "next-auth/providers/github";

...
providers: [
    GitHubProvider({
        clientId: process.env.GITHUB_CLIENT_ID,
        clientSecret: process.env.GITHUB_CLIENT_SECRET
    }),
],
...

Google

プロバイダの公式ドキュメントhttps://developers.google.com/identity/protocols/oauth2
NextAuth.jsの詳細ページhttps://next-auth.js.org/providers/google
import GoogleProvider from "next-auth/providers/google";

...
providers: [
    GoogleProvider({
        clientId: process.env.GOOGLE_CLIENT_ID,
        clientSecret: process.env.GOOGLE_CLIENT_SECRET
    }),
],
...

Instagram

プロバイダの公式ドキュメントhttps://developers.facebook.com/docs/instagram-basic-display-api/getting-started
NextAuth.jsの詳細ページhttps://next-auth.js.org/providers/instagram
import InstagramProvider from "next-auth/providers/instagram";

...
providers: [
    InstagramProvider({
        clientId: process.env.INSTAGRAM_CLIENT_ID,
        clientSecret: process.env.INSTAGRAM_CLIENT_SECRET
    }),
],
...

Instagramでサインインを実装する場合には下記の記載が必要になります。

import { signIn } from "next-auth/react"

...
<button onClick={() => signIn("instagram")}>  // signInの中に"instagram"を記載
    Sign in
</button>

LINE

プロバイダの公式ドキュメントhttps://developers.line.biz/en/docs/line-login/integrate-line-login/
NextAuth.jsの詳細ページhttps://next-auth.js.org/providers/line
import LineProvider from "next-auth/providers/line";

...
providers: [
    LineProvider({
        clientId: process.env.LINE_CLIENT_ID,
        clientSecret: process.env.LINE_CLIENT_SECRET
    }),
],
...

Twitch

プロバイダの公式ドキュメントhttps://dev.twitch.tv/docs/authentication
NextAuth.jsの詳細ページhttps://next-auth.js.org/providers/twitch
import TwitchProvider from "next-auth/providers/twitch";

...
providers: [
    TwitchProvider({
        clientId: process.env.TWITCH_CLIENT_ID,
        clientSecret: process.env.TWITCH_CLIENT_SECRET
    }),
],
...

Twitter

プロバイダの公式ドキュメントhttps://developer.twitter.com/
NextAuth.jsの詳細ページhttps://next-auth.js.org/providers/twitter
import NextAuth from "next-auth"
import TwitterProvider from "next-auth/providers/twitter";

export default NextAuth({
    providers: [
        TwitterProvider({
            clientId: process.env.TWITTER_CLIENT_ID,
            clientSecret: process.env.TWITTER_CLIENT_SECRET
        }),
        ...,
    ],
})

その他

42 School, Amazon Cognito, Apple, Atlassian, Auth0, Authentik, Azure Active Directory, Azure Active Directory B2C, Battle.net, Box, BoxyHQ SAML, Bungie, Coinbase, Discord, Dropbox, EVE Online, Facebook, FACEIT, Foursquare, Freshbooks, FusionAuth, GitHub, GitLab, Google, IdentityServer4, Instagram, Kakao, Keycloak, LINE, LinkedIn, Mail.ru, Mailchimp, Medium, Naver, Netlify, Okta, OneLogin, Osso, Osu!, Patreon, Pipedrive, Reddit, Salesforce, Slack, Spotify, Strava, Trakt, Twitch, Twitter, United Effects, VK, WordPress.com, WorkOS, Yandex, Zoho, Zoom

出典:OAuth | NextAuth.js