メインコンテンツまでスキップ

運用ガイダンス

idp-server 固有の運用知識とトラブルシューティング手順。


📌 本ドキュメントの責任範囲

✅ 本ドキュメントで扱う内容

  • ヘルスチェック: Actuator エンドポイント、テナント固有ヘルスチェック
  • ログ運用: JSON構造化ログ、MDCフィールド、リクエストデバッグログ
  • アプリケーションライフサイクル: Graceful Shutdown、マルチインスタンス運用
  • 定期メンテナンスタスク: pg_cron ジョブの監視
  • トラブルシューティング: 起動失敗、Redis障害、RLS問題、パフォーマンス

❌ 本ドキュメントで扱わない内容(利用者の責任範囲)

  • インフラ監視: CloudWatch、Datadog等の監視ツール設定
  • アラート設計: 閾値設定、通知チャネル設計
  • ログ収集基盤: Fluentd、CloudWatch Logs等のログ転送設定
  • 性能チューニング: OS・JVM・データベースレベルの最適化

1. ヘルスチェック

1.1 Actuator エンドポイント

idp-server は Spring Boot Actuator を使用してヘルスチェックエンドポイントを提供します。Actuator はアプリケーションと同じポート(デフォルト: 8080)で動作します。

エンドポイント用途チェック対象
GET /actuator/health総合ヘルスチェックDB + Redis + その他すべて
GET /actuator/health/readinessReadiness ProbeDB接続、Redis接続
GET /actuator/health/livenessLiveness Probeアプリケーション生存確認(ping)

レスポンス例:

正常時:

{
"status": "UP"
}

異常時:

{
"status": "DOWN"
}

有効な Actuator エンドポイント:

application.yaml の設定により、公開されるエンドポイントは healthinfo のみです。

management:
endpoints:
web:
exposure:
include: health,info
endpoint:
health:
probes:
enabled: true
show-details: when-authorized
health:
readiness-state:
enabled: true
liveness-state:
enabled: true

1.2 テナント固有ヘルスチェック

Actuator とは別に、テナント単位のヘルスチェックエンドポイントが提供されています。テナントごとのデータベース接続を検証できます。

GET /{tenant-id}/v1/health

レスポンス例:

正常時(HTTP 200):

{
"status": "UP"
}

異常時(HTTP 503):

{
"status": "DOWN"
}

用途: 特定テナントに対するリクエストが正常に処理可能かを確認する際に使用します。テナント設定の問題やRLS接続の確認に有効です。

1.3 Kubernetes 設定例

apiVersion: apps/v1
kind: Deployment
spec:
template:
spec:
containers:
- name: idp-server
readinessProbe:
httpGet:
path: /actuator/health/readiness
port: 8080
initialDelaySeconds: 30
periodSeconds: 5
failureThreshold: 3
livenessProbe:
httpGet:
path: /actuator/health/liveness
port: 8080
initialDelaySeconds: 60
periodSeconds: 10
failureThreshold: 3

ポイント:

  • readinessProbe はDB・Redisへの接続を検証するため、initialDelaySeconds をアプリケーション起動完了まで十分に設定してください
  • livenessProbe はアプリケーションの生存のみを確認するため、readinessProbe より長い間隔で問題ありません

2. ログ運用

2.1 JSON 構造化ログ

idp-server は Logback + LogstashEncoder を使用し、すべてのログをJSON形式で出力します。プロファイルによる出力形式の切り替えはなく、常にJSON出力です。

<!-- logback-spring.xml -->
<configuration>
<appender name="JSON_CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
<encoder class="net.logstash.logback.encoder.LogstashEncoder">
<includeContext>true</includeContext>
<includeMdc>true</includeMdc>
<timestampPattern>yyyy-MM-dd HH:mm:ss.SSS</timestampPattern>
</encoder>
</appender>

<root level="INFO">
<appender-ref ref="JSON_CONSOLE"/>
</root>
</configuration>

出力例:

{
"@timestamp": "2025-01-15 10:30:45.123",
"@version": "1",
"message": "Authorization request processed",
"logger_name": "org.idp.server.core.oidc",
"thread_name": "http-nio-8080-exec-1",
"level": "INFO",
"request_id": "550e8400-e29b-41d4-a716-446655440000",
"tenant_id": "tenant-abc-123",
"client_id": "my-client",
"user_id": "user-xyz-789"
}

2.2 MDC フィールド一覧

