Contents
Okta Developer コンソールへのサインアップとアプリケーション登録
このセクションでは、Okta の開発者向けアカウント作成から OIDC クライアント(Web アプリ)を登録するまでの一連の流れを解説します。開発環境で認証機能をすぐに試したい方は、以下の手順を順に実行してください。
開発者アカウント作成手順
まずは Okta の公式サイトから無料の Developer アカウントを取得します。
- 公式ページへアクセス – https://developer.okta.com/(右上の Sign Up ボタン)
- メールアドレスとパスワードを入力し、送信された確認メールのリンクをクリック
- 組織名(例:
my-company)と使用するリージョン(US, EU など)を選択して完了
作成が成功すると、Developer コンソールに自動的に遷移します。ここから API の設定やクライアント登録が行えます。
OAuth クライアント ID と Secret の取得方法
- コンソール左メニューの Applications → Add Application をクリック
- 「Web」テンプレートを選択し、アプリ名と任意の説明を入力
- Client authentication は「Send client secret in body」を推奨します(PKCE を利用する場合は必須ではありません)
作成後に表示される Client ID と Client Secret は、環境変数やシークレットストアに安全に保存してください。
リダイレクト URI の設定ポイント
| 環境 | 推奨リダイレクト URI |
|---|---|
| 開発 | http://localhost:3000/authorization-code/callback |
| 本番 | https://your-domain.com/auth/callback |
注意:リダイレクト URI は完全一致が必要です。末尾のスラッシュやポート番号まで正確に設定しないと、認可エラーが発生します。
API トークンの作成と安全な管理
API トークンは Okta 管理 API への呼び出しに必須です。このセクションではトークンの生成手順と、漏洩リスクを最小化する保管方法を紹介します。
API トークン発行画面へのアクセス
- 管理コンソールで Security → API → Tokens タブを開く(最新ドキュメント: https://developer.okta.com/docs/guides/create-api-token/main/)
- Create Token ボタンをクリックし、用途に合わせた名前を入力
作成直後に表示される文字列は唯一のシークレットです。画面遷移後は再表示できないため、必ず安全な場所へコピーしてください。
トークンの権限設定と有効期限
- スコープ は必要最小限(例:
okta.users.read)に絞ります。過剰な権限は攻撃対象を広げる原因となります。 - 有効期限 は組織ポリシーで管理し、デフォルトのまま使用する場合は Okta のドキュメント(https://developer.okta.com/docs/reference/api/overview/)をご確認ください。90 日という数値はあくまで一例です。
環境変数・シークレットマネージャへの安全な保存
| 環境 | 推奨手法 |
|---|---|
| ローカル開発 | .env ファイルに OKTA_API_TOKEN=xxxxx と記述し、.gitignore に追加。ファイルは 絶対にリポジトリにコミットしない こと。 |
| 本番環境 | AWS Secrets Manager、Google Secret Manager、Azure Key Vault 等のマネージドシークレットサービスへ格納し、アプリ起動時にロードする仕組みを実装。 |
ベストプラクティス:トークンはコード中にハードコーディングせず、必ず外部から注入する形で使用します。
OAuth 2.0 授権コードフローと OpenID Connect の基本概念
この章では、Okta が提供するエンドポイントを利用した標準的な認可コードフローの概要と、2026 年時点で推奨されているセキュリティ拡張(PKCE)について説明します。
認可エンドポイントとトークンエンドポイント
| エンドポイント | 主な役割 |
|---|---|
https://{yourOktaDomain}/oauth2/default/v1/authorize |
ユーザー認証・認可コード取得 |
https://{yourOktaDomain}/oauth2/default/v1/token |
認可コードからアクセストークン/IDトークン取得 |
すべて HTTPS(TLS 1.3 推奨)で通信します。
PKCE の位置付けと実装上の注意点
2026 年現在、Okta は PKCE を推奨 していますが、全クライアントに対して必須かどうかは公式ドキュメント(https://developer.okta.com/docs/guides/implement-auth-code-pkce/)で最新情報を確認してください。PKCE の主な利点は、認可コードの盗聴やリプレイ攻撃を防止できる点です。
PKCE 実装手順(簡易概要)
- 43〜128文字のランダム文字列
code_verifierを生成 - SHA‑256 ハッシュを取り、Base64URL エンコードした結果を
code_challengeとして認可リクエストに付与
この手順は多くの SDK が自動化していますが、独自実装する場合は上記ロジックを必ず検証してください。
Scope とクレームの設定例
|
1 2 3 4 5 6 |
scope = openid profile email offline_access claims = { "id_token": {"email": null, "name": null}, "access_token": {"groups": null} } |
openidは OIDC の必須スコープです。offline_accessを付与するとリフレッシュトークンが発行され、長期的なセッション維持が可能になります。
@okta/oidc-middleware を使った Node.js / Express アプリへの認証組み込み
この章では、実際に Node.js(Express)アプリで Okta の OIDC フローを動かすための手順と、セキュリティ上重要なポイント(エラーハンドリング・環境変数の安全な取り扱い)を解説します。
プロジェクト初期化と依存パッケージインストール
以下のコマンドでプロジェクトディレクトリを作成し、必要ライブラリをインストールします。
|
1 2 3 4 |
mkdir okta-express-demo && cd $_ npm init -y npm install express @okta/oidc-middleware dotenv cookie-parser express-session node-fetch@2 |
ポイント:
dotenvは開発時にのみ使用し、本番環境ではシークレットマネージャから直接読み込む構成が安全です。
環境変数の設定と取り扱い上の注意
.env ファイル(ローカル用)例:
|
1 2 3 4 5 |
OKTA_ORG_URL=https://dev-123456.okta.com OKTA_CLIENT_ID=0oa1abcd2EFGH3IJ4KL5 OKTA_CLIENT_SECRET=yourClientSecret SESSION_SECRET=strongRandomStringAtLeast32Chars |
安全対策
| 項目 | 推奨方法 |
|---|---|
.env ファイルの管理 |
git checkout --orphan で履歴から除外し、.gitignore に必ず追加 |
| 本番環境のシークレット取得 | 環境変数は OS のプロセスレベルまたはクラウドプロバイダのシークレットサービス経由で注入 |
| ログ出力 | process.env.OKTA_CLIENT_SECRET など機密情報は決してコンソールに出さない |
ミドルウェア設定コード例(app.js)
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 |
// ----------------------------------------------------- // 初期化処理 // ----------------------------------------------------- require('dotenv').config(); // 開発時のみ有効 const express = require('express'); const session = require('express-session'); const { ExpressOIDC } = require('@okta/oidc-middleware'); const app = express(); // ----------------------------------------------------- // セッション設定(必ず secret を環境変数から取得) // ----------------------------------------------------- app.use(session({ secret: process.env.SESSION_SECRET, resave: false, saveUninitialized: false, cookie: { httpOnly: true, secure: process.env.NODE_ENV === 'production' } })); // ----------------------------------------------------- // OIDC 設定 // ----------------------------------------------------- const oidc = new ExpressOIDC({ issuer: `${process.env.OKTA_ORG_URL}/oauth2/default`, client_id: process.env.OKTA_CLIENT_ID, client_secret: process.env.OKTA_CLIENT_SECRET, redirect_uri: 'http://localhost:3000/authorization-code/callback', scope: 'openid profile email offline_access' // 必要に応じて追加 }); // OIDC のルーティングを自動マウント app.use(oidc.router); // ----------------------------------------------------- // 保護されたエンドポイント例 // ----------------------------------------------------- app.get('/protected', oidc.ensureAuthenticated(), (req, res) => { const user = req.userContext?.userinfo; res.send(`Hello ${user?.name || 'user'}, you are authenticated!`); }); // ----------------------------------------------------- // ログアウトハンドラ // ----------------------------------------------------- app.get('/logout', (req, res) => { req.logout() .then(() => res.redirect('/')) .catch(err => console.error('Logout error:', err)); }); // ----------------------------------------------------- // エラーハンドリング(OIDC、ネットワークエラー等) // ----------------------------------------------------- oidc.on('error', err => { console.error('OIDC configuration error:', err); }); app.use((err, req, res, next) => { // 想定外の例外はここで捕捉 console.error('Unexpected server error:', err); res.status(500).json({ message: '内部サーバーエラーが発生しました', details: err.message }); }); // ----------------------------------------------------- // サーバ起動 // ----------------------------------------------------- oidc.on('ready', () => { const port = process.env.PORT || 3000; app.listen(port, () => console.log(`App listening on http://localhost:${port}`)); }); |
コードのポイント解説
secureクッキーは本番環境でのみ有効にし、HTTPS が必須になることを保証。oidc.on('error')でミドルウェア起動時の設定エラーを捕捉し、早期にデプロイ失敗を検知。- 汎用エラーハンドラはスタックトレースをサーバ側ログに残すだけで、クライアントには詳細情報を送らないようにしています。
2026 年版 MFA と FIDO2 のベストプラクティス
多要素認証(MFA)はアカウント保護の第一ラインです。この章では、Okta が提供する FIDO2/WebAuthn と YubiKey OTP を組み合わせた実装手順と運用上の注意点をまとめます。
MFA ポリシー設計の基本方針
| 条件 | 推奨設定 |
|---|---|
| 全ユーザー(管理者・開発者) | MFA 必須化 |
| 社外ネットワークからのアクセス、または新規デバイス使用時 | 追加認証(条件付き MFA) |
このように「全員必須」+「リスクベースで追加要求」の二段階アプローチを取ると、ユーザー体験を損なわずにセキュリティを高められます。
FIDO2 / WebAuthn の有効化手順
- コンソール左メニュー Security → Multifactor → Factors に移動
- FIDO2 (WebAuthn) を「ON」に切り替える
- 必要に応じて デバイス登録期限(例:30 日)や ユーザー属性ベースの適用 を設定
ポイント:FIDO2 はパスワードレス認証にも利用でき、フィッシング耐性が高い点が大きな利点です。
YubiKey OTP の有効化手順(簡略版)
- 同じ Factors ページで YubiKey OTP を「ON」にする
- ユーザーは Okta ポータルの Security > Devices > Add からシリアル番号と OTP を入力して登録
MFA フローをコード側でチェックする例(Express)
|
1 2 3 4 5 6 7 8 |
// 認証済みだけど MFA 未完了の場合にリダイレクト app.use((req, res, next) => { if (req.isAuthenticated() && !req.userContext?.mfaCompleted) { return res.redirect('/login/mfa'); } next(); }); |
このミドルウェアは、認証後のすべてのリクエストに対して MFA 完了フラグを検査し、未完了なら専用ページへ誘導します。
運用上の留意点
- デバイス削除・再登録:ユーザーが端末を紛失した場合は管理者が即座に該当デバイスを無効化できるよう、Okta の API(
/api/v1/users/{id}/factors)で自動化すると便利です。 - ログ監査:MFA 関連のイベントは必ず監査ログに出力し、SIEM と連携させて異常検知を行います。
アクセストークン・ID トークンの検証とリフレッシュトークン運用
取得した JWT はサーバ側で署名や有効期限を必ず検証してから使用します。この章では Node.js での実装例と、リフレッシュトークンを安全に扱うベストプラクティスを示します。
JWKS を利用した署名検証と期限チェック
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 |
const jwt = require('jsonwebtoken'); const jwksClient = require('jwks-rsa'); // Okta の公開鍵エンドポイント(最新 URL はドキュメントで確認) const client = jwksClient({ jwksUri: `${process.env.OKTA_ORG_URL}/oauth2/default/v1/keys` }); function getSigningKey(header, callback) { client.getSigningKey(header.kid, (err, key) => { if (err) return callback(err); const signingKey = key.publicKey || key.rsaPublicKey; callback(null, signingKey); }); } /** * ID トークンを検証し、デコード済みペイロードを返す * @param {string} token - JWT文字列 * @returns {Promise<object>} */ function verifyIdToken(token) { return new Promise((resolve, reject) => { jwt.verify(token, getSigningKey, { algorithms: ['RS256'] }, (err, decoded) => { if (err) return reject(err); // exp が現在時刻より未来か確認 if (decoded.exp * 1000 < Date.now()) { return reject(new Error('Token expired')); } resolve(decoded); }); }); } |
トークン検証エラーハンドリング例(API エンドポイント)
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
app.get('/api/secure-data', async (req, res) => { try { const authHeader = req.headers.authorization || ''; const token = authHeader.split(' ')[1]; if (!token) throw new Error('No token provided'); const payload = await verifyIdToken(token); // 認可情報(例: groups)を元にアクセス制御 res.json({ data: '機密情報', user: payload.sub }); } catch (e) { console.warn('Token verification failed:', e.message); res.status(401).json({ error: '認証が無効です。再ログインしてください。' }); } }); |
リフレッシュトークンの安全な保管とローテーション
- サーバ側のみで保持:データベースまたは Secrets Manager に暗号化して保存し、クライアントへは絶対に送信しない。
- 使用後即時無効化:リフレッシュ API が成功したら古いトークンを削除し、新しいものと入れ替えるロジックを実装する。
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
const fetch = require('node-fetch'); /** * リフレッシュトークンで新しいアクセストークン取得 * @param {string} refreshToken * @returns {Promise<object>} */ async function refreshAccessToken(refreshToken) { const response = await fetch(`${process.env.OKTA_ORG_URL}/oauth2/default/v1/token`, { method: 'POST', headers: { 'Content-Type': 'application/x-www-form-urlencoded' }, body: new URLSearchParams({ grant_type: 'refresh_token', client_id: process.env.OKTA_CLIENT_ID, client_secret: process.env.OKTA_CLIENT_SECRET, refresh_token: refreshToken }) }); const data = await response.json(); if (!response.ok) { // エラーメッセージは Okta の仕様に合わせてハンドリング throw new Error(data.error_description || 'リフレッシュトークン取得失敗'); } // TODO: DB に保存し直すロジックを実装 return data; // { access_token, id_token, refresh_token, expires_in, token_type } } |
セキュリティ上のポイント:リフレッシュトークンが漏洩した場合、攻撃者は長期間アクセスできるため、定期的なローテーションと侵害検知(例: 異常IPからの利用)を必ず組み合わせてください。
まとめ
- 開発者コンソールでアカウント作成 → OIDC クライアント取得
- API トークンは最小権限・有効期限を設定し、シークレットマネージャへ安全に保存
- PKCE は推奨されるが必須かは公式ドキュメントで随時確認
- @okta/oidc-middlewareと Express の組み合わせで数行のコードで認証が完結、エラーハンドリングと環境変数管理に注意
- MFAは FIDO2 と YubiKey OTP を併用し、条件付きポリシーで柔軟に運用
- トークン検証・リフレッシュは JWKS 取得と期限チェックを必ず行い、サーバ側だけでリフレッシュトークンを管理
上記手順を踏むことで、2026 年時点の Okta が提供する最新ベストプラクティスに沿った、安全かつ拡張性の高い認証基盤を構築できます。ぜひご自身のプロジェクトに取り入れて、ユーザー体験とセキュリティの両立を実現してください。