0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【書評】 実践 Keycloak ―OpenID Connect、OAuth 2.0を利用したモダンアプリケーションのセキュリティー保護

0
Posted at

はじめに

認証・認可を自前で作り込むのは、設計の観点でもっとも割に合わない領域の一つです。パスワードの保管、多要素認証、セッション管理、SSO、トークンの失効と、考えるべきことが多く、しかも間違えたときの被害が大きいためです。

本書『実践 Keycloak』は、その課題に対して OSS の IAM(Identity and Access Management)である Keycloak を軸に答えを出す一冊です。原書はプロジェクトリーダーとコアデベロッパーが自ら執筆したもので、日本語版では Keycloak 18.0.2(Quarkus ベース)に合わせて全体が書き直されています。

この記事では、設計・アーキテクチャに関心のあるエンジニア向けに、本書の構成と「設計判断として持ち帰れるポイント」を中心にまとめます。

記事中のバージョンや設定項目名は、本書が前提とする Keycloak 18.0.2 の内容に基づきます。新しいバージョンでは管理コンソールの画面や一部の設定項目が変わっているため、実際の導入時は公式ドキュメントも併せて確認してください。

本書の概要

項目 内容
書名 実践 Keycloak ―OpenID Connect、OAuth 2.0を利用したモダンアプリケーションのセキュリティー保護
著者 Stian Thorgersen、Pedro Igor Silva
訳者 和田 広之、田村 広平、乗松 隆志、田畑 義之
対象バージョン Keycloak 18.0.2(Quarkus 版)
想定読者 開発者、システム管理者、セキュリティーエンジニア
日本語版の追加 補章「クライアントポリシーによるセキュリティー保護」

全体の構成

本書は 4 つのパートに分かれています。

  1. 第1部:Keycloak の基礎と、サンプルアプリの保護
  2. 第2部:OIDC / OAuth 2.0 の理解と、各種アプリの保護方法
  3. 第3部:本番運用に向けた設定、ユーザー管理、拡張
  4. 第4部:セキュリティー上の考慮事項

第1部:まず動かして全体像をつかむ

1章:Keycloak を始めよう

Keycloak は SPA、モバイル、REST API といったモダンなアプリケーションを意識した IAM です。認証をアプリから切り離して Keycloak に委譲することで、アプリ側はユーザーのクレデンシャルに触れずに済みます。代わりに受け取るのは、必要な権限だけを持つセキュリティートークンです。

本書では最初に、次の 3 つの方法で起動できることが示されます。

  • Docker のコンテナとして起動する
  • 物理マシンや VM 上で JVM を使って起動する
  • Kubernetes(Operator を含む)上で動かす

その上で、管理コンソールを使って以下を作成します。この流れが 2 章以降の土台になります。

  • レルム:他から完全に分離されたテナントのような単位
  • ユーザー、グループ、ロール

設計上の見どころは レルム の考え方です。社内向けと顧客向けでレルムを分ける、といった形で 1 つの Keycloak を複数の用途に使い分けられます。

2章:サンプルアプリケーションを保護する

フロントエンド(SPA)とバックエンド(REST API)の最小構成で、OIDC による保護を体験します。ここで押さえておきたいのは次の 2 点です。

  1. ログインは 認可コードフロー で行い、認可コードを ID トークン・アクセストークン・リフレッシュトークンに交換する
  2. バックエンドは Keycloak の公開鍵でトークンの署名を検証するため、リクエストごとに Keycloak へ問い合わせる必要がない

クライアント登録時の Valid Redirect URIs は、悪意あるサイトが正規アプリになりすますのを防ぐ重要な設定として強調されています。

第2部:プロトコルを理解し、アプリの種類ごとに守る

3章:標準仕様の整理

OAuth 2.0、OIDC、JWT、SAML 2.0 を簡潔に整理する章です。特に役立つのは、どのフローを使うかの判断基準です。

状況 使うフロー
アプリ自身の権限でリソースにアクセスする クライアントクレデンシャルズフロー
ブラウザがない、または入力に制約があるデバイス デバイスフロー
上記以外 認可コードフロー(PKCE 併用)

また、使うべきでないフローも明確に示されています。

  • インプリシットフロー(安全でないとされている)
  • リソースオーナーパスワードクレデンシャルズフロー(アプリにパスワードを直接渡すことになる)

JWT については、alg=none の受け入れや、RSA 公開鍵を HMAC の共通鍵として扱ってしまう実装ミスといった既知の落とし穴が紹介されています。自前で検証ロジックを書くより、信頼できるライブラリかイントロスペクションエンドポイントを使う方が安全という立場です。

4章:OIDC によるユーザー認証

