14
5

More than 1 year has passed since last update.

Next.jsにDB追加してVercelで公開してみた②

Last updated at Posted at 2023-04-24

この記事の目的

記事の概要

今回はNext.jsにDB追加してVercelで公開してみた①の続きとなり、認証機能を追加しVercelで公開するところまでをまとめています。

また、本記事では自分用にまとめているので、細かい内容については下記の記事を参考にしてみて下さい!

使用技術と前提

使用技術

  • Next.js(バージョンは12)
  • react
  • typescript
  • prisma
  • Supabase

前提

  • GitHubアカウント (OAuthアプリを作成するために使用)
  • Googleアカウント (OAuthアプリを作成するために使用)
  • Vercelアカウント (作成したアプリをデプロイするために使用)
  • Supabaseアカウント (PostgreSQLをDBとして用意するために使用)

プロジェクト公開までのフロー

  • ①Next.jsのプロジェクト作成
  • ②prismaインストール
  • ③supabaseの設定
  • ④DB設定(schema.prismaでテーブル作成)
  • ⑤投稿データ取得等の処理実装(Prisma Client)
  • ⑥NextAuth.js ライブラリをインストール
  • ⑦ログイン機能追加
  • ⑧GitHub認証設定
  • ⑨Google認証設定
  • ⑩Vercelで公開してみる

※長くなるためこの記事では⑥以降をまとめています
※バックエンドを実装してVercel公開できることを目的としているので、コードは載せていますが細かいは説明せずにさらっと説明しているので、ソースコード全体についてはこちらのGitHubを参考にして下さい。

⑥NextAuth.js ライブラリをインストール

下記のコマンドでNextAuth ライブラリと NextAuth Prisma アダプタをインストールします。

npm install next-auth@4 @next-auth/prisma-adapter

⑦ログイン機能追加

ヘッダーにLoginボタンを追加

components/Header.tsxを下記のよう変更して下さい。

components/Header.tsxコードをクリックして全て表示
components/Header.tsx
// Header.tsx
import React from 'react';
import Link from 'next/link';
import { useRouter } from 'next/router';
import { signOut, useSession } from 'next-auth/react';

const Header: React.FC = () => {
  const router = useRouter();
  const isActive: (pathname: string) => boolean = (pathname) =>
    router.pathname === pathname;

  const { data: session, status } = useSession();

  let left = (
    <div className="left">
      <Link href="/">
        <a className="bold" data-active={isActive('/')}>
          Feed
        </a>
      </Link>
      <style jsx>{`
        .bold {
          font-weight: bold;
        }

        a {
          text-decoration: none;
          color: var(--geist-foreground);
          display: inline-block;
        }

        .left a[data-active='true'] {
          color: gray;
        }

        a + a {
          margin-left: 1rem;
        }
      `}</style>
    </div>
  );

  let right = null;

  if (status === 'loading') {
    left = (
      <div className="left">
        <Link href="/">
          <a className="bold" data-active={isActive('/')}>
            Feed
          </a>
        </Link>
        <style jsx>{`
          .bold {
            font-weight: bold;
          }

          a {
            text-decoration: none;
            color: var(--geist-foreground);
            display: inline-block;
          }

          .left a[data-active='true'] {
            color: gray;
          }

          a + a {
            margin-left: 1rem;
          }
        `}</style>
      </div>
    );
    right = (
      <div className="right">
        <p>Validating session ...</p>
        <style jsx>{`
          .right {
            margin-left: auto;
          }
        `}</style>
      </div>
    );
  }

  if (!session) {
    right = (
      <div className="right">
        <Link href="/api/auth/signin">
          <a data-active={isActive('/signup')}>Log in</a>
        </Link>
        <style jsx>{`
          a {
            text-decoration: none;
            color: var(--geist-foreground);
            display: inline-block;
          }

          a + a {
            margin-left: 1rem;
          }

          .right {
            margin-left: auto;
          }

          .right a {
            border: 1px solid var(--geist-foreground);
            padding: 0.5rem 1rem;
            border-radius: 3px;
          }
        `}</style>
      </div>
    );
  }

  if (session) {
    left = (
      <div className="left">
        <Link href="/">
          <a className="bold" data-active={isActive('/')}>
            Feed
          </a>
        </Link>
        <Link href="/drafts">
          <a data-active={isActive('/drafts')}>My drafts</a>
        </Link>
        <style jsx>{`
          .bold {
            font-weight: bold;
          }

          a {
            text-decoration: none;
            color: var(--geist-foreground);
            display: inline-block;
          }

          .left a[data-active='true'] {
            color: gray;
          }

          a + a {
            margin-left: 1rem;
          }
        `}</style>
      </div>
    );
    right = (
      <div className="right">
        <p>
          {session.user.name} ({session.user.email})
        </p>
        <Link href="/create">
          <button>
            <a>New post</a>
          </button>
        </Link>
        <button onClick={() => signOut()}>
          <a>Log out</a>
        </button>
        <style jsx>{`
          a {
            text-decoration: none;
            color: var(--geist-foreground);
            display: inline-block;
          }

          p {
            display: inline-block;
            font-size: 13px;
            padding-right: 1rem;
          }

          a + a {
            margin-left: 1rem;
          }

          .right {
            margin-left: auto;
          }

          .right a {
            border: 1px solid var(--geist-foreground);
            padding: 0.5rem 1rem;
            border-radius: 3px;
          }

          button {
            border: none;
          }
        `}</style>
      </div>
    );
  }

  return (
    <nav>
      {left}
      {right}
      <style jsx>{`
        nav {
          display: flex;
          padding: 2rem;
          align-items: center;
        }
      `}</style>
    </nav>
  );
};

