【Next.js+Vercel】NextAuthでfacebookログインを実装する
自分の個人開発しているアプリでfacebookログインを実装するために試行錯誤しました。その実装方法をまとめます。
前提
開発環境のバージョンを以下の通りです。
ソフトウェア、アプリ | バージョン | 確認方法 |
---|---|---|
docker | Docker version 20.10.14 | コマンドで確認 |
Node | node:14.17.0 | Dockerfileで確認 |
Next.js | "next": "12.1.4" | package.json |
yarn | "yarn": "1.22.5” | yarn -v で確認 |
typescript | "typescript": "4.6.3" | package.json |
実装手順
実装は以下の手順で行い、解説していきます。
- facebookのアプリを作成する
- next-authでfacebookログインを実装する
- vercelにデプロイする
- facebookのアプリにredirect_urlを設定する
facebookのアプリを作成する
facebookログインを実現するにはfacebookの中にアプリとして自分のWEBアプリを登録する必要があります。
↓ここからfacebookアプリを作成できます。
facebookのアプリ作成は画面の指示に従えば、特に詰まることはないです。今回は「生活者(Consumer)」を選択します。
これで一旦、facebookのアプリの作成は完了です。
NextAuthでfacebookログインを実装する
facebookログインを実現するために、Next.jsのライブラリであるNextAuth.jsを使います。
next-authをインストールする
next-authをyarnで追加します。npmを使っている人は適宜読み替えてください。
yarn add next-auth
こんなエラーがvscodeに表示されるかもしれません。
【Next.js】Parsing error: Cannot find module 'next/babel'
その時はこの記事の方法で対応することができます。
NextAuthのファイルを作成する
続いて公式のドキュメントに沿って、pages以下にファイルを作っていきます。
[...nextauth].jsでNextAuth.jsの主な設定を記述します。
公式の今回はデフォルトのまま使っています。
import NextAuth from "next-auth";
import FacebookProvider from "next-auth/providers/facebook";
export default NextAuth({
providers: [
FacebookProvider({
clientId: process.env.NEXT_PUBLIC_FACEBOOK_CLIENT_ID,
clientSecret: process.env.NEXT_PUBLIC_FACEBOOK_CLIENT_SECRET
})
],
secret: process.env.NEXT_PUBLIC_NEXTAUTH_SECRET,
callbacks: {
async jwt({ token, account }) {
if (account) {
token.accessToken = account.access_token
}
return token
},
async session({ session, token, user }) {
session.accessToken = token.accessToken
return session
},
async signIn({ user, account, profile, email, credentials }) {
return true
},
},
pages: {
// signIn: '/auth/signin',
// signOut: '/auth/signout',
}
})
SSRをする場合は↓このファイルも必要になります。
import authOptions from './auth/[...nextauth]';
import { unstable_getServerSession } from "next-auth/next";
export default async (req, res) => {
const session = await unstable_getServerSession(req, res, authOptions)
if (session) {
res.send({
content:
"This is protected content. You can access this content because you are signed in.",
})
} else {
res.send({
error: "You must be sign in to view the protected content on this page.",
})
}
}
ログイン処理を実装する
ここまででNextAuthを使う準備は整いました。次にログイン処理を実装していきます。
NextAuthのsignInメソッドは適当なところで実行すれば、Providerに合わせて適当に処理をしてくれます。今回はfacebookをログインをするため[...nextauth].jsでFacebookをProviderとして指定しています。
実装についてはコンポーネントから直接onClickイベントを検知して、signInメソッドを実行してもいいですし、コンポーネントを作ってイベントを子コンポーネントから検知して実行する方法でもOKです。
今回はsingnInメソッドを予め作っておいたLoginFormコンポーネントのイベントをキャッチしてsignInメソッドを実行します。
また、signInメソッドにはcallbackUrlを設定することができ、signInに成功したら別のページに遷移させることができます。
// signInをclickNewUserButtonのメソッドとして実装
const clickNewUserButton = () => {
signIn(undefined, {callbackUrl: '/auth/signInSuccsess'});
}
// onClickNewUserButtonのイベントを検知して、clickNewUserButtonを発火させる
<LoginForm
session={session}
nextAuthStatus={status}
onClickNewUserButton={() => {clickNewUserButton()}}
/>
Vercelにデプロイする
今回のNext.jsのアプリはVercelにホストすることを想定しています。
VercelでNextAuthを実行するのには少しコツがいるので、それについて解説します。
Vercelの環境変数をセットする
Vercel上のアプリがNextAuthを使う場合、NextAuth自体が意図したものであることを保証するためにNextAuthにsecretをセットする必要があります。
今回はVercelの環境変数を使って、このsecretをセットします。
このsecretは適当なランダムな文字列でOKです。
そのため [...nextauth].jsでNextAuthのオブジェクトの中のsecretにprocess.env.NEXT_PUBLIC_NEXTAUTH_SECRET を宣言しています。
import NextAuth from "next-auth";
import FacebookProvider from "next-auth/providers/facebook";
export default NextAuth({
providers: [
FacebookProvider({
clientId: process.env.NEXT_PUBLIC_FACEBOOK_CLIENT_ID,
clientSecret: process.env.NEXT_PUBLIC_FACEBOOK_CLIENT_SECRET
})
],
secret: process.env.NEXT_PUBLIC_NEXTAUTH_SECRET,
callbacks: {
async jwt({ token, account }) {
if (account) {
token.accessToken = account.access_token
}
return token
},
async session({ session, token, user }) {
session.accessToken = token.accessToken
return session
},
async signIn({ user, account, profile, email, credentials }) {
return true
},
},
pages: {
// signIn: '/auth/signin',
// signOut: '/auth/signout',
}
})
NEXT_PUBLIC_NEXTAUTH_SECRET に環境変数でNextAuthのシークレットをセットします。
今回は公式にあるコマンドから実行して、vercelの環境変数にセットします。
↓シークレットを生成するコマンドです。
$ openssl rand -base64 32
facebookのredirect_urlをセットする
ローカル環境ではfacebookログインはうまくいきます。しかしVercelにホストするとFacebook側でブロックされうまくいきません。
Vercel上のアプリからfacebookログインを実現するには、facebookのアプリの設定でfacebookログインを許可するURLを設定しておく必要があります。
Vercelではブランチごとにドメインがアサインされるので、developブランチや必要なブランチのドメインをfacebookアプリのURLにセットします。
具体的には以下のようなURLになります。
// hogehogeというプロジェクト名だった場合
https://hogehoge.vercel.app/
https://hogehoge.vercel.app/api/auth/callback/facebook
以上でVercelにホストしたアプリからfacebookログインが可能になります。
宣伝
カフェインレスコーヒーを集めたサイトを運営しています。
カフェインレスコーヒーを集めたサイトを作っています。カフェインレスコーヒーは夜に飲んでもぐっすり眠れるので、エンジニアの人にも試してみてほしいな、と思い作りました。よければのぞいてみてください。
これから色々と機能を追加していく予定です。
(初期ロード時に15秒くらいかかることがあります)
参考・補足
NextAuthのバグ?
callback_urlをスラッシュを指定するとアンダースコア、シャープ、イコールがついたURLに遷移させられる。
バグ?なのかもしれない?
Discussion