Next.jsを活用したGitHubとGoogleのOAuth認証実装完全ガイド — スムーズなユーザーログインの実現方法

2024/06/11に公開

はじめに

これまでの記事でアカウント作成〜ログイン〜ログアウトまでの一連の処理を実装した後に、認証に関して運用上必要となる下記の機能について実装してきました。

  • メールアドレス存在有無の確認
  • パスワードリセット
  • 二要素認証

基本的には登録されたメールアドレスを本人確認するツールとしてトークンを渡しつつ、本人確認ができたのちに上記の処理を実施するという流れでした。実装パターンがある程度決まってはいるものの、それなりのコード量で一つずつ手元で実装された方からすると結構な時間と労力を要したかと思います。

自前で認証に関する機能を実装するとなるとやはりそれなりに時間がかかります。これから新しいサービスを立ち上げるケースなどでは自前で認証機能を実装するにはリソースが足りない場合が多いです。

そういったケースはOauthを活用して認証周りを外部サービスに任せるのが有効になってきます。
今回はGithub、Googleの認証基盤を活用しOauth認証を実装していきます。

※サービスが安定してきたら、メールアドレス/パスワードによる認証を実装しより多くのユーザーを獲得するとより良いかと思います。(ので、これまでご紹介してきた記事も意味がないわけではありませんのでご安心ください)

https://shinagawa-web.com/blogs/nextjs-login-email-password

今回のゴール

Github、Googleの認証基盤を活用しOauth認証でログインできるようにしていきます。

ログイン画面に設置したGithub、GoogleそれぞれのアイコンをクリックするとOAuth同意画面が表示され許可するとログイン済み状態となり設定画面に遷移できるようになります。

GitHubの場合

Image from Gyazo

Googleの場合

Image from Gyazo

OAuth認証について

実装に入る前に簡単にOauth認証についてご紹介しておきたいと思います。

OAuthは、オンラインサービス間で安全に「他のアプリケーションに一部の情報や機能へのアクセスを許可する仕組み」のことです。簡単に言うと、「あなたのアカウント情報を他のアプリに渡さずに、必要な許可だけを与えるための手続き」です。

たとえば、GitHubのアカウントを使って今回作成している認証チュートリアルウェブサービス(以下、認証チュートリアル)にログインしたいときに、OAuthでは、以下のような仕組みでこれを安全に行います。

  1. GitHubにログイン:認証チュートリアルにGitHubでログインする際、GitHubのログイン画面が表示されます。ここで、GitHubのパスワードを入力しますが、これは認証チュートリアル側では認識しません。

  2. 許可のリクエスト:認証チュートリアルからGithubでログインする際は、「〇〇の情報にアクセスしてもいいですか?」とGitHubにリクエストを送ります。この許可はあなたが設定する範囲で、例えば「プロフィール情報だけ」とか「リポジトリにアクセス」といった部分的なものです。

  3. あなたが許可するかどうか決める:GitHubは「このアプリが〇〇にアクセスしようとしていますが、許可しますか?」と確認します。ここで、アクセスしていいかどうかを自分で選択します。

  4. トークンを発行:もし許可すると、GitHubはそのサービスに「トークン」と呼ばれるキーを発行します。このトークンを使うことで、パスワードを直接渡さずにアクセスができるようになります。

  5. 認証チュートリアルがトークンを使ってアクセス:認証チュートリアルは、あなたのGitHubアカウントに対して、許可された範囲内で操作を行うことができます。トークンがあれば、パスワードなしで許可された操作ができるということです。

認証チュートリアル側の要件としてはあくまで今アクセスされている人は誰なのか?を特定したいだけなので、GithubでもGoogleでもMetaでもXでもなんでも大丈夫です。今回は実装が簡単なGithubとGoogleを使って実装していきます。

GitHub

OAuthアプリの作成

既にGitHubのアカウントをお持ちの方は下記URLにアクセスしOAuthアプリ作成を進めていきます。

https://github.com/settings/developers

GitHubの任意のページの右上にあるプロフィール写真をクリックし、「設定」をクリックします。
左のサイドバーで「開発者設定」をクリックします。
左のサイドバーで「OAuthアプリ」をクリックします。

Image from Gyazo

初めて訪れる方はまだここに何も作成されていないかと思います。

「New OAuth app」をクリックし作成していきます。

入力が必要な箇所は

  • Application name: 検証用とわかりやすくするため「nextjs-14-auth」
  • Homepage URL: Next.jsのトップページを指定します。
  • Authorization callback URL: GitHubからの認証後にユーザーがリダイレクトされるURLを指定します。

