はじめに
認証基盤といえば手軽に使えるAuth0が好きですが、会社の状況によっては使えないことがあると思います。
NextAuthを使いつつ、色々なIdPを試してみようと思いますが、今回はナレッジが少なそうなAzureAD B2Cを試してみようと思います。
まずはいつもの
yarn create next-app --typescript
をします。
プロジェクトのディレクトリに移動し、
yarn add -D next-auth
します。
Azure AD B2Cの設定
docs.microsoft.com
docs.microsoft.com
docs.microsoft.com
をもとに設定します。設定するときに次の設定はどこかにコピペしておくようにします。
- テナント(場所によってはディレクトリと表現)作成時に入力する、テナント名(場所によっては組織名と表現)
- 登録したアプリのアプリケーション名(Azureによって採番された、a90abcd...のようなuuid形式のようなID)
- 登録したアプリに対するクライアントシークレットの値
- ユーザーフローの名前
アプリのリダイレクトURIは次の値を設定します。
https://jwt.ms
http://localhost:3000/api/auth/callback/azure-ad-b2c
https://<本番環境のドメイン>/api/auth/callback/azure-ad-b2c
ユーザーフローの「ユーザー属性とトークン要求」では次のように設定します。
.env.localの設定
AZURE_AD_B2C_TENANT_NAME=<テナント名>
AZURE_AD_B2C_CLIENT_ID=<アプリケーション名>
AZURE_AD_B2C_CLIENT_SECRET=<クライアントシークレットの値>
AZURE_AD_B2C_PRIMARY_USER_FLOW=<ユーザーフローの名前>
NEXTAUTH_SECRET=<任意のランダム文字列>
公式ドキュメントで紹介されていますが、NEXTAUTH_SECRET
は openssl rand -base64 32
コマンドで作ると良さそうです。
Options | NextAuth.js
Providerの設定
ドキュメントをもとに次のようなファイルを作成しました。
import AzureADB2CProvider from "next-auth/providers/azure-ad-b2c"
import NextAuth from 'next-auth'
export default NextAuth({
providers: [
AzureADB2CProvider({
tenantId: process.env.AZURE_AD_B2C_TENANT_NAME,
clientId: process.env.AZURE_AD_B2C_CLIENT_ID,
clientSecret: process.env.AZURE_AD_B2C_CLIENT_SECRET,
primaryUserFlow: process.env.AZURE_AD_B2C_PRIMARY_USER_FLOW,
authorization: { params: { scope: "offline_access openid" } },
}),
]
})
IDEで次のようなwarningが表示されました。
process.env.AZURE_AD_B2C_TENANT_NAME
は string | undefined
であることにかかわらず、providerのオプションの tenantId
が string
になっているせいで発生しています。
process.env.AZURE_AD_B2C_TENANT_NAME
が設定されていないときにアプリは起動したくないので、起動時にチェックすることで、tenantId
としては必ず string
が渡されるようにします。
起動時のチェックは、次の記事を参考にしました。
zenn.dev
結果、次のような実装になります。
import AzureADB2CProvider from "next-auth/providers/azure-ad-b2c"
import NextAuth from 'next-auth'
if (!process.env.AZURE_AD_B2C_TENANT_NAME || !process.env.AZURE_AD_B2C_CLIENT_ID || !process.env.AZURE_AD_B2C_CLIENT_SECRET || !process.env.AZURE_AD_B2C_PRIMARY_USER_FLOW) {
console.error('Azure AD B2Cの環境変数が設定されていません!')
process.exit()
}
export default NextAuth({
providers: [
AzureADB2CProvider({
tenantId: process.env.AZURE_AD_B2C_TENANT_NAME,
clientId: process.env.AZURE_AD_B2C_CLIENT_ID,
clientSecret: process.env.AZURE_AD_B2C_CLIENT_SECRET,
primaryUserFlow: process.env.AZURE_AD_B2C_PRIMARY_USER_FLOW,
authorization: { params: { scope: "offline_access openid" } },
}),
]
})
認証をmiddlewareで実装する
Next.jsで最近追加されたmiddlewareで認証を実装します。
nextjs.org
export { default } from "next-auth/middleware"
これだけです!
トップページでユーザー名を表示できるようにする
_app.tsx
で SessionProvider
コンポーネントを追加します。
import '../styles/globals.css'
import type { AppProps } from 'next/app'
import { SessionProvider } from 'next-auth/react'
function MyApp({ Component, pageProps }: AppProps) {
return (
<SessionProvider>
<Component {...pageProps} />
</SessionProvider>
)
}
export default MyApp
トップページで表示名を表示するようにします。
import type { NextPage } from 'next'
import styles from '../styles/Home.module.css'
import { useSession } from 'next-auth/react'
const Home: NextPage = () => {
const { data: session, status } = useSession()
if (status === 'loading') {
return (
<div className={styles.container}>
<main className={styles.main}>
<h1 className={styles.title}>
読み込み中
</h1>
</main>
</div>
)
}
if (status === 'unauthenticated') {
return (
<div className={styles.container}>
<main className={styles.main}>
認証に失敗しました
</main>
</div>
)
}
return (
<div className={styles.container}>
<main className={styles.main}>
<h1 className={styles.title}>
Welcome {session?.user?.name}!!
</h1>
</main>
</div>
)
}
export default Home
動作確認
next dev
で起動し、 http://localhost:3000
にアクセスしてみると、、
サインイン用の画面が出ました!
(Providerが一つしかないのは、もの寂しいですね、、)
ボタンをクリックするとサインイン画面が表示されます
「Sign up now」からユーザーを作ってサインインします。
(うまくいかないときは他のログインが残っていることがあるので、シークレットブラウザで試すといいかも)
サインインできました!!
おわりに
今回、デフォルトの設定に従って、プロバイダの選択画面とAzure AD B2Cサインイン画面を表示していましたが、next-auth/react
の signIn
関数を呼び出すことによって、この画面(プロバイダの選択画面)をスキップするという技もあります。
github.com
普通に使えますが、標準でデフォルトのプロバイダが選べるようになるといいなと、思います。
github.com
あと、個人的にはAzureの独特の日本語に苦しめられました。。笑
今回のコードのリポジトリはこちらです。
github.com