すべてのログエントリに自動付与されるMDC(Mapped Diagnostic Context)フィールドです。ログ検索・フィルタリングに活用してください。

MDCキー説明設定タイミング
request_idリクエスト固有のUUIDリクエスト受信時に自動生成
tenant_idテナント識別子テナント解決後
client_idOAuthクライアントIDクライアント認証後
user_idユーザー内部IDユーザー認証後
user_ex_subユーザー外部サブジェクトユーザー認証後
user_nameユーザー名ユーザー認証後

セキュリティイベントログでは、StructuredJsonLogFormatter が独自のJSON構造に log_type フィールドを直接付与します(MDC経由ではありません)。

log_type出力元説明
security_eventStructuredJsonLogFormatter認証成功/失敗、OAuth操作等のセキュリティイベント

ログ検索例(jq):

# 特定テナントのエラーログを抽出
cat app.log | jq 'select(.tenant_id == "tenant-abc-123" and .level == "ERROR")'

# 特定リクエストのトレース
cat app.log | jq 'select(.request_id == "550e8400-e29b-41d4-a716-446655440000")'

# セキュリティイベントのみ抽出
cat app.log | jq 'select(.log_type == "security_event")'

# 認証失敗イベントの抽出
cat app.log | jq 'select(.log_type == "security_event" and (.tags | index("failure")))'

2.3 ログレベル設定

パッケージ単位でログレベルを環境変数で制御できます。

環境変数対象デフォルト
LOGGING_LEVEL_ROOTアプリケーション全体info
LOGGING_LEVEL_WEBSpring Webinfo
LOGGING_LEVEL_IDP_SERVER_PLATFORMプラットフォーム基盤info
LOGGING_LEVEL_IDP_SERVER_AUTHENTICATION_INTERACTORS認証インタラクションinfo
LOGGING_LEVEL_IDP_SERVER_CONTROL_PLANE管理APIinfo
LOGGING_LEVEL_IDP_SERVER_CORE_OIDCOIDC コア処理info
LOGGING_LEVEL_IDP_SERVER_CORE_OPENIDOpenID コア処理info
LOGGING_LEVEL_IDP_SERVER_CORE_ADAPTERSアダプター層info
LOGGING_LEVEL_IDP_SERVER_CORE_EXTENSIONコア拡張info
LOGGING_LEVEL_IDP_SERVER_EMAIL_AWSAWS メール送信info
LOGGING_LEVEL_IDP_SERVER_FEDERATION外部IdP連携info
LOGGING_LEVEL_IDP_SERVER_NOTIFICATION_PUSH_FCMFCM プッシュ通知info
LOGGING_LEVEL_IDP_SERVER_SECURITY_EVENT_HOOK_SSFSSF セキュリティイベントフックinfo
LOGGING_LEVEL_IDP_SERVER_SECURITY_EVENT_HOOKSセキュリティイベントフックinfo
LOGGING_LEVEL_IDP_SERVER_ADAPTERS_SPRING_BOOTSpring Boot アダプターinfo
LOGGING_LEVEL_IDP_SERVER_USECASESユースケース層info
LOGGING_LEVEL_IDP_SERVER_AUTHENTICATORS_WEBAUTHN4JWebAuthn4J 認証器info
LOGGING_LEVEL_IDP_SERVER_HTTP_REQUEST_EXECUTOR外部HTTP通信info
LOGGING_LEVEL_REQUEST_RESPONSE_LOGGING_FILTERリクエスト/レスポンスログinfo

本番環境推奨: info(デフォルト)。debug への変更は一時的な調査時のみ使用し、調査完了後に戻してください。

2.4 リクエスト/レスポンスデバッグログ

OAuth/OIDC エンドポイントのHTTPリクエスト・レスポンスの詳細をログ出力する機能です。外部サービスとの連携問題を調査する際に使用します。

デフォルトでは無効 です。有効化するには以下の2つの設定が必要です。

1. プロパティ有効化:

IDP_LOGGING_REQUEST_RESPONSE_ENABLED=true

2. ログレベルを DEBUG に設定:

LOGGING_LEVEL_REQUEST_RESPONSE_LOGGING_FILTER=debug

設定パラメータ:

