diff options
Diffstat (limited to 'eaaf_modules/eaaf_module_auth_sl20/src')
2 files changed, 183 insertions, 124 deletions
| diff --git a/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/tasks/AbstractReceiveQualEidTask.java b/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/tasks/AbstractReceiveQualEidTask.java index 87dd6263..655cc2c6 100644 --- a/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/tasks/AbstractReceiveQualEidTask.java +++ b/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/tasks/AbstractReceiveQualEidTask.java @@ -1,28 +1,11 @@  package at.gv.egiz.eaaf.modules.auth.sl20.tasks;  import java.io.IOException; -import java.io.StringWriter; -import java.net.URISyntaxException; -import java.util.HashMap;  import java.util.Map; -import java.util.UUID;  import javax.servlet.http.HttpServletRequest;  import javax.servlet.http.HttpServletResponse; -import org.apache.commons.lang3.StringUtils; -import org.apache.http.client.utils.URIBuilder; -import org.apache.http.entity.ContentType; -import org.jose4j.base64url.Base64Url; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.beans.factory.annotation.Autowired; - -import com.fasterxml.jackson.core.JsonParseException; -import com.fasterxml.jackson.databind.JsonNode; -import com.fasterxml.jackson.databind.node.ObjectNode; - -import at.gv.egiz.eaaf.core.api.data.EaafConstants;  import at.gv.egiz.eaaf.core.api.idp.process.ExecutionContext;  import at.gv.egiz.eaaf.core.exceptions.EaafAuthenticationException;  import at.gv.egiz.eaaf.core.exceptions.EaafStorageException; @@ -40,14 +23,21 @@ import at.gv.egiz.eaaf.modules.auth.sl20.exceptions.SlCommandoParserException;  import at.gv.egiz.eaaf.modules.auth.sl20.utils.IJoseTools;  import at.gv.egiz.eaaf.modules.auth.sl20.utils.JsonMapper;  import at.gv.egiz.eaaf.modules.auth.sl20.utils.SL20Constants; -import at.gv.egiz.eaaf.modules.auth.sl20.utils.SL20JsonBuilderUtils;  import at.gv.egiz.eaaf.modules.auth.sl20.utils.SL20JsonExtractorUtils; +import at.gv.egiz.eaaf.modules.auth.sl20.utils.SL20ResponseUtils; + +import org.apache.commons.lang3.StringUtils; +import org.jose4j.base64url.Base64Url; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; + +import com.fasterxml.jackson.core.JsonParseException; +import com.fasterxml.jackson.databind.JsonNode;  public abstract class AbstractReceiveQualEidTask extends AbstractAuthServletTask {    private static final Logger log = LoggerFactory.getLogger(AbstractReceiveQualEidTask.class); -  private static final String PATTERN_PENDING_REQ_ID = "#PENDINGREQID#"; -    @Autowired(required = true)    private IJoseTools joseTools; @@ -177,10 +167,14 @@ public abstract class AbstractReceiveQualEidTask extends AbstractAuthServletTask          // write SL2.0 response          if (sl20ReqObj != null) { -          // buildResponse(request, response, sl20ReqObj, aTrustErrorWorkAround); -          buildResponse(request, response, sl20ReqObj); +          final String resumeEndpoint = new DataUrlBuilder().buildDataUrl(pendingReq.getAuthUrl(), +              getResumeEndPoint(), pendingReq.getPendingRequestId()); +          SL20ResponseUtils.buildResponse(request, response, pendingReq, resumeEndpoint, +              SL20JsonExtractorUtils.getStringValue(sl20ReqObj, SL20Constants.SL20_TRANSACTIONID, false), +              authConfig); +          } else { -          buildErrorResponse(response, "2000", "General transport Binding error"); +          SL20ResponseUtils.buildErrorResponse(response, "2000", "General transport Binding error");          }        } @@ -213,106 +207,5 @@ public abstract class AbstractReceiveQualEidTask extends AbstractAuthServletTask    protected abstract String getResumeEndPoint(); -  private void buildErrorResponse(final HttpServletResponse response, final String errorCode, final String errorMsg) -      throws Exception { -    final ObjectNode error = SL20JsonBuilderUtils.createErrorCommandResult(errorCode, errorMsg); -    final ObjectNode errorCommand = SL20JsonBuilderUtils -        .createCommandResponse(SL20Constants.SL20_COMMAND_IDENTIFIER_ERROR, error, null); - -    final ObjectNode respContainer = SL20JsonBuilderUtils.createGenericResponse(UUID.randomUUID().toString(), null, -        null, errorCommand, null); - -    log.trace("SL20 response to VDA: " + respContainer); -    final StringWriter writer = new StringWriter(); -    writer.write(respContainer.toString()); -    final byte[] content = writer.toString().getBytes("UTF-8"); -    response.setStatus(HttpServletResponse.SC_OK); -    response.setContentLength(content.length); -    response.setContentType(ContentType.APPLICATION_JSON.toString()); -    response.getOutputStream().write(content); - -  } - -  private void buildResponse(final HttpServletRequest request, final HttpServletResponse response, -      final JsonNode sl20ReqObj) throws IOException, SL20Exception, URISyntaxException { -    // create response -    final Map<String, String> reqParameters = new HashMap<>(); -    reqParameters.put(EaafConstants.PARAM_HTTP_TARGET_PENDINGREQUESTID, pendingReq.getPendingRequestId()); -    final ObjectNode callReqParams = SL20JsonBuilderUtils.createCallCommandParameters( -        new DataUrlBuilder().buildDataUrl(pendingReq.getAuthUrl(), getResumeEndPoint(), null), -        SL20Constants.SL20_COMMAND_PARAM_GENERAL_CALL_METHOD_GET, false, reqParameters); -    final ObjectNode callCommand = SL20JsonBuilderUtils.createCommand(SL20Constants.SL20_COMMAND_IDENTIFIER_CALL, -        callReqParams); - -    // build first redirect command for app -    final ObjectNode redirectOneParams = SL20JsonBuilderUtils -        .createRedirectCommandParameters(generateIpcRedirectUrlForDebugging(), callCommand, null, true); -    final ObjectNode redirectOneCommand = SL20JsonBuilderUtils -        .createCommand(SL20Constants.SL20_COMMAND_IDENTIFIER_REDIRECT, redirectOneParams); - -    // build second redirect command for IDP -    final ObjectNode redirectTwoParams = SL20JsonBuilderUtils.createRedirectCommandParameters(new DataUrlBuilder() -        .buildDataUrl(pendingReq.getAuthUrl(), getResumeEndPoint(), pendingReq.getPendingRequestId()), -        redirectOneCommand, null, false); -    final ObjectNode redirectTwoCommand = SL20JsonBuilderUtils -        .createCommand(SL20Constants.SL20_COMMAND_IDENTIFIER_REDIRECT, redirectTwoParams); - -    // build generic SL2.0 response container -    final String transactionId = SL20JsonExtractorUtils.getStringValue(sl20ReqObj, SL20Constants.SL20_TRANSACTIONID, -        false); -    final ObjectNode respContainer = SL20JsonBuilderUtils.createGenericRequest(UUID.randomUUID().toString(), -        transactionId, redirectTwoCommand, null); - -    if (request.getHeader(SL20Constants.HTTP_HEADER_SL20_CLIENT_TYPE) != null && request -        .getHeader(SL20Constants.HTTP_HEADER_SL20_CLIENT_TYPE).equals(SL20Constants.HTTP_HEADER_VALUE_NATIVE)) { -      log.debug("Client request containts 'native client' header ... "); -      log.trace("SL20 response to VDA: " + respContainer); -      final StringWriter writer = new StringWriter(); -      writer.write(respContainer.toString()); -      final byte[] content = writer.toString().getBytes("UTF-8"); -      response.setStatus(HttpServletResponse.SC_OK); -      response.setContentLength(content.length); -      response.setContentType(ContentType.APPLICATION_JSON.toString()); -      response.getOutputStream().write(content); - -    } else { -      log.info("SL2.0 DataURL communication needs http header: '" + SL20Constants.HTTP_HEADER_SL20_CLIENT_TYPE + "'"); - -      log.debug("Client request containts is no native client ... "); -      final URIBuilder clientRedirectUri = new URIBuilder(new DataUrlBuilder().buildDataUrl(pendingReq.getAuthUrl(), -          getResumeEndPoint(), pendingReq.getPendingRequestId())); -      response.setStatus(Integer.parseInt(authConfig.getBasicConfiguration(Constants.CONFIG_PROP_HTTP_REDIRECT_CODE, -          Constants.CONFIG_PROP_HTTP_REDIRECT_CODE_DEFAULT_VALUE))); -      response.setHeader("Location", clientRedirectUri.build().toString()); - -      // throw new SL20Exception("sl20.06", -      // new Object[] {"SL2.0 DataURL communication needs http header: '" + -      // SL20Constants.HTTP_HEADER_SL20_CLIENT_TYPE + "'"}); - -    } -  } - -  /** -   * Generates a IPC redirect URL that is configured on IDP side. -   * -   * @return IPC ReturnURL, or null if no URL is configured -   */ -  private String generateIpcRedirectUrlForDebugging() { - -    String ipcRedirectUrlConfig = authConfig.getBasicConfiguration(Constants.CONFIG_PROP_IPC_RETURN_URL); -    if (StringUtils.isNotEmpty(ipcRedirectUrlConfig)) { -      if (ipcRedirectUrlConfig.contains(PATTERN_PENDING_REQ_ID)) { -        log.trace("Find 'pendingReqId' pattern in IPC redirect URL. Update url ... "); -        ipcRedirectUrlConfig = ipcRedirectUrlConfig.replaceAll("#PENDINGREQID#", -            EaafConstants.PARAM_HTTP_TARGET_PENDINGREQUESTID + "=" + pendingReq.getPendingRequestId()); - -      } - -      return ipcRedirectUrlConfig; -    } - -    return null; - -  }  } diff --git a/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/utils/SL20ResponseUtils.java b/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/utils/SL20ResponseUtils.java new file mode 100644 index 00000000..4bb91634 --- /dev/null +++ b/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/utils/SL20ResponseUtils.java @@ -0,0 +1,166 @@ +package at.gv.egiz.eaaf.modules.auth.sl20.utils; + +import java.io.IOException; +import java.io.StringWriter; +import java.net.URISyntaxException; +import java.net.URL; +import java.util.HashMap; +import java.util.Map; +import java.util.UUID; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import at.gv.egiz.eaaf.core.api.IRequest; +import at.gv.egiz.eaaf.core.api.data.EaafConstants; +import at.gv.egiz.eaaf.core.api.idp.IConfiguration; +import at.gv.egiz.eaaf.modules.auth.sl20.Constants; +import at.gv.egiz.eaaf.modules.auth.sl20.exceptions.SL20Exception; + +import org.apache.commons.lang3.StringUtils; +import org.apache.http.client.utils.URIBuilder; +import org.apache.http.entity.ContentType; + +import com.fasterxml.jackson.databind.node.ObjectNode; +import lombok.extern.slf4j.Slf4j; + +@Slf4j +public class SL20ResponseUtils { +  private static final String PATTERN_PENDING_REQ_ID = "#PENDINGREQID#"; + +  /** +   * Build a generic SL2.x error-response without redirect to AuthHandler. +   * +   * @param response http response object +   * @param errorCode ErrorCode +   * @param errorMsg Error message +   * @throws Exception In case of a message generation error +   */ +  public static void buildErrorResponse(final HttpServletResponse response, +      final String errorCode, final String errorMsg) +      throws Exception { +    final ObjectNode error = SL20JsonBuilderUtils.createErrorCommandResult(errorCode, errorMsg); +    final ObjectNode errorCommand = SL20JsonBuilderUtils +        .createCommandResponse(SL20Constants.SL20_COMMAND_IDENTIFIER_ERROR, error, null); + +    final ObjectNode respContainer = SL20JsonBuilderUtils.createGenericResponse(UUID.randomUUID().toString(), null, +        null, errorCommand, null); + +    log.trace("SL20 response to VDA: " + respContainer); +    final StringWriter writer = new StringWriter(); +    writer.write(respContainer.toString()); +    final byte[] content = writer.toString().getBytes("UTF-8"); +    response.setStatus(HttpServletResponse.SC_OK); +    response.setContentLength(content.length); +    response.setContentType(ContentType.APPLICATION_JSON.toString()); +    response.getOutputStream().write(content); + +  } + +  /** +   * Build a Security-Layer 2.x conform redirect response. +   * +   * @param request http request +   * @param response http response +   * @param pendingReq Current pending request +   * @param fullRedirectUrl Endpoint, where the auth. process should be resumed after redirect +   * @param transactionId SL2.0 transactionId if available +   * @param authConfig Basic application configuration +   * @throws IOException In case of a http servlet error +   * @throws SL20Exception In case of a SL2.0 request generation error +   * @throws URISyntaxException In case of an invalid Redirect URL +   */ +  public static void buildResponse(final HttpServletRequest request, final HttpServletResponse response, +      IRequest pendingReq, String fullRedirectUrl, String transactionId, IConfiguration authConfig) +          throws IOException, SL20Exception, URISyntaxException { +    // create response +    final Map<String, String> reqParameters = new HashMap<>(); + +    final URL redirectUrl = new URL(fullRedirectUrl); +    if (redirectUrl.getQuery() != null) { +      final String [] elements = redirectUrl.getQuery().split("&"); +      for (final String element : elements) { +        final String[] keyValue = element.split("="); +        if (keyValue.length == 2) { +          reqParameters.put(keyValue[0], keyValue[1]); + +        } else { +          log.warn("Ignore parameter with name: {}", keyValue[0]); + +        } +      } +    } + +    //reqParameters.put(EaafConstants.PARAM_HTTP_TARGET_PENDINGREQUESTID, pendingReq.getPendingRequestId()); + +    final ObjectNode callReqParams = SL20JsonBuilderUtils.createCallCommandParameters( +        fullRedirectUrl.split("\\?")[0], +        SL20Constants.SL20_COMMAND_PARAM_GENERAL_CALL_METHOD_GET, false, reqParameters); +    final ObjectNode callCommand = SL20JsonBuilderUtils.createCommand(SL20Constants.SL20_COMMAND_IDENTIFIER_CALL, +        callReqParams); + +    // build first redirect command for app +    final ObjectNode redirectOneParams = SL20JsonBuilderUtils +        .createRedirectCommandParameters(generateIpcRedirectUrlForDebugging( +            pendingReq, +            authConfig.getBasicConfiguration(Constants.CONFIG_PROP_IPC_RETURN_URL)), +            callCommand, null, true); +    final ObjectNode redirectOneCommand = SL20JsonBuilderUtils +        .createCommand(SL20Constants.SL20_COMMAND_IDENTIFIER_REDIRECT, redirectOneParams); + +    // build second redirect command for IDP +    final ObjectNode redirectTwoParams = SL20JsonBuilderUtils.createRedirectCommandParameters( +        fullRedirectUrl, +        redirectOneCommand, null, false); +    final ObjectNode redirectTwoCommand = SL20JsonBuilderUtils +        .createCommand(SL20Constants.SL20_COMMAND_IDENTIFIER_REDIRECT, redirectTwoParams); + +    // build generic SL2.0 response container +    final ObjectNode respContainer = SL20JsonBuilderUtils.createGenericRequest(UUID.randomUUID().toString(), +        transactionId, redirectTwoCommand, null); + +    if (request.getHeader(SL20Constants.HTTP_HEADER_SL20_CLIENT_TYPE) != null && request +        .getHeader(SL20Constants.HTTP_HEADER_SL20_CLIENT_TYPE).equals(SL20Constants.HTTP_HEADER_VALUE_NATIVE)) { +      log.debug("Client request containts 'native client' header ... "); +      log.trace("SL20 response to VDA: " + respContainer); +      final StringWriter writer = new StringWriter(); +      writer.write(respContainer.toString()); +      final byte[] content = writer.toString().getBytes("UTF-8"); +      response.setStatus(HttpServletResponse.SC_OK); +      response.setContentLength(content.length); +      response.setContentType(ContentType.APPLICATION_JSON.toString()); +      response.getOutputStream().write(content); + +    } else { +      log.info("SL2.0 DataURL communication needs http header: '" + SL20Constants.HTTP_HEADER_SL20_CLIENT_TYPE + "'"); + +      log.debug("Client request containts is no native client ... "); +      final URIBuilder clientRedirectUri = new URIBuilder(fullRedirectUrl); +      response.setStatus(Integer.parseInt(authConfig.getBasicConfiguration(Constants.CONFIG_PROP_HTTP_REDIRECT_CODE, +          Constants.CONFIG_PROP_HTTP_REDIRECT_CODE_DEFAULT_VALUE))); +      response.setHeader("Location", clientRedirectUri.build().toString()); + +    } +  } + +  /** +   * Generates a IPC redirect URL that is configured on IDP side. +   * +   * @return IPC ReturnURL, or null if no URL is configured +   */ +  private static String generateIpcRedirectUrlForDebugging(IRequest pendingReq, String ipcRedirectUrlConfig) { +    if (StringUtils.isNotEmpty(ipcRedirectUrlConfig)) { +      if (ipcRedirectUrlConfig.contains(PATTERN_PENDING_REQ_ID)) { +        log.trace("Find 'pendingReqId' pattern in IPC redirect URL. Update url ... "); +        ipcRedirectUrlConfig = ipcRedirectUrlConfig.replaceAll("#PENDINGREQID#", +            EaafConstants.PARAM_HTTP_TARGET_PENDINGREQUESTID + "=" + pendingReq.getPendingRequestId()); + +      } + +      return ipcRedirectUrlConfig; +    } + +    return null; + +  } +} | 
