Implémentation d'un service de découverte IdP
Comme indiqué précédemment, OAM/SP peut être configuré pour utiliser un service de repérage IdP distant dont la fonction est de déterminer la valeur IdP à utiliser pour l'opération SSO de fédération.
La spécification SAML 2.0 "Identity Provider Discovery Service Protocol and Profile" publiée par OASIS définit le protocole d'interaction entre un SP SAML 2.0 et un service de découverte IdP.
Cet article implémente un exemple de service de repérage IdP, puis configure OAM/SP pour qu'il utilise ce service.
-
Le service doit prendre en charge le protocole défini par la spécification SAML 2.0 "Identity Provider Discovery Service Protocol and Profile"
-
Le service est un service HTTP qui peut être déployé n'importe où
-
OAM/SP est configuré pour rediriger l'utilisateur vers ce service distant lors du démarrage d'une opération SSO de fédération
IdP Protocole du service de découverte
Comme indiqué précédemment, le flux IdP Discovery Service est décrit dans la spécification (http://docs.oasis-open.org/security/saml/Post2.0/sstc-saml-idp-discovery.pdf?
) et comprend les étapes suivantes :
-
Le processeur de service est configuré pour utiliser un service de repérage IdP distant afin de déterminer le fichier IdP à utiliser pour l'opération SSO de fédération
-
Le SP redirige l'utilisateur vers le service de découverte IdP via un réacheminement HTTP 302 et fournit les paramètres suivants dans la chaîne de requête
-
entityID
: émetteur/ProviderID
d'OAM/SP -
returnIDParam
: nom du paramètre de chaîne de requête que le service doit utiliser pour le paramètre contenant la valeur IdPProviderID
, lors du réacheminement de l'utilisateur vers OAM/SP -
return
: URL à utiliser pour rediriger l'utilisateur vers OAM/SP
-
-
Le service détermine la valeur IdP à utiliser.
-
Le service redirige l'utilisateur vers OAM/SP via un réacheminement HTTP 302 basé sur le paramètre de requête "return" spécifié par le SP et fournit les paramètres suivants dans la chaîne de requête
-
Paramètre de requête contenant la valeur IdP
ProviderID
. Le nom de ce paramètre de requête est indiqué par le processeur de service dans le paramètre de requêtereturnIDParam
.
Outre l'échange de protocole, le service peut être mis en oeuvre de toute manière jugée acceptable par l'implémenteur.
Service personnalisé
Présentation
Dans cet exemple, écrivez un service qui :
-
Notez la liste des éléments IdPs connus, référencés par les identificateurs
ProviderID
/Issuer
. -
Laisser l'utilisateur sélectionner l'élément IdP à utiliser dans une liste déroulante
-
Enregistrez le choix de l'utilisateur dans un cookie appelé
IDPDiscService
-
Lors de l'exécution, le service vérifie si
IDPDiscService
est présent -
S'il est présent et contient une valeur IdP valide, le service redirige automatiquement l'utilisateur vers le SP avec la valeur
ProviderID
/Issuer
du fournisseur d'identités : aucune interaction utilisateur n'a lieu -
Sinon, le service affiche une page contenant une liste déroulante des IdPs connus.
En termes de mise en œuvre :
-
Utiliser une page JSP
-
Déployez WAR/JSP sur un conteneur J2EE distant, différent du serveur WLS sur lequel OAM est exécuté.
Exemples de pages
Le service de repérage IdP personnalisé est composé de deux pages JSP :
-
landing.jsp
-
Page sur laquelle l'utilisateur est redirigé depuis le SP vers le service
-
Commencez par vérifier si le cookie
IDPDiscService
est présent et contient un élément IdP connu -
Le cas échéant, il redirige l'utilisateur vers le SP avec
ProviderID
/Issuer
du fournisseur d'identités -
Sinon, elle affiche une page demandant à l'utilisateur de sélectionner une IdP.
-
La page demandant à l'utilisateur de sélectionner un élément IdP est constituée d'une liste déroulante
-
Lors de la soumission du choix, l'utilisateur publie les données sur la page
/idpdiscoveryservice/submit.jsp
-
Cette page est accessible via
/idpdiscoveryservice/landing.jsp
-
submit.jsp
Page sur laquelle l'utilisateur publie son choix, à partir delanding.jsp
-
Enregistre le fichier IdP dans le cookie
IDPDiscService
-
La valeur est celle des fournisseurs d'identités encodés en
Base64
. -
ProviderID
/Issuer
-
Le cookie est marqué comme persistant
-
redirige l'utilisateur vers le SP avec
-
IdP's
ProviderID
/Issuer
Implémentation
Page de destination
<%@ 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>
Soumettre une page
<%@ 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
Après avoir placé les fichiers landing.jsp
et submit.jsp
dans un répertoire contenant uniquement ces fichiers, créez le fichier WAR Ale idpDiscService.war
à l'aide de l'outil JAR :
jar cvf idpDiscService.war *.jsp
Le contenu de ce fichier WAR est visible via la commande unzip : ` unzip -l idpDiscService.war Archive : idpDiscService.war`
Longueur | Date | Heure | Nom |
---|---|---|---|
0 | 01-09-2014 | 19 h 00 | MÉTA-INF/ |
76 (homonymie) | 01-09-2014 | 19 h 00 | MÉTA-INF/MANIFEST.MF |
(2898) | 01-09-2014 | 19:57 | landing.jsp |
(1838) | 01-09-2014 | 19:57 | submit.jsp |
(4812) | 4 fichiers |
Déployez ensuite ce fichier WAR sur un conteneur J2EE, en utilisant /idpdiscoveryservice
comme chemin racine. De cette façon, les deux pages sont accessibles à l'aide des commandes /idpdiscoveryservice /landing.jsp
et /idpdiscoveryservice/submit.jsp
.
Configuration d'OAM/SP
Pour configurer OAM/SP afin qu'il utilise un service de repérage IdP, procédez comme suit :
-
Entrez dans l'environnement WLST en exécutant :
$IAM_ORACLE_HOME/common/bin/wlst.sh
-
Connectez-vous au serveur d'administration WLS :
connect()
-
Accédez au branchement d'exécution de domaine :
domainRuntime()
-
Activer/désactiver OAM/SP pour utiliser un service de repérage IdP : ` putBooleanProperty("/spglobal /idpdiscoveryserviceenabled", "true")`
-
Définissez l'emplacement du service de repérage IdP distant :
putStringProperty("/spglobal /idpdiscoveryserviceurl","http://remote.idp.disc.service.com /idpdiscoveryservice/landing.jsp")
-
Quittez l'environnement WLST :
exit()
Tester
Lorsqu'OAM/SP est appelé pour démarrer un SSO de fédération, il redirige l'utilisateur vers mon service de repérage IdP personnalisé (/idpdiscoveryservice/landing.jsp
)
Lors de la première visite, l'utilisateur reçoit une liste déroulante et est invité à sélectionner un serveur SSO IdP :
Description de l'image IdP_SSO_Server.jpg
Lors de la soumission du choix à /idpdiscoveryservice /submit.jsp
, la page valide le choix, l'enregistre dans le cookie IDPDiscService
et redirige l'utilisateur vers OAM/SP avec le fournisseur d'identités ProviderID
: à partir de là, OAM/SP démarre l'authentification unique de fédération avec ce IdP.
La prochaine fois qu'OAM/SP démarre une connexion unique de fédération pour cet utilisateur :
-
Le serveur redirige l'utilisateur vers mon service de repérage IdP personnalisé (
/idpdiscoveryservice/landing.jsp
) -
La page détecte le cookie
IDPDiscService
et décode le fichierProviderID
du fournisseur d'identités -
La page redirige l'utilisateur vers OAM/SP avec la valeur
ProviderID
du fournisseur d'identités -
OAM/SP démarre l'authentification unique de fédération avec ce IdP.
Ressources de formation supplémentaires
Parcourez d'autres ateliers sur docs.oracle.com/learn ou accédez à d'autres contenus de formation gratuite sur le canal Oracle Learning YouTube. En outre, visitez le site education.oracle.com/learning-explorer pour devenir un explorateur Oracle Learning.
Pour consulter la documentation du produit, visitez le site Oracle Help Center.
Implementing an IdP Discovery Service
F60448-01
September 2022
Copyright © 2022, Oracle and/or its affiliates.