Implementando um IdP Discovery Service
Conforme discutido anteriormente, o OAM/SP pode ser configurado para usar um Serviço de Descoberta IdP remoto cuja função é determinar qual IdP usar para a operação SSO de Federação.
A especificação SAML 2.0 "Identity Provider Discovery Service Protocol and Profile" publicada pelo OASIS define o protocolo de interação entre um SP SAML 2.0 e um Serviço de Descoberta IdP.
Este artigo implementa um Serviço de Descoberta IdP de amostra e, em seguida, configura o OAM/SP para usar esse serviço.
-
O serviço precisa suportar o protocolo definido pela especificação SAML 2.0 "Identity Provider Discovery Service Protocol and Profile"
-
O serviço é HTTP e pode ser implantado em qualquer lugar
-
O OAM/SP está configurado para redirecionar o usuário para esse serviço remoto ao iniciar uma operação SSO de Federação
IdP Protocolo do Serviço de Descoberta
Conforme mencionado anteriormente, o fluxo do IdP Discovery Service é descrito na especificação (http://docs.oasis-open.org/security/saml/Post2.0/sstc-saml-idp-discovery.pdf?
) e é feito das seguintes etapas:
-
O SP está configurado para usar um Serviço de Descoberta IdP remoto para determinar o IdP a ser usado para a operação SSO de Federação
-
O SP redireciona o usuário para o Serviço de Descoberta IdP por meio de um redirecionamento HTTP 302 e fornece os seguintes parâmetros na string de consulta
-
entityID
: o Emissor/ProviderID
do OAM/SP -
returnIDParam
: o nome do parâmetro da string de consulta que o serviço precisa usar para o parâmetro que contém o valor IdPProviderID
, ao redirecionar o usuário de volta para OAM/SP -
return
: o URL a ser usado para redirecionar o usuário para o OAM/SP
-
-
O serviço determina o IdP a ser usado
-
O serviço redireciona o usuário para o OAM/SP por meio de um redirecionamento HTTP 302 com base no parâmetro de consulta "return" especificado pelo SP e fornece os seguintes parâmetros na string de consulta
-
Um parâmetro de consulta que contém o valor IdP
ProviderID
; o nome desse parâmetro de consulta é especificado pelo SP no parâmetro de consultareturnIDParam
.
Além da troca de protocolo, o serviço pode ser implementado de qualquer forma considerada aceitável pelo implementador.
Serviço Personalizado
Visão Geral
Neste exemplo, crie um serviço que:
-
Esteja ciente de uma lista de IdPs conhecidos, referenciados pelos identificadores
ProviderID
/Issuer
-
Permita que o usuário selecione o IdP a ser usado em uma lista drop-down
-
Salve a escolha do usuário em um cookie chamado
IDPDiscService
-
No runtime, o serviço verifica se o
IDPDiscService
está presente -
Se estiver presente e contiver um IdP válido, o serviço redirecionará automaticamente o usuário de volta para o SP com o
ProviderID
/Issuer
do IdP: nenhuma interação do usuário ocorrerá -
Caso contrário, o serviço exibirá uma página contendo uma lista drop-down do IdPs conhecido
Em termos de implementação:
-
Usar uma página JSP
-
Implante o WAR/JSP em um contêiner J2EE remoto, diferente do servidor WLS no qual o OAM está em execução
Páginas de amostra
O IdP Discovery Service personalizado é feito de duas páginas JSP:
-
landing.jsp
-
Página na qual o usuário é redirecionado do SP para o serviço
-
Primeiro verifique se o cookie
IDPDiscService
está presente e contém um IdP conhecido -
Se estiver presente, ele redireciona o usuário de volta ao SP com o
ProviderID
/Issuer
do IdP -
Caso contrário, ele exibirá uma página solicitando que o usuário selecione um IdP
-
A página que pede ao usuário para selecionar um IdP é feita de uma lista drop-down
-
Ao enviar a opção, o usuário publica dados na página
/idpdiscoveryservice/submit.jsp
-
Esta página pode ser acessada via
/idpdiscoveryservice/landing.jsp
-
submit.jsp
Página na qual o usuário publica sua escolha, emlanding.jsp
-
Salva o IdP no cookie
IDPDiscService
-
O valor é de IdP codificado em
Base64
-
ProviderID
/Issuer
-
O cookie é marcado como persistente
-
redireciona o usuário de volta ao SP com o
-
IdP's
ProviderID
/Issuer
Implementação
Página Inicial
<%@ 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>
Submeter Página
<%@ 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());
%>
Embalagem
Depois de colocar landing.jsp
e submit.jsp
em um diretório que só contém esses arquivos, crie o idpDiscService.war
WAR Ale usando a ferramenta JAR:
jar cvf idpDiscService.war *.jsp
O conteúdo desse arquivo WAR pode ser visto por meio do comando unzip: ` unzip -l idpDiscService.war Archive: idpDiscService.war`
Tamanho | Data | Hora | Nome |
---|---|---|---|
0 | 01-09-2014 | 19h00 | META-INF/ |
76 | 01-09-2014 | 19h00 | META-INF/MANIFEST.MF |
2898 | 01-09-2014 | 19h57 | landing.jsp |
1838 | 01-09-2014 | 19h57 | submit.jsp |
4812 | 4 arquivos |
Em seguida, implante esse arquivo WAR em um contêiner J2EE, usando /idpdiscoveryservice
como caminho raiz. Dessa forma, ambas as páginas podem ser acessadas usando /idpdiscoveryservice /landing.jsp
e /idpdiscoveryservice/submit.jsp
.
Configuração do OAM/SP
Para configurar o OAM/SP para usar um Serviço de Descoberta IdP, execute as seguintes etapas:
-
Informe o ambiente WLST executando:
$IAM_ORACLE_HOME/common/bin/wlst.sh
-
Conecte-se ao servidor de Administração WLS:
connect()
-
Navegue até a ramificação Runtime do Domínio:
domainRuntime()
-
Ative/desative o OAM/SP para usar um Serviço de Descoberta IdP: ` putBooleanProperty("/spglobal /idpdiscoveryserviceenabled", "verdadeiro")`
-
Defina a localização do Serviço de Descoberta IdP remoto:
putStringProperty("/spglobal /idpdiscoveryserviceurl","http://remote.idp.disc.service.com /idpdiscoveryservice/landing.jsp")
-
Saia do ambiente WLST:
exit()
Teste
Quando o OAM/SP é chamado para iniciar um SSO de Federação, ele redireciona o usuário para meu IdP Discovery Service personalizado (/idpdiscoveryservice/landing.jsp
)
Na primeira visita, o usuário recebe uma lista drop-down e é solicitado a selecionar um Servidor SSO IdP:
Descrição da ilustração IdP_SSO_Server.jpg
Ao enviar a opção para /idpdiscoveryservice /submit.jsp
, a página valida a escolha, salva-a no cookie IDPDiscService
e redireciona o usuário para OAM/SP com o ProviderID
do IdP: a partir daí, o OAM/SP inicia o SSO da Federação com esse IdP.
Na próxima vez que o OAM/SP iniciar um SSO de Federação para esse usuário:
-
O servidor redireciona o usuário para meu IdP Discovery Service personalizado (
/idpdiscoveryservice/landing.jsp
) -
A página detecta o cookie
IDPDiscService
e decodifica oProviderID
do IdP -
A página redireciona o usuário para o OAM/SP com o
ProviderID
do IdP -
O OAM/SP inicia o SSO de Federação com esse IdP.
Mais Recursos de Aprendizagem
Explore outros laboratórios em docs.oracle.com/learn ou acesse mais conteúdo de aprendizado gratuito no canal YouTube do Oracle Learning. Além disso, visite education.oracle.com/learning-explorer para se tornar um Oracle Learning Explorer.
Para obter a documentação do produto, visite o Oracle Help Center.
Implementing an IdP Discovery Service
F60448-01
September 2022
Copyright © 2022, Oracle and/or its affiliates.