Image from Gyazo

OAuthアプリが作成できると下記のような画面が表示されるかと思います。

Image from Gyazo

環境変数にClient IDとClient secretsを設定します。

GITHUB_CLIENT_ID : Client ID
GITHUB_CLIENT_SECRET : Client secrets

GITHUB_CLIENT_ID=xxxxxxxxxxxxxxxxxxxxxxx
GITHUB_CLIENT_SECRET=xxxxxxxxxxxxxxxxxxxxxxxxxxxxx

続いてAuth.js側でGitHubをプロバイダーとして扱えるよう設定します。

auth.config.ts
+ import Github from 'next-auth/providers/github'

export default {
  providers: [
+     Github({
+       clientId: process.env.GITHUB_CLIENT_ID,
+       clientSecret: process.env.GITHUB_CLIENT_SECRET,
+     }),

このように設定することで、GihHubでのOAuth認証をユーザーが選択した際に今回作成したGitHubのOAuthアプリにリダイレクトされ、認証が通った後にAuth.jsとトークンの受け渡しができるようになります。

トークンの格納

トークンの受け渡しが可能になりましたらDBに格納するためにスキーマの準備を行います。

新しくAccountというモデルを作成し既に作成済みのUserと紐づけます。

model User {
  id            String    @id @default(cuid())
-   name          String
+   name          String?
-   email         String   @unique
+   email         String?   @unique
  emailVerified DateTime?
+   image         String?
-   password      String
+   password      String?
+   accounts      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])
+ }

Userモデルはこれまでメールアドレス/パスワードでの認証を前提としていたため、emailpasswordnameなどを必須扱いにしていました。

今回、GitHubによるOAuth認証を導入する場合はこれらの項目に値がセットされなくなるため必須扱いから任意に変更する必要があります。

詳しくはこちらのドキュメントもご参考ください。

https://authjs.dev/getting-started/adapters/prisma#configuration

スキーマの作成が完了しましたら下記コマンドで型の生成とDBの反映を行います。

npx prisma generate
npx prisma db push

画面の実装

最後にユーザーがGitHubのボタンを押す処理を実装します。

/components/auth/social.tsxファイルがそれに該当するのですがこちらは下記の記事でUIだけ作成済みでした。

https://shinagawa-web.com/blogs/nextjs-tailwind-shadcn-account-registration-form

social.tsx
+ import { signIn } from 'next-auth/react'
import { FaGithub } from 'react-icons/fa'
import { FcGoogle } from 'react-icons/fc'
import { Button } from '@/components/ui/button'
+ import { DEFAULT_LOGIN_REDIRECT } from '@/route'

