小学生でもわかるWorkOS / 第2話の補足資料

自分のアプリに、ログインを付ける

上から順に、そのとおりにやれば終わります。 打つ文字はすべてコピーボタンから取れます。手で打たないでください(打ち間違いがいちばん多い原因です)。 1つずつ「どの窓でやるか」「何が起きるか」「こうなったら成功か」を書いてあります。

選ぶと、キー操作もコマンドもそのパソコン用に切り替わります。あとから変えられます。

対象:Next.js(App Router) 環境:練習環境(Staging)/ 0円 必要:Node.js 22.11以上 基準日:2026年8月27日

この手順で使う窓は、4つだけです

「いま何をしているのか分からない」の正体は、たいていどの窓の話か分からないことです。 なので、これから出てくる手順には、全部この色の札を付けました。札を見れば、どこを開けばいいかが分かります。

🖥 ターミナル

文字で命令する窓

黒い画面です。開き方は 00 で説明します。貼り付けて Enter を押すだけ。

📝 エディタ

ファイルを書く窓

CursorやVS Codeの、コードが並んでいるところ。ここではファイルを作って、貼って、保存します。

🌐 WorkOSのダッシュボード

設定をクリックする窓

ブラウザで開くWorkOSの管理画面。第1話でログイン画面の色を決めたところと同じです。

🌐 自分のアプリ

できたものを見る窓

ブラウザで localhost:3000 を開いたところ。動いているかを確かめるのはここです。

ターミナルが怖い人へ

反応がなくても、たいてい動いています。とくに最初の1回は数分かかります。文字が出るまで待ってください。

そして、試すのは複製したフォルダです。壊れても元は無事なので、安心して進めてください。

00

ターミナルを開く

ここが最初の関門です。3つの道のうち、どれか1つでいいです

A
📝 エディタ

いちばん楽な道:CursorやVS Codeの中で開く

CursorかVS Codeを使っている人は、これがいちばん楽です。 エディタで自分のアプリのフォルダを開いてから、次のキーを押してください。 開いた時点で、もう自分のアプリの場所にいます。移動の操作が要りません。