環境変数説明デフォルト
IDP_LOGGING_REQUEST_RESPONSE_ENABLED有効/無効false
IDP_LOGGING_REQUEST_RESPONSE_MASK_TOKENSトークンマスクtrue
IDP_LOGGING_REQUEST_RESPONSE_MAX_BODY_SIZE最大ボディサイズ(バイト)10000
IDP_LOGGING_REQUEST_RESPONSE_ENDPOINTS対象エンドポイント/v1/tokens,/v1/authorizations,/v1/backchannel/authentications,/v1/userinfo

自動マスク対象パラメータ:

  • access_token, refresh_token, id_token, client_secret, password

⚠️ 注意: この機能はリクエスト・レスポンスの全ボディをログに記録します。本番環境での常時有効化は推奨しません。問題調査時に一時的に有効化し、調査完了後に無効に戻してください。

2.5 監査ログ

idp-server は認証・認可操作の監査ログを非同期で記録します。

非同期処理の仕様:

  • 監査ログは ThreadPoolTaskExecutor により非同期で処理されます
  • キューが満杯になった場合、リトライキューに退避されます

リトライ仕様:

  • リトライ間隔: 60秒
  • 最大リトライ回数: 3回
  • 最大リトライ超過時: ログ出力して破棄

関連する環境変数:

環境変数説明デフォルト
AUDIT_LOG_CORE_POOL_SIZEコアスレッド数5
AUDIT_LOG_MAX_POOL_SIZE最大スレッド数30
AUDIT_LOG_QUEUE_CAPACITYキュー容量5000

Graceful Shutdown 時の動作: アプリケーション停止時、リトライキューに残っている監査ログのフラッシュを試みます。ただし、DB接続がすでに切断されている場合、すべてのログの処理は保証されません。


3. アプリケーションライフサイクル

3.1 Graceful Shutdown

idp-server は Kubernetes 環境での安全なシャットダウンのために、4段階のGraceful Shutdown機構を実装しています。

シャットダウンシーケンス:

SIGTERM受信
├── 1. GracefulShutdownLifecycle(5秒)
│ ├── Readiness Probe が DOWN に遷移
│ └── Kubernetes が Service エンドポイントから Pod を削除するのを待機
├── 2. Tomcat GracefulShutdown(最大30秒)
│ └── 処理中の HTTP リクエスト完了を待機
├── 3. ThreadPoolTaskExecutor シャットダウン(各最大30秒)
│ └── 3つの executor(セキュリティイベント/監査ログ/ユーザーライフサイクル)が順次停止
│ 各タスクは通常数ms で完了するため、実測では数秒以内に終了
└── 4. RetryScheduler @PreDestroy
└── リトライキューに残っているイベントのフラッシュを試行
(DB接続が切断済みの場合、処理は保証されない)

設定パラメータ:

設定環境変数デフォルト説明
シャットダウンディレイIDP_SERVER_SHUTDOWN_DELAY5sK8sエンドポイント削除待機時間
Tomcat グレースフル停止タイムアウト30s処理中リクエストの完了待機時間
非同期タスク完了待機30sThreadPoolTaskExecutor のタスク完了待機時間(3つの executor が順次停止、理論上最大90秒だが通常は数秒で完了)

Kubernetes 設定例:

spec:
terminationGracePeriodSeconds: 70 # delay(5s) + tomcat-graceful(30s) + executor-await(30s) + margin(5s)
containers:
- name: idp-server
lifecycle:
preStop:
exec:
command: ["sh", "-c", "sleep 5"] # shutdown delay と一致させる

ポイント:

  • terminationGracePeriodSeconds は「シャットダウンディレイ(5s) + Tomcat グレースフル停止タイムアウト(30s) + 非同期タスク完了待機(30s) + マージン」以上に設定してください
  • preStopsleep 値は IDP_SERVER_SHUTDOWN_DELAY と一致させてください

3.2 マルチインスタンスデプロイ

idp-server はステートレス設計のため、複数インスタンスの並行稼働が可能です。

アーキテクチャ:

                  ┌──────────────────┐
│ Load Balancer │
└──────┬───────────┘
┌─────────┼─────────┐
▼ ▼ ▼
┌─────────┐ ┌─────────┐ ┌─────────┐
│ Pod 1 │ │ Pod 2 │ │ Pod 3 │
│idp-server│ │idp-server│ │idp-server│
└────┬────┘ └────┬────┘ └────┬────┘
│ │ │
┌──────┴───────────┴───────────┴──────┐
│ Redis (セッション共有) │
└─────────────────────────────────────┘
┌──────┴───────────┴───────────┴──────┐
│ PostgreSQL (データ共有/RLS) │
└─────────────────────────────────────┘