export const Social = () => {
+   const onClick = (provider: 'google' | 'github') => {
+     signIn(provider, {
+       callbackUrl: DEFAULT_LOGIN_REDIRECT,
+     })
+   }
  return (
    <div className="flex w-full items-center gap-x-2">

(※一部省略)

      <Button
        size="lg"
        className="w-full"
        variant="outline"
+         onClick={() => onClick('github')}
      >
        <FaGithub className="size-5" />
      </Button>

GitHubのアイコンがついているボタンをクリックするとAuth.jsのsignIn処理が動きます。
GitHub、Googleのどちらかを受け取る前提で、認証が成功しトークンの受け渡しが終わった後にユーザーがアクセスするページをDEFAULT_LOGIN_REDIRECTとしています。

こちらは下記の記事で設定した値となっております。

http://localhost:3000/blogs/nextjs-middleware-auth-access-control

具体的にはhttp://localhost:3000/settingsを指しており、ログインしたユーザーが一番最初にアクセスする設定ページに遷移するよう設定しましています。

動作確認

ログイン画面からGitHubのアイコンをクリックすると、GitHubのOAuthアプリに遷移します。

「Authorize」(許可する)をクリックすると再びNext.js側に戻り設定画面に遷移します。

Image from Gyazo

npx prisma migrate reset

Google

GitHubでのOAuth認証が成功しましたらGoogleも同じような形で実装を進めていきます。

OAuthアプリの作成

まずはGoogle Cloud Platformで新しいプロジェクトを作成します。

https://console.cloud.google.com/welcome

Image from Gyazo

新しいプロジェクトの作成

Image from Gyazo

作成したプロジェクトを選択した後に、「APIs & Services」→「OAuth consent screen」の順にクリック。

Image from Gyazo

OAuth同意画面でUser TypeをExternalに設定。(Next.jsアプリケーションからの接続なのでGoogle Cloudから見ると外部アプリケーションという扱いになります)

Image from Gyazo

App nameとUser support emailの設定を行います。

App nameはGitHubの時と同様「nextjs-14-auth」とします。

Image from Gyazo

ここは特に設定なしで大丈夫です。

Image from Gyazo

Test usersの設定も今回は不要ですので、「SAVE AND CONTINUE」をクリックし作成します。

Image from Gyazo

下記の画面が表示されれば作成完了となります。

Image from Gyazo

同意画面が作成し終わりましたので次はOAuth client IDの発行を行います。

「CREATE CREDENTIALS」 -> 「OAuth client ID」を選択。

Image from Gyazo

下記を登録します。

Authorized JavaScript origins

http://localhost:3000

Authorized redirect URIs

http://localhost:3000/api/auth/callback/google

Image from Gyazo

OAuth client IDの発行が完了しましたらClient IDとClient Secretを確認します。

GitHubの時と同様、環境変数にClient IDとClient secretsを設定します。

GOOGLE_CLIENT_ID : Client ID
GOOGLE_CLIENT_SECRET : Client Secret

GOOGLE_CLIENT_ID=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
GOOGLE_CLIENT_SECRET=xxxxxxxxxxxxxxxxxxxxxxxxxxxx

続いてAuth.js側でGitHubをプロバイダーとして扱えるよう設定します。

auth.config.ts
import Github from 'next-auth/providers/github'
+ import Google from 'next-auth/providers/google'

export default {
  providers: [
    Github({
      clientId: process.env.GITHUB_CLIENT_ID,
      clientSecret: process.env.GITHUB_CLIENT_SECRET,
    }),
+     Google({
+       clientId: process.env.GOOGLE_CLIENT_ID,
+       clientSecret: process.env.GOOGLE_CLIENT_SECRET,
+     }),

このように設定することで、GoogleでのOAuth認証をユーザーが選択した際に今回作成したGoogleのOAuthアプリにリダイレクトされ、認証が通った後にAuth.jsとトークンの受け渡しができるようになります。

画面の実装

受け取ったトークンの格納するデータベースの設定はGitHubの設定の中で済ませていたのでGoogle側の設定をする際は不要となります。

残りはユーザーがGoogleアイコンのボタンを押す処理を実装します。

/components/auth/social.tsxファイルがそれに該当するのですがこちらは下記の記事でUIだけ作成済みでした。

https://shinagawa-web.com/blogs/nextjs-tailwind-shadcn-account-registration-form

social.tsx
import { signIn } from 'next-auth/react'
import { FaGithub } from 'react-icons/fa'
import { FcGoogle } from 'react-icons/fc'
import { Button } from '@/components/ui/button'
import { DEFAULT_LOGIN_REDIRECT } from '@/route'

export const Social = () => {
  const onClick = (provider: 'google' | 'github') => {
    signIn(provider, {
      callbackUrl: DEFAULT_LOGIN_REDIRECT,
    })
  }
  return (
    <div className="flex w-full items-center gap-x-2">
      <Button
        size="lg"
        className="w-full"
        variant="outline"
+         onClick={() => onClick('google')}
      >
        <FcGoogle className="size-5" />
      </Button>
      <Button
        size="lg"
        className="w-full"
        variant="outline"
        onClick={() => onClick('github')}
      >
        <FaGithub className="size-5" />
      </Button>
    </div>
  )

動作確認

ログイン画面からGoogleのアイコンをクリックすると、GoogleのOAuthアプリに遷移します。

「nextjs-14-authにログイン」で「次へ」をクリックすると再びNext.js側に戻り設定画面に遷移します。

Image from Gyazo

npx prisma migrate reset

さいごに

Github、Googleの認証基盤を活用しOauthアプリを作成しました。

その後、Next.jsアプリケーションと連携できる設定をしトークンを受け取った後データベースに格納する設定を行いOAuth認証の実装を行いました。

Github、Googleどちらもシンプルな設定で連携可能となっており実際に実装してみると意外と簡単だと思われたかと思います。

ユーザー管理に関わる部分を他サービスに任せることでユーザー管理で必要な様々な機能を実装せずサービスにより重要な機能に注力することが可能となります。

これらのサービスを有効活用し開発スピードの向上につながればと思います。

記事に関するお問い合わせ📝

記事の内容に関するご質問、ご意見などは、下記よりお気軽にお問い合わせください。
ご質問フォームへ

技術支援などお仕事に関するお問い合わせ📄

技術支援やお仕事のご依頼に関するお問い合わせは、下記よりお気軽にお問い合わせください。
お問い合わせフォームへ