Next.jsで、認証のプラットフォームにAuth0を用いる際のメモ。概ねここに書いてあるのだが…自分用の備忘録として。なお、Auth0はFreeでもいいのでなんらか既にアカウントを持っていることを前提とする。
Auth0 - Create Application
「Regular Web Applications」を選ぶ。Next.jsだと「Single Web Applications」とか選びたくなるが、それではない。
Auth0 - Settingsタブ
- 「Application URLs」のコーナーにおいて、「Allowed Callback URLs」に
http://localhost:3000/api/auth/callback
をいれる。これはローカルでNext.js立ち上げたときのコールバックURL。ポートはデフォの3000にしてるけど環境によって変えてる場合は要変更。他環境の分いれるときは、カンマ(,
)区切りでこの後URLを続けて書いていく。間にスペースとかは特に不要。基本的に、各URLの末尾に/api/auth/callback
入れとけばよい。 - 「Allowed Logout URLs」に
http://localhost:3000/
をいれる。これもローカルでNext.js立ち上げたときのコールバックURL。ポート変えてる場合は同様にポート要変更。上と同じようにカンマ(,
)区切りで複数のURLを指定できる。各URLのルートにあたるパス/
を指定しておけばとりあえずOKらしい
環境変数の準備
- ローカルだと
.env.local
をつくって以下のような内容を書き込めばよい。どういう値にすればいいとかそういう細かい話はGitHubで説明されている。ただ、Auth0でアプリケーション作ったあと、「Quick Start」タブの「Configure the SDK」っていう場所にほぼそのままコピペ可能な内容で(つくったアプリケーションのClient IDやClient Secret等がそのまま.env
の形式で使用できる形で)載ってるので、それこのままコピペしたほうが良い。(画像参照) - GitHubにも書いてあるが、唯一
AUTH0_SECRET
だけは自分で用意しなければならない。コマンドは指示されていて、openssl rand -hex 32
を実行して出力された値をコピって貼り付ければよいだけである。
/pages/api/auth/[...auth0].js
- 各プロジェクトに
/pages/api/auth/[...auth0].js
というファイルを用意する。内容のサンプルはAuth0がGitHubに載せている。超スッキリしてるけどこれだけで認証部分は動く。一応。 - ただ逆に言うとこれは「最低限の動作」をするようにしか書かれていないので、これだけだとあんまりイケてなかったりする。例えばログインした直後に同じページにまた戻ってくるので、「ログイン後にポータル(的な)画面に遷移させたいなあ」とか、そういうもうちょっと複雑な動きさせたいなーとか思ったらこれに少し手を加える必要がある。これは
handleLogin
でreturnTo
にパスを指定することで実現できる。(参考)こんなかんじ↓/pages/api/auth/[...auth0].jsimport { handleAuth , handleLogin, handleLogout } from '@auth0/nextjs-auth0'; export default handleAuth({ async login(req, res) { await handleLogin(req, res, { returnTo: "/portal", authorizationParams: { scope: 'openid profile email read:products', } }); }, async logout(req,res) { await handleLogout(req,res , { returnTo: '/', }); }, });
ログイン判定
@auth0/nextjs-auth0/client
からuseUser
をimportして、user
オブジェクトの有無で切り分けできる。各画面でやるっていうよりは、共通のコンポーネント(Layoutとか)に仕込んでおいて、どの画面でも未ログインだったりセッション切れてたらログイン促すような感じにしておいた方がいいのではないかと思う。(私は個人的にそうやってます)なお、ログインは/api/auth/login
にリンクさせれば、(環境変数や/pages/api/auth/[...auth0].js
がちゃんと整備されている前提であれば)それでそのままAuth0のログイン画面に飛んでいく。ので、user
オブジェクトがNullの場合は、Link
でも用意してここに遷移させればいい。こんなかんじ↓
import { useUser } from '@auth0/nextjs-auth0/client';
import { ReactNode } from "react";
type Props = {
children?: ReactNode;
};
const Layout = ({ children }: Props) => {
const { user, error, isLoading } = useUser();
return (
<>
{user ? <div>
<p>こんにちは {user.email}</p>
{children}
</div>
: <div>
<Link href="/api/auth/login">
ログインする
</Link>
</div>
}
</>
);
};
export default Layout;
ログインが必要なAPI
ログイン後の画面操作でAPIを呼び出す際に、「ログインしていること」を前提とするAPIを作りたいときは、@auth0/nextjs-auth0
からwithApiAuthRequired
というfunctionをimportして、これでfunctionをラップする。(参考)こんなかんじ↓
import type { NextApiRequest , NextApiResponse } from 'next';
import { withApiAuthRequired, } from '@auth0/nextjs-auth0';
const authApiTest = withApiAuthRequired(function api (req: NextApiRequest, res: NextApiResponse){
const test = String(req.query.test);
res.status(200).json({text: test});
});
export default authApiTest;
このAPIをログインしないで叩くと以下のようなレスポンスが返ってくる。HTTP statusは401 Unauthorized
。
{"error":"not_authenticated","description":"The user does not have an active session or is not authenticated"}
環境
"@auth0/nextjs-auth0": "^2.3.1",
"next": "13.2.4",
"react": "18.2.0",
"react-dom": "18.2.0",
"typescript": "5.0.2"