【連載 第5回】WebアプリをSSO化せよ。Apacheとmod_auth_openidcで実装するOpenID Connect連携

「ID・パスワード入力画面」を、アプリケーションから捨て去る日。

こんにちは!「LINUX工房」管理人の「リナックス先生」です。
前回(第4回)は、KeycloakとActive Directoryを連携させ、社員全員のユーザー情報を同期することに成功しました。
これで「通行証(ID)」の発行所は完成です。

しかし、肝心の「アトラクション(利用するアプリ)」がまだありません。
SSOの真価は、「Webアプリ側が独自のログイン画面を持たず、認証をすべてKeycloakに丸投げする」ことにあります。
これにより、アプリ開発者はセキュリティ実装の重圧から解放され、ユーザーはパスワード地獄から解放されるのです。

コウ君

先生、いよいよアプリですね!
でも、Webアプリの認証って難しそう…。
PHPとかJavaのプログラムをガリガリ書かないといけないんですか?
僕、インフラエンジニア志望なのでプログラミングはちょっと苦手で…。

リナックス先生

安心して、コウ君。
今回は「リバースプロキシ型」のアプローチをとるわ。
Webサーバー(Apache)のモジュール機能を使うから、プログラムは一行も書かなくてOKよ。
設定ファイル(conf)を数行書くだけで、既存のどんなWebサイトも「会員専用サイト」に変身させられるの。
これができれば、社内の古いWebシステムも簡単にSSO化できるわよ!

本記事では、世界標準のプロトコル「OpenID Connect (OIDC)」を使用し、Apache WebサーバーとKeycloakを連携させる手順を徹底解説します。

🚀 本連載のカリキュラム(全8回)


1. OIDC連携の仕組みと「mod_auth_openidc」

構築に入る前に、今回の主役であるmod_auth_openidcについて理解しておきましょう。

認証を代行する「門番」

通常、Webアプリを作る際は「ログイン画面」や「セッション管理」の機能をプログラムする必要があります。
しかし、Apacheのモジュールである mod_auth_openidc を使うと、Webサーバー自体が「門番」となり、認証されていないアクセスを自動的にKeycloakへ転送してくれます。

  1. ユーザーがWebページにアクセスする。
  2. Apache(門番)が「通行証(セッション)」を確認する。なければKeycloakへ追い返す(リダイレクト)。
  3. ユーザーはKeycloakでログインする。
  4. Keycloakが「認証コード」を持ってApacheに戻す。
  5. Apacheが裏でKeycloakと通信し、トークンを取得してユーザーを通す。

この仕組みを使えば、HTMLだけの静的なサイトや、認証機能を持たない古いCGIプログラムなども、簡単にSSO化することができます。


2. Webサーバー(Apache)コンテナの構築

それでは構築に入ります。
AlmaLinux 9ベースのApacheコンテナを作成し、そこにSSOモジュールをインストールします。

2-1. Dockerfileの作成

既存の httpd イメージには mod_auth_openidc が入っていないため、自作のイメージを作ります。
作業ディレクトリに web フォルダを作成します。

mkdir -p ~/sso-project/web
cd ~/sso-project/web
vi Dockerfile

以下の内容を記述します。

FROM almalinux:9

# Apacheとmod_auth_openidc、SSLモジュールをインストール
RUN dnf install -y httpd mod_ssl mod_auth_openidc && \
    dnf clean all

# コンテンツ配置用ディレクトリ
RUN mkdir -p /var/www/html

# 証明書配置用ディレクトリ
RUN mkdir -p /etc/httpd/conf/certs

# Apacheをフォアグラウンドで実行
CMD ["/usr/sbin/httpd", "-D", "FOREGROUND"]

2-2. docker-compose.yml の追記

作成したDockerfileを使ってコンテナを起動するように、docker-compose.yml を編集します。

cd ~/sso-project
vi docker-compose.yml