本書専用のプレイグラウンドアプリを使い、リクエストとレスポンスの中身を実際に見ながら OIDC を理解します。扱う内容は次のとおりです。

  • ディスカバリーエンドポイント(/.well-known/openid-configuration)
  • 認証リクエストの主なパラメータ(prompt、max_age、login_hint など)
  • ID トークンの構造とクレーム
  • UserInfo エンドポイント
  • ログアウト

実務で役に立つ指摘として、ユーザーの識別には変わりうる preferred_username ではなく、不変の sub クレームを使うべき、という点があります。

ログアウト方式の整理

SSO に比べて、ログアウト(特にシングルログアウト)は難しい問題です。本書は各方式の特性を率直に整理しています。

方式 特徴
トークンの短い有効期間に任せる 最もシンプルで堅牢。ただし反映に数分かかる
Session Management iframe で Cookie を監視する方式。ブラウザのサードパーティコンテンツ制限の影響を受け、有効性が下がっている
Back-Channel Logout Keycloak がアプリへログアウトトークンを送る。即時性が必要な場合に有効。ただしクラスター構成のアプリでは実装に工夫が要る
Front-Channel Logout 非表示 iframe を使うため、信頼性に欠ける面がある

結論としては、短いセッションとトークン寿命を基本とし、即時性が必要な場合のみ Back-Channel Logout を使うという整理です。

5章:OAuth 2.0 によるアクセス認可

アクセストークンの取得から検証までを扱います。設計上もっとも重要なのは、アクセストークンの権限をどう絞るかという話です。

アクセス権限を制限する手段は 3 つあります。

  1. Audience:そのトークンを受け入れるべきサービスを限定する
  2. ロール:アプリがユーザーに代わって使えるロールを制御する
  3. スコープ:クライアントスコープとして定義し、同意画面と連動させる

Full Scope Allowed がデフォルトで ON になっており、ユーザーの全ロールがトークンに入る点には注意が必要です。本書も、本番ではこのままにしないよう述べています。

スコープ設計のヒントも実用的です。

albums:view
albums:create
albums:delete

このようにサービス名をプレフィックスにして、組織内で一意になるようにします。さらに、閲覧権限だけをデフォルトにして作成・削除をオプションにすると、必要になった時点で追加の同意を求める インクリメンタル認可 を実現できます。

トークン検証の二択

方式 長所 短所
イントロスペクションエンドポイント 実装が簡単。セッション失効も反映される 通信コストと認可サーバーへの負荷
JWT をローカル検証 低レイテンシで認可サーバーへの負荷も小さい 検証の実装ミスのリスク。失効の反映が遅れる

後者の検証では、署名、有効期限、発行者、Audience、タイプの確認が必要です。Keycloak のアダプターは後者の方式を採っています。

6章:アプリの種類別の保護方法

この章は設計判断の宝庫です。まず 内部アプリ(ファーストパーティ)と外部アプリ(サードパーティ)の区別から始まり、Consent Required の設定を分けることで同意画面の要否を切り替えます。

Web アプリの 4 パターン

パターン 方針
サーバーサイド Web アプリ コンフィデンシャルクライアント。ID トークンで HTTP セッションを確立
専用 REST API を持つ SPA 専用 API 側でコードフローを処理し、SPA とは Cookie セッションで連携
仲介 REST API を持つ SPA BFF パターン。トークンをブラウザに出さず、仲介 API が外部 API を呼ぶ
外部 REST API を直接呼ぶ SPA パブリッククライアント。簡易だがトークン漏洩リスクが高い

最後のパターンでは、リフレッシュトークンの短寿命化とローテーション、PKCE の使用、XSS 対策といった緩和策を組み合わせます。最終的には「セキュリティーと利便性・コストのトレードオフを管理者が判断する」という立場です。

共通して「やってはいけない」こと

  • ログイン画面をアプリ内に持ち、パスワードをトークンと交換する(ROPC)
  • Keycloak のログイン画面を iframe で埋め込む

どちらも、アプリが侵害されたときにクレデンシャルが漏れる、多要素認証や SSO の恩恵を受けられない、といった問題を抱えます。

ネイティブ/モバイルアプリ

PKCE 付きの認可コードフローを使い、ブラウザで認証します。埋め込み WebView は推奨されず、外部ブラウザや In-App ブラウザタブを使います。リダイレクト URI は、安全性の高い順に Claimed HTTPS スキーム、カスタム URI スキーム、ループバックなどが示されています。ブラウザを使えない CLI やサーバーではデバイスフローが適しています。

API・マイクロサービス

