./knowledge-base/docs/okta-auth-architecture.md
# 🔐 Okta 認証アーキテクチャ
> 最終更新: 2026-03-17
> ステータス: **移行完了**(会社 Okta `nhk.okta.com` への移行は 2026年3月4日 に完了)
---
## 概要
時代考証アシストシステムでは、**`/era-assist/` ページへのアクセスに Okta 認証** を使用しています。
番組制作スタッフなど、Okta アカウントを持つ NHK 社員のみが利用できます。
| 項目 | 値 |
| ------------ | ---------------------------------------------------------------- |
| 対象 URL | `https://historical-research-dev.xmc.nhk.or.jp/era-assist/` |
| 認証方式 | OIDC / Authorization Code + **PKCE** |
| Okta テナント | `nhk.okta.com` |
| Client ID | `0oa10n3lsio10F5TG698` |
| Issuer URI | `https://nhk.okta.com/oauth2/default` |
> 💡 **PKCE とは?**
> ブラウザ上で動く Web アプリは、パスワードのような秘密情報(Client Secret)を安全に保管できません。
> そのため、代わりに「使い捨てのランダムコード」で認証を保護する仕組みが PKCE です。Client Secret は不要です。
---
## システム構成
```mermaid
graph LR
User["👤 ユーザー\n(社内ブラウザ)"]
CF["☁️ CloudFront\nhistorical-research-dev\n.xmc.nhk.or.jp"]
Okta["🔑 Okta\nnhk.okta.com"]
S3["📦 S3\nReact SPA\n(ログイン画面等)"]
Edge["⚡ Lambda@Edge\nCookie 認証ガード"]
App["🚀 App Runner\n時代考証アシスト"]
User -->|"① アクセス"| CF
CF -->|"静的ファイル配信"| S3
S3 -->|"② 未認証 → Okta サインイン画面へ"| Okta
Okta -->|"③ 認証後 → /login/callback へリダイレクト"| S3
S3 -->|"④ トークンを Cookie に保存"| User
User -->|"⑤ /era-assist/ にアクセス"| CF
CF -->|"⑥ Cookie を確認"| Edge
Edge -->|"認証済み → 通過"| App
Edge -->|"未認証 → / へリダイレクト"| User
```
**ポイント:**
- ユーザーのブラウザと Okta が直接 OIDC 認証を行います(バックエンドサーバー経由ではありません)
- 認証後に発行されたアクセストークンを Cookie(`okta_access_token`)に保存します
- `/era-assist/` へのアクセス時、Lambda@Edge が Cookie を確認して未認証ならトップページへリダイレクトします
---
## 認証フロー
```mermaid
sequenceDiagram
actor User as ユーザー
participant App as Webアプリ(ブラウザ)
participant Okta as Okta (nhk.okta.com)
participant Edge as Lambda@Edge
User->>App: /era-assist/ にアクセス
App->>Edge: Viewer Request(Cookie を確認)
Edge-->>App: 未認証のため / へリダイレクト
User->>App: サインインボタンをクリック
App->>Okta: Okta サインイン画面へリダイレクト(PKCE フロー開始)
Note over Okta: ユーザーが社内 ID/PW でログイン
Okta-->>App: 認証コードを発行して /login/callback へリダイレクト
App->>Okta: 認証コード → アクセストークンに交換
Okta-->>App: アクセストークン・IDトークン発行
Note over App: トークンを Cookie にセット<br/>(okta_access_token)
User->>App: /era-assist/ に再アクセス
App->>Edge: Viewer Request(Cookie を確認)
Edge-->>App: 有効なトークン → App Runner へ通過
App-->>User: 時代考証アシスト画面を表示
```
---
## Okta アプリ設定
| 項目 | 値 |
| --------------------- | ---------------------------------------------------------------- |
| アプリタイプ | Single-Page Application(SPA) |
| 認証フロー | Authorization Code + PKCE |
| Sign-in Redirect URI | `https://historical-research-dev.xmc.nhk.or.jp/login/callback` |
| Sign-out Redirect URI | `https://historical-research-dev.xmc.nhk.or.jp` |
| Allowed grant types | Authorization Code のみ |
| アプリ割り当て | 全ユーザー(グループ制限なし) |
---
## 要求スコープ
| スコープ | 用途 |
| --------- | ------------------- |
| `openid` | OIDC 認証の基本要件 |
| `profile` | ユーザー名の取得 |
| `email` | メールアドレスの取得|
---
## Lambda@Edge による認証ガード
`/era-assist/*` へのリクエストは、CloudFront の Viewer Request フェーズで **Lambda@Edge** が Cookie を確認します。
```
ユーザーのリクエスト
↓
Lambda@Edge(EraAssistEdgeAuth)
↓
Cookie あり・有効期限内?
┌── YES ──→ App Runner へ転送(Next.js 画面を表示)
└── NO ──→ / へリダイレクト(ログイン画面へ)
```
Lambda@Edge のコードは [knowledge-base/lambda/edge-auth/](../lambda/edge-auth/) にあります。
---
## トラブルシューティング
| 症状 | 確認するポイント |
| ---- | --------------- |
| ログイン後に `/era-assist/` に戻れない | `Sign-in Redirect URI` が Okta に正しく登録されているか確認 |
| ログインページが無限ループする | Cookie の `okta_access_token` が正しくセットされているか確認(ブラウザの開発者ツール) |
| 「アクセスが拒否されました」と表示される | Okta のアプリにユーザーが割り当てられているか確認 |
| 変更が反映されない | CloudFront キャッシュが残っている可能性があります。[Actions タブ](https://github.com/nhk-ds/HistoricalAccuracy/actions) からフロントエンドを再デプロイしてください |