services: セクションに以下を追記します。

  # --- Webアプリケーション (Apache + OIDC) ---
  webapp:
    build: ./web
    container_name: sso-webapp
    environment:
      # Keycloak連携に必要な環境変数(後で使います)
      OIDC_PROVIDER_METADATA_URL: https://sso.linuxkoubou.local/realms/DemoCorp/.well-known/openid-configuration
      OIDC_CLIENT_ID: my-webapp
      OIDC_CLIENT_SECRET: "SET_ME_LATER"
      OIDC_REDIRECT_URI: https://app.linuxkoubou.local/redirect_uri
      OIDC_CRYPTO_PASSPHRASE: "secret_passphrase_for_cookie_encryption"
    volumes:
      # SSL証明書を共有
      - ./certs/server.crt:/etc/httpd/conf/certs/server.crt:ro
      - ./certs/server.key:/etc/httpd/conf/certs/server.key:ro
      # 設定ファイルをマウント
      - ./web/oidc.conf:/etc/httpd/conf.d/oidc.conf
      # コンテンツをマウント
      - ./web/html:/var/www/html
    ports:
      - "443:443" # ホストの443番を使用(Keycloakと被る場合はIPを変えるかポートを変える)
    networks:
      - sso-net
    depends_on:
      - keycloak

⚠️ 重要:ポート重複の回避
第3回でKeycloakを443番で起動している場合、このままではポートが競合して起動できません。
本番環境ではリバースプロキシで振り分けますが、今回は学習用として、Keycloak側のポートを「8443:8443」に変更するか、Webアプリ側を「8080:443」にするなどして回避してください。
※本記事では、Keycloak=8443、Webアプリ=443(HTTPS) の構成を前提に進めます。


3. Keycloakでの「クライアント」登録

Webアプリを起動する前に、Keycloak側で「このアプリからの接続を許可する」設定が必要です。
これを「クライアント登録」と呼びます。

3-1. クライアントの作成

  1. Keycloak管理コンソールにログインし、「DemoCorp」レルムを選択します。
  2. 左メニューの 「Clients」 をクリックし、「Create client」 を押します。
  3. 以下の設定を入力します。
    • Client type: OpenID Connect
    • Client ID: my-webapp
    • Name: 社内ポータル(任意の表示名)
  4. 「Next」をクリックします。

3-2. 機能設定 (Capability config)

SSOの動作モードを決めます。

  • Client authentication: ON
    (これをONにすると、IDだけでなく「シークレット(秘密鍵)」を使った厳密な認証になります。Webアプリ連携では必須です)
  • Authentication flow: Standard flow (ON), Direct access grants (OFF)

「Next」をクリックします。

3-3. アクセス設定 (Access settings)

「どこへリダイレクトして良いか」という許可リストです。
ここを間違えると、ログイン後にエラー画面になります。

  • Root URL: https://app.linuxkoubou.local/
  • Home URL: https://app.linuxkoubou.local/
  • Valid redirect URIs: https://app.linuxkoubou.local/redirect_uri
  • Web origins: + (Root URLと同じ許可を与える)

「Save」をクリックして保存します。

3-4. クライアントシークレットの取得

保存後、画面上部の 「Credentials」 タブをクリックします。
Client secret という項目の「目のアイコン」をクリックし、表示された文字列をコピーしてください。
これが、ApacheがKeycloakと通信するための「合言葉」になります。


4. ApacheへのSSO設定投入

コピーしたシークレットを使って、Apacheの設定ファイルを作成します。

4-1. 設定ファイル (oidc.conf) の作成

cd ~/sso-project/web
vi oidc.conf

以下の内容を記述します。KeycloakのURLやシークレットは環境に合わせて書き換えてください。

# SSL設定 (自己署名証明書)
SSLEngine on
SSLCertificateFile /etc/httpd/conf/certs/server.crt
SSLCertificateKeyFile /etc/httpd/conf/certs/server.key

# OIDC設定
OIDCProviderMetadataURL ${OIDC_PROVIDER_METADATA_URL}
OIDCClientID ${OIDC_CLIENT_ID}
OIDCClientSecret ${OIDC_CLIENT_SECRET}

# リダイレクトURI (Keycloakに登録したものと完全一致させること)
OIDCRedirectURI ${OIDC_REDIRECT_URI}

# Cookie暗号化用パスフレーズ (ランダムな文字列)
OIDCCryptoPassphrase ${OIDC_CRYPTO_PASSPHRASE}

