/******************************************************************************* * Copyright 2014 Federal Chancellery Austria * MOA-ID has been developed in a cooperation between BRZ, the Federal * Chancellery Austria - ICT staff unit, and Graz University of Technology. * * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by * the European Commission - subsequent versions of the EUPL (the "Licence"); * You may not use this work except in compliance with the Licence. * You may obtain a copy of the Licence at: * http://www.osor.eu/eupl/ * * Unless required by applicable law or agreed to in writing, software * distributed under the Licence is distributed on an "AS IS" basis, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the Licence for the specific language governing permissions and * limitations under the Licence. * * This product combines work with different licenses. See the "NOTICE" text * file for details on the various modules and licenses. * The "NOTICE" text file is part of the distribution. Any derivative works * that you distribute must include a readable copy of the "NOTICE" text file. *******************************************************************************/ package at.gv.egovernment.moa.id.protocols.saml1; import java.io.IOException; import java.util.Arrays; import java.util.List; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.apache.commons.lang.StringEscapeUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import at.gv.egiz.eaaf.core.api.IRequest; import at.gv.egiz.eaaf.core.api.idp.IModulInfo; import at.gv.egiz.eaaf.core.exceptions.EAAFConfigurationException; import at.gv.egiz.eaaf.core.exceptions.EAAFException; import at.gv.egiz.eaaf.core.exceptions.EAAFStorageException; import at.gv.egiz.eaaf.core.exceptions.InvalidProtocolRequestException; import at.gv.egiz.eaaf.core.exceptions.ProtocolNotActiveException; import at.gv.egiz.eaaf.core.impl.idp.controller.AbstractAuthProtocolModulController; import at.gv.egovernment.moa.id.advancedlogging.MOAIDEventConstants; import at.gv.egovernment.moa.id.auth.exception.WrongParametersException; import at.gv.egovernment.moa.id.auth.servlet.RedirectServlet; import at.gv.egovernment.moa.id.commons.MOAIDAuthConstants; import at.gv.egovernment.moa.id.commons.api.AuthConfiguration; import at.gv.egovernment.moa.id.commons.api.IOAAuthParameters; import at.gv.egovernment.moa.id.commons.api.data.SAML1ConfigurationParameters; import at.gv.egovernment.moa.id.commons.api.exceptions.MOAIDException; import at.gv.egovernment.moa.id.protocols.pvp2x.PVPConstants; import at.gv.egovernment.moa.id.util.ParamValidatorUtils; import at.gv.egovernment.moa.logging.Logger; import at.gv.egovernment.moa.util.MiscUtil; import at.gv.egovernment.moa.util.URLEncoder; /** * SAML1 authentication protocol implementation * * @deprecated * @author tlenz * */ @Controller public class SAML1Protocol extends AbstractAuthProtocolModulController implements IModulInfo { @Autowired private SAML1AuthenticationServer saml1AuthServer; public static final String REQ_DATA_SOURCEID = "saml1_sourceID"; public static final String REQ_DATA_TARGET = "saml1_target"; public static final String NAME = SAML1Protocol.class.getName(); public static final String PATH = "id_saml1"; public static final String GETARTIFACT = "GetArtifact"; public static final List DEFAULTREQUESTEDATTRFORINTERFEDERATION = Arrays.asList( new String[] { PVPConstants.BPK_NAME, PVPConstants.EID_SECTOR_FOR_IDENTIFIER_NAME, PVPConstants.GIVEN_NAME_NAME, PVPConstants.PRINCIPAL_NAME_NAME, PVPConstants.BIRTHDATE_NAME, PVPConstants.EID_CCS_URL_NAME, PVPConstants.EID_CITIZEN_QAA_LEVEL_NAME, PVPConstants.EID_IDENTITY_LINK_NAME, PVPConstants.EID_SOURCE_PIN_NAME, PVPConstants.EID_SOURCE_PIN_TYPE_NAME }); @Autowired(required=true) AuthConfiguration moaAuthConfig; public String getName() { return NAME; } @Override public String getAuthProtocolIdentifier() { return PATH; } @RequestMapping(value = "/StartAuthentication", method = {RequestMethod.POST, RequestMethod.GET}) public void SAML1AuthnRequest(HttpServletRequest req, HttpServletResponse resp) throws IOException, EAAFException { if (!moaAuthConfig.getAllowedProtocols().isSAML1Active()) { Logger.info("SAML1 is deaktivated!"); throw new ProtocolNotActiveException("auth.22", new Object[] { "SAML 1" }); } SAML1RequestImpl pendingReq = applicationContext.getBean(SAML1RequestImpl.class); pendingReq.initialize(req, authConfig); pendingReq.setModule(NAME); revisionsLogger.logEvent(MOAIDEventConstants.SESSION_CREATED, pendingReq.getUniqueSessionIdentifier()); revisionsLogger.logEvent(MOAIDEventConstants.TRANSACTION_CREATED, pendingReq.getUniqueTransactionIdentifier()); revisionsLogger.logEvent( pendingReq.getUniqueSessionIdentifier(), pendingReq.getUniqueTransactionIdentifier(), MOAIDEventConstants.TRANSACTION_IP, req.getRemoteAddr()); //preProcess SAML1 Request preProcess(req, resp, pendingReq); performAuthentication(req, resp, pendingReq); return; } public void preProcess(HttpServletRequest request, HttpServletResponse response, SAML1RequestImpl pendingRequest) throws MOAIDException, InvalidProtocolRequestException, EAAFConfigurationException, EAAFStorageException { try { String oaURL = (String) request.getParameter(MOAIDAuthConstants.PARAM_OA); //oaURL = StringEscapeUtils.escapeHtml(oaURL); String target = (String) request.getParameter(MOAIDAuthConstants.PARAM_TARGET); target = StringEscapeUtils.escapeHtml(target); String sourceID = request.getParameter(MOAIDAuthConstants.PARAM_SOURCEID); sourceID = StringEscapeUtils.escapeHtml(sourceID); //the target parameter is used to define the OA in SAML1 standard if (target != null && target.startsWith("http")) { oaURL = target; target = null; } if (MiscUtil.isEmpty(oaURL)) { Logger.info("Receive SAML1 request with no OA parameter. Authentication STOPPED!"); throw new WrongParametersException("StartAuthentication", MOAIDAuthConstants.PARAM_OA, "auth.12"); } if (!ParamValidatorUtils.isValidOA(oaURL)) throw new WrongParametersException("StartAuthentication", MOAIDAuthConstants.PARAM_OA, "auth.12"); pendingRequest.setSPEntityId(oaURL); Logger.info("Dispatch SAML1 Request: OAURL=" + oaURL); if (!ParamValidatorUtils.isValidSourceID(sourceID)) throw new WrongParametersException("StartAuthentication", MOAIDAuthConstants.PARAM_SOURCEID, "auth.12"); //load Target only from OA config IOAAuthParameters oaParam = authConfig.getServiceProviderConfiguration(oaURL, IOAAuthParameters.class); if (oaParam == null) throw new InvalidProtocolRequestException("auth.00", new Object[] { null }); SAML1ConfigurationParameters saml1 = oaParam.getSAML1Parameter(); if (saml1 == null || !(saml1.isIsActive() != null && saml1.isIsActive()) ) { Logger.info("Online-Application " + oaURL + " can not use SAML1 for authentication."); throw new InvalidProtocolRequestException("auth.00", new Object[] { null }); } pendingRequest.setOnlineApplicationConfiguration(oaParam); //check and set SourceID if (oaParam.getSAML1Parameter() != null && MiscUtil.isNotEmpty(oaParam.getSAML1Parameter().getSourceID())) { pendingRequest.setSourceID(oaParam.getSAML1Parameter().getSourceID()); } else pendingRequest.setSourceID(sourceID); revisionsLogger.logEvent(pendingRequest, MOAIDEventConstants.AUTHPROTOCOL_SAML1_AUTHNREQUEST); if (MiscUtil.isNotEmpty(target)) { pendingRequest.setRawDataToTransaction(REQ_DATA_TARGET, target); pendingRequest.setTarget(MOAIDAuthConstants.PREFIX_CDID + target); } else { String targetArea = oaParam.getAreaSpecificTargetIdentifier(); pendingRequest.setTarget(targetArea); if (targetArea.startsWith(MOAIDAuthConstants.PREFIX_CDID)) pendingRequest.setRawDataToTransaction(REQ_DATA_TARGET, targetArea.substring(MOAIDAuthConstants.PREFIX_CDID.length())); } //AuthnRequest needs authentication pendingRequest.setNeedAuthentication(true); //set protocol action, which should be executed after authentication pendingRequest.setAction(GetArtifactAction.class.getName()); } catch (WrongParametersException e) { throw new InvalidProtocolRequestException(e.getMessageId(), e.getParameters()); } catch (InvalidProtocolRequestException e) { throw e; } } public boolean generateErrorMessage(Throwable e, HttpServletRequest request, HttpServletResponse response, IRequest protocolRequest) throws Throwable{ if (!protocolRequest.getServiceProviderConfiguration(IOAAuthParameters.class).getSAML1Parameter().isProvideAllErrors()) return false; else { String samlArtifactBase64 = saml1AuthServer.BuildErrorAssertion(e, protocolRequest); String url = protocolRequest.getAuthURL() + "/RedirectServlet"; url = addURLParameter(url, RedirectServlet.REDIRCT_PARAM_URL, URLEncoder.encode(protocolRequest.getSPEntityId(), "UTF-8")); url = addURLParameter(url, MOAIDAuthConstants.PARAM_SAMLARTIFACT, URLEncoder.encode(samlArtifactBase64, "UTF-8")); url = response.encodeRedirectURL(url); response.setContentType("text/html"); response.setStatus(302); response.addHeader("Location", url); Logger.debug("REDIRECT TO: " + url); return true; } } public boolean validate(HttpServletRequest request, HttpServletResponse response, IRequest pending) { return true; } protected static String addURLParameter(String url, String paramname, String paramvalue) { String param = paramname + "=" + paramvalue; if (url.indexOf("?") < 0) return url + "?" + param; else return url + "&" + param; } }