アクセストークンを Bearer トークンとして伝播すれば、マイクロサービス間でもエンドツーエンドのユーザー認証が成立します。サービス自身が主体の場合は、サービスアカウントとクライアントクレデンシャルズフローを使います。gRPC や WebSocket でも同じ考え方が適用できます。

7章:アプリとの統合

Go、Java、JavaScript、Node.js、Python といった言語ごとの統合方法に加えて、リバースプロキシで言語を問わず保護するアプローチも紹介されています。改修できないレガシーなアプリを守る選択肢として覚えておく価値があります。

8章:認可の戦略

「ユーザーはリソースにアクセスできるか?」に答えるために、次の戦略を比較します。

戦略 概要 注意点
RBAC ロールで制御 ロール数の爆発に注意。細粒度の認可には向かない
GBAC グループにロールを付与し、メンバーに継承 グループ情報はトークンに自動では入らない。マッパーが必要
スコープ ユーザーの同意に基づく委譲 システムを「クライアント」から守る発想
ABAC トークンのクレームで柔軟に制御 柔軟だが実装と管理が難しい
中央集権型認可 Keycloak の認可サービスに判断を外部化 追加通信の問題はトークンベース認可で緩和

特に示唆的なのは、次の対比です。

// ロールに密結合したコード
if (User.hasRole("manager")) { ... }

// リソースに紐づく判断を外部化したコード
if (User.canAccess("Manager Resource")) { ... }

前者は要件が変わるたびに再デプロイが必要になりますが、後者は認可サービス側のポリシー変更だけで済みます。認可ロジックをアプリから切り離すという設計思想が、ここで明確に語られています。

また、複合ロールを多用するよりも、グループにロールを割り当てる方が自然なモデルだという推奨もあります。

第3部:本番運用と拡張

9章:本番環境の設定

アーキテクチャの観点で最も読み応えがある章です。start-dev から start に切り替えるところから始まり、次の要素を順に設定していきます。

  1. ホスト名:フロントエンド URL、バックエンド URL、管理用 URL を区別する
  2. TLS:外部からの通信は常に HTTPS。レルムごとに TLS 制約も設定できる
  3. データベース:デフォルトの H2 は本番で使わない。コネクションプールも調整する
  4. クラスタリング:Infinispan による分散キャッシュ
  5. リバースプロキシ:HAProxy を例に構成する

押さえておきたい設計ポイント

  • 複数インスタンスを 単一の issuer に見せるためにホスト名を固定する。そうしないとトークンや Cookie が発行元のインスタンスでしか通用しなくなる
  • 管理コンソールは /admin/ 配下をプロキシで保護し、公開しない
  • セッション系キャッシュは owners="2" とすることで、1 ノード障害でも状態を失わない
  • realms や users のキャッシュはローカルキャッシュであり、ノード間では複製されない
  • セッションアフィニティ をプロキシ側で維持し、キャッシュ参照のオーバーヘッドを抑える
keycloak.conf(章の設定の要点)
hostname=mykeycloak
hostname-strict-backchannel=true
db=postgres
cache=ispn
proxy=reencrypt

最後に、1 ノードを停止しても再認証なしで管理コンソールを使い続けられることを確認し、ロードバランシングとフェイルオーバーを実際にテストする流れになっています。

10章:ユーザー管理

ユーザー管理機能の詳細に加えて、LDAP、SNS、外部 IdP といった外部ソースからのユーザー連携を扱います。

11章:ユーザー認証

2 要素認証やセキュリティーキーなど、Keycloak が提供する認証機能を扱います。認証手段を強化してもアプリ側の変更が要らない、という委譲の利点がここで生きてきます。

12章:トークンとセッションの管理

Keycloak は認証・認可だけでなく、サーバーサイドのセッションを軸にトークンを管理するシステムでもあります。

2 階層のセッション

  • ユーザーセッション(SSO セッション):HTTP セッションに近い存在
  • クライアントセッション:各クライアントでの活動を追跡し、リフレッシュトークンの寿命を決める

それぞれに最大時間とアイドル時間があり、レルム単位で設定した上でクライアント単位に上書きできます。

トークン寿命の設計

トークン 性質
ID/アクセストークン 短命(デフォルト5分)。漏洩時の影響を小さくする
リフレッシュトークン 長命。クライアントセッションに紐づく

注意点として、JWT をローカル検証している場合、セッションが失効してもトークンが期限内なら受け入れてしまうことがあります。この状況が許容できないなら、イントロスペクションの併用を検討します。

漏洩への備え

  • リフレッシュトークンのローテーション(Revoke Refresh Token)
  • not-before ポリシーによる時間ベースの一括無効化
  • トークン失効エンドポイント(RFC 7009)の利用

