IdP検出サービスの実装
前述のように、OAM/SPは、フェデレーションSSO操作に使用するIdPを決定する機能を持つリモートIdP検出サービスを使用するように構成できます。
OASISによって公開される「アイデンティティ・プロバイダ検出サービス・プロトコルおよびプロファイル」SAML 2.0仕様は、SAML 2.0 SPとIdP検出サービス間の相互作用プロトコルを定義します。
この記事では、サンプルのIdP検出サービスを実装し、そのサービスを使用するようにOAM/SPを構成します。
-
サービスは、"Identity Provider Discovery Service Protocol and Profile" SAML 2.0仕様で定義されているプロトコルをサポートする必要があります
-
サービスはHTTPサービスであり、どこにでもデプロイできます。
-
OAM/SPは、フェデレーションSSO操作の開始時にユーザーをそのリモート・サービスにリダイレクトするように構成されています
IdP検出サービス・プロトコル
前述のように、IdP検出サービス・フローは仕様(http://docs.oasis-open.org/security/saml/Post2.0/sstc-saml-idp-discovery.pdf?)で説明されており、次のステップで構成されています。
-
SPは、リモートのIdP検出サービスを使用して、フェデレーションSSO操作に使用するIdPを決定するように構成されます
-
SPは、302 HTTPリダイレクトを介してユーザーをIdP検出サービスにリダイレクトし、問合せ文字列に次のパラメータを提供します
-
entityID: OAM/SPの発行者/ProviderID -
returnIDParam: ユーザーをOAM/SPにリダイレクトするときに、IdPProviderID値を含むパラメータに対してサービスで使用する必要がある問合せ文字列パラメータの名前 -
return: ユーザーをOAM/SPにリダイレクトするために使用するURL
-
-
サービスによって、使用するIdPが決定されます。
-
サービスは、SPによって指定された問合せパラメータ「return」に基づいて302 HTTPリダイレクトを介してユーザーをOAM/SPにリダイレクトし、問合せ文字列に次のパラメータを提供します
-
IdP
ProviderID値を含む問合せパラメータ。その問合せパラメータの名前は、SPによってreturnIDParam問合せパラメータで指定されます。
プロトコル交換とは別に、実装者が許容できる任意の方法でサービスを実装できます。
カスタム・サービス
概要
この例では、次のことを行うサービスを記述します。
-
ProviderID/Issuer識別子によって参照される既知のIdPsのリストに注意してください。 -
使用するIdPをドロップダウン・リストから選択します
-
ユーザーの選択内容を
IDPDiscServiceというCookieに保存します -
実行時に、サービスは
IDPDiscServiceが存在するかどうかをチェックします。 -
有効なIdPが存在し、含まれている場合、サービスは、IdPの
ProviderID/Issuerを使用してユーザーをSPに自動的にリダイレクトします。ユーザー・インタラクションは行われません。 -
それ以外の場合は、既知のIdPsのドロップダウン・リストを含むページが表示されます。
実装に関して:
-
JSPページの使用
-
OAMが実行されているWLSサーバーとは異なるリモートJ2EEコンテナにWAR/JSPをデプロイします。
サンプル・ページ
カスタムIdP検出サービスは、次の2つのJSPページで構成されています。
-
landing.jsp
-
ユーザーがSPからサービスにリダイレクトされるページ
-
最初に、
IDPDiscServiceCookieが存在し、既知のIdPが含まれているかどうかを確認します -
存在する場合は、IdPの
ProviderID/Issuerを使用してユーザーをSPにリダイレクトします。 -
それ以外の場合は、ユーザーにIdPの選択を求めるページが表示されます。
-
IdPの選択をユーザーに求めるページはドロップダウンで構成されています
-
選択を送信すると、ユーザーは
/idpdiscoveryservice/submit.jspページにデータを投稿します -
このページには、
/idpdiscoveryservice/landing.jspからアクセスできます -
submit.jspユーザーがlanding.jspから選択を投稿するページ -
IdPを
IDPDiscServiceCookieに保存します -
値は
Base64でエンコードされたIdPです -
ProviderID/Issuer -
Cookieは永続としてマークされます
-
次のコマンドを使用して、ユーザーをSPにリダイレクトします。
-
IdPの
ProviderID/Issuer
実装
ランディング・ページ
<%@ page buaer="5kb" autoFlush="true" session="false"%\> \<%@ page language="java"import="java.util.\*,sun.misc.\*,java.net.\*"%>
<%response.setHeader("Expires", "Sat, 1 Jan 200000:00:00 GMT"); response.setHeader("Cache-Control", "no-cache"); response.setHeader("Pragma", "no-cache"); request.setCharacterEncoding("UTF-8"); response.setContentType("text/html; charset=UTF-8");
// list of known IdPs, keys being the displayed names,and values the ProviderID/Issuer IDs
Map idps = new HashMap(); idps.put("AcmeIdP", "https://acme.com/fed"); idps.put("IdP1", "https://idp1.com/saml"); idps.put("MyIdentiyProvider.com", "https://myidentityprovider.com/saml2.0");
// entityID of the requesting SP
String entityID = request.getParameter("entityID");
// the query parameter that contains the IdP's ProviderID/Issuer when
// redirecting the user back to the SP
String returnIDParam = request.getParameter("returnIDParam");
// the URL where the user should be redirected at the SP
String returnURL = request.getParameter("return");
// check if the IDPDiscService cookie is set, and if it is a known IdP
Cookie\[\] cookies = request.getCookies();
if (cookies != null && cookies.length \> 0)
{
for (int i = 0; i \< cookies.length; i++)
{
if ("IDPDiscService".equals(cookies\[i\].getName()))
{
// decode the idp
BASE64Decoder b64 = new BASE64Decoder();
String idp = new
String(b64.decodeBuaer(cookies\[i\].getValue()));
if (idps.containsValue(idp))
{
// redirects to the SP
StringBuaer redirectStringBuaer = new
StringBuaer(returnURL);
if (returnURL.indexOf('?') == -1)
redirectStringBuaer.append("?");
else if (returnURL.charAt(returnURL.length() - 1)
!= '&')
redirectStringBuaer.append("&");
redirectStringBuaer.append(returnIDParam);
redirectStringBuaer.append("="); redirectStringBuaer.append(URLEncoder.encode(idp));
response.sendRedirect(redirectStringBuaer.toString());
return;
}
}
}
}
%>
<html>
<head>
<title>Select your Single Sign-On Server</title>
</head>
<body>
<p style="text-align: center;"\>Select your SingleSign-On Server</p>
<form action="/idpdiscoveryservice/submit.jsp" method="post" name="idpselection"/>
<input name="entityID" type="hidden" value="<%=entityID%\>" />
<input name="returnIDParam" type="hidden" value="<%=returnIDParam%\>" />
<input name="return" type="hidden" value="<%=returnURL%>" />
<p style="text-align: center;"\>Single Sign-On Server:
<select name="selectedidp"\>
<%Iterator idpsIterator = idps.keySet().iterator();while(idpsIterator.hasNext())
{
String displayIdP = (String)idpsIterator.next();
String providerIDIdP = (String)idps.get(displayIdP);
%>
<option value="<%=providerIDIdP%>">
<%=displayIdP%><option>
<%
}
%>
</select>
</p>
<p style="text-align: center;">
<input name="submit" type="submit"value="Submit" />
</p>
</form>
</body>
</html>
ページの送信
<%@ page buaer="5kb" autoFlush="true" session="false"%> <%@ page language="java"import="java.util.*,sun.misc.*,java.net.*"%>
<%response.setHeader("Expires", "Sat, 1 Jan 200000:00:00 GMT"); response.setHeader("Cache-Control", "no-cache"); response.setHeader("Pragma", "no-cache"); request.setCharacterEncoding("UTF-8"); response.setContentType("text/html; charset=UTF-8");
// list of known IdPs with values being the ProviderID/Issuer IDs
List idps = new ArrayList(); idps.add("https://acme.com/fed"); idps.add("https://idp1.com/saml"); idps.add("https://myidentityprovider.com/saml2.0");
// entityID of the requesting SP
String entityID = request.getParameter("entityID");
// the query parameter that contains the IdP's ProviderID/Issuer when
// redirecting the user back to the SP
String returnIDParam =request.getParameter("returnIDParam");
// the URL where the user should be redirected at the SP
String returnURL = request.getParameter("return");
// the idp selected by the user
String idp = request.getParameter("selectedidp");
// check that the selected IdP is one of the known IdPs
if (!idps.contains(idp))
throw new Exception("Unknown IdP");
// save the idp in the IDPDiscService cookie
BASE64Encoder b64Encoder = new
BASE64Encoder();
response.addHeader("Set-Cookie", "IDPDiscService="
+
b64Encoder.encode(idp.getBytes()) + "; expires=Wed, 01-Jan-2020 00:00:00 GMT; path=/");
// redirects to the SP
StringBuaer redirectStringBuaer = new StringBuaer(returnURL); if (returnURL.indexOf('?') == -1) redirectStringBuaer.append("?");
else if (returnURL.charAt(returnURL.length() - 1) != '&')
redirectStringBuaer.append("&"); redirectStringBuaer.append(returnIDParam); redirectStringBuaer.append("="); redirectStringBuaer.append(URLEncoder.encode(idp));
response.sendRedirect(redirectStringBuaer.toString());
%>
パッケージング
これらのファイルのみを含むディレクトリにlanding.jspおよびsubmit.jspを配置したら、JARツールを使用してidpDiscService.war WAR Aleを作成します。
jar cvf idpDiscService.war *.jsp
そのWARファイルの内容は、unzipコマンドで確認できます: ` unzip - l idpDiscService.WAR Archive: idpDiscService.WAR`
| 長さ | 日付 | 時間 | 名前 |
|---|---|---|---|
| 0 | 01-09-2014 | 19:00 | メタイン/ |
| 76 | 01-09-2014 | 19:00 | メタイン/MANIFEST.MF |
| 2898 | 01-09-2014 | 19:57 | landing.jsp |
| 1838 | 01-09-2014 | 19:57 | submit.jsp |
| 4812 | 4ファイル |
次に、/idpdiscoveryserviceをルート・パスとして使用して、このWARファイルをJ2EEコンテナにデプロイします。これにより、/idpdiscoveryservice /landing.jspおよび/idpdiscoveryservice/submit.jspを使用して両方のページにアクセスできます。
OAM/SPの構成
IdP検出サービスを使用するようにOAM/SPを構成するには、次のステップを実行します。
-
$IAM_ORACLE_HOME/common/bin/WLST.shを実行して、WLST環境を入力します。 -
WLS管理サーバー(
connect())に接続します。 -
ドメイン・ランタイム・ブランチ
domainRuntime()に移動します -
IdP検出サービスを使用するためのOAM/SPの有効化/無効化: ` putBooleanProperty("/spglobal /idpdiscoveryserviceenabled"、 "true")`
-
リモートIdP検出サービスの場所を設定します:
putStringProperty("/spglobal /idpdiscoveryserviceurl","http://remote.idp.disc.service.com /idpdiscoveryservice/landing.jsp") -
WLST環境を終了します:
exit()
テスト
OAM/SPを起動してフェデレーションSSOを起動すると、カスタムのIdP検出サービス(/idpdiscoveryservice/landing.jsp)にユーザーがリダイレクトされます。
初回訪問時に、ユーザーにドロップダウン・リストが表示され、IdP SSOサーバーを選択するように求められます。

/idpdiscoveryservice /submit.jspに選択を送信すると、ページによって選択が検証され、IDPDiscService Cookieに保存されて、IdPのProviderIDを使用してユーザーをOAM/SPにリダイレクトします。そこから、OAM/SPはそのIdPでフェデレーションSSOを開始します。
次にOAM/SPがそのユーザーのフェデレーションSSOを開始したとき:
-
サーバーは、ユーザーをカスタムのIdP検出サービス(
/idpdiscoveryservice/landing.jsp)にリダイレクトします -
ページは
IDPDiscServiceCookieを検出し、IdPのProviderIDをデコードします -
このページは、IdPの
ProviderIDを使用してユーザーをOAM/SPにリダイレクトします。 -
OAM/SPは、そのIdPを使用してフェデレーションSSOを開始します。
その他の学習リソース
docs.oracle.com/learnで他のラボを探すか、Oracle Learning YouTubeチャネルで無料のラーニング・コンテンツにアクセスしてください。また、education.oracle.com/learning-explorerにアクセスしてOracle Learning Explorerになります。
製品ドキュメントについては、Oracle Help Centerを参照してください。
Implementing an IdP Discovery Service
F60448-01
September 2022
Copyright © 2022, Oracle and/or its affiliates.