nextjsでも簡単にauth0を使いたい!
と思ってサンプルに従うと、Dockerビルドってかproduction buildするとエラーで落ちちゃいます。
configのサンプル
auth0/nextjs-auth0: Next.js SDK for signing in with Auth0 (Experimental) - https://github.com/auth0/nextjs-auth0#runtime-configuration
import { initAuth0 } from '@auth0/nextjs-auth0';
import config from './config';
export default initAuth0({
domain: process.env.AUTHO_DOMAIN,
clientId: process.env.AUTHO_DOMAIN,
clientSecret: process.env.APP_SECRRET,
scope: 'openid profile',
エラー内容こんな感じ。process.env.XXXが見れないから落ちてるのかな。
Automatically optimizing pages...
> Build error occurred
Error: A valid Auth0 Domain must be provided
at Object.createInstance [as default] (/usr/src/app/node_modules/@auth0/nextjs-auth0/dist/instance.node.js:10:15)
at initAuth0 (/usr/src/app/node_modules/@auth0/nextjs-auth0/dist/index.js:8:46)
at Object.xMDF (/usr/src/app/.next/server/static/GDDYxjIWKG2mlWWc4bTrE/pages/_app.js:781:127)
at __webpack_require__ (/usr/src/app/.next/server/static/GDDYxjIWKG2mlWWc4bTrE/pages/_app.js:23:31)
at Module.1TCz (/usr/src/app/.next/server/static/GDDYxjIWKG2mlWWc4bTrE/pages/_app.js:147:13)
at __webpack_require__ (/usr/src/app/.next/server/static/GDDYxjIWKG2mlWWc4bTrE/pages/_app.js:23:31)
at Object.0 (/usr/src/app/.next/server/static/GDDYxjIWKG2mlWWc4bTrE/pages/_app.js:99:18)
at __webpack_require__ (/usr/src/app/.next/server/static/GDDYxjIWKG2mlWWc4bTrE/pages/_app.js:23:31)
at /usr/src/app/.next/server/static/GDDYxjIWKG2mlWWc4bTrE/pages/_app.js:91:18
at Object.<anonymous> (/usr/src/app/.next/server/static/GDDYxjIWKG2mlWWc4bTrE/pages/_app.js:94:10)
error Command failed with exit code 1
ボツ案
issue投げて聞いてみたら、 .env
を仮データで追加し実行時に再ビルドすると大丈夫らしい。試したらできた。
Can't build on docker. · Issue #86 · auth0/nextjs-auth0 - https://github.com/auth0/nextjs-auth0/issues/86
FROM node:14 as builder
WORKDIR /app
COPY .env.template .env
COPY package.json yarn.lock ./
RUN yarn install
COPY . .
RUN yarn build
# ------------------
FROM node:14-alpine as release
WORKDIR /app
COPY --from=builder /app/package.json /app/yarn.lock ./
RUN yarn install
COPY --from=builder /app/.next ./.next
COPY . .
EXPOSE 3000
CMD ["yarn", "start:build"]
"scripts": {
"start": "next start",
"start:build": "yarn build && yarn start",
"build": "next build",
確かにできるんだけど、CI時にビルド2回ぐらい回しちゃうことになって、めっちゃ時間かかる・・・
改善案
initAuth0のオブジェクトを直接export defaultすると、環境変数がバインドされちゃうので、関数にしてあとからprocess.envを評価すればいいじゃんって案
Document best practices for using nextjs-auth0 with a nextjs production build. · Issue #154 · auth0/nextjs-auth0 - https://github.com/auth0/nextjs-auth0/issues/154
環境変数はgetConfig()経由で受け取り、バインドすると想定通り動いてくれた。やったね!
import getConfig from 'next/config';
import { initAuth0 } from '@auth0/nextjs-auth0';
const { serverRuntimeConfig, publicRuntimeConfig } = getConfig();
let auth0 = null;
const proc = () => {
if (!auth0) {
auth0 = initAuth0({
clientId: publicRuntimeConfig.auth0.clientId,
domain: publicRuntimeConfig.auth0.domain,
scope: 'openid email profile',
postLogoutRedirectUri: publicRuntimeConfig.baseUrl,
redirectUri: `${publicRuntimeConfig.baseUrl}/api/auth/signed-in`,
clientSecret: serverRuntimeConfig?.auth0?.secret ?? '',
session: {
cookieSecret: serverRuntimeConfig?.appSecret ?? '',
// Set to 8 hours
cookieLifetime: 60 * 60 * 8,
storeIdToken: false,
storeAccessToken: false,
storeRefreshToken: false,
},
oidcClient: {
// Optionally configure the timeout in milliseconds for HTTP requests to Auth0.
httpTimeout: 2500,
// Optionally configure the clock tolerance in milliseconds, if the time on your server is running behind.
clockTolerance: 10000,
},
});
}
return auth0;
};
export default proc;
const nextConfig = {
serverRuntimeConfig: {
appSecret: process.env.APP_SECRET,
auth0: {
secret: process.env.AUTH0_CLIENT_SECRET,
},
},
publicRuntimeConfig: {
baseUrl: process.env.NEXT_PUBLIC_BASE_URL,
auth0: {
clientId: process.env.NEXT_PUBLIC_AUTH0_CLIENT_ID,
domain: process.env.NEXT_PUBLIC_AUTH0_DOMAIN,
},
},
};
module.exports = nextConfig;
diff --git a/pages/api/auth/sign-in.js b/pages/api/auth/sign-in.js
index 7b109a7..d271932 100644
--- a/pages/api/auth/sign-in.js
+++ b/pages/api/auth/sign-in.js
@@ -1,6 +1,8 @@
-import auth0 from '../../../src/lib/auth0';
+import Auth0 from '../../../src/lib/auth0';
import { checkHeaders } from '../../../src/lib/middleware/auth';
+const auth0 = Auth0();
+
const login = checkHeaders(async (req, res) => {
try {
await auth0.handleLogin(req, res);