/** * Signs Federation termination request before sending it to the remote provider. * * @param msg <code>SOAPMessage</code> which includes termination request to be sent to remote * provider * @param idAttrName name of the id attribute to be signed * @param id the value of the id attributer to be signed * @return signed termination request in <code>SOAPMessage</code> * @exception SAMLException if an error occurred during signing */ protected SOAPMessage signTerminationRequest(SOAPMessage msg, String idAttrName, String id) throws SAMLException { FSUtils.debug.message("FSSPFedTerminationHandler.signTerminationRequest: Called"); String certAlias = IDFFMetaUtils.getFirstAttributeValueFromConfig( hostedConfig, IFSConstants.SIGNING_CERT_ALIAS); if (certAlias == null || certAlias.length() == 0) { if (FSUtils.debug.messageEnabled()) { FSUtils.debug.message( "FSSPFedTerminationHandler.signTerminationRequest: couldn't" + "obtain this site's cert alias."); } throw new SAMLResponderException(FSUtils.bundle.getString(IFSConstants.NO_CERT_ALIAS)); } if (FSUtils.debug.messageEnabled()) { FSUtils.debug.message( "FSSPFedTerminationHandler.signTerminationRequest: Provider's " + "certAlias is found: " + certAlias); } XMLSignatureManager manager = XMLSignatureManager.getInstance(); Document doc = (Document) FSServiceUtils.createSOAPDOM(msg); String xpath = "//*[local-name()=\'ProviderID\']"; manager.signXML( doc, certAlias, SystemConfigurationUtil.getProperty(SAMLConstants.XMLSIG_ALGORITHM), idAttrName, id, false, xpath); return FSServiceUtils.convertDOMToSOAP(doc); }
/** * Initiates the federation termination operation. * * @param request HTTP request * @param response HTTP response * @param ssoToken corresponding to the user's session * @return <code>true</code> if the termination initiation operation is successful; <code>false * </code> otherwise. */ public boolean handleFederationTermination( HttpServletRequest request, HttpServletResponse response, Object ssoToken) { FSUtils.debug.message("Entered FSFedTerminationHandler::handleFederationTermination"); this.request = request; this.locale = FSServiceUtils.getLocale(request); this.response = response; this.ssoToken = ssoToken; setTerminationURL(); if (managerInst == null) { FSUtils.debug.error("FSSPFedTerminationHandler " + "Account Manager instance is null"); if (FSUtils.debug.messageEnabled()) { FSUtils.debug.message( "FSSPFedTerminationHandler::handleFederationTermination" + "failed to get Account Manager instance"); } FSServiceUtils.returnLocallyAfterOperation( response, termination_done_url, false, IFSConstants.TERMINATION_SUCCESS, IFSConstants.TERMINATION_FAILURE); return false; } try { this.userID = SessionManager.getProvider().getPrincipalName(ssoToken); } catch (SessionException e) { FSUtils.debug.error("FSFedTerminationHandler::handleFederationTermination:", e); // cannot proceed without user LogUtil.error(Level.INFO, LogUtil.USER_NOT_FOUND, null, ssoToken); return false; } boolean bStatus = updateAccountInformation(null); FSUtils.debug.message("After updateAccountInformation"); if (!bStatus) { if (FSUtils.debug.messageEnabled()) { FSUtils.debug.message( "FSSPFedTerminationHandler::handleFederationTermination " + "Federation Termination failed locally. Cannot update " + "account"); } String[] data = {userID}; LogUtil.error(Level.INFO, LogUtil.TERMINATION_FAILED, data, ssoToken); FSServiceUtils.returnLocallyAfterOperation( response, termination_done_url, false, IFSConstants.TERMINATION_SUCCESS, IFSConstants.TERMINATION_FAILURE); return false; } FSUtils.debug.message("Status of local update true"); String[] data = {userID}; LogUtil.access(Level.INFO, LogUtil.TERMINATION_SUCCESS, data, ssoToken); resetFederateCookie(); boolean bRemoteStatus = doFederationTermination(request, response, acctInfo); return bRemoteStatus; }
/** * Processes the termination request received from a remote provider. Invoded when Http redirect * profile is used. * * @param request HTTP request * @param response HTTP response * @param reqTermination the federation termination request received from remote provider */ public void processTerminationRequest( HttpServletRequest request, HttpServletResponse response, FSFederationTerminationNotification reqTermination) { FSUtils.debug.message("Entered FSFedTerminationHandler::processTerminationRequest..."); this.request = request; this.locale = FSServiceUtils.getLocale(request); this.response = response; this.relayState = reqTermination.getRelayState(); setTerminationURL(); if (managerInst == null) { FSUtils.debug.error( "FSSPFedTerminationHandler " + FSUtils.bundle.getString(IFSConstants.FEDERATION_FAILED_ACCOUNT_INSTANCE)); if (FSUtils.debug.messageEnabled()) { FSUtils.debug.message( "FSSPFedTerminationHandler::handleFederationTermination" + "failed to get Account Manager instance"); } returnToSource(); return; } boolean bStatus = updateAccountInformation(reqTermination.getNameIdentifier()); if (!bStatus) { FSUtils.debug.message("Termination request processing failed"); String[] data = { FSUtils.bundle.getString(IFSConstants.TERMINATION_REQUEST_PROCESSING_FAILED) }; LogUtil.error(Level.INFO, LogUtil.TERMINATION_FAILED, data, ssoToken); returnToSource(); return; } FSUtils.debug.message("User sucessfully defederated"); String[] data = {FSUtils.bundle.getString(IFSConstants.TERMINATION_SUCCEEDED)}; LogUtil.access(Level.INFO, LogUtil.TERMINATION_SUCCESS, data, ssoToken); // Call SP Adaper for remote IDP initiated HTTP profile if (hostedProviderRole != null && hostedProviderRole.equalsIgnoreCase(IFSConstants.SP)) { FederationSPAdapter spAdapter = FSServiceUtils.getSPAdapter(hostedEntityId, hostedConfig); if (spAdapter != null) { FSUtils.debug.message("FSFedTerminationHandler.HTTP"); try { spAdapter.postTerminationNotificationSuccess( hostedEntityId, request, response, userID, reqTermination, IFSConstants.TERMINATION_IDP_HTTP_PROFILE); } catch (Exception e) { // ignore adapter exception FSUtils.debug.error("postTermNotification.IDP/HTTP", e); } } } returnToSource(); return; }
/** * Determines the return location and redirects based on federation termination Return URL of the * provider that sent the termination request. */ private void returnToSource() { FSUtils.debug.message("Entered FSFedTerminationHandler::returnToSource"); try { StringBuffer finalReturnURL = new StringBuffer(); String retURL = remoteDescriptor.getFederationTerminationServiceReturnURL(); if (FSUtils.debug.messageEnabled()) { FSUtils.debug.message("Redirecting to : " + retURL); } resetFederateCookie(); FSUtils.debug.message("Checking retURL for null value"); if (retURL == null || retURL.length() < 1) { FSUtils.debug.error("Return URL is null"); FSServiceUtils.showErrorPage( response, error_page_url, IFSConstants.TERMINATION_INVALID_REDIRECT_URL, IFSConstants.METADATA_ERROR); return; } else { finalReturnURL.append(retURL); if (!(relayState == null || relayState.length() < 1)) { char delimiter; if (retURL.indexOf(IFSConstants.QUESTION_MARK) < 0) { delimiter = IFSConstants.QUESTION_MARK; } else { delimiter = IFSConstants.AMPERSAND; } finalReturnURL .append(delimiter) .append(RELAY_STATE) .append(IFSConstants.EQUAL_TO) .append(URLEncDec.encode(relayState)); } if (FSUtils.debug.messageEnabled()) { FSUtils.debug.message("Now sendRedirecting to : " + finalReturnURL.toString()); } response.sendRedirect(finalReturnURL.toString()); return; } } catch (IOException e) { FSUtils.debug.error( "Unable to get LRURL. No location to redirect." + " processing completed", e); } // create new bundle entry for redirect failure FSUtils.debug.message("After exception calling response.sendError"); FSServiceUtils.showErrorPage( response, error_page_url, IFSConstants.TERMINATION_INVALID_REDIRECT_URL, IFSConstants.METADATA_ERROR); return; }
/** * Handles termination return message. * * @param request <code>HttpServletRequest</code> object that contains the request the client has * made of the servlet. * @param response <code>HttpServletResponse</code> object that contains the response the servlet * sends to the client. * @exception ServletException if an input or output error is detected when the servlet handles * the request * @exception IOException if the request could not be handled */ private void doGetPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { FSUtils.debug.message("FSTerminationReturnServlet doGetPost..."); String providerAlias = FSServiceUtils.getMetaAlias(request); if (providerAlias == null || providerAlias.length() < 1) { if (FSUtils.debug.messageEnabled()) { FSUtils.debug.message( "Unable to retrieve alias, Hosted" + " Provider. Cannot process request"); } response.sendError( response.SC_INTERNAL_SERVER_ERROR, FSUtils.bundle.getString("aliasNotFound")); return; } StringBuffer terminationDone = new StringBuffer(); BaseConfigType hostedConfig = null; try { String hostedRole = metaManager.getProviderRoleByMetaAlias(providerAlias); String hostedEntityId = metaManager.getEntityIDByMetaAlias(providerAlias); String realm = IDFFMetaUtils.getRealmByMetaAlias(providerAlias); if (hostedRole != null && hostedRole.equalsIgnoreCase(IFSConstants.IDP)) { hostedConfig = metaManager.getIDPDescriptorConfig(realm, hostedEntityId); } else if (hostedRole != null && hostedRole.equalsIgnoreCase(IFSConstants.SP)) { hostedConfig = metaManager.getSPDescriptorConfig(realm, hostedEntityId); } if (hostedRole == null || hostedConfig == null) { throw new IDFFMetaException((String) null); } } catch (IDFFMetaException e) { FSUtils.debug.error("Failed to get Hosted Provider"); response.sendError( response.SC_INTERNAL_SERVER_ERROR, FSUtils.bundle.getString(IFSConstants.FAILED_HOSTED_DESCRIPTOR)); return; } terminationDone.append( FSServiceUtils.getTerminationDonePageURL(request, hostedConfig, providerAlias)); if (FSUtils.debug.messageEnabled()) { FSUtils.debug.message("Final Done page URL at local end: " + terminationDone.toString()); } response.sendRedirect(terminationDone.toString()); return; }
/** Invoked to set some commonly used URLs based on hosted provider. */ protected void setTerminationURL() { termination_done_url = FSServiceUtils.getTerminationDonePageURL(request, hostedConfig, metaAlias); error_page_url = FSServiceUtils.getErrorPageURL(request, hostedConfig, metaAlias); }
/** * Initiates federation termination at remote end. The termination requested is constructed and * based on the profile the request is sent over SOAP or as HTTP redirect. Profile is always based * on the SPs profile * * @param acctInfo represents the user account federation information * @return <code>true</code> if termination request is sent to remote provider successfully; * <code>false</code> otherwise. */ private boolean doFederationTermination( HttpServletRequest request, HttpServletResponse response, FSAccountFedInfo acctInfo) { FSUtils.debug.message("Entered FSFedTerminationHandler::doFederationTermination"); try { if (FSUtils.debug.messageEnabled()) { FSUtils.debug.message( "FSFedTerminationHandler::doFederationTermination create" + " request start"); } FSFederationTerminationNotification reqFedTermination = createFederationTerminationRequest(acctInfo); reqFedTermination.setMinorVersion( FSServiceUtils.getMinorVersion(remoteDescriptor.getProtocolSupportEnumeration())); if (reqFedTermination == null) { if (FSUtils.debug.messageEnabled()) { FSUtils.debug.message( "FSIDPFedTerminationHandler::Termination request could " + "not be formed"); } // Always show success page since local termination succeeded FSServiceUtils.returnLocallyAfterOperation( response, termination_done_url, true, IFSConstants.TERMINATION_SUCCESS, IFSConstants.TERMINATION_FAILURE); return false; } if (FSUtils.debug.messageEnabled()) { FSUtils.debug.message( "FSIDPFedTerminationHandler::Termination request formed" + "successfully"); } // Find out which profile to use boolean isSOAPProfile = true; if (acctInfo.isRoleIDP()) { List hostProfiles = hostedDescriptor.getFederationTerminationNotificationProtocolProfile(); if (hostProfiles == null || hostProfiles.isEmpty()) { FSUtils.debug.error( "FSFedTerminationHandler::" + "doFederationTermination no termination profile" + " cannot process request"); FSServiceUtils.returnLocallyAfterOperation( response, termination_done_url, true, IFSConstants.TERMINATION_SUCCESS, IFSConstants.TERMINATION_FAILURE); return false; } String profile = (String) hostProfiles.iterator().next(); if (profile.equalsIgnoreCase(IFSConstants.TERMINATION_SP_SOAP_PROFILE) || profile.equalsIgnoreCase(IFSConstants.TERMINATION_IDP_SOAP_PROFILE)) { isSOAPProfile = true; } else if (profile.equalsIgnoreCase(IFSConstants.TERMINATION_SP_HTTP_PROFILE) || profile.equalsIgnoreCase(IFSConstants.TERMINATION_IDP_HTTP_PROFILE)) { isSOAPProfile = false; } else { FSUtils.debug.error( "FSFedTerminationHandler::" + "doFederationTermination Invalid termination profile" + " cannot process request"); FSServiceUtils.returnLocallyAfterOperation( response, termination_done_url, true, IFSConstants.TERMINATION_SUCCESS, IFSConstants.TERMINATION_FAILURE); return false; } } else { List remoteProfiles = remoteDescriptor.getFederationTerminationNotificationProtocolProfile(); if (remoteProfiles == null || remoteProfiles.isEmpty()) { FSUtils.debug.error( "FSFedTerminationHandler::" + "doFederationTermination no termination profile" + " cannot process request"); FSServiceUtils.returnLocallyAfterOperation( response, termination_done_url, true, IFSConstants.TERMINATION_SUCCESS, IFSConstants.TERMINATION_FAILURE); return false; } String profile = (String) remoteProfiles.iterator().next(); if (profile.equalsIgnoreCase(IFSConstants.TERMINATION_SP_SOAP_PROFILE) || profile.equalsIgnoreCase(IFSConstants.TERMINATION_IDP_SOAP_PROFILE)) { isSOAPProfile = true; } else if (profile.equalsIgnoreCase(IFSConstants.TERMINATION_SP_HTTP_PROFILE) || profile.equalsIgnoreCase(IFSConstants.TERMINATION_IDP_HTTP_PROFILE)) { isSOAPProfile = false; } else { FSUtils.debug.error( "FSFedTerminationHandler::" + "doFederationTermination Invalid termination profile" + " cannot process request"); FSServiceUtils.returnLocallyAfterOperation( response, termination_done_url, true, IFSConstants.TERMINATION_SUCCESS, IFSConstants.TERMINATION_FAILURE); return false; } } if (isSOAPProfile) { FSSOAPService instSOAP = FSSOAPService.getInstance(); if (instSOAP != null) { FSUtils.debug.message("Signing suceeded. To call bindTerminationRequest"); // String id = reqFedTermination.getRequestID(); reqFedTermination.setID(IFSConstants.TERMINATIONID); SOAPMessage msgTermination = instSOAP.bind(reqFedTermination.toXMLString(true, true)); if (msgTermination != null) { try { if (FSServiceUtils.isSigningOn()) { int minorVersion = reqFedTermination.getMinorVersion(); if (minorVersion == IFSConstants.FF_11_PROTOCOL_MINOR_VERSION) { msgTermination = signTerminationRequest( msgTermination, IFSConstants.ID, reqFedTermination.getID()); } else if (minorVersion == IFSConstants.FF_12_PROTOCOL_MINOR_VERSION) { msgTermination = signTerminationRequest( msgTermination, IFSConstants.REQUEST_ID, reqFedTermination.getRequestID()); } else { FSUtils.debug.message("invalid minor version."); } } boolean sendStatus = instSOAP.sendTerminationMessage( msgTermination, remoteDescriptor.getSoapEndpoint()); // Call SP Adapter for SP initiated SOAP profile if (hostedProviderRole != null && hostedProviderRole.equalsIgnoreCase(IFSConstants.SP)) { FederationSPAdapter spAdapter = FSServiceUtils.getSPAdapter(hostedEntityId, hostedConfig); if (spAdapter != null) { try { spAdapter.postTerminationNotificationSuccess( hostedEntityId, request, response, userID, reqFedTermination, IFSConstants.TERMINATION_SP_SOAP_PROFILE); } catch (Exception e) { // ignore adapter exception FSUtils.debug.error("postTerm.SP/SOAP", e); } } } // Always show success page since local termination // succeeded and that is what is important FSServiceUtils.returnLocallyAfterOperation( response, termination_done_url, true, IFSConstants.TERMINATION_SUCCESS, IFSConstants.TERMINATION_FAILURE); return sendStatus; } catch (Exception e) { FSUtils.debug.error( "FSFedTerminationHandler::" + "doFederationTermination " + FSUtils.bundle.getString(IFSConstants.TERMINATION_FAILED_SEND_REMOTE)); // Always show success page since local // termination succeeded FSServiceUtils.returnLocallyAfterOperation( response, termination_done_url, true, IFSConstants.TERMINATION_SUCCESS, IFSConstants.TERMINATION_FAILURE); return false; } } else { if (FSUtils.debug.messageEnabled()) { FSUtils.debug.message( "FSSPFedTerminationHandler::doFederation" + "Termination failed. Error in forming Message"); } FSUtils.debug.error( "FSSPFedTerminationHandler.doFederationTermination " + FSUtils.bundle.getString(IFSConstants.TERMINATION_FAILED_SEND_REMOTE)); // Always show success page since local termination // succeeded FSServiceUtils.returnLocallyAfterOperation( response, termination_done_url, true, IFSConstants.TERMINATION_SUCCESS, IFSConstants.TERMINATION_FAILURE); return false; } } if (FSUtils.debug.messageEnabled()) { FSUtils.debug.message( "FSFedTerminationHandler::doFederationTermination " + "failed. Cannot get Service Manager instance"); } FSUtils.debug.error( "FSSPFedTerminationHandler::doFederationTermination " + FSUtils.bundle.getString(IFSConstants.TERMINATION_FAILED_SEND_REMOTE)); // Always show success page since local termination succeeded FSServiceUtils.returnLocallyAfterOperation( response, termination_done_url, true, IFSConstants.TERMINATION_SUCCESS, IFSConstants.TERMINATION_FAILURE); return false; } else { if (FSUtils.debug.messageEnabled()) { FSUtils.debug.message( "FSFedTerminationHandler::doFederationTermination " + "In Redirect profile"); } String urlEncodedRequest = reqFedTermination.toURLEncodedQueryString(); // Sign the request querystring if (FSServiceUtils.isSigningOn()) { String certAlias = IDFFMetaUtils.getFirstAttributeValueFromConfig( hostedConfig, IFSConstants.SIGNING_CERT_ALIAS); if (certAlias == null || certAlias.length() == 0) { if (FSUtils.debug.messageEnabled()) { FSUtils.debug.message( "FSBrowserArtifactConsumerHandler:: " + "signSAMLRequest:" + "couldn't obtain this site's cert alias."); } throw new SAMLResponderException(FSUtils.bundle.getString(IFSConstants.NO_CERT_ALIAS)); } urlEncodedRequest = FSSignatureUtil.signAndReturnQueryString(urlEncodedRequest, certAlias); } StringBuffer redirectURL = new StringBuffer(); if (FSUtils.debug.messageEnabled()) { FSUtils.debug.message("Request to be sent : " + urlEncodedRequest); } String retURL = remoteDescriptor.getFederationTerminationServiceURL(); redirectURL.append(retURL); if (retURL.indexOf(IFSConstants.QUESTION_MARK) == -1) { redirectURL.append(IFSConstants.QUESTION_MARK); } else { redirectURL.append(IFSConstants.AMPERSAND); } redirectURL.append(urlEncodedRequest); if (FSUtils.debug.messageEnabled()) { FSUtils.debug.message( "FSFedTerminationHandler::Redirect URL is " + redirectURL.toString()); } // Call SP Adaper for SP initiated HTTP profile // ideally this should be called from the // FSTerminationReturnServlet, but info not available there if (hostedProviderRole != null && hostedProviderRole.equalsIgnoreCase(IFSConstants.SP)) { FederationSPAdapter spAdapter = FSServiceUtils.getSPAdapter(hostedEntityId, hostedConfig); if (spAdapter != null) { try { spAdapter.postTerminationNotificationSuccess( hostedEntityId, request, response, userID, reqFedTermination, IFSConstants.TERMINATION_SP_HTTP_PROFILE); } catch (Exception e) { // ignore adapter exception FSUtils.debug.error("postTerm.SP/HTTP", e); } } } response.sendRedirect(redirectURL.toString()); return true; } } catch (IOException e) { FSUtils.debug.error( "FSFedTerminationHandler" + FSUtils.bundle.getString(IFSConstants.FEDERATION_REDIRECT_FAILED)); } catch (FSMsgException e) { FSUtils.debug.error( "FSFedTerminationHandler::doFederationTermination " + FSUtils.bundle.getString(IFSConstants.TERMINATION_FAILED_SEND_REMOTE)); } catch (SAMLResponderException e) { FSUtils.debug.error( "FSFedTerminationHandler::doFederationTermination " + FSUtils.bundle.getString(IFSConstants.TERMINATION_FAILED_SEND_REMOTE)); } // Always show success page since local termination succeeded FSServiceUtils.returnLocallyAfterOperation( response, termination_done_url, true, IFSConstants.TERMINATION_SUCCESS, IFSConstants.TERMINATION_FAILURE); return false; }
/** * Processes the termination request received from a remote provider. Invoded when SOAP profile is * used. * * @param reqTermination the federation termination request received from remote provider * @return <code>true</code> when the process is successful; <code>false</code> otherwise. */ public boolean processSOAPTerminationRequest( HttpServletRequest request, HttpServletResponse response, FSFederationTerminationNotification reqTermination) { FSUtils.debug.message("Entered FSFedTerminationHandler::processSOAPTerminationRequest"); if (managerInst == null) { FSUtils.debug.error("FSSPFedTerminationHandler " + "Account Manager instance is null"); if (FSUtils.debug.messageEnabled()) { FSUtils.debug.message( "FSSPFedTerminationHandler::handleFederationTermination" + "failed to get Account Manager instance"); } return false; } if (FSUtils.debug.messageEnabled()) { FSUtils.debug.message("Begin processTerminationRequest SOAP profile..."); } boolean bStatus = false; if (reqTermination != null) { boolean bUserStatus = setUserID(reqTermination); if (bUserStatus) { bStatus = updateAccountInformation(reqTermination.getNameIdentifier()); if (!bStatus) { FSUtils.debug.error( "FSFedTerminationHandler " + FSUtils.bundle.getString(IFSConstants.TERMINATION_REQUEST_PROCESSING_FAILED)); return false; } else { FSUtils.debug.message("User sucessfully defederated"); // Call SP Adapter for remote IDP initiated SOAP case if (hostedProviderRole != null && hostedProviderRole.equalsIgnoreCase(IFSConstants.SP)) { FederationSPAdapter spAdapter = FSServiceUtils.getSPAdapter(hostedEntityId, hostedConfig); if (spAdapter != null) { FSUtils.debug.message("FSFedTerminationHandler.SOAP"); try { spAdapter.postTerminationNotificationSuccess( hostedEntityId, request, response, userID, reqTermination, IFSConstants.TERMINATION_IDP_SOAP_PROFILE); } catch (Exception e) { // ignore adapter exception FSUtils.debug.error("postTerm.IDP/SOAP", e); } } } return true; } } else { FSUtils.debug.message("Failed to get UserDN. Invalid termination request"); return false; } } else { FSUtils.debug.error( "FSFedTerminationHandler::processTerminationRequest " + "Federation termination request is improper"); return false; } }