はじめに
これまでの記事でアカウント作成〜ログイン〜ログアウトまでの一連の処理を実装した後に、認証に関して運用上必要となる下記の機能について実装してきました。
- メールアドレス存在有無の確認
- パスワードリセット
- 二要素認証
基本的には登録されたメールアドレスを本人確認するツールとしてトークンを渡しつつ、本人確認ができたのちに上記の処理を実施するという流れでした。実装パターンがある程度決まってはいるものの、それなりのコード量で一つずつ手元で実装された方からすると結構な時間と労力を要したかと思います。
自前で認証に関する機能を実装するとなるとやはりそれなりに時間がかかります。これから新しいサービスを立ち上げるケースなどでは自前で認証機能を実装するにはリソースが足りない場合が多いです。
そういったケースはOauthを活用して認証周りを外部サービスに任せるのが有効になってきます。
今回はGithub、Googleの認証基盤を活用しOauth認証を実装していきます。
※サービスが安定してきたら、メールアドレス/パスワードによる認証を実装しより多くのユーザーを獲得するとより良いかと思います。(ので、これまでご紹介してきた記事も意味がないわけではありませんのでご安心ください)
今回のゴール
Github、Googleの認証基盤を活用しOauth認証でログインできるようにしていきます。
ログイン画面に設置したGithub、GoogleそれぞれのアイコンをクリックするとOAuth同意画面が表示され許可するとログイン済み状態となり設定画面に遷移できるようになります。
GitHubの場合
Googleの場合
OAuth認証について
実装に入る前に簡単にOauth認証についてご紹介しておきたいと思います。
OAuthは、オンラインサービス間で安全に「他のアプリケーションに一部の情報や機能へのアクセスを許可する仕組み」のことです。簡単に言うと、「あなたのアカウント情報を他のアプリに渡さずに、必要な許可だけを与えるための手続き」です。
たとえば、GitHubのアカウントを使って今回作成している認証チュートリアルウェブサービス(以下、認証チュートリアル)にログインしたいときに、OAuthでは、以下のような仕組みでこれを安全に行います。
-
GitHubにログイン:認証チュートリアルにGitHubでログインする際、GitHubのログイン画面が表示されます。ここで、GitHubのパスワードを入力しますが、これは認証チュートリアル側では認識しません。
-
許可のリクエスト:認証チュートリアルからGithubでログインする際は、「〇〇の情報にアクセスしてもいいですか?」とGitHubにリクエストを送ります。この許可はあなたが設定する範囲で、例えば「プロフィール情報だけ」とか「リポジトリにアクセス」といった部分的なものです。
-
あなたが許可するかどうか決める:GitHubは「このアプリが〇〇にアクセスしようとしていますが、許可しますか?」と確認します。ここで、アクセスしていいかどうかを自分で選択します。
-
トークンを発行:もし許可すると、GitHubはそのサービスに「トークン」と呼ばれるキーを発行します。このトークンを使うことで、パスワードを直接渡さずにアクセスができるようになります。
-
認証チュートリアルがトークンを使ってアクセス:認証チュートリアルは、あなたのGitHubアカウントに対して、許可された範囲内で操作を行うことができます。トークンがあれば、パスワードなしで許可された操作ができるということです。
認証チュートリアル側の要件としてはあくまで今アクセスされている人は誰なのか?を特定したいだけなので、GithubでもGoogleでもMetaでもXでもなんでも大丈夫です。今回は実装が簡単なGithubとGoogleを使って実装していきます。
GitHub
OAuthアプリの作成
既にGitHubのアカウントをお持ちの方は下記URLにアクセスしOAuthアプリ作成を進めていきます。
GitHubの任意のページの右上にあるプロフィール写真をクリックし、「設定」をクリックします。
左のサイドバーで「開発者設定」をクリックします。
左のサイドバーで「OAuthアプリ」をクリックします。
初めて訪れる方はまだここに何も作成されていないかと思います。
「New OAuth app」をクリックし作成していきます。
入力が必要な箇所は
- Application name: 検証用とわかりやすくするため「nextjs-14-auth」
- Homepage URL: Next.jsのトップページを指定します。
- Authorization callback URL: GitHubからの認証後にユーザーがリダイレクトされるURLを指定します。
OAuthアプリが作成できると下記のような画面が表示されるかと思います。
環境変数に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をプロバイダーとして扱えるよう設定します。
+ 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
モデルはこれまでメールアドレス/パスワードでの認証を前提としていたため、email
やpassword
、name
などを必須扱いにしていました。
今回、GitHub
によるOAuth認証を導入する場合はこれらの項目に値がセットされなくなるため必須扱いから任意に変更する必要があります。
詳しくはこちらのドキュメントもご参考ください。
スキーマの作成が完了しましたら下記コマンドで型の生成とDBの反映を行います。
npx prisma generate
npx prisma db push
画面の実装
最後にユーザーがGitHubのボタンを押す処理を実装します。
/components/auth/social.tsx
ファイルがそれに該当するのですがこちらは下記の記事でUIだけ作成済みでした。
+ 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/settings
を指しており、ログインしたユーザーが一番最初にアクセスする設定ページに遷移するよう設定しましています。
動作確認
ログイン画面からGitHubのアイコンをクリックすると、GitHubのOAuthアプリに遷移します。
「Authorize」(許可する)をクリックすると再びNext.js側に戻り設定画面に遷移します。
npx prisma migrate reset
GitHubでのOAuth認証が成功しましたらGoogleも同じような形で実装を進めていきます。
OAuthアプリの作成
まずはGoogle Cloud Platformで新しいプロジェクトを作成します。
新しいプロジェクトの作成
作成したプロジェクトを選択した後に、「APIs & Services」→「OAuth consent screen」の順にクリック。
OAuth同意画面でUser TypeをExternalに設定。(Next.jsアプリケーションからの接続なのでGoogle Cloudから見ると外部アプリケーションという扱いになります)
App nameとUser support emailの設定を行います。
App nameはGitHubの時と同様「nextjs-14-auth」とします。
ここは特に設定なしで大丈夫です。
Test usersの設定も今回は不要ですので、「SAVE AND CONTINUE」をクリックし作成します。
下記の画面が表示されれば作成完了となります。
同意画面が作成し終わりましたので次はOAuth client IDの発行を行います。
「CREATE CREDENTIALS」 -> 「OAuth client ID」を選択。
下記を登録します。
Authorized JavaScript origins
http://localhost:3000
Authorized redirect URIs
http://localhost:3000/api/auth/callback/google
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をプロバイダーとして扱えるよう設定します。
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だけ作成済みでした。
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側に戻り設定画面に遷移します。
npx prisma migrate reset
さいごに
Github、Googleの認証基盤を活用しOauthアプリを作成しました。
その後、Next.jsアプリケーションと連携できる設定をしトークンを受け取った後データベースに格納する設定を行いOAuth認証の実装を行いました。
Github、Googleどちらもシンプルな設定で連携可能となっており実際に実装してみると意外と簡単だと思われたかと思います。
ユーザー管理に関わる部分を他サービスに任せることでユーザー管理で必要な様々な機能を実装せずサービスにより重要な機能に注力することが可能となります。
これらのサービスを有効活用し開発スピードの向上につながればと思います。
関連記事
- Next.jsとAuth.jsで認証機能を実装するチュートリアル
2024/09/13 - Next.jsでのメール認証処理の実装ガイド:アカウント登録からトークン検証まで
2024/05/10 - Next.jsでのメール認証処理の実装ガイド:トークン検証からログイン画面へのリダイレクト処理までの詳細解説
2024/05/13 - Next.jsでログイン画面を作ってメールアドレス/パスワードでログインできるようにする
2024/02/27 - Next.jsとmicroCMSで作るブログ:ヘッドレスCMSによるコンテンツ管理と表示
2024/12/16 - Next.js と Auth.js を使ったログイン状態に応じたアクセス制御の実装
2024/03/02 - ユーザー向けパスワードリセット機能の実装方法:トークン発行からメール送信、セキュリティ対策まで
2024/04/20 - ユーザー向けパスワードリセット機能の実装方法:トークン認証から新しいパスワードの設定まで
2024/04/22