IdP Discovery Service implementieren
Wie bereits erläutert, kann OAM/SP so konfiguriert werden, dass ein Remote IdP Discovery Service verwendet wird, dessen Funktion darin besteht, zu bestimmen, welches IdP für den Federation-SSO-Vorgang verwendet werden soll.
Die von OASIS veröffentlichte SAML 2.0-Spezifikation "Identity Provider Discovery Service Protocol and Profile" definiert das Interaktionsprotokoll zwischen einem SAML 2.0-SP und einem IdP-Discovery Service.
In diesem Artikel wird ein Beispiel für IdP Discovery Service implementiert. Anschließend wird OAM/SP für die Verwendung dieses Service konfiguriert.
-
Der Service muss das Protokoll unterstützen, das durch die SAML 2.0-Spezifikation "Identity Provider Discovery Service Protocol and Profile" definiert ist
-
Der Service ist ein HTTP-Service und kann überall bereitgestellt werden
-
OAM/SP ist so konfiguriert, dass der Benutzer beim Starten eines Federation-SSO-Vorgangs an diesen Remote-Service umgeleitet wird
IdP Discovery Service-Protokoll
Wie bereits erwähnt, wird der Discovery Service-Ablauf IdP in der Spezifikation (http://docs.oasis-open.org/security/saml/Post2.0/sstc-saml-idp-discovery.pdf?
) beschrieben und umfasst die folgenden Schritte:
-
SP ist für die Verwendung eines Remote-Discovery Service IdP konfiguriert, um die IdP zu bestimmen, die für den Federation-SSO-Vorgang verwendet werden soll
-
Der SP leitet den Benutzer über eine 302-HTTP-Umleitung zum Discovery Service IdP um und stellt die folgenden Parameter in der Abfragezeichenfolge bereit
-
entityID
: Aussteller/ProviderID
von OAM/SP -
returnIDParam
: Der Name des Abfragezeichenfolgenparameters, den der Service für den Parameter mit dem Wert IdPProviderID
verwenden muss, wenn der Benutzer zurück zu OAM/SP umgeleitet wird -
return
: Die URL für die Umleitung des Benutzers zu OAM/SP
-
-
Der Service bestimmt die zu verwendende IdP
-
Der Service leitet den Benutzer über eine 302-HTTP-Umleitung basierend auf dem vom SP angegebenen Abfrageparameter "return" an OAM/SP um und stellt die folgenden Parameter in der Abfragezeichenfolge bereit
-
Ein Abfrageparameter mit dem Wert IdP
ProviderID
. Der Name dieses Abfrageparameters wird vom SP im AbfrageparameterreturnIDParam
angegeben.
Neben dem Protokollaustausch kann der Service in jeder für den Implementierer akzeptablen Weise implementiert werden.
Benutzerdefinierter Service
Überblick
In diesem Beispiel schreiben Sie einen Service, der:
-
Beachten Sie eine Liste der bekannten IdPs, die von den
ProviderID
/Issuer
-IDs referenziert wird -
Der Benutzer soll die zu verwendende IdP in einer Dropdown-Liste auswählen
-
Speichern Sie die Auswahl des Benutzers in einem Cookie mit dem Namen
IDPDiscService
-
Zur Laufzeit prüft der Service, ob
IDPDiscService
vorhanden ist -
Wenn der Service vorhanden ist und einen gültigen IdP enthält, leitet er den Benutzer automatisch mit
ProviderID
/Issuer
des IdP an den SP zurück: Es erfolgt keine Benutzerinteraktion -
Andernfalls zeigt der Service eine Seite an, die eine Dropdown-Liste der bekannten IdPs enthält.
Umsetzung:
-
JSP-Seiten verwenden
-
WAR/JSP auf einem Remote-Container J2EE bereitstellen, der sich von dem WLS-Server unterscheidet, auf dem OAM ausgeführt wird
Beispielseiten
Der benutzerdefinierte IdP Discovery Service besteht aus zwei JSP-Seiten:
-
landing.jsp
-
Seite, auf der der Benutzer vom SP zum Service umgeleitet wird
-
Prüfen Sie zunächst, ob das
IDPDiscService
-Cookie vorhanden ist und ein bekanntes IdP enthält. -
Falls vorhanden, leitet er den Benutzer mit
ProviderID
/Issuer
des IdP zurück an den SP. -
Andernfalls wird eine Seite angezeigt, auf der der Benutzer aufgefordert wird, eine IdP auszuwählen.
-
Die Seite, die den Benutzer zur Auswahl eines IdP auffordert, besteht aus einer Dropdown-Liste.
-
Nach dem Weiterleiten der Auswahl sendet der Benutzer Daten auf der Seite
/idpdiscoveryservice/submit.jsp
. -
Diese Seite ist über
/idpdiscoveryservice/landing.jsp
zugänglich. -
submit.jsp
Seite, auf der der der Benutzer seine Auswahl auslanding.jsp
veröffentlicht -
Speichert die IdP im
IDPDiscService
-Cookie -
Der Wert ist
Base64
-codierte IdPs -
ProviderID
/Issuer
-
Das Cookie wird als persistent markiert
-
leitet den Benutzer mit dem
-
IdP
ProviderID
/Issuer
Implementierung
Landingpage
<%@ 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>
Seite senden
<%@ 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());
%>
Packaging
Nachdem Sie landing.jsp
und submit.jsp
in ein Verzeichnis geschrieben haben, das nur diese Dateien enthält, erstellen Sie mit dem JAR-Tool idpDiscService.war
WAR Ale:
jar cvf idpDiscService.war *.jsp
Der Inhalt dieser WAR-Datei kann über den unzip-Befehl angezeigt werden: "unzip -l idpDiscService.WAR Archive: idpDiscService.WAR"
Länge | Datum | Zeit | Name |
---|---|---|---|
0 | 01.09.2014 | 19:00 Uhr | META-INF/ |
76 | 01.09.2014 | 19:00 Uhr | META-INF/MANIFEST.MF |
(2898) | 01.09.2014 | 19:57 Uhr | landing.jsp |
(1838) | 01.09.2014 | 19:57 Uhr | submit.jsp |
(4812) | 4 Dateien |
Stellen Sie diese WAR-Datei dann in einem J2EE-Container bereit, und verwenden Sie /idpdiscoveryservice
als Root-Pfad. Auf diese Weise sind beide Seiten mit /idpdiscoveryservice /landing.jsp
und /idpdiscoveryservice/submit.jsp
zugänglich.
OAM/SP konfigurieren
Führen Sie die folgenden Schritte aus, um OAM/SP für die Verwendung eines IdP Discovery Service zu konfigurieren:
-
Geben Sie die WLST-Umgebung ein, indem Sie Folgendes ausführen:
$IAM_ORACLE_HOME/common/bin/WLST.sh
-
Stellen Sie eine Verbindung zum WLS-Admin-Server her:
connect()
-
Navigieren Sie zur Domainlaufzeitverzweigung:
domainRuntime()
-
Aktivieren/deaktivieren Sie OAM/SP zur Verwendung eines IdP Discovery Service: ` putBooleanProperty("/spglobal /idpdiscoveryserviceenabled", "true")`
-
Legen Sie den Speicherort des Remote-Discovery-Service IdP fest:
putStringProperty("/spglobal /idpdiscoveryserviceurl","http://remote.idp.disc.service.com /idpdiscoveryservice/landing.jsp")
-
Beenden Sie die WLST-Umgebung:
exit()
Testen
Wenn OAM/SP aufgerufen wird, um ein Federation-SSO zu starten, wird der Benutzer zu meinem benutzerdefinierten IdP Discovery Service (/idpdiscoveryservice/landing.jsp
) umgeleitet.
Beim ersten Besuch wird dem Benutzer eine Dropdown-Liste angezeigt, in der er aufgefordert wird, einen IdP-SSO-Server auszuwählen:
Beschreibung der Abbildung IdP_SSO_Server.jpg
Nach dem Weiterleiten der Auswahl an /idpdiscoveryservice /submit.jsp
validiert die Seite die Auswahl, speichert sie im IDPDiscService
-Cookie und leitet den Benutzer mit dem IdP ProviderID
an OAM/SP um: Von dort startet OAM/SP Federation SSO mit diesem IdP.
Wenn OAM/SP das nächste Mal ein Federation-SSO für diesen Benutzer startet:
-
Der Server leitet den Benutzer zu meinem benutzerdefinierten IdP Discovery Service (
/idpdiscoveryservice/landing.jsp
) um -
Die Seite erkennt das
IDPDiscService
-Cookie und decodiert dieProviderID
des IdP -
Die Seite leitet den Benutzer mit
ProviderID
des IdP an OAM/SP um. -
OAM/SP startet Federation SSO mit diesem IdP.
Weitere Lernressourcen
Sehen Sie sich weitere Übungen unter docs.oracle.com/learn an, oder greifen Sie auf weitere kostenlose Lerninhalte im Oracle Learning-Kanal YouTube zu. Besuchen Sie außerdem education.oracle.com/learning-explorer, um Oracle Learning Explorer zu werden.
Die Produktdokumentation finden Sie im Oracle Help Center.
Implementing an IdP Discovery Service
F60448-01
September 2022
Copyright © 2022, Oracle and/or its affiliates.