mcpField
N
nodeops-auth

nodeops-auth

github.com/nodeops-app開発2564 回インストール5 週間前に更新
リポジトリ

nodeops-auth について

nodeops-authは、既存のNext.js App RouterプロジェクトにNodeOps PKCE OAuthを追加するセットアップスキルです。プロジェクト構成を確認し、必要なルートやコールバックページ、環境設定を作成します。完了済みの作業はスキップします。

主な機能

  1. 01Next.jsとApp Routerの検出
  2. 02パッケージマネージャーに応じたOAuthパッケージの導入
  3. 03認証APIルートとコールバックページの作成
  4. 04ルートレイアウトへのAuthProvider追加
  5. 05環境変数と除外ルールの管理
  6. 06Dockerデプロイ設定の確認

活用シーン

  1. 01既存のNext.jsアプリへのNodeOpsログイン追加
  2. 02OAuthコールバック用リダイレクトページの設定
  3. 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_ を含む場合は、環境変数ファイルの作成をスキップします。

手順

  1. プロジェクトの設定を確認する — package.json を読み込み、ロックファイルを確認します。

    • パッケージマネージャー:pnpm-lock.yaml があれば pnpm、yarn.lock があれば yarn、それ以外は npm
    • TypeScript:tsconfig.json があれば .ts/.tsx 拡張子を使用し、なければ .js/.jsx を使用します。
    • app/ ディレクトリ(App Router)があることを確認します。pages/ だけが存在する場合は作業を中止します。
    • 依存関係に next があることを確認します。なければ作業を中止します。
  2. パッケージをインストールする — 適切なインストールコマンドを実行します。

    • npm:npm install @nodeops-createos/integration-oauth
    • pnpm:pnpm add @nodeops-createos/integration-oauth
    • yarn:yarn add @nodeops-createos/integration-oauth
    • インストールに失敗した場合:ユーザーがネットワークにアクセスできるか、レジストリに到達できるか確認します。失敗が続く場合は、コマンドを手動で実行するよう提案してください。
  3. 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';
    
  4. レイアウトを 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} がある場所でラップします。
    • レイアウトファイルがない場合は作業を中止し、先にルートレイアウトを作成するようユーザーに伝えてください。
  5. コールバックページを作成する — ログイン後にユーザーをどこへリダイレクトするか尋ねます。「(デフォルト:/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;
    }
    
  6. .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
    
  7. .env.local を作成する — .env.local がまだ存在しない場合は、.env.example を .env.local にコピーし、NodeOps 開発者ポータルで取得した認証情報を使って NEXT_PUBLIC_NODEOPS_CLIENT_ID と NODEOPS_CLIENT_SECRET を設定するようユーザーに伝えてください。.env.local がすでに存在する場合は、不足している NODEOPS_ 変数だけを追加し、既存の値は上書きしないでください。

  8. .gitignoreを確認する — .gitignoreが存在する場合は読み取ります。.env.localが記載されていない場合は、シークレットが漏えいしないよう追加します。また、.envも記載されていることを確認します。.gitignoreが存在しない場合は、少なくとも以下の内容で作成します。

    .env
    .env.local
    
  9. 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は不要です。これらのプラットフォームでは、ビルド前に環境変数が自動的に注入されます。プラットフォームのダッシュボードで変数を追加するよう、ユーザーに案内してください。

  10. CreateOS/ビルド後に環境変数を注入するプラットフォーム — CreateOSはDockerfileがある場合、それを使用しますが、ビルドステップの後に環境変数を注入します。そのため、DockerfileでARG/ENVを設定していても、ビルド時にはNEXT_PUBLIC_*変数がundefinedになります。以下の実行時設定の回避策を使用するか、Dockerfileを完全に削除してCreateOSのデフォルトのインストール/実行コマンドに切り替えてください。

    パッケージが自動的に処理する内容(v1.x以降)

    @nodeops-createos/integration-oauth v1.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 に設定されます。

  11. 概要を表示する — 明確な概要を表示します。

    • 作成/変更したファイル(それぞれ列挙)
    • スキップしたファイル(すでに存在していたものがあれば)
    • 必須の環境変数 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();
      

コメント