Tech Sketch Bucket of Technical Chips by TIS Inc.

OpenAMによるシングルサインオン(2)リバースプロキシー編

Pocket

前回 はシングルサインオンのプロダクトOpenAMのエージェントを用い、WebアプリケーションjPetStoreのソースコードを改変してシングルサインオン化する手順を紹介しました。今回はリバースプロキシーOpenIGを用い、ソースコードの改変なしにシングルサインオン化する手順を紹介します。


OpenIGとは

リバースプロキシーとは

既存のWebアプリケーションをシングルサインオン化するにあたっては、Webアプリケーションのソースコードが公開されていない場合、あるいは改変が難しい場合はリバースプロキシーを使用します。
リバースプロキシーはブラウザーとアプリケーションサーバーの中間に位置し、URL・レスポンスデータの内容からログインページを検知するとユーザー認証の処理を自動で行うように設定します。

今回はForgeRock社において開発されるリバースプロキシー OpenIG を用い、そこにOpenAMのエージェントもインストールします。これによりOpenIG使用時はOpenAMでユーザー認証済みの状態になり、シングルサインオンの対象となります。
OpenIGにはWebアプリケーションのユーザー認証が必要なページ・認証時にPOSTする内容を登録し、そのページが呼ばれた場合にOpenAMでのユーザー認証済みの情報をWebアプリケーションにPOSTすることでユーザー認証処理が自動で行われます。

openig_0.jpg

OpenIGのインストール

OpenIG (WARファイルです)はJavaアプリケーションサーバー上で稼働します。今回は Tomcat7.0.39 を用います。
OpenIGのWARファイルは ForgeRock社のサイト から入手できます。今回使用したバージョンは2.2.0-SNAPSHOTです。
このWARファイルをTomcatのwebapp/ROOTに展開し、さらに前回紹介したOpenAMのエージェントをインストールします。

OpenIGの環境設定

OpenIGがリバースプロキシーとしてどのように振る舞うかの環境設定は$HOME/.ForgeRock/OpenIG/config.jsonで行います。
この中では、送受信するHTTPリクエストのハンドリング方法をJSON(JavaScript Object Notation)形式

で指定していきます。この型(type)にはHTTPレスポンスの内容を解析する、POSTデータを送信するといった物が用意されています。
以降、この環境設定の具体例を示していきます。

単なるリバースプロキシーの設定

まずは単純にブラウザーより受け付けたHTTPリクエストをjPetStoreのアプリケーションサーバーにそのまま転送する設定を見ていきます。config.jsonの設定内容を示します。

名称がHandlerServletの箇所は型がHandlerServletなので(処理の入り口です)、受け付けたHTTPリクエストをClientHandlerという名前のhandlerに処理させます。またアプリケーションサーバーの在処をbaseURIに設定します。詳細は HandlerServletのマニュアル を参照ください。
名称がClientHandlerの箇所は型が ClientHandler なので、受け付けたHTTPリクエストをそのままHandlerServletで指定されたbaseURIのアプリケーションサーバーに転送します。

フィルターの使用:ログ取得の場合

HTTPリクエストをアプリケーションサーバーに転送する前にフィルターを設定し様々な処理を行えます。
簡単な例として、どのようなHTTPのリクエストを処理したかをログファイルに出力する方法を示します。設定内容を抜粋します(先ほどの"単なるリバースプロキシー"との差異になる箇所)。

違いは、HandlerServletがClientHandlerを直接呼ぶのではなく、型が Chain の物を介在させ、そこにフィルター(filters)の設定を行います。
本例のOutgoingChainではClientHandlerを呼び出す前後において、CaptureFilterという名称のフィルターが適用されます。これは型が CaptureFilter なので、指定されたfileに次のような処理を行ったHTTPリクエスト/レスポンスの内容を出力します。

OpenIGが期待通りにHTTPリクエストをハンドリングしているかの確認はこのCaptureFilterで行います。

jPetStoreに固定のユーザー名で自動ログイン

jPetStoreに固定のユーザー名・パスワードで自動でログインする設定を見ていきます。
まず、jPetStoreでログインページだと機械的に判断する方法は、jPetStoreからのHTTPのレスポンスデータ中に次のFORMがあった場合です。

よって、OpenIGでjPetStoreに固定のユーザー名でログインさせるには、

  • レスポンスデータにFORMがあるかをチェック
  • FORMがあればログインのためのPOSTデータを送信

の処理が必要です。設定内容を抜粋します(先ほどの"ログ取得"との差異になる箇所)。