export default Header;

NextAuth.jsで認証用の特定のルートを設定

pages/api/auth/配下に[...nextauth].tsを作成し下記のように編集して下さい。
今回はGitHub認証設定Google認証設定を追加するのでprovidersに2つ追加しています。
他にもFaceBook認証とかと追加する場合は、providersにさらに追加していくイメージになります。

pages/api/auth/[...nextauth].tsコードをクリックして全て表示
pages/api/auth/[...nextauth].ts
import { NextApiHandler } from 'next';
import NextAuth from 'next-auth';
import { PrismaAdapter } from '@next-auth/prisma-adapter';
import GitHubProvider from 'next-auth/providers/github';
import GoogleProvider from "next-auth/providers/google";
import prisma from '../../../lib/prisma';

// Next.js APIルートのハンドラーを定義
const authHandler: NextApiHandler = (req, res) => NextAuth(req, res, options);
export default authHandler;

const options = {
  // 認証プロバイダーのリストを指定
  providers: [
    // GitHub認証プロバイダーを追加
    GitHubProvider({
      // GitHub OAuthアプリケーションのクライアントID
      clientId: process.env.GITHUB_ID,
      // GitHub OAuthアプリケーションのクライアントシークレット
      clientSecret: process.env.GITHUB_SECRET,
    }),
    // Google認証プロバイダーを追加
    GoogleProvider({
      // Google OAuthクライアントID
      clientId: process.env.GOOGLE_CLIENT_ID,
      // Google OAuthクライアントシークレット
      clientSecret: process.env.GOOGLE_CLIENT_SECRET,
      authorization: {
        params: {
          prompt: "consent",// 認証時Googleに表示されるダイアログの種類を指定
          access_type: "offline",// Google OAuthアクセストークン取得に必要な許可を要求
          response_type: "code"// Google OAuth認証レスポンスタイプを指定。"code"はアクセストークンを受け取るための認証コードを返す
        }
      }
    }),
  ],
  // データベースアダプターを指定する
  adapter: PrismaAdapter(prisma),
  // トークン署名に使用する秘密鍵を指定する
  secret: process.env.SECRET,
};

⑧GitHub認証設定

