nodeops-auth について
nodeops-authは、既存のNext.js App RouterプロジェクトにNodeOps PKCE OAuthを追加するセットアップスキルです。プロジェクト構成を確認し、必要なルートやコールバックページ、環境設定を作成します。完了済みの作業はスキップします。
主な機能
- 01Next.jsとApp Routerの検出
- 02パッケージマネージャーに応じたOAuthパッケージの導入
- 03認証APIルートとコールバックページの作成
- 04ルートレイアウトへのAuthProvider追加
- 05環境変数と除外ルールの管理
- 06Dockerデプロイ設定の確認
活用シーン
- 01既存のNext.jsアプリへのNodeOpsログイン追加
- 02OAuthコールバック用リダイレクトページの設定
- 03コンテナデプロイ時のビルド環境変数の確認
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ nodeops-app/ skills --skill nodeops-authインストール後、Claude Code で/nodeops-authを入力して読み込まれたか確認します。
詳細
NodeOps 認証の設定
既存の Next.js(App Router)プロジェクトに NodeOps PKCE OAuth を追加します。
前提条件
作業を開始する前に、プロジェクトに互換性があることを確認してください。
- App Router が必要です:
app/ディレクトリがあるか確認します。pages/だけが存在する場合は作業を中止し、ユーザーに「このスキルは Next.js App Router のみをサポートしています。プロジェクトでは Pages Router が使用されています。」と伝えてください。 - Next.js が必要です:
package.jsonの依存関係にnextがあるか確認します。なければ作業を中止し、このパッケージは Next.js 専用であることをユーザーに伝えてください。
冪等性
各ステップの前に、作業がすでに完了しているか確認してください。完了済みのステップはスキップします。
@nodeops-createos/integration-oauthがすでにpackage.jsonの依存関係にある場合は、インストールをスキップします。app/api/auth/me/route.tsとapp/api/auth/token/route.tsがすでに存在する場合は、ルートの作成をスキップします。@nodeops-createos/integration-oauthのAuthProviderがすでにレイアウトでインポートされている場合は、ラップをスキップします。app/callback/page.tsx(または.jsx)がすでに存在する場合は、コールバックページの作成をスキップします。.env.exampleがすでに存在し、NODEOPS_を含む場合は、環境変数ファイルの作成をスキップします。
手順
-
プロジェクトの設定を確認する —
package.jsonを読み込み、ロックファイルを確認します。- パッケージマネージャー:
pnpm-lock.yamlがあれば pnpm、yarn.lockがあれば yarn、それ以外は npm - TypeScript:
tsconfig.jsonがあれば.ts/.tsx拡張子を使用し、なければ.js/.jsxを使用します。 app/ディレクトリ(App Router)があることを確認します。pages/だけが存在する場合は作業を中止します。- 依存関係に
nextがあることを確認します。なければ作業を中止します。
- パッケージマネージャー:
-
パッケージをインストールする — 適切なインストールコマンドを実行します。
- npm:
npm install @nodeops-createos/integration-oauth - pnpm:
pnpm add @nodeops-createos/integration-oauth - yarn:
yarn add @nodeops-createos/integration-oauth - インストールに失敗した場合:ユーザーがネットワークにアクセスできるか、レジストリに到達できるか確認します。失敗が続く場合は、コマンドを手動で実行するよう提案してください。
- npm:
-
API ルートを作成する — 必要に応じてディレクトリを作成し、2 つのルートファイルを個別に作成します。
app/api/auth/me/route.ts(または.js):export { GET } from '@nodeops-createos/integration-oauth/server/me';app/api/auth/token/route.ts(または.js):export { POST } from '@nodeops-createos/integration-oauth/server/token'; -
レイアウトを AuthProvider でラップする — ルートレイアウトファイルを読み込みます。
app/layout.tsx、app/layout.jsx、app/layout.js、app/layout.tsのいずれかです。存在するファイルを確認してください。- ファイルの先頭にインポートを追加します。
import { AuthProvider } from '@nodeops-createos/integration-oauth'; <body>タグ内の{children}を探し、<AuthProvider>でラップします。<AuthProvider>{children}</AuthProvider>- レイアウトに「use client」を追加しないでください。
AuthProviderは内部ですでに"use client"として設定されているため、Server Component のレイアウトからインポートしても問題なく動作します。 - レイアウトにほかのプロバイダーがすでにある場合(例:ThemeProvider、QueryClientProvider)は、それらと並べて
<AuthProvider>をネストします。既存のプロバイダーを削除または置き換えないでください。 {children}が<body>の直下にない場合(例:ラッパーの div やフラグメント内にある場合)は、{children}がある場所でラップします。- レイアウトファイルがない場合は作業を中止し、先にルートレイアウトを作成するようユーザーに伝えてください。
- ファイルの先頭にインポートを追加します。
-
コールバックページを作成する — ログイン後にユーザーをどこへリダイレクトするか尋ねます。「(デフォルト:/dashboard)」。回答を
redirectToの値として使用します。その後、app/callback/page.tsx(または.jsx)を作成します。"use client"; import { useCallbackHandler } from "@nodeops-createos/integration-oauth"; export default function Callback() { const { loading, error } = useCallbackHandler({ redirectTo: "/dashboard" }); if (loading) return ( <div style={{ display: "flex", justifyContent: "center", alignItems: "center", height: "100vh" }}> <p>Signing in...</p> </div> ); if (error) return <p>Login failed: {error}</p>; return null; } -
.env.exampleを作成する — プロジェクトのルートにこのファイルを作成します。# ── Client-side (exposed to browser via NEXT_PUBLIC_ prefix) ────────────────── NEXT_PUBLIC_NODEOPS_AUTH_URL=https://id.nodeops.network/oauth2/auth NEXT_PUBLIC_NODEOPS_CLIENT_ID=your_client_id_here NEXT_PUBLIC_NODEOPS_REDIRECT_URI=http://localhost:3000/callback NEXT_PUBLIC_NODEOPS_SCOPES=offline_access offline openid # ── Server-side only (never sent to browser) ────────────────────────────────── NODEOPS_CLIENT_SECRET=your_client_secret_here NODEOPS_TOKEN_URL=https://id.nodeops.network/oauth2/token NODEOPS_USERINFO_URL=https://autogen-v2-api.nodeops.network/v1/users/me -
.env.localを作成する —.env.localがまだ存在しない場合は、.env.exampleを.env.localにコピーし、NodeOps 開発者ポータルで取得した認証情報を使ってNEXT_PUBLIC_NODEOPS_CLIENT_IDとNODEOPS_CLIENT_SECRETを設定するようユーザーに伝えてください。.env.localがすでに存在する場合は、不足しているNODEOPS_変数だけを追加し、既存の値は上書きしないでください。 -
.gitignoreを確認する —.gitignoreが存在する場合は読み取ります。.env.localが記載されていない場合は、シークレットが漏えいしないよう追加します。また、.envも記載されていることを確認します。.gitignoreが存在しない場合は、少なくとも以下の内容で作成します。.env .env.local -
Docker/コンテナでのデプロイ — プロジェクトのルートに
Dockerfileが存在するか確認します。存在する場合は、NodeOps環境変数が正しく処理されることを確認し、正しく処理されない場合はユーザーに警告します。ユーザーからDockerやデプロイについて質問された場合は、Dockerfileを作成または更新します。重要:
NEXT_PUBLIC_*変数は、Next.jsによってビルド時にJSバンドルへ埋め込まれます。RUN npm run buildより前に、DockerfileでENVまたはARGとして設定する必要があります。実行時にのみ設定しても効果はなく、バンドル内の値はundefinedになります。変数は次の2種類に分かれます。
変数 必要なタイミング 理由 NEXT_PUBLIC_NODEOPS_AUTH_URLビルド時 クライアントのJSバンドルにインライン化されます NEXT_PUBLIC_NODEOPS_CLIENT_IDビルド時 クライアントのJSバンドルにインライン化されます NEXT_PUBLIC_NODEOPS_REDIRECT_URIビルド時 クライアントのJSバンドルにインライン化されます NEXT_PUBLIC_NODEOPS_SCOPESビルド時 クライアントのJSバンドルにインライン化されます NODEOPS_CLIENT_SECRET実行時のみ リクエストごとにAPIルートで読み取られます NODEOPS_TOKEN_URL実行時のみ リクエストごとにAPIルートで読み取られます NODEOPS_USERINFO_URL実行時のみ リクエストごとにAPIルートで読み取られます CreateOSに関する注意:CreateOSは、Dockerfileがある場合、それを使用します。このプラットフォームでは
COPY --from=builderを使ったマルチステージビルドは失敗するため、単一ステージのDockerfileのみを使用してください。Dockerfileを完全に削除すると、CreateOSのデフォルトのインストール/実行コマンドに切り替わります。NEXT_PUBLIC_*変数の実行時設定を回避する方法については、CreateOSのセクション(手順10)を参照してください。Dockerfileの例(単一ステージ、CreateOS対応):
FROM node:20-alpine WORKDIR /app COPY package*.json ./ RUN npm ci COPY . . # NEXT_PUBLIC_* must be present at build time — they get baked into the JS bundle ARG NEXT_PUBLIC_NODEOPS_AUTH_URL=https://id.nodeops.network/oauth2/auth ARG NEXT_PUBLIC_NODEOPS_CLIENT_ID ARG NEXT_PUBLIC_NODEOPS_REDIRECT_URI ARG NEXT_PUBLIC_NODEOPS_SCOPES=offline_access offline openid ENV NEXT_PUBLIC_NODEOPS_AUTH_URL=$NEXT_PUBLIC_NODEOPS_AUTH_URL ENV NEXT_PUBLIC_NODEOPS_CLIENT_ID=$NEXT_PUBLIC_NODEOPS_CLIENT_ID ENV NEXT_PUBLIC_NODEOPS_REDIRECT_URI=$NEXT_PUBLIC_NODEOPS_REDIRECT_URI ENV NEXT_PUBLIC_NODEOPS_SCOPES=$NEXT_PUBLIC_NODEOPS_SCOPES # Server-side vars — only needed at runtime, read per-request by API routes ENV NODEOPS_CLIENT_SECRET="" ENV NODEOPS_TOKEN_URL=https://id.nodeops.network/oauth2/token ENV NODEOPS_USERINFO_URL=https://autogen-v2-api.nodeops.network/v1/users/me RUN npm run build EXPOSE 3000 CMD ["npm", "start"].dockerignoreで.env.localも除外されていることを確認します。.env .env.local node_modules .nextプロジェクトをVercelなどにデプロイする場合:Dockerfileは不要です。これらのプラットフォームでは、ビルド前に環境変数が自動的に注入されます。プラットフォームのダッシュボードで変数を追加するよう、ユーザーに案内してください。
-
CreateOS/ビルド後に環境変数を注入するプラットフォーム — CreateOSはDockerfileがある場合、それを使用しますが、ビルドステップの後に環境変数を注入します。そのため、DockerfileでARG/ENVを設定していても、ビルド時には
NEXT_PUBLIC_*変数がundefinedになります。以下の実行時設定の回避策を使用するか、Dockerfileを完全に削除してCreateOSのデフォルトのインストール/実行コマンドに切り替えてください。パッケージが自動的に処理する内容(v1.x以降)
@nodeops-createos/integration-oauthv1.x以降のAuthProviderは、バンドルにNEXT_PUBLIC_*変数がない場合、実行時に/api/configを自動取得します。追加の設定は不要です。以下の手順10aのとおり、APIルートが存在することだけ確認してください。古いバージョンのパッケージを使用している場合は、手動で追加します。
10a.
app/api/config/route.ts(または.js)を作成します。import { NextResponse } from 'next/server'; export const dynamic = 'force-dynamic'; export async function GET() { return NextResponse.json({ NEXT_PUBLIC_NODEOPS_AUTH_URL: process.env.NEXT_PUBLIC_NODEOPS_AUTH_URL || 'https://id.nodeops.network/oauth2/auth', NEXT_PUBLIC_NODEOPS_CLIENT_ID: process.env.NEXT_PUBLIC_NODEOPS_CLIENT_ID || '', NEXT_PUBLIC_NODEOPS_REDIRECT_URI: process.env.NEXT_PUBLIC_NODEOPS_REDIRECT_URI || '', NEXT_PUBLIC_NODEOPS_SCOPES: process.env.NEXT_PUBLIC_NODEOPS_SCOPES || 'offline_access offline openid', }); }このルートは、実行時にサーバー環境で利用可能な
NEXT_PUBLIC_*変数を読み取り、JSONエンドポイントを介してクライアントに公開します。10b.
components/EnvBootstrap.tsx(または.jsx)を作成します。"use client"; import { useEffect, useState } from "react"; export default function EnvBootstrap({ children }: { children: React.ReactNode }) { const [ready, setReady] = useState( // 変数がすでに設定されている場合(例:ローカル開発時)は、フェッチをスキップします typeof window !== "undefined" && !!process.env.NEXT_PUBLIC_NODEOPS_CLIENT_ID ); useEffect(() => { if (ready) return; fetch("/api/config") .then((r) => r.json()) .then((env) => { // AuthProvider が値を取得できるよう、process.env を更新します Object.assign(process.env, env); setReady(true); }) .catch((err) => { console.error("Failed to load runtime config:", err); setReady(true); // エラー状態を表示できるよう、そのままレンダリングします }); }, [ready]); if (!ready) return null; return <>{children}</>; }10c. ルートレイアウトを更新し、
AuthProviderをEnvBootstrapでラップします。import { AuthProvider } from '@nodeops-createos/integration-oauth'; import EnvBootstrap from '@/components/EnvBootstrap'; // <body> 内: <EnvBootstrap> <AuthProvider>{children}</AuthProvider> </EnvBootstrap>これにより、クライアント上で
AuthProviderが初期化される前に、環境変数がサーバーから取得され、process.envに設定されます。 -
概要を表示する — 明確な概要を表示します。
- 作成/変更したファイル(それぞれ列挙)
- スキップしたファイル(すでに存在していたものがあれば)
- 必須の環境変数
NEXT_PUBLIC_NODEOPS_CLIENT_IDとNODEOPS_CLIENT_SECRETの2つを設定するよう、ユーザーに伝えます - Dockerfile が存在する場合は、Dockerfile 内で
npm run buildを実行する前にNEXT_PUBLIC_*変数を設定する必要があることを伝えます - 任意のページでフックを使用する方法を示します。
import { useAuth, useUser } from '@nodeops-createos/integration-oauth'; const { isAuthenticated, login, logout, loading, authError } = useAuth(); const { user } = useUser();