違いは、OutgoingChainを呼び出す前にFORMを見つけるためにFindLoginPageChainを用います。このChainではフィルターとしてIsLoginPage,FindLoginPageの2つを使用します。
まず、FindLoginPageは型が EntityExtractFilter なので、HTTPのレスポンスデータの中身を取得できます。これで上述のログインページのFORMがあるかを判断し、ログイン後のリダイレクト先を取得します。
次に、IsLoginPageは型が SwitchFilter なので、FindLoginPageの結果を元にログインページと判断した場合だけLoginChainを呼び出します(ログインページでない場合はFindLoginPageChainで指定されたhandlerのOutgoingChainの処理に進みます)。

ログインページと判断された場合のLoginChainでは、ログインのPOSTデータ送信のためにLoginRequestのフィルターを使用します。
LoginRequestは型が StaticRequestFilter なので、アプリケーションサーバーに任意のリクエストを送信できます。ここではjPetStoreのログイン時にPOSTされるデータ(formの欄の固定のユーザー名)、HTTPヘッダー(headersの欄の内容)を設定し、このリクエストをjPetStore(uriで指定されたURL)に送信します。

処理が正常に行われたかはログファイルで確認します。下記のようにブラウザーからのnewOrder.doのリクエストの後に、自動でsignon.doへのPOSTが行われ、元のページへリダイレクトされればOKです。

OpeaAMでユーザー認証されたユーザーで自動ログイン

今回の環境ではOpenIGを使用するにあたっては、OpenAMのエージェントにより最初にOpenAMでユーザー認証されています。この認証されたユーザーでjPetStoreにログインさせる設定を見ていきます(なお、jPetStoreでの認証情報のユーザー名・パスワードはOpenAMのLDAPに登録している前提で話を進めます)。

OpenAMの設定の変更

OpenAMで認証された場合に、ユーザー名、暗号化されたパスワードをHTTPヘッダーに付加します。マニュアル Chapter 8. Tutorial On OpenAM Password Capture & Replay で紹介されている手順をOpenAMのコンソールで設定します。

1)エージェントの設定の"アプリケーション"タブのセッション属性処理を次のように設定します。
openig_1.png

2)"認証"の"すべてのコア設定"を次のように設定します。
openig_2.png

3)パスワードの暗号化に関するキーを生成します。
マニュアルでは使用するJARファイルがamserver.jar、opensso-sharedlib.jarの2つですが、今回使用したOpenAMのバージョンではopenam-core-10.2.0-SNAPSHOT.jar、openam-shared-10.2.0-SNAPSHOT.jarの2つになります。次のコマンドでキーを生成します。

このコマンドの実行結果より"B/gIUdYWBAQ="といったキーが得られます。

4)"設定"の"サーバーおよびサイト"でサーバーを選択し、"高度"で3)で生成したキーを次のように設定します。
openig_3.png

設定が正しいかはTomcat付属のサンプル"/examples/servlets/servlet/RequestHeaderExample"で行います。これはHTTPヘッダーの内容を表示するので、下記のようにusername,passwordが表示されればOKです。
openig_4.png

OpenIGの環境設定

先ほどの"固定のユーザーで自動ログイン"の設定に、HTTPヘッダーのユーザー名、パスワードを利用する設定を追加します。

違いは、LoginChainに CryptoHeaderFilter のフィルターを追加します(keyの欄に上記"OpenAMの設定の変更"3)で生成したキーを指定します)。これにより暗号化されているHTTPヘッダー中のpasswordの項目が復号化されます。
また、jPetStoreにログイン情報をPOSTする際のユーザー名、パスワードにはHTTPヘッダーに設定されている内容を設定します。

稼働確認

以上の設定により、まず最初にOpenAMでユーザー認証が行われ、jPetStoreでユーザー認証が必要になった時は、OpenAMで認証されたユーザーでOpenIGが自動的にjPetStoreにログイン処理を行います。

まず、オリジナルのjPetStoreのユーザー認証時の画面遷移を示します。

jpet_org_flow.jpg

続いて、OpenIGを用いてシングルサインオン化したjPetStoreのユーザー認証時の画面遷移を示します。

jpet_proxy_flow.jpg

このように、オリジナルのjPetStoreで行われていたユーザー認証処理が、リバースプロキシーのOpenIGが自動で実行してくれるため、jPetStoreの認証画面がスキップされることになります。
また、この後に他のOpenAMでユーザー認証を行うWebアプリケーションを使用する際は、この最初にOpenAMで認証された情報が用いられますので再度の認証画面はスキップされ、シングルサインオン化されます。

最後に

Webアプリケーションのシングルサインオンを実現する手段として、前回はOpenAMのエージェントを、今回はリバースプロキシーのOpenIGの使用方法を紹介しました。
今回触れませんでしたがシングルサインオン化するには対象のWebアプリケーションのユーザーIDをどのように統合するかの課題があります。ユーザーIDの統合さえ行えれば、既存のWebアプリケーションのシングルサインオン化がOpenAM,OpenIGで容易に実現することが理解いただけたかと思います。機会があればぜひ使ってみてください。

エンジニア採用中!私たちと一緒に働いてみませんか?