GitHub認証はアプリの認証ページのURLごとに作成する必要があるため、ローカル環境とVercelで公開した場合の2パターン作成します。api/authは認証画面のURLです。

.vercel.appの前のpikimaru-nps部分は後ほどVercelにデプロイする際につけるプロジェクト名になります

【ローカル環境】GitHubで新しいOAuth applicationを作成

GitHub認証を使用するには、GitHubでOAuth applicationを作成を作成する必要もあります。
GitHubにログインしSettingsのDeveloper Settingsを開きOAuth Appsを選択後、「New OAuth App」を選択します。
スクリーンショット 2023-04-21 22.51.43.png

【ローカル環境】必要事項の入力

Authorization callback URLは、Next.js '/api/auth' route: 'http://localhost:3000/api/auth' になります。URLが複数入力できないため環境ごとに作成する必要があります。
スクリーンショット 2023-04-21 23.01.48.png

【ローカル環境】Client IDとClient secretsを確認し設定する

OAuth applicationを作成が作成されると下の画像のような画面になるかと思いますので
Client IDClient secretsを確認していきます。
Client secretsは初期状態だとおそらくないと思うので「Generate a new client secret」を選択し作成して下さい。
スクリーンショット 2023-04-21 23.06.56.png
確認したら.envに設定していきます。

  • GITHUB_IDにClient ID
  • GITHUB_SECRETにClient Secret
  • NEXTAUTH_URLにAuthorization callback URL
.env
# GitHub OAuth
GITHUB_ID=XXXXXXXXXXXXXXXXXXX
GITHUB_SECRET=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
NEXTAUTH_URL=http://localhost:3000/api/auth

⑨Google認証設定

Google認証もGitHub認証と同じくアプリの認証ページのURLごとに作成する必要があるため、ローカル環境とVercelで公開した場合の2パターン作成します。api/authは認証画面のURLです。

.vercel.appの前のpikimaru-nps部分は後ほどVercelにデプロイする際につけるプロジェクト名になります

【ローカル環境】Googleで新しいOAuthクライアントを作成

まずはGoogle Cloud Platfom(GCP)にログインする。
初めてGCPにログインした方は利用規約確認の画面が出るかと思うので、問題がなければチェックし、「同意して続行」ボタンをクリックしてください。”最新情報をメールで通知”は必要でなければチェックは不要です。
左側のサイドバーメニューから「APIとサービス」を選択し、「認証情報」を選択
スクリーンショット 2023-04-22 21.57.34.png

【ローカル環境】プロジェクトを作成

「新しいプロジェクト」を選択(初めてプロジェクトを作成する方は画面は少し異なると思います。)
スクリーンショット 2023-04-22 22.04.02.png
プロジェクトは「プロジェクト名」だけ入力すれば問題ないです。好きな名前を入力して下さい
スクリーンショット 2023-04-22 22.05.18.png

【ローカル環境】OAuthクライアントを作成(同意画面)

プロジェクト作成後、「認証情報を作成」選択し「0AuthクライアントID」を選択して下さい
スクリーンショット 2023-04-22 22.09.03.png
そうすると同意を求められるので「同意画面を設定」を選択し「0Auth同意画面」のUserTypeを外部にチェックをして作成を選択して下さい
スクリーンショット 2023-04-22 22.09.59.png
スクリーンショット 2023-04-22 22.10.55.png
次に「①0Auth同意画面」が表示されるので以下の必須項目3点を記入して下さい

  • アプリ名 : 好きな名前で問題ないです
  • ユーザーサポートメール : 自身のメールアドレス
  • デベロッパーの連絡先情報 : 自身のメールアドレス

上記以外は特に「①0Auth同意画面」、「②スコープ」「③テストユーザー」でも入力する必要ないので、「保存して次へ」を選択して下さい
スクリーンショット 2023-04-22 23.02.38.png
スクリーンショット 2023-04-22 23.04.26.png
「②スコープ」「③テストユーザー」でも、「保存して次へ」を選択すると「④概要」に進み同意画面の作業が完了になります
スクリーンショット 2023-04-22 23.05.34.png