設計上の特徴:

  • セッション: Redis に格納されるため、全インスタンスで共有
  • データ: PostgreSQL + RLS によりテナント分離を維持
  • スティッキーセッション: 不要(ロードバランサーでのセッション固定は不要)
  • スケーリング: HPA(Horizontal Pod Autoscaler)による自動スケール可能

4. 定期メンテナンスタスク

4.1 pg_cron ジョブ一覧

idp-server では PostgreSQL の pg_cron 拡張を使用して定期タスクを実行しています。

ジョブ名スケジュール対象DB処理内容
partman-maintenance毎日 02:00 UTCidpserverパーティション作成・削除(pg_partman)
archive-processing毎日 03:00 UTCidpserverアーカイブパーティションの外部エクスポート

実行順序の設計:

  • partman-maintenance(02:00)が先に実行され、保持期間を超えたパーティションをアーカイブスキーマに退避
  • archive-processing(03:00)が1時間後に実行され、アーカイブスキーマのテーブルを外部ストレージにエクスポート
  • エクスポート成功後にテーブルを削除、失敗時は翌日リトライ

📝 Note: デフォルトではエクスポート関数はスタブ実装(常に FALSE を返す)のため、アーカイブスキーマにテーブルが蓄積されます。クラウド環境に応じたエクスポートロジックの実装が必要です。詳細は データベース設定 を参照してください。

4.2 ジョブ監視

ジョブ登録状態の確認:

-- pg_cron ジョブ一覧(postgres DBで実行)
SELECT jobid, jobname, schedule, command, database, username, active
FROM cron.job
WHERE username = CURRENT_USER;

ジョブ実行履歴の確認:

-- 直近の実行結果(postgres DBで実行)
SELECT jobid, runid, job_pid, database, username, command,
status, return_message,
start_time, end_time
FROM cron.job_run_details
ORDER BY start_time DESC
LIMIT 20;

-- 失敗したジョブのみ抽出
SELECT jobid, runid, status, return_message, start_time
FROM cron.job_run_details
WHERE status = 'failed'
ORDER BY start_time DESC
LIMIT 10;

アラート用クエリ:

idp-server にはジョブ失敗時の通知機構は含まれていません。監視ツール(Datadog、CloudWatch 等)のカスタムクエリ監視で以下のクエリを定期実行し、failed_count > 0 でアラートを発出してください。

-- 直近24時間のジョブ失敗検出(postgres DBで実行)
SELECT COUNT(*) AS failed_count
FROM cron.job_run_details d
JOIN cron.job j ON d.jobid = j.jobid
WHERE j.jobname IN ('partman-maintenance', 'archive-processing')
AND d.status = 'failed'
AND d.start_time > now() - interval '24 hours';

パーティション一覧の確認:

-- 現在のパーティション一覧(idpserver DBで実行)
SELECT parent_table, partition_tablename, partition_range
FROM partman.show_partitions('public.audit_log')
ORDER BY partition_range;

-- アーカイブスキーマのテーブル蓄積確認
SELECT table_name, pg_size_pretty(pg_total_relation_size('archive.' || table_name))
FROM information_schema.tables
WHERE table_schema = 'archive'
ORDER BY table_name;

5. トラブルシューティング

5.1 起動失敗

データベース接続失敗

症状: アプリケーション起動時に HikariCP の接続プール初期化が失敗し、起動が中断される。

エラーログ例(認証失敗の場合):

{
"message": "HikariPool-1 - Starting...",
"level": "INFO"
}
{
"message": "Error starting Tomcat context. Exception: ...Failed to initialize pool: FATAL: password authentication failed for user \"idp_admin_user\"",
"level": "ERROR"
}
{
"message": "Application run failed",
"level": "ERROR",
"stack_trace": "...Caused by: com.zaxxer.hikari.pool.HikariPool$PoolInitializationException: Failed to initialize pool: FATAL: password authentication failed for user \"idp_admin_user\"\n...Caused by: org.postgresql.util.PSQLException: FATAL: password authentication failed for user \"idp_admin_user\"..."
}

キーワード: ログ内で以下のメッセージを検索してください。

  • Failed to initialize pool — HikariCP が接続プール作成に失敗
  • PSQLException: FATAL: — PostgreSQL が接続を拒否(認証失敗、DB不存在等)
  • Connection refused — ネットワーク的にDBへ到達不可

