/******************************************************************************* * 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.eidas; import java.io.IOException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import at.gv.egovernment.moa.id.advancedlogging.MOAIDEventConstants; import at.gv.egovernment.moa.id.auth.exception.AuthenticationException; import at.gv.egovernment.moa.id.auth.exception.MOAIDException; import at.gv.egovernment.moa.id.auth.modules.eidas.Constants; import at.gv.egovernment.moa.id.auth.modules.eidas.utils.MOAPersonalAttributeList; import at.gv.egovernment.moa.id.auth.modules.eidas.utils.SAMLEngineUtils; import at.gv.egovernment.moa.id.config.auth.AuthConfigurationProviderFactory; import at.gv.egovernment.moa.id.config.auth.OAAuthParameter; import at.gv.egovernment.moa.id.moduls.IRequest; import at.gv.egovernment.moa.id.protocols.AbstractAuthProtocolModulController; import at.gv.egovernment.moa.logging.Logger; import at.gv.egovernment.moa.util.MiscUtil; import eu.eidas.auth.commons.EIDASAuthnRequest; import eu.eidas.auth.commons.EIDASUtil; import eu.eidas.auth.engine.EIDASSAMLEngine; /** * eIDAS Protocol Support for outbound authentication * * @author tlenz */ public class EIDASProtocol extends AbstractAuthProtocolModulController { public static final String NAME = EIDASProtocol.class.getName(); public static final String PATH = "eidas"; public String getName() { return NAME; } public String getPath() { return PATH; } //eIDAS metadata end-point @RequestMapping(value = "/eidas/metadata", method = {RequestMethod.GET}) public void eIDASMetadataRequest(HttpServletRequest req, HttpServletResponse resp) throws MOAIDException { //create pendingRequest object EIDASData pendingReq = applicationContext.getBean(EIDASData.class); pendingReq.initialize(req); pendingReq.setModule(NAME); pendingReq.setNeedAuthentication(false); pendingReq.setAuthenticated(false); revisionsLogger.logEvent( pendingReq.getUniqueSessionIdentifier(), pendingReq.getUniqueTransactionIdentifier(), MOAIDEventConstants.TRANSACTION_IP, req.getRemoteAddr()); EidasMetaDataRequest metadataAction = applicationContext.getBean(EidasMetaDataRequest.class); metadataAction.processRequest(pendingReq, req, resp, null); revisionsLogger.logEvent( pendingReq.getUniqueSessionIdentifier(), pendingReq.getUniqueTransactionIdentifier(), Constants.eIDAS_REVERSIONSLOG_METADATA); } //PVP2.x IDP POST-Binding end-point @RequestMapping(value = "/eidas/ColleagueRequest", method = {RequestMethod.POST}) public void PVPIDPPostRequest(HttpServletRequest req, HttpServletResponse resp) throws MOAIDException, IOException { //create pending-request object EIDASData pendingReq = applicationContext.getBean(EIDASData.class); pendingReq.initialize(req); 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 eIDAS request preProcess(req, resp, pendingReq); revisionsLogger.logEvent(pendingReq, Constants.eIDAS_REVERSIONSLOG_IDP_AUTHREQUEST); //AuthnRequest needs authentication pendingReq.setNeedAuthentication(true); //set protocol action, which should be executed after authentication pendingReq.setAction(eIDASAuthenticationRequest.class.getName()); //switch to session authentication performAuthentication(req, resp, pendingReq); } /* First request step - send it to BKU selection for user authentication. After the user credentials and other info are obtained, in the second step the request will be processed and the user redirected */ public void preProcess(HttpServletRequest request, HttpServletResponse response, EIDASData pendingReq) throws MOAIDException { Logger.info("received an eIDaS request"); //get SAML Response and decode it String base64SamlToken = request.getParameter("SAMLRequest"); if (MiscUtil.isEmpty(base64SamlToken)) { Logger.warn("No eIDAS SAMLRequest found in http request."); throw new MOAIDException("HTTP request includes no eIDAS SAML-Request element.", null); } byte[] decSamlToken = EIDASUtil.decodeSAMLToken(base64SamlToken); try { //get eIDAS SAML-engine EIDASSAMLEngine engine = SAMLEngineUtils.createSAMLEngine(); //validate SAML token EIDASAuthnRequest samlReq = engine.validateEIDASAuthnRequest(decSamlToken); // - memorize remote ip pendingReq.setRemoteAddress(request.getRemoteAddr()); // - memorize country code of target country pendingReq.setGenericDataToSession( Constants.eIDAS_GENERIC_REQ_DATA_COUNTRY, samlReq.getCountry()); // - memorize requested attributes pendingReq.setEidasRequestedAttributes(new MOAPersonalAttributeList(samlReq.getPersonalAttributeList())); // - memorize whole request samlReq.setPersonalAttributeList(pendingReq.getEidasRequestedAttributes()); // circumvent non-serializable eidas personal attribute list pendingReq.setEidasRequest(samlReq); // - memorize OA url pendingReq.setOAURL(samlReq.getIssuer()); // - memorize OA config OAAuthParameter oaConfig = AuthConfigurationProviderFactory.getInstance().getOnlineApplicationParameter(pendingReq.getOAURL()); if (oaConfig == null) throw new AuthenticationException("stork.12", new Object[]{pendingReq.getOAURL()}); pendingReq.setOnlineApplicationConfiguration(oaConfig); } catch(Exception e) { Logger.error("error in preprocessing step", e); throw new MOAIDException("error in preprocessing step", null); } } public boolean generateErrorMessage(Throwable e, HttpServletRequest request, HttpServletResponse response, IRequest protocolRequest) throws Throwable { return false; } public boolean validate(HttpServletRequest request, HttpServletResponse response, IRequest pending) { return false; } }