0N/A<%--
644N/A DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
0N/A
0N/A Copyright (c) 2008 Sun Microsystems Inc. All Rights Reserved
0N/A
0N/A The contents of this file are subject to the terms
0N/A of the Common Development and Distribution License
0N/A (the License). You may not use this file except in
0N/A compliance with the License.
0N/A
0N/A You can obtain a copy of the License at
0N/A https://opensso.dev.java.net/public/CDDLv1.0.html or
0N/A opensso/legal/CDDLv1.0.txt
0N/A See the License for the specific language governing
0N/A permission and limitations under the License.
0N/A
0N/A When distributing Covered Code, include this CDDL
0N/A Header Notice in each file and include the License file
0N/A at opensso/legal/CDDLv1.0.txt.
0N/A If applicable, add the following below the CDDL Header,
0N/A with the fields enclosed by brackets [] replaced by
0N/A your own identifying information:
0N/A "Portions Copyrighted [year] [name of copyright owner]"
0N/A
0N/A $Id: spSingleLogoutPOST.jsp,v 1.8 2009/06/24 23:05:31 mrudulahg Exp $
0N/A
0N/A Portions Copyrighted 2013-2015 ForgeRock AS.
0N/A--%>
0N/A
0N/A
0N/A<%@ page import="com.sun.identity.sae.api.SecureAttrs" %>
0N/A<%@ page import="com.sun.identity.saml.common.SAMLUtils" %>
0N/A<%@ page import="com.sun.identity.saml2.common.SAML2Utils" %>
0N/A<%@ page import="com.sun.identity.saml2.common.SAML2Constants" %>
1418N/A<%@ page import="com.sun.identity.saml2.common.SAML2Exception" %>
644N/A<%@ page import="com.sun.identity.saml2.jaxb.entityconfig.SPSSOConfigElement" %>
644N/A<%@ page import="com.sun.identity.saml2.meta.SAML2MetaUtils" %>
0N/A<%@ page import="com.sun.identity.saml2.meta.SAML2MetaManager" %>
0N/A<%@ page import="com.sun.identity.saml2.profile.CacheObject" %>
0N/A<%@ page import="com.sun.identity.saml2.profile.SPCache" %>
0N/A<%@ page import="com.sun.identity.saml2.profile.SPSingleLogout" %>
0N/A<%@ page import="com.sun.identity.saml2.profile.IDPCache" %>
0N/A<%@ page import="com.sun.identity.saml2.protocol.LogoutRequest" %>
0N/A<%@ page import="com.sun.identity.saml2.profile.IDPProxyUtil" %>
0N/A<%@ page import="java.util.HashMap" %>
0N/A<%@ page import="java.util.List" %>
0N/A<%@ page import="java.util.Map" %>
0N/A<%@ page import="java.util.Properties" %>
0N/A<%@ page import="org.owasp.esapi.ESAPI" %>
0N/A<%@ page import="java.io.PrintWriter" %>
0N/A
0N/A<%--
0N/A spSingleLogoutPOST.jsp
- receives the LogoutRequest and sends the LogoutResponse to
Identity Provider from the Service Provider.
OR
- receives the LogoutResponse from the Identity Provider.
Required parameters to this jsp are :
- RelayState - the target URL on successful Single Logout
- SAMLRequest - the LogoutRequest
OR
- SAMLResponse - the LogoutResponse
Check the SAML2 Documentation for supported parameters.
--%>
<%
// Retrieves the LogoutRequest or LogoutResponse
//Retrieves :
//- RelayState - the target URL on successful Single Logout
//- SAMLRequest - the LogoutRequest
//OR
//- SAMLResponse - the LogoutResponse
String relayState = request.getParameter(SAML2Constants.RELAY_STATE);
if (relayState != null) {
CacheObject tmpRs=
(CacheObject) SPCache.relayStateHash.remove(relayState);
if ((tmpRs != null)) {
relayState = (String) tmpRs.getObject();
}
}
if (!ESAPI.validator().isValidInput("HTTP Query String: " + relayState, relayState, "HTTPQueryString", 2000, true)) {
relayState = null;
}
String samlResponse = request.getParameter(SAML2Constants.SAML_RESPONSE);
if (samlResponse != null) {
try {
/**
* Gets and processes the Single <code>LogoutResponse</code> from IDP,
* destroys the local session, checks response's issuer
* and inResponseTo.
*
* @param request the HttpServletRequest.
* @param response the HttpServletResponse.
* @param samlResponse <code>LogoutResponse</code> in the
* XML string format.
* @param relayState the target URL on successful
* <code>LogoutResponse</code>.
* @throws SAML2Exception if error processing
* <code>LogoutResponse</code>.
*/
Map<String, String> infoMap =
SPSingleLogout.processLogoutResponse(request, response, samlResponse, relayState);
String inRes = infoMap.get("inResponseTo");
LogoutRequest origLogoutRequest = (LogoutRequest)
IDPCache.proxySPLogoutReqCache.get(inRes);
if (origLogoutRequest != null && !origLogoutRequest.equals("")) {
IDPCache.proxySPLogoutReqCache.remove(inRes);
IDPProxyUtil.sendProxyLogoutResponse(response, request,
origLogoutRequest.getID(), infoMap,
origLogoutRequest.getIssuer().getValue(),
SAML2Constants.HTTP_POST);
return;
}
} catch (SAML2Exception sse) {
SAML2Utils.debug.error("Error processing LogoutResponse :", sse);
SAMLUtils.sendError(request, response, response.SC_BAD_REQUEST,
"LogoutResponseProcessingError",
SAML2Utils.bundle.getString("LogoutResponseProcessingError") +
" " + sse.getMessage());
return;
} catch (Exception e) {
SAML2Utils.debug.error("Error processing LogoutResponse ",e);
SAMLUtils.sendError(request, response, response.SC_BAD_REQUEST,
"LogoutResponseProcessingError",
SAML2Utils.bundle.getString("LogoutResponseProcessingError") +
" " + e.getMessage());
return;
}
boolean isRelayStateURLValid = false;
if (!SPCache.isFedlet) {
isRelayStateURLValid = relayState != null && !relayState.isEmpty()
&& SAML2Utils.isRelayStateURLValid(request, relayState, SAML2Constants.SP_ROLE)
&& ESAPI.validator().isValidInput("RelayState", relayState, "URL", 2000, true);
} else {
SAML2MetaManager manager = new SAML2MetaManager();
String metaAlias = null;
List<String> spMetaAliases = manager.getAllHostedServiceProviderMetaAliases("/");
if (spMetaAliases != null && !spMetaAliases.isEmpty()) {
// get first one
metaAlias = spMetaAliases.get(0);
}
isRelayStateURLValid = relayState != null && !relayState.isEmpty()
&& SAML2Utils.isRelayStateURLValid(metaAlias, relayState, SAML2Constants.SP_ROLE)
&& ESAPI.validator().isValidInput("RelayState", relayState, "URL", 2000, true);
}
if (isRelayStateURLValid) {
try {
response.sendRedirect(relayState);
} catch (java.io.IOException ioe) {
if (SAML2Utils.debug.messageEnabled()) {
SAML2Utils.debug.message(
"Exception when redirecting to " +
relayState, ioe);
}
}
} else {
%>
<jsp:forward page="/saml2/jsp/default.jsp?message=spSloSuccess" />
<%
}
} else {
String samlRequest = request.getParameter(SAML2Constants.SAML_REQUEST);
if (samlRequest != null) {
// Logout SP app via SAE first. App is obligated to redirect back
// to complete this SLO request.
if (!SPCache.isFedlet) {
if (processSAELogout(request, response)) {
return;
}
}
try {
/**
* Gets and processes the Single <code>LogoutRequest</code> from
* IDP.
*
* @param request the HttpServletRequest.
* @param response the HttpServletResponse.
* @param samlRequest <code>LogoutRequest</code> in the
* XML string format.
* @param relayState the target URL on successful
* <code>LogoutRequest</code>.
* @throws SAML2Exception if error processing
* <code>LogoutRequest</code>.
*/
SPSingleLogout.processLogoutRequest(request,response, new PrintWriter(out, true),
samlRequest,relayState);
} catch (SAML2Exception sse) {
SAML2Utils.debug.error("Error processing LogoutRequest :", sse);
SAMLUtils.sendError(request, response, response.SC_BAD_REQUEST,
"LogoutRequestProcessingError",
SAML2Utils.bundle.getString("LogoutRequestProcessingError")
+ " " + sse.getMessage());
return;
} catch (Exception e) {
SAML2Utils.debug.error("Error processing LogoutRequest ",e);
SAMLUtils.sendError(request, response, response.SC_BAD_REQUEST,
"LogoutRequestProcessingError",
SAML2Utils.bundle.getString("LogoutRequestProcessingError")
+ " " + e.getMessage());
return;
}
}
}
%>
<%!
boolean processSAELogout(
HttpServletRequest request, HttpServletResponse response)
{
String saeData = request.getParameter(SecureAttrs.SAE_PARAM_APPRETURN);
if (saeData != null) { // App returned back.
return false;
}
try {
String metaAlias =
SAML2MetaUtils.getMetaAliasByUri(request.getRequestURI()) ;
String realm = SAML2MetaUtils.getRealmByMetaAlias(metaAlias);
SAML2MetaManager mm = SAML2Utils.getSAML2MetaManager();
String entityId = mm.getEntityByMetaAlias(metaAlias);
SPSSOConfigElement spConfig = mm.getSPSSOConfig(realm, entityId);
String appSLOUrlStr = null;
if (spConfig != null) {
appSLOUrlStr = SAML2Utils.getAttributeValueFromSPSSOConfig(
spConfig, SAML2Constants.SAE_SP_LOGOUT_URL);
}
if (appSLOUrlStr == null) {
SAML2Utils.debug.message(
"spSLOPOST:SAE:appSLOUrl not configured.");
return false;
}
if (SAML2Utils.debug.messageEnabled()) {
SAML2Utils.debug.message(
"spSLOPOST:SAE:processing App SLO"+ appSLOUrlStr);
}
StringBuffer appSLOUrl = new StringBuffer(appSLOUrlStr);
Map hp = SAML2Utils.getSAEAttrs(
realm, entityId, SAML2Constants.SP_ROLE, appSLOUrlStr);
if (hp == null) {
SAML2Utils.debug.error(
"spSLOPOST:SAE:processing App SLO: getSAEAttrs returned null");
return false;
}
String cryptoType = (String) hp.get(SecureAttrs.SAE_CRYPTO_TYPE);
String secret = null;
String encSecret = null;
String encAlg = (String)hp.get(
SecureAttrs.SAE_CONFIG_DATA_ENCRYPTION_ALG);
String encStrength = (String)hp.get(
SecureAttrs.SAE_CONFIG_ENCRYPTION_KEY_STRENGTH);
if (SecureAttrs.SAE_CRYPTO_TYPE_SYM.equals(cryptoType)) {
// Shared secret between FM-IDP and IDPApp
secret = (String) hp.get(SecureAttrs.SAE_CONFIG_SHARED_SECRET );
encSecret = secret;
} else {
// IDPApp's public key
secret = (String) hp.get(SecureAttrs.SAE_CONFIG_PRIVATE_KEY_ALIAS);
encSecret =
(String) hp.get(SecureAttrs.SAE_CONFIG_PUBLIC_KEY_ALIAS);
}
if (secret == null || secret.length() == 0) {
SAML2Utils.debug.error(
"spSLOPOST:SAE:processing App SLO:getSAEAttrs no secret/key");
return false;
}
if (encAlg == null) {
encSecret = null;
}
String returnURL = request.getRequestURL()+
"?"+request.getQueryString()+"&"+
SecureAttrs.SAE_PARAM_APPRETURN+"=true";
HashMap map = new HashMap();
map.put(SecureAttrs.SAE_PARAM_CMD, SecureAttrs.SAE_CMD_LOGOUT);
map.put(SecureAttrs.SAE_PARAM_APPSLORETURNURL, returnURL);
String saInstanceName = cryptoType + "_" + encAlg + "_" + encStrength;
SecureAttrs sa = SecureAttrs.getInstance(saInstanceName);
if (sa == null) {
Properties prop = new Properties();
prop.setProperty(SecureAttrs.SAE_CONFIG_CERT_CLASS,
"com.sun.identity.sae.api.FMCerts");
if (encAlg != null) {
prop.setProperty(
SecureAttrs.SAE_CONFIG_DATA_ENCRYPTION_ALG, encAlg);
}
if (encStrength != null) {
prop.setProperty(
SecureAttrs.SAE_CONFIG_ENCRYPTION_KEY_STRENGTH,encStrength); }
SecureAttrs.init(saInstanceName, cryptoType, prop);
sa = SecureAttrs.getInstance(saInstanceName);
}
if (sa == null) {
SAML2Utils.debug.error(
"spSLOPOST:SAE:processing App SLO:null SecureAttrs instance");
return false;
}
String encodedString = sa.getEncodedString(map, secret, encSecret);
if (encodedString != null) {
if (appSLOUrl.indexOf("?") > 0) {
appSLOUrl.append("&").append(SecureAttrs.SAE_PARAM_DATA)
.append("=").append(encodedString);
} else {
appSLOUrl.append("?").append(SecureAttrs.SAE_PARAM_DATA)
.append("=").append(encodedString);
}
if (SAML2Utils.debug.messageEnabled()) {
SAML2Utils.debug.message("spSLOPOST:SAE:about to redirect"+
appSLOUrl);
}
response.sendRedirect(appSLOUrl.toString());
return true;
} else {
SAML2Utils.debug.error(
"spSLOPOST:SAE:SecureAttrs.getEncodedStr failed");
}
} catch (Exception ex) {
SAML2Utils.debug.error("spSLOPOST:SAE:SecureAttrs.Fatal:",ex);
}
return false;
}
%>