# Keycloakが自己署名証明書の場合、検証をスキップする設定
OIDCSSLValidateServer Off

# 全ページをSSO保護する場合
<Location />
   AuthType openid-connect
   Require valid-user
</Location>

4-2. docker-compose.yml のシークレット更新

先ほど取得したシークレットを、docker-compose.yml の環境変数 OIDC_CLIENT_SECRET に書き込んでください。

4-3. テスト用コンテンツの作成

ログイン成功後に表示されるページを作ります。

mkdir html
vi html/index.html
<html>
<body>
    <h1>認証成功!</h1>
    <p>ここはKeycloakで保護されたエリアです。</p>
    <p>ようこそ、<b>%{REMOTE_USER}s</b> さん。</p>
</body>
</html>

4-4. コンテナのビルドと起動

cd ~/sso-project
# 新しいイメージをビルドして起動
sudo docker compose up -d --build webapp

5. 動作確認と認証フローの体験

すべての準備が整いました。ブラウザからアクセスしてみましょう。

  1. ブラウザで https://app.linuxkoubou.local/ にアクセスします。
  2. Apacheが未認証を検知し、Keycloakのログイン画面へリダイレクトします。
  3. アドレスバーが sso.linuxkoubou.local に変わっていることを確認します。
  4. 前回作成したADユーザー(sso.user01)でログインします。
  5. 認証が成功すると、app.linuxkoubou.local に戻ってきます。
  6. 「認証成功!」という画面が表示されれば、SSO連携は完了です!

Keycloak側でのセッション確認

Keycloak管理コンソールの「Sessions」メニューを見ると、今ログインしたユーザーのセッションが表示されているはずです。
ここから「Sign out」ボタンを押せば、ユーザーを強制的にログアウトさせることも可能です。


6. 【プロの技】リダイレクトURIとCookie設定の落とし穴

OIDC連携で最もハマりやすいポイントを解説します。

罠1:Redirect URI mismatch

Keycloakに設定した「Valid redirect URIs」と、Apache設定の「OIDCRedirectURI」は、一言一句完全に一致している必要があります。
末尾のスラッシュの有無(/)や、httphttps の違いだけでもエラーになります。
エラー画面に「Invalid parameter: redirect_uri」と出たら、ここを疑ってください。

罠2:Cookieの肥大化とエラー

mod_auth_openidc はデフォルトで、認証情報(トークン)をブラウザのCookieに保存します。
ADの所属グループが多いユーザーなどは、トークンサイズが大きくなりすぎて「400 Bad Request」や「500 Internal Server Error」になることがあります。
これを防ぐために、本番環境では以下の設定を追加し、データ自体はサーバーのメモリ(キャッシュ)に保存することを推奨します。

OIDCSessionType server-cache

まとめ:Basic認証はもう古い

お疲れ様でした!
これで、Apache上のWebサイトをKeycloakの認証傘下に入れることができました。
もう .htpasswd を作ってBasic認証を設定する必要はありません。

今回の達成項目:

  • Apache + mod_auth_openidc のコンテナを構築した。
  • KeycloakでOIDCクライアント(Confidential)を作成した。
  • Webアプリへのアクセス時、自動的にログイン画面へ遷移することを確認した。
  • ADユーザーでWebアプリにログインできた。
コウ君

すごい! アプリ側にはログイン画面を作ってないのに、勝手に認証されてユーザー名まで表示されてる!
これがSSOの威力なんですね。
でも先生、毎回IDとパスワードを入れるのは変わらないですね。
「PCにログインしてたら、そのまま入れる」っていうのはまだですか?

お待たせしました。それこそが、Windows環境におけるSSOの到達点「統合Windows認証 (IWA)」です。
次回、【第6回】Windows統合認証 (IWA)では、Kerberosプロトコルを駆使して、パスワード入力すら不要になる「真のシングルサインオン」を実現します。
難易度は上がりますが、効果は絶大です。お楽しみに!

▼ 自宅ラボ環境を作ろう ▼

DockerやADも快適に動く
「おすすめVPS」

VPSランキングを見る

認証基盤エンジニアへ
「ITエンジニア転職」

転職エージェントを見る

コメント