パブリッククライアント向けの 送信者制約付きトークン(DPoP) は、本書の執筆時点では仕様がドラフト段階で、Keycloak には未実装と記されています。

13章:Keycloak の拡張

ログイン画面などの見た目のカスタマイズと、多数の拡張ポイント(プロバイダー)によるカスタム実装を紹介します。認証メカニズム、ユーザーストア連携、トークン内容のカスタマイズなどが例として挙げられています。

第4部:セキュリティー考慮事項

14章:Keycloak とアプリケーションのセキュリティー保護

Keycloak 自体を守るための実践的なチェックリストとして読めます。

  • 通信:エンドツーエンドの暗号化。TLS パススルーが最も安全で、難しい場合は再暗号化
  • ホスト名:固定する。Host ヘッダーを信用すると、パスワードリセットメールに攻撃者のリンクを仕込まれる恐れがある
  • 署名鍵:定期的なローテーション(月 1 回程度が目安)。Active/Passive/Disabled の状態遷移で、無停止で入れ替えられる
  • アップデート:LTS がなくローリングリリースなので、アップグレードの自動化とテストが前提
  • シークレット:外部 Vault から読み込める
  • データベース:ファイアウォール、認証・アクセス制御、暗号化(バックアップも含む)
  • クラスター通信:ファイアウォールと、必要に応じて暗号化
  • ユーザーアカウント:パスワードポリシー、ブルートフォース検出、保存する個人情報の最小化

クライアント設定のセキュリティー観点

設定 推奨
Consent Required サードパーティやネイティブアプリでは ON
Access Type 秘密を保持できるなら confidential
Implicit Flow Enabled 原則 OFF
Direct Access Grants Enabled 原則 OFF
Valid Redirect URIs 完全一致が望ましく、ワイルドカードは避ける

署名アルゴリズムについては、可能なら RSA より ECDSA を選び、トークン検証を強制的にイントロスペクション経由にしたい場合は HMAC を使う、という整理もあります。

日本語版補章:クライアントポリシー

設定ミスを人間のチェックに頼らず、仕組みで防ぐための機能です。

  • ワイルドカードを含むリダイレクト URI を拒否する
  • PKCE(S256)を必須にし、未設定なら自動で設定する
  • Consent Required を自動で ON にする
  • state を含まない認可リクエストを拒否する

条件(例:特定のクライアントロールを持つ)とプロファイル(例:fapi-1-baseline)を組み合わせて、アプリの種類ごとにセキュリティー水準を変えられます。実際に、プロファイルに従わない認可リクエストがエラーになり、従う場合は通常どおりログイン画面に進むことを、ブラウザから確認する手順が載っています。

設計の観点から見た本書の価値

  • 判断基準が明示されている:「このフローは使うな」「この構成は避けよ」と推奨と非推奨がはっきり書かれており、仕様書だけでは迷うところで背中を押してくれます。
  • トレードオフが隠されていない:SPA がトークンを直接扱う危うさ、JWT ローカル検証と失効のずれ、複合ロールの運用負荷などが正直に書かれています。
  • 運用まで視野に入っている:HA 構成、キャッシュ、セッションアフィニティ、鍵のローテーション、アップデート方針まで踏み込みます。
  • 手を動かして理解できる:プレイグラウンドアプリでパラメータを変えながら挙動を確認できます。

気をつけたい点

  • 対象は Keycloak 18.0.2 で、現行バージョンとは画面や一部の設定が異なる
  • 管理コンソールの操作手順が多く、バージョンが離れるほど読み替えが必要
  • 認可サービスやカスタムプロバイダーは概要止まりのため、深く使うなら公式ドキュメントが必要

こんな人におすすめ

  • 認証・認可を自前実装から IdP への委譲 へ移行したい
  • SPA、モバイル、マイクロサービスが混在する環境で、トークンの扱いを設計したい
  • Keycloak を本番運用する前に、可用性と安全性の勘所を押さえておきたい
  • OAuth 2.0/OIDC を「仕様」ではなく「動くもの」として理解したい

まとめ

本書の最大の価値は、Keycloak の使い方に留まらず、モダンなアプリケーションにおける認証認可アーキテクチャの考え方を一通り学べる点にあります。

認証は IdP に委譲し、認可コードフロー + PKCE を基本にする。トークンの権限は絞り、SPA は BFF を第一候補とし、認可ロジックはアプリから切り離す。本番では単一 issuer・TLS・外部 DB・クラスタリングを整え、トークンの寿命・ローテーション・失効で漏洩に備え、設定ミスはクライアントポリシーで仕組みとして防ぐ。この一連の考え方が通して学べます。

認証認可の設計に関わるエンジニアには、手元に置いておく価値のある一冊です。

参考

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?