確認ポイント:

  1. DB接続URLが正しいか(DB_WRITER_URL, DB_READER_URL
  2. ユーザー名・パスワードが正しいか(DB_WRITER_USER_NAME, DB_WRITER_PASSWORD
  3. ネットワーク的にDBへ到達可能か
  4. PostgreSQL が起動しているか
# 接続テスト
psql -h <DB_HOST> -U <DB_USER> -d idpserver -c "SELECT 1;"

Redis 接続失敗

症状: Redis への接続に失敗する。ただし アプリケーションの起動自体は成功する(Redis は遅延接続のため、起動時には接続を試行しません)。実際のリクエスト処理時にエラーが発生します。

キャッシュ操作時のエラーログ(縮退動作 — サービスは継続):

{
"message": "Failed to find cache",
"logger_name": "org.idp.server.core.adapters.datasource.cache.JedisCacheStore",
"level": "ERROR",
"stack_trace": "redis.clients.jedis.exceptions.JedisConnectionException: Failed to create socket.\n...Caused by: java.net.UnknownHostException: <REDIS_HOST>: Name does not resolve..."
}

セッション操作時のエラーログ(認証フロー停止):

{
"message": "Failed to set key: <session-key>",
"logger_name": "org.idp.server.core.adapters.datasource.session.JedisSessionStore",
"level": "ERROR",
"stack_trace": "redis.clients.jedis.exceptions.JedisConnectionException: Failed to create socket.\n...Caused by: java.net.UnknownHostException: <REDIS_HOST>..."
}

セッション操作の場合は SessionStoreException がスローされ、認証フローが中断します。

キーワード: ログ内で以下のメッセージを検索してください。

  • JedisConnectionException: Failed to create socket — Redis への接続失敗
  • UnknownHostException — ホスト名解決失敗
  • Failed to find cache / Failed to put cache — キャッシュ操作失敗(縮退動作)
  • Failed to set key / Failed to get key — セッション操作失敗(サービス影響あり)

⚠️ 注意: ヘルスチェック(/actuator/health)は Redis 障害時でも UP を返す場合があります。Redis の状態を正確に監視するには、Redis 自体の監視(redis-cli ping)が必要です。

確認ポイント:

  1. REDIS_HOST, REDIS_PORT の設定値
  2. Redis が起動しているか
  3. パスワード設定(REDIS_CACHE_PASSWORD, REDIS_SESSION_PASSWORD
# 接続テスト
redis-cli -h <REDIS_HOST> -p <REDIS_PORT> ping

Flyway マイグレーション失敗

症状: スキーマ変更の適用に失敗し、アプリケーションが起動しない。

確認ポイント:

  1. Flyway 実行ユーザー(idp)の権限が十分か
  2. flyway_schema_history テーブルに失敗レコードがないか
  3. 手動でスキーマ変更を適用した場合、バージョン競合していないか
-- Flyway 状態確認
SELECT installed_rank, version, description, type, success
FROM flyway_schema_history
ORDER BY installed_rank DESC
LIMIT 10;

-- 失敗したマイグレーションの修復(注意: 原因特定後に実行)
-- DELETE FROM flyway_schema_history WHERE success = false;

必須環境変数の未設定

症状: 起動時に設定値エラーが発生する。

必須環境変数一覧(設定漏れで起動に失敗する主要項目):

環境変数用途
IDP_SERVER_API_KEY管理API認証キー
IDP_SERVER_API_SECRET管理API認証シークレット
ENCRYPTION_KEYデータ暗号化キー
DB_WRITER_USER_NAME / DB_WRITER_PASSWORDDB接続認証
CONTROL_PLANE_DB_WRITER_USER_NAME / CONTROL_PLANE_DB_WRITER_PASSWORDControl Plane用DB接続認証

詳細は 環境変数設定 を参照してください。

5.2 Redis 障害時の影響

Redis は キャッシュセッション の2つの用途で使用されており、障害時の影響は用途により異なります。

キャッシュ(JedisCacheStore)— 縮退動作

操作障害時の動作影響
put例外をcatch → エラーログ出力キャッシュ未保存(次回DBから取得)
find例外をcatch → Optional.empty() 返却常にDBから取得
exists例外をcatch → false 返却存在チェックが常にfalse
delete例外をcatch → エラーログ出力キャッシュ残留(TTLで自然消滅)
increment例外をcatch → 0 返却カウンタ未更新

影響: サービスは継続可能ですが、すべてのリクエストがDBに直接アクセスするため DB負荷が増大 します。

セッション(JedisSessionStore → OPSessionDataSource / ClientSessionDataSource)— 縮退動作

JedisSessionStore 自体は書き込み系操作で SessionStoreException をスローしますが、呼び出し元の OPSessionDataSource / ClientSessionDataSourceすべての例外を catch して graceful degradation します。

JedisSessionStore レベル(低レベル):

操作障害時の動作
setSessionStoreException throw
getOptional.empty() 返却
deleteSessionStoreException throw
setAdd / setRemoveSessionStoreException throw
expireSessionStoreException throw
ttl-2 返却

DataSource レベル(実際のアプリケーション動作):

操作障害時の動作ログメッセージ
registerエラーログ出力 → セッション未保存で継続Failed to save OP session (graceful degradation)
findByIdOptional.empty() 返却 → セッション未検出扱いFailed to find OP session (graceful degradation)
findByUser空リスト返却Failed to find OP sessions by user (graceful degradation)
deleteエラーログ出力 → 削除失敗で継続Failed to delete OP session (graceful degradation)
updateLastAccessedAtエラーログ出力 → 更新失敗で継続Failed to update OP session lastAccessedAt (graceful degradation)

影響: 認証フロー自体は 停止しません が、以下の機能が無効化されます。

機能Redis 正常時Redis 障害時
認証(ログイン)正常動作毎回再認証が必要(セッション未保存のため)
SSO(シングルサインオン)OPセッション共有で再認証不要無効(OPセッションが保存されない)
RP-Initiated Logout関連セッション一括削除不完全(セッション検索が空を返す)
Back-Channel Logoutクライアントセッション通知不完全(セッション情報を取得できない)

セッションベース認可の失敗

上記の通り、認証フロー自体は停止しませんが、セッションの有効性を検証するフロー(SSO時の authorizeWithSession)では明確なエラーが返却されます。

エラー発生の流れ:

1. 認証成功 → OPSession 作成試行 → Redis 保存失敗(graceful degradation でログ出力のみ)
2. セッション Cookie はブラウザに設定される(Redis の保存失敗とは無関係に設定される)
3. 次回リクエスト(SSO)→ Cookie から OPSession ID を取得 → Redis からセッション取得不可
4. OIDCSessionVerifier: opSession == null → sessionNotFound
5. クライアントに BAD_REQUEST を返却

セッション Cookie は設定されているにもかかわらず、Redis にセッションデータが存在しないため、セッションベースの認可(SSO)は BAD_REQUEST エラーで失敗します。クライアントアプリケーションは prompt=login を付与して完全な再認証フローにフォールバックする必要があります。

対処方針:

  1. Redis の復旧を優先する(認証は動くがユーザー体験が大幅に低下するため)
  2. ログで graceful degradation を検索し、Redis 障害の影響範囲を確認する
  3. Redis 復旧後、既存ユーザーは再ログインが必要になる

5.3 AUTH_SESSION 検証エラー(セッション同一性確認)

認証ポリシーで auth_session_binding_required(デフォルト: true)が有効な場合、認可フローの各ステップで IDP_AUTH_SESSION Cookie と AuthenticationTransaction(DB)の auth_session_id の一致を検証します。この検証は認可フローハイジャック攻撃を防止するためのセキュリティ機構です。

エラーメッセージ:

エラーHTTP Status原因
auth_session_mismatch: Missing AUTH_SESSION cookie. Please restart the authorization flow.401Cookie がブラウザから送信されていない
auth_session_mismatch: AUTH_SESSION cookie does not match. This authorization request may have been initiated by a different browser session.401Cookie の値が DB の値と一致しない

よくある原因と対処:

原因詳細対処
クロスオリジン環境で SameSite=Lax(デフォルト)認証UIとAPIが異なるドメインの場合、ブラウザが Cookie を送信しないIDP_AUTH_SESSION_SAME_SITE=None + IDP_AUTH_SESSION_SECURE=true に設定
HTTP 環境で Secure=true(デフォルト)HTTP では Secure 属性の Cookie をブラウザが送信しない開発環境のみ IDP_AUTH_SESSION_SECURE=false に設定
リバースプロキシによるパス変更Cookie path は /{tenantId}/ にスコープされており、プロキシでパスが書き換わると一致しないプロキシでパスプレフィクスを維持するか、session_config.cookie_path を設定
複数タブでの認可フロー各認可リクエストが新しい auth_session_id で Cookie を上書きするため、先に開始したタブの Cookie が無効になるユーザー操作上の制約(同時に複数の認可フローを開始しない)

確認手順:

# ログで AUTH_SESSION 検証失敗を検索
cat app.log | jq 'select(.message | contains("auth_session_mismatch"))'

設定値:

環境変数デフォルト説明
IDP_AUTH_SESSION_SAME_SITELaxCookie SameSite 属性(Lax / None
IDP_AUTH_SESSION_SECUREtrueCookie Secure フラグ(true / false

📝 Note: auth_session_binding_requiredfalse に設定すると検証をスキップできますが、認可フローハイジャック攻撃のリスクが生じるため、本番環境では推奨しません。

5.4 エラーレスポンス形式

すべてのAPIエラーは統一されたJSON形式で返却されます。

{
"error": "invalid_request",
"error_description": "詳細なエラーメッセージ"
}

例外クラスとHTTPステータスのマッピング:

例外クラスHTTP Statuserror
BadRequestException400 Bad Requestinvalid_request
MaliciousInputException400 Bad Requestinvalid_request
HttpMessageConversionException400 Bad Requestinvalid_request
DateTimeParseException400 Bad Requestinvalid_request
HttpMediaTypeNotSupportedException400 Bad Requestinvalid_request
UnauthorizedException401 Unauthorizedinvalid_request
ForbiddenException403 Forbiddeninvalid_request
NotFoundException404 Not Foundinvalid_request
HttpRequestMethodNotSupportedException405 Method Not Allowedinvalid_request
HttpMediaTypeNotAcceptableException406 Not Acceptableinvalid_request
ConflictException409 Conflictinvalid_request
SqlDuplicateKeyException409 Conflictinvalid_request
InvalidConfigurationException500 Internal Server Errorserver_error
その他 Exception500 Internal Server Errorserver_error

セキュリティ上の注意: MaliciousInputException(攻撃検知)の場合、クライアントには汎用的なエラーメッセージのみ返却し、攻撃の詳細はサーバーログに ERROR レベルで記録されます。

5.5 パフォーマンス問題

HikariCP 接続プール枯渇

症状: レスポンス遅延の増加、Connection is not available エラー。

確認ポイント:

  • DB_WRITER_MAX_POOL_SIZE(デフォルト: 30)が負荷に対して十分か
  • DB_READER_MAX_POOL_SIZE(デフォルト: 30)が負荷に対して十分か
  • スロークエリがコネクションを長時間占有していないか

関連設定:

環境変数デフォルト説明
DB_WRITER_MAX_POOL_SIZE30Writer 最大接続数
DB_WRITER_TIMEOUT30000 (30秒)接続取得タイムアウト
DB_WRITER_MAX_LIFETIME1800000 (30分)接続の最大生存時間
DB_READER_MAX_POOL_SIZE30Reader 最大接続数

非同期キュー飽和

idp-server は 3 つの非同期キューを持ち、キュー容量を超えるとリトライキューに退避します。

各キューの流入元API:

キュー流入元APIイベント発生タイミング
セキュリティイベントOAuth/OIDC エンドポイント(token, authorize, userinfo, CIBA)リクエスト毎に1イベント
監査ログ管理API(テナント/ユーザー/クライアント等の CRUD)管理操作毎に1イベント
ユーザーライフサイクルイベントアカウントロック、ユーザー削除極めて低頻度

セキュリティイベントキューは OAuth/OIDC トラフィックに比例して負荷が増加します。監査ログキューは管理 API の呼び出し頻度(一括ユーザーインポート等)に依存します。ユーザーライフサイクルイベントキューは実運用で飽和することはほぼありません。

処理フロー:

リクエスト処理スレッド
└── 非同期タスク投入
├── タスクキューに空きあり → 非同期スレッドで処理
└── タスクキューが満杯 → RejectedExecutionHandler
├── [セキュリティイベント] discardable → ログ出力して破棄
└── [全キュー共通] → リトライキューに退避
└── 60秒間隔でリトライ(最大3回)→ 超過で破棄

キュー設定一覧:

キューコアプール最大プールタスクキュー容量リトライキュー容量
セキュリティイベント53050005000(制限あり)
ユーザーライフサイクルイベント5101000無制限
監査ログ5305000無制限

セキュリティイベントの discardable 判定:

タスクキューが満杯になった際、以下の読み取り系イベントは低優先度として即座に破棄されます(INFO ログのみ)。認証成功・失敗等の重要イベントはリトライキューに退避されます。

  • userinfo_success — UserInfo 取得
  • inspect_token_success / inspect_token_expired — トークンイントロスペクション
  • identity_verification_application_findList / identity_verification_result_findList — 身元確認一覧参照
  • user_get — 管理API ユーザー詳細参照

監視すべきログメッセージ:

ログメッセージレベル意味
security event rejected, queuing for retryWARNOAuth/OIDC トラフィック過多 → リトライキュー退避
security event discarded (low priority)INFO読み取り系イベント破棄(正常動作)
retry queue full, dropping security eventERRORリトライキューも満杯 → イベント消失
audit log rejected, queuing for retryWARN管理API 呼び出し過多 → リトライキュー退避
max retries exceeded, dropping audit logERRORリトライ3回失敗 → 監査ログ消失
max retries exceeded, dropping security eventERRORリトライ3回失敗 → イベント消失

⚠️ 注意: 監査ログのリトライキューには容量制限がありません。各イベントのリトライ回数は最大3回で制限されていますが、管理 API への一括操作(大量ユーザーインポート等)でタスクキュー溢れが繰り返し発生する場合、リトライキューがメモリ上で膨張するリスクがあります。processing audit log retry queue: N events のログで蓄積数を監視してください。

関連する環境変数:

環境変数デフォルト説明
SECURITY_EVENT_CORE_POOL_SIZE5セキュリティイベント コアスレッド数
SECURITY_EVENT_MAX_POOL_SIZE30セキュリティイベント 最大スレッド数
SECURITY_EVENT_QUEUE_CAPACITY5000セキュリティイベント タスクキュー容量
SECURITY_EVENT_RETRY_QUEUE_CAPACITY5000セキュリティイベント リトライキュー容量
AUDIT_LOG_CORE_POOL_SIZE5監査ログ コアスレッド数
AUDIT_LOG_MAX_POOL_SIZE30監査ログ 最大スレッド数
AUDIT_LOG_QUEUE_CAPACITY5000監査ログ タスクキュー容量
USER_LIFECYCLE_EVENT_CORE_POOL_SIZE5ユーザーライフサイクル コアスレッド数
USER_LIFECYCLE_EVENT_MAX_POOL_SIZE10ユーザーライフサイクル 最大スレッド数
USER_LIFECYCLE_EVENT_QUEUE_CAPACITY1000ユーザーライフサイクル タスクキュー容量

Redis 接続プール枯渇

症状: セッション操作・キャッシュ操作のタイムアウト。

関連設定:

環境変数デフォルト説明
REDIS_MAX_TOTAL20キャッシュ用最大接続数
REDIS_SESSION_MAX_TOTAL20セッション用最大接続数
REDIS_CACHE_TIMEOUT10000 (10秒)キャッシュ用接続タイムアウト
REDIS_SESSION_TIMEOUT10000 (10秒)セッション用接続タイムアウト

Tomcat スレッド枯渇

症状: 新規リクエストの受付拒否、レスポンスタイムの急増。

関連設定:

環境変数デフォルト説明
SERVER_TOMCAT_THREADS_MAX300最大ワーカースレッド数
SERVER_TOMCAT_THREADS_MIN_SPARE50最小スペアスレッド数

6. 運用チェックリスト

日次確認

  • ヘルスチェック(/actuator/health)が UP を返すこと
  • pg_cron ジョブ(partman-maintenance, archive-processing)が成功していること
  • ERROR レベルのログが異常増加していないこと
  • 監査ログのリトライキューが蓄積していないこと

週次確認

  • パーティションが適切に作成・削除されていること
  • アーカイブスキーマにテーブルが蓄積していないこと(エクスポート関数実装済みの場合)
  • HikariCP 接続プール使用率が上限に達していないこと
  • Redis メモリ使用量が閾値以内であること

デプロイ時確認

  • Flyway マイグレーションが正常に完了していること(flyway_schema_history
  • Readiness Probe が UP を返していること
  • テナント固有ヘルスチェック(/{tenant-id}/v1/health)が正常であること
  • ログ出力が正常に行われていること(JSON形式、MDCフィールド付与)

🔗 関連ドキュメント