キーボードで Ctrl + @(または Ctrl + `)を押します。

キーボードで Control + ` を押します(⌘ ではなく Control です)。

キーが分からなければ、上のメニューの 「表示」→「ターミナル」 を選んでも同じです。

こうなったら成功 画面の下半分に、文字が打てる黒っぽい領域が出てくる。そこがターミナルです。
B
🖥 ターミナル

エディタを使っていない:Windowsで単体で開く

いちばん確実なのは、フォルダから直接開く方法です。移動のコマンドを打たずに済みます。

  1. エクスプローラーで、自分のアプリのフォルダを開く
  2. フォルダの中の何もないところで、Shift を押しながら右クリック
  3. メニューの中から 「ターミナルで開く」(または「PowerShell ウィンドウをここで開く」)を選ぶ
こうなったら成功

黒か紺色の窓が開いて、いちばん下の行が PS C:\…\自分のアプリ> のようになっている。

その > のうしろに文字を貼り付けて Enter、が基本の操作です。

その項目が出てこないとき

Windowsの版によっては出ないことがあります。その場合はこちらで開けます。

  1. キーボードの Windowsキー を押す
  2. ターミナル と打つ(日本語のままでOK)
  3. 出てきた「ターミナル」を選ぶ
この開き方だと、場所が違います この方法で開くと、自分のアプリではなくユーザーのフォルダにいます。 そのまま打つと失敗するので、次の「C」で移動してください。
C
🖥 ターミナル

ターミナルを、自分のアプリの場所へ移動させる

Aの道、またはBの「フォルダから開く」でうまくいった人は、ここは飛ばして 01 へ。

まず、自分のアプリのフォルダの場所(パス)を調べます。

  1. エクスプローラーで、自分のアプリのフォルダを開く
  2. 上のアドレスバーの何もないところをクリックする(文字が反転します)
  3. Ctrl + C でコピー

これで:ターミナルの居場所が、そのフォルダに変わります。

terminal / 引用符の中に、コピーしたパスを貼る
> cd "ここに貼り付け"

上をコピーしてターミナルに貼り、ここに貼り付け の文字を消してから、 さっきコピーしたパスを貼ってください。引用符(")は消さないでください。 フォルダ名に空白が入っていると、引用符が無いと失敗します。

こうなったら成功 行の頭が PS C:\…\自分のアプリ> に変わっている。
D
🖥 ターミナル

いま開いているのが、どちらの窓か確かめる

Windowsには、似ているけれど中身が違う窓が2つあります。行の頭を見れば分かります。

行の頭正体この手順では
PS C:\…>PowerShellこれが正解。この資料のコマンドはそのまま通ります
C:\…>(PSが無い)コマンドプロンプト一部のコマンドが通りません。下を読んでください
コマンドプロンプトだった人へ

そのままでも大半は動きますが、2つだけ違います。

  • ls は使えません → dir と打ってください
  • mkdir -p app/secret は危険です。エラーも出さずに -p という名前のフォルダを作ります → mkdir app\secret と打ってください

迷うくらいなら、PowerShellに切り替えるのがおすすめです。Bの手順で開き直せます。

B
🖥 ターミナル

エディタを使っていない:Macで単体で開く

いちばん速いのは、Spotlight(検索)から開く方法です。

  1. ⌘ + スペース を押す(画面の真ん中に検索窓が出ます)
  2. ターミナル と打つ
  3. Enter を押す

アプリ一覧から開きたい人は、「アプリケーション」→「ユーティリティ」→「ターミナル」にあります。

こうなったら成功

白か黒の窓が開いて、いちばん下の行が ユーザー名@… % のようになっている。

その % のうしろに文字を貼り付けて Enter、が基本の操作です。

この開き方だと、場所が違います 開いた直後は、自分のアプリではなくホームフォルダにいます。 そのまま打つと失敗するので、次の「C」で移動してください。
C
🖥 ターミナル

ターミナルを、自分のアプリの場所へ移動させる

Aの道でうまくいった人は、ここは飛ばして 01 へ。

Macには、打たずに済むいい方法があります。フォルダをドラッグするだけです。

  1. ターミナルに cd と打つ(cd のうしろに半角スペースを1つ入れる)
  2. Finderで、自分のアプリのフォルダをターミナルの窓にドラッグ&ドロップする
  3. パスが自動で入るので、Enter を押す
terminal / これを打ってから、フォルダをドラッグ
% cd 

ドラッグを使わない人は、Finderでフォルダを右クリック → option を押しながら 「"◯◯"のパス名をコピー」でパスが取れます。 それを cd のうしろに貼ってください。

こうなったら成功 行の頭に、自分のアプリのフォルダ名が出ている。
D
🖥 ターミナル

Macの人が間違えやすいキー

ターミナルでは ⌘ ではありません

動いているコマンドを止めるのは Control + C です。 ⌘ + C はコピーになってしまい、止まりません。

これはMacの人が必ず一度は間違えるところです。止めたいときは Control。

やりたいこと押すキー
ターミナルに貼り付ける⌘ + V
動いているものを止めるControl + C
エディタでファイルを保存する⌘ + S
E
🖥 ターミナル

正しい場所にいるか、最後に1回だけ確かめる

これで:いまいる場所にあるファイルの一覧が出ます。見るだけで、何も変えません。

terminal(PowerShell)
> ls

コマンドプロンプトの人は、こちらです。

terminal(コマンドプロンプト)
> dir
terminal
% ls
こうなったら成功

一覧の中に package.json という名前がある。これがあれば、正しい場所にいます。

まだの状態:無い/何も出ない。まだ自分のアプリの場所にいません。CかBをやり直してください。

01

始める前に、3つ用意する

ここを飛ばすと、あとのコマンドがわかりにくい形で止まります

1
🌐 WorkOSのダッシュボード

第1話で作ったWorkOSのアカウントがあるか見る

ブラウザで dashboard.workos.com を開いて、ログインできればOKです。練習環境(Staging)のまま使います。

こうなったら成功 ダッシュボードが開いて、画面のどこかに Staging と出ている。クレジットカードは要りません。
2
🖥 ターミナル

自分のアプリを、フォルダごと複製する

前に作ったアプリで構いません。ただし、そのままでは試さないでください。

取り返しがつきません

このあと打つコマンドは、あなたのプロジェクトのファイルを書き換えます。 いちばん安全なのは、フォルダごと複製して、そのコピーで試すことです。

エクスプローラーでフォルダを右クリック →「コピー」→ 何もないところで右クリック →「貼り付け」。それで十分です。

Finderでフォルダを右クリック →「複製」。それで十分です。

Gitを使っている人は、複製したフォルダで「いまどうなっているか」を先に見ておきます。

これで:いま変更が残っていないかを確かめます。何も出なければ、きれいな状態です。

terminal
git status --short
こうなったら成功

何も表示されないのがいちばん良い状態です。次に進めます。

ファイル名がずらっと出た人は、まだ保存していない変更があります。下のやり方で片付けてから進んでください。

やってはいけない git add -A や git add . は使わないでください。 「全部まとめて追加」という意味なので、ずっと前から置きっぱなしのメモや、別の鍵ファイルまで一緒にコミットしてしまうことがあります。

これで:名前を指定したファイルだけを、いまの状態で保存します。

terminal / <ファイル名> は自分のものに置き換える
git add <ファイル名>
git commit -m "WorkOSを入れる前の状態"

Gitに慣れていない人は、無理に使わずフォルダの複製だけで進めてください。そのほうが確実です。

そもそもアプリを持っていない人へ

この2行で、練習用のアプリを1本作れます。質問は出ません。 できるのは、この資料と同じ形(App Router・TypeScript)のまっさらなアプリです。 この場合、複製もgitも要りません。失敗したらフォルダごと消すだけです。

terminal / アプリが無い人だけ
npx create-next-app@latest my-login-app --ts --app --use-npm --eslint --no-tailwind --no-src-dir --import-alias "@/*"
cd my-login-app
3
🖥 ターミナル

Node.js 22.11以上が入っているか確かめる

これで:いま入っているNode.jsの版が表示されます。何も壊しません。見るだけです。

terminal
node -v
こうなったら成功

v22.11.0 のような数字が出て、22.11以上である。

まだの状態:数字が小さい/ 'node' は認識されていません と出るcommand not found: node と出る。 この場合は nodejs.org からNode.jsを入れてください。

ここが効きます 飛ばすと、あとのコマンドが途中で止まります。しかもエラーの文面がわかりにくいので、先に確認しておくのが得です。
02

STEP1:CLIにおまかせで入れる

ここは全部ターミナル。自分で書くコードはゼロです

1
🖥 ターミナル

WorkOSにログインする

これで:ブラウザが自動で開きます。そこでログインすると、パソコンとWorkOSのアカウントが結びつきます。

terminal
npx workos@latest auth login

開いたブラウザで、第1話で作ったアカウントでログインしてください。「どのアカウントだっけ」となった人は、第1話で登録したメールアドレスです。

こうなったら成功 ブラウザに「認証できました」といった意味の画面が出て、ターミナルに戻ると次の行が打てる状態になっている。
最初の1回は、とても時間がかかります このCLIは、初回だけ大きなファイルを取ってきます。数分かかりますが、正常です。 止まったように見えても待ってください。2回目からは待たされません。 会社や学校の回線で、容量の制限がある人は気をつけてください。

npx は「入れずに、その場で動かす」という道具です。この3文字がコマンドの頭に付いているのはそのためです。

2
🖥 ターミナル

練習部屋(Staging)を選ぶ

①これで:使える環境の一覧が出ます。まだ何も変えません。

terminal / ①一覧を見る
npx workos@latest env list

②これで:どれを使うか聞かれます。Staging(練習)を選んでください。

terminal / ②切り替える
npx workos@latest env switch

③これで:もう一度一覧を出して、切り替わったかを目で確かめます。ここは必ずやってください。

terminal / ③確かめる
npx workos@latest env list
こうなったら成功

一覧の中の練習環境(Staging)のほうに印が付いている。

危ない状態:印が本番(Production)に付いている。このまま進むと、本番をいじってしまいます。

ここが第2話の分かれ目 飛ばすと、いま選ばれている環境に設定が書き込まれます。 それが本番だった場合、本番をいじってしまいます。 (認証情報が無いときだけ、一時的な環境が自動で作られます)
コマンドが見つからないと言われたら 新しい版では、このコマンドの正式名が profile に変わりました(env でも動きます)。 見つからないときは profile list / profile switch を試してください。 表示名はアカウントによって変わるので、練習用のほうが選ばれていることを確かめてください。
3
🖥 ターミナル

入れる(この回の本体)

打つ前に、これだけ読んでください 次のコマンドは、AIがプロジェクトの中身を読んで書き換えます。 会社・学校・お客さんのコードで使う前に、社内のルールを確認してください。

その「AI」がどこで動くのか(実機で確かめました)

初回に約230MB取ってくるのは、AIを動かすためのプログラム本体です (~/.workos/cache/agent-sdk/ に置かれます)。これは手元で動きます。 ただし、考えるところは手元ではありません。ログにこう書かれていました。

実機のログから
[credential-proxy] Started on http://127.0.0.1:52012,
                   forwarding to https://api.workos.com/llm-gateway

つまり、読み取ったコードは WorkOS のサーバーに送られます。 --direct を付けると自分のAnthropicのAPIキーで直接つなぐ形に変わりますが、 どちらにしても手元だけで完結はしません。

.env.local の中身も送られます

実機のログで、AIが cat .env.local を実行し、 その出力がまるごと会話に入っていることを確認しました。 同じ内容は ~/.workos/logs/ にも平文で残ります。

今回は中身がWorkOS自身の鍵だけでした。問題は、 あなたの .env.local に他社の鍵が入っている場合です。 決済サービスの鍵、データベースの接続先、ほかのAIサービスの鍵。 同じファイルに入っていれば、まとめて送られ、ログにも残ります。

フォルダを複製しても .env.local は一緒に付いてきます。複製だけでは防げません。 関係のない鍵が入っているプロジェクトでは、練習用に新しいアプリを作るか、 このSTEPの最後にある手で入れるやり方を選んでください。

これで:部品を2つ入れて、必要なファイルを5つ作って、ダッシュボード側の設定を3つ書き込みます。数分かかります。

これだけでは、まだ止まりません このコマンドが作るのは「ログイン状態を運ぶ」ところまでです。 どのページを止めるかは、このあと自分で書きます(このSTEPの5番)。
terminal
npx workos@latest install --no-branch --no-commit

うしろの2つには、それぞれ役目があります。どちらも「勝手にやらないで」という意味です。

  • --no-branch … 新しいブランチを勝手に作るのを止める
  • --no-commit … 勝手にコミットするのを止める

付けないと、変更内容を確かめる前に、別のブランチでコミットまで済んでしまいます。次の手順(何が変わったか見る)ができなくなります。

こうなったら成功

「完了」といった意味のメッセージが出て、最後にビルドが通る。

途中でいくつか質問されることがあります。落ち着いて読んで答えてください。

自分のパソコンの中だけの話ではありません このコマンドは、ダッシュボード側の設定も書き換えます。だから2番で環境を確かめました。

止まってしまったときは、--debug を付けて打ち直すと詳しい情報が出ます。

terminal / 詰まったときだけ
npx workos@latest install --no-branch --no-commit --debug
4
🖥 ターミナル

何が変わったか、自分の目で見る

ここは飛ばさないでください 自分のプロジェクトに何が起きたかを知らないまま進むのは、あとで必ず困ります。 4つ打ちますが、どれも見るだけで、何も書き換えません。

①これで:増えたファイルと変わったファイルの名前だけが出ます。

terminal / ①名前を見る
git status --short --untracked-files=all

②これで:どのファイルが何行変わったかが出ます。中身は出ないので安全です。

terminal / ②量を見る
git diff --stat

③これで:名前を指定したファイルだけ、中身の変化を見ます。

terminal / ③中身を見る
git diff -- app/ proxy.ts middleware.ts package.json
鍵が画面に出ます git diff を、うしろに何も付けずに打たないでください。 .env.local が変更に含まれていると、APIキーがそのまま画面に出ます。 上のように、見たいファイルを必ず指定してください。

④これで:.env.local が Git に載っていないかを確かめます。開かずに確かめられます。

terminal / ④鍵が守られているか
git check-ignore -v .env.local
git ls-files -- .env.local
こうなったら成功
  • 上のコマンド … .gitignore の行が表示される(無視の指定がある、という意味)
  • 下のコマンド … 何も表示されない。これが安全のしるしです

危ない状態:下のコマンドで .env.local と表示される。 Gitに載ってしまっているので、この状態でコミットしないでください。

.env.local は開かない 画面共有していたら、それだけで流出します。中身を見る必要はありません。 Gitに載っていないことだけ確かめれば十分です。

①で出た名前を見ながら、確かめるのはこの3点です。

  • 見たことのないファイルが増えていないか
  • 自分が書いた大事なファイルが書き換えられていないか
  • .env.local ができているか
トップページも書き換わります

まっさらなNext.jsで実際に流したところ、こうなりました。

  • 書き換えられた … app/layout.tsx(1行)/ app/page.tsx(89行)/package.json/package-lock.json
  • 新しく作られた … app/auth/callback/route.ts/app/auth/sign-in/route.ts/ app/auth/sign-up/route.ts/app/auth/actions.ts/proxy.ts

増えるファイルが大半ですが、トップページは中身が作り替えられます。 自分で書いたトップページがある人は、ここがいちばん影響を受けます。 すでに middleware.ts を持っているプロジェクトでは、それも書き換わることがあります。

②が空っぽだったら --no-branch --no-commit を付け忘れると、CLIが自動でブランチを作ってコミットします。 git status -sb で、いまどのブランチにいるかがわかります。 コミットされていた場合は git show --name-only --format= HEAD でファイル名だけを確認してください。 中身まで出すコマンドは使わないでください。.env.local の秘密の値が画面に出ます。
5
📝 エディタ

★ 見張り役に「止めて」と書き足す(これが無いと動きません)

ここを飛ばすと、ログイン画面に飛ばずにエラーになります

CLIが作る見張り役のファイルは、まだ誰も止めない設定です。 このまま次のSTEPに進むと、ログインしていない人が守ったページを開いたときに、 ログイン画面ではなく500エラーが出ます。

出るのはこの文です。ログインの話だと気づけないので、先に書いておきます。

飛ばすと出るエラー
Error: Cookies can only be modified in a Server Action or Route Handler.

エディタで、プロジェクト直下のこのファイルを開いてください。

使っているNext.js開くファイル
16以降proxy.ts
15以下middleware.ts

これで:ログインしていない人を、ページに着く前に止めてログイン画面へ送ります。

proxy.ts ── まるごと貼り替え(Next.js 16以降)
import { authkitProxy } from '@workos-inc/authkit-nextjs';

export default authkitProxy({
  middlewareAuth: {
    enabled: true,
    unauthenticatedPaths: ['/'],
  },
});

export const config = {
  matcher: [
    '/((?!_next/static|_next/image|favicon.ico).*)',
  ],
};
middleware.ts ── まるごと貼り替え(Next.js 15以下)
import { authkitMiddleware } from '@workos-inc/authkit-nextjs';

export default authkitMiddleware({
  middlewareAuth: {
    enabled: true,
    unauthenticatedPaths: ['/'],
  },
});

export const config = {
  matcher: ['/((?!_next/static|_next/image|favicon.ico).*)'],
};
unauthenticatedPaths が「見せていいページ」の一覧

ここに書いた道だけ、ログインなしで見られます。'/' はトップページのこと。 ほかにも見せたいページがあれば、['/', '/about'] のように足してください。

書き忘れたページは、全部ログインが要るようになります。 トップページを入れ忘れると、誰も入口にたどり着けません。

こうなったら成功

保存したら、次のSTEPでページを作ってから確かめます。ここでは保存だけでOKです。

(05で npm run dev したあと、守ったページを開いて ログイン画面に飛べば成功。エラーが出たらここに戻ってきてください)

なぜCLIが書いてくれないのか CLIが作るのは「ログイン状態を運ぶ」ところまでで、どのページを止めるかはアプリごとに違うので、 決めるのは作る人です。だから空のまま置かれます。
6
🖥 ターミナル

(会社のPCなど)コマンドが使えないときは、手で入れる

4番がうまくいった人は、ここは飛ばして 03 へ進んでください。

会社や学校のパソコンで、AIがコードを書き換えるコマンドを実行できないことがあります。その場合は、部品だけ手で入れられます。

terminal / 手で入れる場合だけ
npm install @workos-inc/authkit-nextjs @workos-inc/node

そのうえで、自分で用意するものが4つあります。コマンドは1つで済みますが、書く量は増えます。

  • 帰り道を受け止める受け口のファイル
  • アプリ全体を包む設定
  • 毎回通って、ログイン状態をページに渡す場所
  • .env.local に4つの値
この道には、もうひとつ利点があります AIがプロジェクトを読まないので、コードも .env.local も外に出ません。 他社の鍵が入っているプロジェクトなら、こちらを選んでください。
この道の続きは 細かい書き方は、公式のNext.js向けガイドが確実です。この資料はコマンドで入れた前提で進みます。
03

STEP2:ダッシュボードで2か所を設定する

ここはターミナルを離れて、ブラウザでクリックします

1
🌐 WorkOSのダッシュボード

練習環境にいるか確認して、アプリを選ぶ

ブラウザでダッシュボードを開いたら、まず Staging の表示になっているか見てください。 練習と本番は中身が別物です。ここを間違えると、設定した先が違います。

そのうえで、Applications を開いて、対象のアプリを選びます。

こうなったら成功 画面に Staging と出ていて、自分のアプリの名前が選ばれている。
2
🌐 WorkOSのダッシュボード

帰り道(リダイレクトURI)を確認する

選んだアプリの Redirects タブを開きます。 STEP1のコマンドが自動で入れてくれているので、ここは見るだけです。

CLIが入れた値(実機で確認しました)
http://localhost:3000/auth/callback
すでに入っている値を、書き換えないでください

公式のNext.jsガイド(手で入れる道)は http://localhost:3000/callback を案内しています。 CLIで入れると /auth/callback になります。入れ方で規約が違うだけで、どちらかが間違いではありません。

大事なのは1点だけです。.env.local の NEXT_PUBLIC_WORKOS_REDIRECT_URI と、 ダッシュボードの値が一字一句そろっていること。 この資料の値に合わせて書き換えると、動かなくなります。

こうなったら成功

Redirects の一覧に住所が1行入っている。値は .env.local と同じ。

1行も入っていなかったときだけ、上の値をコピーして足してください。

練習と本番の違いが、ここで効きます 練習環境では http:// と localhost が使えます。本番では https:// が必須です。
3
🌐 WorkOSのダッシュボード

★ ログアウト後の戻り先を設定する

第2話いちばんの落とし穴

公式ドキュメントに、はっきり書いてあります。 「Sign-out URI を設定していないと、ログアウトのときに利用者にエラーが出ます」

つらいのは、ログインは普通に通るところです。「できた!」と喜んでログアウトを押した瞬間にエラーが出るので、 原因がログインまわりにあるように見えます。そして、ログインのコードを何度見直しても、そこには何も問題がありません。

さっきと同じ画面で Sign-out URI(ログアウト後の戻り先)を探して、これを入れて保存します。 ここは自動では入りません。自分で足す唯一の設定です。

貼る値
http://localhost:3000
こうなったら成功 Sign-out URI の欄に上の住所が入って、保存できた。 (うしろに /callback は付きません。2番とは別の値です)
その名前の項目が見当たらないとき 画面の項目名は時期によって変わります。「サインアウト」「ログアウト後」といった意味の英語を探してください。 Redirects と同じ画面の中にあります。
04

STEP3:守りたいページを、守る形にする

ファイルを1枚作って、貼って、保存する。それだけです

対象を確認 ここからのコードは Next.js(App Router)専用です。ほかの作り方では書き方が変わります。
1
📝 エディタ

空のファイルを1枚、新しく作る

エディタの左側にファイルの一覧が出ているはずです。そこで、 app の下に secret というフォルダを作り、その中に page.tsx を置きます。

作るファイルの場所
app/secret/page.tsx

ターミナルから作りたい人は

terminal(PowerShell)
mkdir -p app/secret
コマンドプロンプトの人は、上を打たないでください コマンドプロンプトで mkdir -p を打つと、エラーも出さずに -p という名前のフォルダを作ります。 こちらを使ってください。
terminal(コマンドプロンプト)
mkdir app\secret
terminal
mkdir -p app/secret
こうなったら成功 エディタに page.tsx という名前の、中身が空のファイルが開いている。
なぜ新しいファイルなのか いま動いているページを触らずに済むからです。失敗しても、このファイルを消せば元どおり。 いきなり既存のページを守ろうとすると、うまくいかないときに 「守れていないのか、ページが壊れたのか」が分からなくなります。
2
📝 エディタ

いま作ったファイルに、これを全部貼って保存する

空のファイルなので、まるごと貼って大丈夫です。ログアウトのボタンまで入っています。 意味が分からなくても動きます。読むのはあとでいいです。

app/secret/page.tsx ── これで完成
import { withAuth, signOut } from '@workos-inc/authkit-nextjs';

export default async function Page() {
  const { user } = await withAuth({ ensureSignedIn: true });

  return (
    <div>
      <p>ようこそ、{user.firstName ?? user.email} さん</p>
      <form action={async () => { 'use server'; await signOut(); }}>
        <button type="submit">ログアウト</button>
      </form>
    </div>
  );
}
こうなったら成功 貼って保存できた(Ctrl + S⌘ + S)。 これでSTEP3は終わりです。05へ進んでください。
止めているのは、実は見張り役のほう

await withAuth({ ensureSignedIn: true }) は 「ログインしていることを確かめて、その人の情報をちょうだい」という1行です。

ただし、実際にログインしていない人を止めているのは 02の5番で直した見張り役です。 見張り役が先に止めるので、このページにはログイン済みの人しか着きません。 だからここでは、安心して user を取り出せます。

見張り役を直していないと、この行のところで Cookies can only be modified in a Server Action or Route Handler というエラーが出ます。実機で確かめました(Next.js 15でも16でも同じ)。

ほかの行は、それを動かすための入れ物です。 1行目の import は部品の呼び出し、async は「待つ処理がある」という印、 'use server' は「ログアウトはサーバー側で動かす」という印です。

名前が出ないことがあります メールアドレスだけで登録した人には、名前の情報がありません。 だから ?? で「名前があれば名前、なければメールアドレス」と書いています。 ここを {user.firstName} だけにすると、「ようこそ、 さん」という寂しい画面になります。
3
📝 エディタ

(あとで)すでにあるページを守りたくなったら

ここは1枚目がちゃんと動いてからでいいです。初めての人は飛ばして 05 へ。

上のコードを丸ごと貼らない いま書いてある中身が消えます。足すのは次の3つだけで、 return の中身は、いまのまま残してください。
  1. いちばん上に import を1行足す
  2. export default function Page() を export default async function Page() にする
  3. return の前に withAuth の1行を足す
足すのはこの2行だけ
import { withAuth } from '@workos-inc/authkit-nextjs';

const { user } = await withAuth({ ensureSignedIn: true });
ページの1行目に 'use client' と書いてあったら この書き方は使えません。その場合は、ブラウザ側用の useAuth を使います。 ログアウトのボタンも、そのままでは置けません(別ファイルに切り出す形になります。この回では扱いません)。
'use client' のページ
'use client';
import { useAuth } from '@workos-inc/authkit-nextjs/components';

export default function Page() {
  const { user, loading } = useAuth({ ensureSignedIn: true });
  if (loading) return <p>読み込み中…</p>;
  return <p>ようこそ、{user.firstName ?? user.email} さん</p>;
}
引数なしでは止まりません useAuth() は「いま誰がログインしているか」を取るだけで、止めてはくれません。 ログイン必須にしたいなら { ensureSignedIn: true } を必ず付けてください。
一気に広げない 守るページは1枚ずつ増やしてください。まとめて足すと、どこで失敗したか分からなくなります。
05

動かしてみる

ターミナルで起動して、ブラウザで確かめます

1
🖥 ターミナル

アプリを起動する

これで:自分のパソコンの中でアプリが動き出します。この窓は開いたままにしてください。閉じると止まります。

terminal
npm run dev
こうなったら成功 http://localhost:3000 のようなURLが表示されて、そこで止まっている(=動き続けている状態です)。
止めたくなったら このターミナルで CtrlControl + C を押します。 ⌘ ではありません。⌘+C はコピーになってしまい、止まりません。
出た番号が 3000 以外だったら 3か所そろえてください。番号が違うだけで止まります。直したら、いったん止めて起動し直します。
  • ダッシュボードの Redirect URI
  • ダッシュボードの Sign-out URI
  • .env.local の NEXT_PUBLIC_WORKOS_REDIRECT_URI
2
🌐 自分のアプリ

守ったページを開く

ブラウザで、さっき作ったページを開きます。ターミナルは開いたままにしておいてください。

ブラウザで開く住所
http://localhost:3000/secret

こういう順番で動きます。

  1. ページを開こうとする
  2. ログインしていないので、WorkOSのログイン画面へ飛ばされる
  3. 前回、自分で色を決めたあの画面が出る
  4. メールアドレスで登録する(自分のアドレスでOK。他人のアドレスは使わない)
  5. さっきのページに戻ってくる
  6. 「ようこそ、◯◯さん」と出る
こうなったら成功

「ようこそ、◯◯さん」と、ログアウトのボタンが出ている。ここまで来たら、この回の目的は達成です。

エラーが出たら: Cookies can only be modified in a Server Action or Route Handler なら、02の5番(見張り役に「止めて」と書き足す)をやっていません。そこへ戻ってください。

練習環境の目印 練習環境から届くメールは、件名の頭に [STAGING] が付きます。 逆に言うと、この印が付いていない=本番を触っているということです。
3
🌐 自分のアプリ

3つ、試してみる

  • ログアウトして、もう一度開く … また入口で止められるはずです。ここでエラーが出たら 03 の3番です
  • トップページを開く … こちらはログインなしで見られます。unauthenticatedPaths に '/' を入れたからです
  • 別のブラウザ(またはシークレットウィンドウ)で同じURLを開く … ログインしていない状態なので、入口で止められます
  • 守っていないページを開く … 今までどおり、誰でも開けます。守るのはページ単位だ、ということが体で分かります
こうなったら成功 3つとも、思ったとおりの結果になった。ここまで確認して、はじめて「できた」と言えます。
4
📝 エディタ

最後に、鍵の話をひとつ

取り返しがつきません Next.jsでは NEXT_PUBLIC_ が付いた環境変数はブラウザから丸見えです。 「動かないから付けてみよう」は、APIキーを世界に公開する行為になります。

.env.local について守るのは、この3つだけです。

  • Gitに追跡させない(02の4番で確認しました)
  • 画面に出さない(git diff を裸で打たない)
  • 人に見せない(画面共有中は開かない)
06

うまくいかないとき

上から順に、よくある順です

*
🖥 ターミナル

どこが悪いか分からないときは、まずこれ

これで:いまのプロジェクトを調べて、WorkOSまわりの問題点を並べてくれます。何も書き換えません。

terminal
npx workos@latest doctor

自分で原因を探す前に、これを1回打ってみてください。当たりが付きます。

守ったページを開くと、ログイン画面ではなく500エラーが出る

出ているのはこの文のはずです。

Error: Cookies can only be modified in a Server Action or Route Handler.

02の5番(見張り役に「止めて」と書き足す)をやっていません。そこへ戻ってください。

ログインの話だとまったく分からない文面ですが、原因はこれです。 Next.jsは「ページを描いている最中にクッキーを書くこと」を許していません。 ログイン画面へ送るにはクッキーが要るので、ページの中からは送れないのです。 クッキーを書ける場所は見張り役なので、そこで止めます。

Next.js 15でも16でも同じでした(実機で確認)。版の問題ではありません。

ログインは通るのに、ログアウトでエラーが出る

Sign-out URI が設定されていません。03 の3番をやってください。これがいちばん多いはずです。

ログイン側のコードをいくら見直しても直りません。原因はダッシュボード側です。

コマンドを打っても「そんなコマンドは無い」と言われる

'○○' は、内部コマンドまたは外部コマンド…として認識されていません と出た場合です。

command not found: ○○ と出た場合です。

原因は3つのどれかです。

  • 打ち間違い … 手で打たず、コピーボタンを使ってください
  • Node.jsが入っていない … 01の3番に戻って node -v を確かめてください
  • コマンドプロンプトで ls を打った … dir を使ってください
ファイルが見つからない・場所が違うと言われる

ターミナルが、自分のアプリとは別の場所にいます。00のEに戻って ls(またはコマンドプロンプトなら dir)ls を打ち、package.json があるか確かめてください。

無ければ、00のCで移動し直します。

ログイン後に「リダイレクトURIが違う」と怒られる

ダッシュボードに登録した住所と、アプリが使っている住所が食い違っています。見比べるポイントは3つです。

  • http と https が同じか
  • 末尾にスラッシュが付いているかどうかが同じか
  • ポート番号(3000のところ)が同じか

1文字違うだけで止まります。

node -v の数字が 22.11 より小さい

Node.jsを新しくしてください。ここを飛ばすとコマンドが途中で止まります。

コマンドが途中で止まる/終わらない

まず、本当に止まっているかを確かめてください。最初の1回は数分かかります。

本当に止めたいときは CtrlControl + C です。

--debug を付けて打ち直すと、どこで止まったかが出ます。 変更を抱えたまま打つと、CLIが止めることがあります。先にコミットするか、いったん退避してください。

ログインしたのに、また入口で止められる

セッションが作れていない可能性があります。 .env.local の WORKOS_COOKIE_PASSWORD が32文字以上あるか確認してください。

ログインした人の名前が出ない

名前を登録していない人です。エラーではありません。メールアドレスを出す書き方(??)にしてあれば、そちらが表示されます。

どこを守ったのかわからなくなった

いったん全部の ensureSignedIn: true を外して、1枚だけに戻してください。一気に広げると、原因の切り分けができなくなります。

画面の項目名が、この資料と違う

WorkOSは更新が速いサービスです。この資料は2026年8月27日時点のものです。意味が近い英語を探してください。だいたい隣にあります。

それでも解決しないとき

第2話の記事にリプをください。どこで止まったか(打ったコマンドと、出たメッセージ)を書いてもらえると早いです。

ただし、貼り付けるときは .env.local の中身と、sk_ で始まる文字列を必ず消してください。それは鍵そのものです。