【ローカル環境】OAuthクライアントを作成 

同意画面の作業が完了したので、目的のOAuthクライアントを作成していきます。
先ほど同様「認証情報を作成」選択し「0AuthクライアントID」を選択して下さい
スクリーンショット 2023-04-22 21.59.00.png
そうすると今度は「0AuthクライアントIDの作成」画面が表示されるので以下の4項目を選択または入力して下さい。

  • アプリケーションの種類 : ウェブアプリケーション
  • 名前 : 好きな名前で問題ないです(今回はローカル環境用なので例としてローカルと分かる名前にしています)
  • 承認済みのJavaScript生成元 : http://localhost:3000
  • 承認済みのリダイレクトURI : http://localhost:3000/api/auth/callback/google

※承認済みのリダイレクトURLにはhttp://localhost:3000/api/auth/providersに対してGETリクエストを送信した際に取得したcallbackUrlであるhttp://localhost:3000/api/auth/callback/googleを入力する必要があります
スクリーンショット 2023-04-22 23.17.13.png
作成が完了すると画面上にクライアントIDとクライアントシークレットの情報が表示さるかと思います。
スクリーンショット 2023-04-22 23.25.29.png
クライアントIDとクライアントシークレットを.envに設定していきます。

  • GOOGLE_CLIENT_IDにクライアントID
  • GOOGLE_CLIENT_SECRETにクライアントシークレット
.env
# Google OAuth
GOOGLE_CLIENT_ID=XXXXXXXXXXXXXXXXXXX
GOOGLE_CLIENT_SECRET=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

【ローカル環境】ローカル環境で認証動作確認

