diff options
Diffstat (limited to 'eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/auth/modules/AbstractAuthServletTask.java')
-rw-r--r-- | eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/auth/modules/AbstractAuthServletTask.java | 479 |
1 files changed, 238 insertions, 241 deletions
diff --git a/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/auth/modules/AbstractAuthServletTask.java b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/auth/modules/AbstractAuthServletTask.java index ce9ba57c..c785e1cb 100644 --- a/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/auth/modules/AbstractAuthServletTask.java +++ b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/auth/modules/AbstractAuthServletTask.java @@ -1,29 +1,22 @@ -/******************************************************************************* - * Copyright 2017 Graz University of Technology - * EAAF-Core Components has been developed in a cooperation between EGIZ, - * A-SIT Plus, A-SIT, and Graz University of Technology. +/* + * Copyright 2017 Graz University of Technology EAAF-Core Components has been developed in a + * cooperation between EGIZ, A-SIT Plus, A-SIT, and Graz University of Technology. * - * Licensed under the EUPL, Version 1.2 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: + * Licensed under the EUPL, Version 1.2 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: * https://joinup.ec.europa.eu/news/understanding-eupl-v12 * - * 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. - *******************************************************************************/ -/******************************************************************************* - *******************************************************************************/ -/******************************************************************************* - *******************************************************************************/ + * 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.egiz.eaaf.core.impl.idp.auth.modules; import java.io.ByteArrayOutputStream; @@ -34,21 +27,8 @@ import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Map.Entry; - import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; - -import org.apache.commons.fileupload.FileItem; -import org.apache.commons.fileupload.FileItemFactory; -import org.apache.commons.fileupload.FileUploadException; -import org.apache.commons.fileupload.disk.DiskFileItemFactory; -import org.apache.commons.fileupload.servlet.ServletFileUpload; -import org.apache.commons.lang3.ArrayUtils; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.core.io.ResourceLoader; - import at.gv.egiz.eaaf.core.api.IRequest; import at.gv.egiz.eaaf.core.api.IRequestStorage; import at.gv.egiz.eaaf.core.api.data.EAAFConstants; @@ -56,216 +36,233 @@ import at.gv.egiz.eaaf.core.api.idp.IConfiguration; import at.gv.egiz.eaaf.core.api.idp.auth.services.IProtocolAuthenticationService; import at.gv.egiz.eaaf.core.api.idp.process.ExecutionContext; import at.gv.egiz.eaaf.core.api.logging.IRevisionLogger; -import at.gv.egiz.eaaf.core.exceptions.EAAFException; +import at.gv.egiz.eaaf.core.exceptions.EaafException; import at.gv.egiz.eaaf.core.exceptions.TaskExecutionException; import at.gv.egiz.eaaf.core.impl.idp.controller.ProtocolFinalizationController; import at.gv.egiz.eaaf.core.impl.idp.process.springweb.AbstractTask; -import at.gv.egiz.eaaf.core.impl.utils.DataURLBuilder; +import at.gv.egiz.eaaf.core.impl.utils.DataUrlBuilder; +import org.apache.commons.fileupload.FileItem; +import org.apache.commons.fileupload.FileItemFactory; +import org.apache.commons.fileupload.FileUploadException; +import org.apache.commons.fileupload.disk.DiskFileItemFactory; +import org.apache.commons.fileupload.servlet.ServletFileUpload; +import org.apache.commons.lang3.ArrayUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.core.io.ResourceLoader; /** - * Task based counterpart to {@link AuthServlet}, providing the same utility methods (error handling, parameter parsing - * etc.).</p> The code has been taken from {@link AuthServlet}. + * Task based counterpart to {@link AuthServlet}, providing the same utility methods (error + * handling, parameter parsing etc.). + * </p> + * The code has been taken from {@link AuthServlet}. */ public abstract class AbstractAuthServletTask extends AbstractTask { - private static final Logger log = LoggerFactory.getLogger(AbstractAuthServletTask.class); - - @Autowired(required=true) IProtocolAuthenticationService protAuchService; - @Autowired(required=true) protected IRequestStorage requestStoreage; - @Autowired(required=true) protected IConfiguration authConfig; - @Autowired(required=true) protected ResourceLoader resourceLoader; - - @Autowired protected IRevisionLogger revisionsLogger; - - protected static final String ERROR_CODE_PARAM = "errorid"; - - protected IRequest pendingReq = null; - - @Override - public abstract void execute(ExecutionContext executionContext, HttpServletRequest request, - HttpServletResponse response) throws TaskExecutionException; - - - @Override - protected final IRequest internalExecute(IRequest pendingReq, ExecutionContext executionContext, HttpServletRequest request, - HttpServletResponse response) throws TaskExecutionException { - //set pending-request object - this.pendingReq = pendingReq; - - //add latest pendingRequestId on execution context - executionContext.put(EAAFConstants.PROCESS_ENGINE_PENDINGREQUESTID, pendingReq.getPendingRequestId()); - - //execute task specific action - execute(executionContext, request, response); - - //return pending-request object - return this.pendingReq; - } - - /** - * Redirect the authentication process to protocol specific finalization endpoint. - * @param executionContext - * - * @param pendingReq Actually processed protocol specific authentication request - * @param httpResp - * @throws IOException - * @throws EAAFException - */ - protected void performRedirectToProtocolFinialization(ExecutionContext executionContext, IRequest pendingReq, HttpServletRequest httpReq, HttpServletResponse httpResp) throws EAAFException, IOException { - final Object frontChannelRedirectFlagObj = executionContext.get(EAAFConstants.PROCESS_ENGINE_REQUIRES_NO_POSTAUTH_REDIRECT); - if (frontChannelRedirectFlagObj != null && frontChannelRedirectFlagObj instanceof Boolean && - (Boolean)frontChannelRedirectFlagObj) { - log.info("AuthProcess finished. Forward to Protocol finalization."); - protAuchService.finalizeAuthentication(httpReq, httpResp, pendingReq); - - } else { - log.info("AuthProcess finished. Redirect to Protocol Dispatcher."); - requestStoreage.storePendingRequest(pendingReq); - performRedirectToItself(pendingReq, httpResp, ProtocolFinalizationController.ENDPOINT_FINALIZEPROTOCOL); - - } - - - - } - - /** - * Redirect the authentication process to IDP itself - * - * @param pendingReq Actually processed protocol specific authentication request - * @param httpResp - * @param idpEndPoint Servlet EndPoint that should receive the redirect - */ - protected void performRedirectToItself(IRequest pendingReq, HttpServletResponse httpResp, String idpEndPoint) { - final String redirectURL = new DataURLBuilder().buildDataURL(pendingReq.getAuthURL(), - idpEndPoint, pendingReq.getPendingRequestId()); - - httpResp.setContentType("text/html"); - httpResp.setStatus(302); - httpResp.addHeader("Location", redirectURL); - log.debug("REDIRECT TO: " + redirectURL); - - } - - - /** - * Parses the request input stream for parameters, assuming parameters are - * encoded UTF-8 (no standard exists how browsers should encode them). - * - * @param req - * servlet request - * - * @return mapping parameter name -> value - * - * @throws IOException - * if parsing request parameters fails. - * - * @throws FileUploadException - * if parsing request parameters fails. - */ - protected Map<String, String> getParameters(HttpServletRequest req) throws IOException, - FileUploadException { - - final Map<String, String> parameters = new HashMap<String, String>(); - - if (ServletFileUpload.isMultipartContent(req)) { - // request is encoded as mulitpart/form-data - final FileItemFactory factory = new DiskFileItemFactory(); - ServletFileUpload upload = null; - upload = new ServletFileUpload(factory); - List items = null; - items = upload.parseRequest(req); - for (int i = 0; i < items.size(); i++) { - final FileItem item = (FileItem) items.get(i); - if (item.isFormField()) { - // Process only form fields - no file upload items - parameters.put(item.getFieldName(), item.getString("UTF-8")); - - //log requests on trace - if (log.isTraceEnabled()) { - final String logString = item.getString("UTF-8"); - - // TODO use RegExp - final String startS = "<pr:Identification><pr:Value>"; - final String endS = "</pr:Value><pr:Type>urn:publicid:gv.at:baseid</pr:Type>"; - String logWithMaskedBaseid = logString; - final int start = logString.indexOf(startS); - if (start > -1) { - final int end = logString.indexOf(endS); - if (end > -1) { - logWithMaskedBaseid = logString.substring(0, start); - logWithMaskedBaseid += startS; - logWithMaskedBaseid += "xxxxxxxxxxxxxxxxxxxxxxxx"; - logWithMaskedBaseid += logString.substring(end, - logString.length()); - } - } - - log.debug("Processed multipart/form-data request parameter: \nName: " - + item.getFieldName() - + "\nValue: " - + logWithMaskedBaseid); - } - - } - } - } - - else { - final Iterator<Entry<String, String[]>> requestParamIt = req.getParameterMap().entrySet().iterator(); - while (requestParamIt.hasNext()) { - final Entry<String, String[]> entry = requestParamIt.next(); - final String key = entry.getKey(); - final String[] values = entry.getValue(); - // take the last value from the value array since the legacy code above also does it this way - parameters.put(key, ArrayUtils.isEmpty(values) ? null : values[values.length-1]); - } - - } - - return parameters; - } - - /** - * Reads bytes up to a delimiter, consuming the delimiter. - * - * @param in - * input stream - * @param delimiter - * delimiter character - * @return String constructed from the read bytes - * @throws IOException - */ - protected String readBytesUpTo(InputStream in, char delimiter) - throws IOException { - final ByteArrayOutputStream bout = new ByteArrayOutputStream(); - boolean done = false; - int b; - while (!done && (b = in.read()) >= 0) { - if (b == delimiter) - done = true; - else - bout.write(b); - } - return bout.toString(); - } - - /** - * Adds a parameter to a URL. - * - * @param url - * the URL - * @param paramname - * parameter name - * @param paramvalue - * parameter value - * @return the URL with parameter added - */ - protected static String addURLParameter(String url, String paramname, - String paramvalue) { - final String param = paramname + "=" + paramvalue; - if (url.indexOf("?") < 0) - return url + "?" + param; - else - return url + "&" + param; - } + private static final Logger log = LoggerFactory.getLogger(AbstractAuthServletTask.class); + + @Autowired(required = true) + IProtocolAuthenticationService protAuchService; + @Autowired(required = true) + protected IRequestStorage requestStoreage; + @Autowired(required = true) + protected IConfiguration authConfig; + @Autowired(required = true) + protected ResourceLoader resourceLoader; + + @Autowired + protected IRevisionLogger revisionsLogger; + + protected static final String ERROR_CODE_PARAM = "errorid"; + + protected IRequest pendingReq = null; + + @Override + public abstract void execute(ExecutionContext executionContext, HttpServletRequest request, + HttpServletResponse response) throws TaskExecutionException; + + + @Override + protected final IRequest internalExecute(final IRequest pendingReq, + final ExecutionContext executionContext, final HttpServletRequest request, + final HttpServletResponse response) throws TaskExecutionException { + // set pending-request object + this.pendingReq = pendingReq; + + // add latest pendingRequestId on execution context + executionContext.put(EAAFConstants.PROCESS_ENGINE_PENDINGREQUESTID, + pendingReq.getPendingRequestId()); + + // execute task specific action + execute(executionContext, request, response); + + // return pending-request object + return this.pendingReq; + } + + /** + * Redirect the authentication process to protocol specific finalization endpoint. + * + * @param executionContext + * + * @param pendingReq Actually processed protocol specific authentication request + * @param httpResp http response object + * @throws IOException In case of a general error + * @throws EaafException In case of an application error + */ + protected void performRedirectToProtocolFinialization(final ExecutionContext executionContext, + final IRequest pendingReq, final HttpServletRequest httpReq, + final HttpServletResponse httpResp) throws EaafException, IOException { + final Object frontChannelRedirectFlagObj = + executionContext.get(EAAFConstants.PROCESS_ENGINE_REQUIRES_NO_POSTAUTH_REDIRECT); + if (frontChannelRedirectFlagObj != null && frontChannelRedirectFlagObj instanceof Boolean + && (Boolean) frontChannelRedirectFlagObj) { + log.info("AuthProcess finished. Forward to Protocol finalization."); + protAuchService.finalizeAuthentication(httpReq, httpResp, pendingReq); + + } else { + log.info("AuthProcess finished. Redirect to Protocol Dispatcher."); + requestStoreage.storePendingRequest(pendingReq); + performRedirectToItself(pendingReq, httpResp, + ProtocolFinalizationController.ENDPOINT_FINALIZEPROTOCOL); + + } + + + + } + + /** + * Redirect the authentication process to IDP itself. + * + * @param pendingReq Actually processed protocol specific authentication request + * @param httpResp http response + * @param idpEndPoint Servlet EndPoint that should receive the redirect + */ + protected void performRedirectToItself(final IRequest pendingReq, + final HttpServletResponse httpResp, final String idpEndPoint) { + final String redirectUrl = new DataUrlBuilder().buildDataUrl(pendingReq.getAuthUrl(), + idpEndPoint, pendingReq.getPendingRequestId()); + + httpResp.setContentType("text/html"); + httpResp.setStatus(302); + httpResp.addHeader("Location", redirectUrl); + log.debug("REDIRECT TO: " + redirectUrl); + + } + + + /** + * Parses the request input stream for parameters, assuming parameters are encoded UTF-8 (no + * standard exists how browsers should encode them). + * + * @param req servlet request + * + * @return mapping parameter name -> value + * + * @throws IOException if parsing request parameters fails. + * + * @throws FileUploadException if parsing request parameters fails. + */ + protected Map<String, String> getParameters(final HttpServletRequest req) + throws IOException, FileUploadException { + + final Map<String, String> parameters = new HashMap<>(); + + if (ServletFileUpload.isMultipartContent(req)) { + // request is encoded as mulitpart/form-data + final FileItemFactory factory = new DiskFileItemFactory(); + ServletFileUpload upload = null; + upload = new ServletFileUpload(factory); + List items = null; + items = upload.parseRequest(req); + for (int i = 0; i < items.size(); i++) { + final FileItem item = (FileItem) items.get(i); + if (item.isFormField()) { + // Process only form fields - no file upload items + parameters.put(item.getFieldName(), item.getString("UTF-8")); + + // log requests on trace + if (log.isTraceEnabled()) { + final String logString = item.getString("UTF-8"); + + // TODO use RegExp + final String startS = "<pr:Identification><pr:Value>"; + final String endS = "</pr:Value><pr:Type>urn:publicid:gv.at:baseid</pr:Type>"; + String logWithMaskedBaseid = logString; + final int start = logString.indexOf(startS); + if (start > -1) { + final int end = logString.indexOf(endS); + if (end > -1) { + logWithMaskedBaseid = logString.substring(0, start); + logWithMaskedBaseid += startS; + logWithMaskedBaseid += "xxxxxxxxxxxxxxxxxxxxxxxx"; + logWithMaskedBaseid += logString.substring(end, logString.length()); + } + } + + log.debug("Processed multipart/form-data request parameter: \nName: " + + item.getFieldName() + "\nValue: " + logWithMaskedBaseid); + } + + } + } + + } else { + final Iterator<Entry<String, String[]>> requestParamIt = + req.getParameterMap().entrySet().iterator(); + while (requestParamIt.hasNext()) { + final Entry<String, String[]> entry = requestParamIt.next(); + final String key = entry.getKey(); + final String[] values = entry.getValue(); + // take the last value from the value array since the legacy code above also does it this + // way + parameters.put(key, ArrayUtils.isEmpty(values) ? null : values[values.length - 1]); + } + + } + + return parameters; + } + + /** + * Reads bytes up to a delimiter, consuming the delimiter. + * + * @param in input stream + * @param delimiter delimiter character + * @return String constructed from the read bytes + * @throws IOException In case of a general error + */ + protected String readBytesUpTo(final InputStream in, final char delimiter) throws IOException { + final ByteArrayOutputStream bout = new ByteArrayOutputStream(); + boolean done = false; + int b; + while (!done && (b = in.read()) >= 0) { + if (b == delimiter) { + done = true; + } else { + bout.write(b); + } + } + return bout.toString("UTF-8"); + + } + + /** + * Adds a parameter to a URL. + * + * @param url the URL + * @param paramname parameter name + * @param paramvalue parameter value + * @return the URL with parameter added + */ + protected static String addUrlParameter(final String url, final String paramname, + final String paramvalue) { + final String param = paramname + "=" + paramvalue; + if (url.indexOf("?") < 0) { + return url + "?" + param; + } else { + return url + "&" + param; + } + } } |