ここまででローカル環境のGitHub認証設定とGoogle認証設定が完了したのでローカル環境(http://localhost:3000/)で確認していきます
わかりやすいように画面を拡大したものを載せています

Loginを選択

http://localhost:3000/にアクセスしヘッダーの右側に「Login」があると思うので選択する
スクリーンショット 2023-04-22 23.36.47.png

認証画面確認

「Login」選択すると下のような認証ボタンが出てくるかと思いますので
GitHubまたはGoogle認証を選択しログインできることを確認してみて下さい。
最初の1回目のみ各媒体お馴染みののログイン画面が出てくるかと思います。
スクリーンショット 2023-04-22 23.35.03.png
ログインが成功するとヘッダー部分にログインしたユーザー情報がでるかと思います。
ログアウトしてもう一方の認証も同じように確認してみて下さい
スクリーンショット 2023-04-22 23.42.11.png

データベースでユーザー情報確認

ログインを行うとログインしたユーザー情報がデータベースに登録されるのでSupabaseもしくはprisma studioで確認します

Supabase確認

下記のようにレコードが追加され、providerでどの認証機能を使用しているかなど確認できるかと思います
スクリーンショット 2023-04-22 23.46.15.png

prisma studio確認

http://localhost:5555/に遷移するとみれるかと思います。
prisma studioを停止している場合はnpx prisma studioで起動してアクセスしてみて下さい
スクリーンショット 2023-04-22 23.46.45.png

⑩Vercelで公開してみる

ローカル環境で確認できたので、実際にVercelにデプロイしバックエンドも備えたサイトを公開していきます。
流れとしては以下になります

  • 【公開用】GitHub認証設定
  • 【公開用】Google認証設定
  • Vercelでプロジェクト作成デプロイ

また、ここからソースコードは変更しないのでGitHubにリポジトリを作成しコミットプッシュまで行って下さい
先ほど編集した.envはローカルでしか使用されないので削除等はしなくて問題ないです。(GitHubにも載らないので)

【公開用】GitHub認証設定

⑧GitHub認証設定で作成したローカル用のOAuth applicationと同様にして
Vercel公開用のOAuth applicationを作成していきます。

【Vercel公開用】GitHubで新しいOAuth applicationを作成

先ほどと手順は同じくGitHubにログインしSettingsのDeveloper Settingsを開きOAuth Appsを選択後、「New OAuth App」を選択し必要事項の入力していきます

※Vercelのプロジェクト名については、Vercelでデプロイする際に決めることができるので、ここで入力したVercelのプロジェクト名を使用して後ほどVercelのプロジェクトを作成していきます
ここではVercelのプロジェクト名をpikimaru-npsとしています
スクリーンショット 2023-04-23 17.19.14.png

OAuth applicationを作成が作成されると下の画像のような画面になるかと思いますので
Client IDClient secretsを確認していきます。
Client secretsは初期状態だとおそらくないと思うので「Generate a new client secret」を選択し作成して下さい
Vercelでプロジェクト作成際にClient IDClient secretsが必要になります
スクリーンショット 2023-04-23 16.14.52.png

【公開用】Google認証設定

⑨Google認証設定で作成したローカル用のOAuthクライアントと同様にして
Vercel公開用のOAuthクライアントを作成していきます。
まずはGoogle Cloud Platfom(GCP)にログインする。
先ほどローカル用で作成しているため「同意画面を設定」は飛ばせるかと思います。

※Vercelのプロジェクト名については、Vercelでデプロイする際に決めることができるので、ここで入力したVercelのプロジェクト名を使用して後ほどVercelのプロジェクトを作成していきます
スクリーンショット 2023-04-23 17.05.34.png
Vercelでプロジェクト作成際にClient IDClient secretsが必要になります
スクリーンショット 2023-04-23 16.40.14.png

Vercelでプロジェクト作成デプロイ

ここからは実際にVercelに認証を設定したプロジェクトを作成し公開していきます。

Vercelプロジェクト作成

Vercelのダッシュボードに移動して「Add New」を選択し「Project」を選択します
スクリーンショット 2023-04-23 16.54.10.png
「Project」を選択後、リポジトリを選択する画面になるかと思いますので、今回あげたリポジトリの「import」を選択する。
スクリーンショット 2023-04-23 16.55.34.png

プロジェクト作成画面に遷移するかと思いますので下記の必要項目を入力します。
Environment Variablesを選択すると環境変数が追加できるようになるかと思います。

  • Project name: Vercelのプロジェクト名(先ほど認証の際に使用していたもの本記事ではpikimaru-nps
  • DATABASE_URL: '.env' と同じ値
  • GITHUB_ID: GitHub OAuth appのClient IDをコピーして入力してください
  • GITHUB_SECRET: GitHub OAuth appのClient secretsをコピーして入力してください
  • NEXTAUTH_URL: GitHub OAuth appのAuthorization Callback URLをコピーして入力してください
  • SECRET: GITHUB_SECRETと同じものを入力してください。Prismaが使用します。
  • GOOGLE_CLIENT_ID: Google認証設定で取得したClient IDをコピーして入力してください
  • GOOGLE_CLIENT_SECRET: Google認証設定で取得したClient secretsをコピーして入力してください

入力が完了したら「Deploy」を選択するとデプロイが始まります!
スクリーンショット 2023-04-23 17.11.50.png
デプロイがビジ完了すると下の画像のように表示されるかと思います!
表示されたら「Continue to Dashubooar」を選択し、その後「Visit」を選択すると公開されたページに遷移して確認することができます
スクリーンショット 2023-04-23 17.42.50.png
スクリーンショット 2023-04-23 17.43.07.png
本記事で公開したURLはhttps://pikimaru-nps.vercel.app/となっておりこちらで遷移すると下の画像のように表示されるかと思います。
投稿機能およびログイン認証も確認できたので、DB追加したNext.jsのプロジェクトをVercelで公開できました!!
スクリーンショット 2023-04-23 17.45.22.png
スクリーンショット 2023-04-23 17.49.31.png

参考

14
5
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
14
5