diff options
| author | Thomas Lenz <thomas.lenz@egiz.gv.at> | 2020-11-10 14:20:56 +0100 | 
|---|---|---|
| committer | Thomas Lenz <thomas.lenz@egiz.gv.at> | 2020-11-10 14:20:56 +0100 | 
| commit | b49e72d172d9671898a79842b6cd3db7a7304937 (patch) | |
| tree | 776a77377384a3679efacaf5d9f02f286f994140 /eaaf_modules/eaaf_module_auth_sl20/src | |
| parent | 83697944c66fff1b5ee47850b46fd970907a9757 (diff) | |
| parent | 0964aa4dfbf5543fff4e023290beefaeed31f3c5 (diff) | |
| download | EAAF-Components-b49e72d172d9671898a79842b6cd3db7a7304937.tar.gz EAAF-Components-b49e72d172d9671898a79842b6cd3db7a7304937.tar.bz2 EAAF-Components-b49e72d172d9671898a79842b6cd3db7a7304937.zip | |
Merge branch 'nightlyBuild' of gitlab.iaik.tugraz.at:egiz/eaaf_components into nightlyBuild
Diffstat (limited to 'eaaf_modules/eaaf_module_auth_sl20/src')
3 files changed, 153 insertions, 104 deletions
| diff --git a/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/tasks/AbstractCreateQualEidRequestTask.java b/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/tasks/AbstractCreateQualEidRequestTask.java index 56084d94..9a041028 100644 --- a/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/tasks/AbstractCreateQualEidRequestTask.java +++ b/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/tasks/AbstractCreateQualEidRequestTask.java @@ -12,6 +12,19 @@ import java.util.Map;  import javax.servlet.http.HttpServletRequest;  import javax.servlet.http.HttpServletResponse; +import org.apache.commons.lang3.StringUtils; +import org.apache.http.NameValuePair; +import org.apache.http.client.entity.UrlEncodedFormEntity; +import org.apache.http.client.methods.HttpPost; +import org.apache.http.client.utils.URIBuilder; +import org.apache.http.message.BasicNameValuePair; +import org.jose4j.base64url.Base64Url; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.i18n.LocaleContextHolder; + +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.node.ObjectNode; +  import at.gv.egiz.eaaf.core.api.idp.IConfigurationWithSP;  import at.gv.egiz.eaaf.core.api.idp.ISpConfiguration;  import at.gv.egiz.eaaf.core.api.idp.process.ExecutionContext; @@ -30,22 +43,9 @@ import at.gv.egiz.eaaf.modules.auth.sl20.exceptions.SlCommandoParserException;  import at.gv.egiz.eaaf.modules.auth.sl20.utils.SL20Constants;  import at.gv.egiz.eaaf.modules.auth.sl20.utils.SL20Constants.VdaAuthMethod;  import at.gv.egiz.eaaf.modules.auth.sl20.utils.SL20HttpBindingUtils; +import at.gv.egiz.eaaf.modules.auth.sl20.utils.SL20HttpBindingUtils.Sl20ResponseHolder;  import at.gv.egiz.eaaf.modules.auth.sl20.utils.SL20JsonBuilderUtils;  import at.gv.egiz.eaaf.modules.auth.sl20.utils.SL20JsonExtractorUtils; - -import org.apache.commons.lang3.StringUtils; -import org.apache.http.HttpResponse; -import org.apache.http.NameValuePair; -import org.apache.http.client.entity.UrlEncodedFormEntity; -import org.apache.http.client.methods.HttpPost; -import org.apache.http.client.utils.URIBuilder; -import org.apache.http.message.BasicNameValuePair; -import org.jose4j.base64url.Base64Url; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.context.i18n.LocaleContextHolder; - -import com.fasterxml.jackson.databind.JsonNode; -import com.fasterxml.jackson.databind.node.ObjectNode;  import lombok.extern.slf4j.Slf4j;  @Slf4j @@ -113,12 +113,21 @@ public abstract class AbstractCreateQualEidRequestTask extends AbstractAuthServl            Base64Url.encode(sl20Req.toString().getBytes(StandardCharsets.UTF_8)));        // request VDA -      final HttpResponse httpResp = httpClientFactory.getHttpClient(false).execute(httpReq); - +      final Sl20ResponseHolder httpResp = httpClientFactory.getHttpClient(false).execute( +          httpReq, SL20HttpBindingUtils.sl20ResponseHandler()); + +      //check on error on http channel +      if (httpResp.getError() != null) { +        log.info("Basic SL2.0 response processing has an error. HTTP-StatusCode: {}  ErrorMsg: {}", +            httpResp.getResponseStatus().getStatusCode(), httpResp.getError().getMessage()); +        throw httpResp.getError(); +         +      } +              // parse response        log.info("Receive response from VDA ... "); -      final JsonNode sl20Resp = SL20JsonExtractorUtils.getSL20ContainerFromResponse(httpResp); -      final VerificationResult respPayloadContainer = SL20JsonExtractorUtils.extractSL20PayLoad(sl20Resp, null, false); +      final VerificationResult respPayloadContainer =  +          SL20JsonExtractorUtils.extractSL20PayLoad(httpResp.getResponseBody(), null, false);        if (respPayloadContainer.isValidSigned() == null) {          log.debug("Receive unsigned payLoad from VDA"); @@ -139,7 +148,7 @@ public abstract class AbstractCreateQualEidRequestTask extends AbstractAuthServl              SL20Constants.SL20_COMMAND_PARAM_GENERAL_REDIRECT_SIGNEDCOMMAND, false);          // create forward SL2.0 command -        final ObjectNode sl20Forward = sl20Resp.deepCopy(); +        final ObjectNode sl20Forward = httpResp.getResponseBody().deepCopy();          SL20JsonBuilderUtils.addOnlyOnceOfTwo(sl20Forward, SL20Constants.SL20_PAYLOAD, SL20Constants.SL20_SIGNEDPAYLOAD,              command.deepCopy(), signedCommand); @@ -223,7 +232,7 @@ public abstract class AbstractCreateQualEidRequestTask extends AbstractAuthServl      final Locale locale = LocaleContextHolder.getLocale();      final String language = locale.getLanguage();      if (StringUtils.isNotEmpty(language)) { -      log.trace("Find i18n context. Inject locale: {} into VDA request", locale.getLanguage()); +      log.trace("Find i18n context). Inject locale: {} into VDA request", locale.getLanguage());        parameters.add(new BasicNameValuePair(            SL20Constants.PARAM_SL20_REQ_AUTH_VDA_LOCALE,            language.toUpperCase(locale))); diff --git a/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/utils/SL20HttpBindingUtils.java b/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/utils/SL20HttpBindingUtils.java index 1d7c9646..d07c0e66 100644 --- a/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/utils/SL20HttpBindingUtils.java +++ b/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/utils/SL20HttpBindingUtils.java @@ -3,23 +3,129 @@ package at.gv.egiz.eaaf.modules.auth.sl20.utils;  import java.io.IOException;  import java.io.StringWriter;  import java.net.URISyntaxException; +import java.text.MessageFormat;  import javax.annotation.Nonnull;  import javax.annotation.Nullable;  import javax.servlet.http.HttpServletRequest;  import javax.servlet.http.HttpServletResponse; +import org.apache.http.Header; +import org.apache.http.HttpEntity; +import org.apache.http.ParseException; +import org.apache.http.StatusLine; +import org.apache.http.client.ResponseHandler;  import org.apache.http.client.utils.URIBuilder; +import org.apache.http.util.EntityUtils;  import org.jose4j.base64url.Base64Url;  import org.slf4j.Logger;  import org.slf4j.LoggerFactory; +import org.springframework.http.HttpStatus;  import org.springframework.http.MediaType;  import com.fasterxml.jackson.databind.JsonNode; +import at.gv.egiz.eaaf.modules.auth.sl20.exceptions.SlCommandoParserException; +import lombok.Data; +import lombok.Getter; +  public class SL20HttpBindingUtils {    private static final Logger log = LoggerFactory.getLogger(SL20HttpBindingUtils.class); +  private static JsonMapper mapper = new JsonMapper(); +   +  @Data +  @Getter +  public static class Sl20ResponseHolder { +    private final JsonNode responseBody; +    private final StatusLine responseStatus; +    private SlCommandoParserException error; + +  } +   +  /** +   * Security-Layer 2.0 specific response-handler for Apache HTTP client. +   *  +   * @return {@link Sl20ResponseHolder} +   */ +  public static ResponseHandler<Sl20ResponseHolder> sl20ResponseHandler() { +    return response -> { +      try { +        final int httpStatusCode = response.getStatusLine().getStatusCode(); +        if (httpStatusCode == HttpStatus.OK.value()) { +          if (response.getEntity().getContentType() == null) { +            throw new SlCommandoParserException("SL20 response contains NO ContentType"); +             +          } + +          if (!response.getEntity().getContentType().getValue().startsWith("application/json")) { +            throw new SlCommandoParserException( +                "SL20 response with a wrong ContentType: " + response.getEntity().getContentType().getValue()); +             +          }  +           +          //parse OK response from body +          return new Sl20ResponseHolder(parseSL20ResultFromResponse(response.getEntity()), +              response.getStatusLine());                     +         +        } else if (httpStatusCode == HttpStatus.SEE_OTHER.value()  +            || httpStatusCode == HttpStatus.TEMPORARY_REDIRECT.value()) { +          final Header[] locationHeader = response.getHeaders("Location"); +          if (locationHeader == null) { +            throw new SlCommandoParserException("Find Redirect statuscode but not Location header"); +             +          } + +          final String sl20RespString = new URIBuilder(locationHeader[0].getValue()).getQueryParams().get(0).getValue(); +          return new Sl20ResponseHolder(mapper.getMapper().readTree(Base64Url.decode(sl20RespString)),  +              response.getStatusLine());  +                              +        } else if ( +            httpStatusCode == HttpStatus.INTERNAL_SERVER_ERROR.value()  +            || httpStatusCode == HttpStatus.UNAUTHORIZED.value() +            || httpStatusCode == HttpStatus.BAD_REQUEST.value()) { +          log.info("SL20 response with http-code: {}. Search for error message", httpStatusCode);                     +           +          String bodyMsg = "_EMPTY_"; +          try { +            //extract JSON body from defined http error-codes +            bodyMsg = EntityUtils.toString(response.getEntity());             +            log.info("SL20 response with http-code: {0} and errorMsg: {1}", httpStatusCode, bodyMsg); +            Sl20ResponseHolder holder = new Sl20ResponseHolder( +                mapper.getMapper().readTree(bodyMsg), response.getStatusLine()); +            return holder;  +             +          } catch (final IOException | ParseException e) { +            log.warn("SL20 response contains no valid JSON", e);             +            throw new SlCommandoParserException(MessageFormat.format( +                "SL20 response with http-code: {0} with body: {1} and generic response-processing error: {2}",  +                httpStatusCode, bodyMsg, e.getMessage())); +             +          } +       +        } else { +          //all other HTTP StatusCodes +          throw new SlCommandoParserException(MessageFormat.format( +              "SL20 response with http-code: {0} and errorMsg: {1}",  +              httpStatusCode, EntityUtils.toString(response.getEntity()))); +           +        } +       +      } catch (SlCommandoParserException e) { +        Sl20ResponseHolder holder = new Sl20ResponseHolder(null, response.getStatusLine()); +        holder.setError(e); +        return holder; +         +      } catch (final Exception e) {         +        Sl20ResponseHolder holder = new Sl20ResponseHolder(null, response.getStatusLine()); +        holder.setError( +            new SlCommandoParserException("SL20 response parsing FAILED! Reason: " + e.getMessage(), e)); +        return holder; +         +      } +    }; +  } +        /**     * Write SL2.0 response into http-response object     * @@ -59,6 +165,24 @@ public class SL20HttpBindingUtils {        httpResp.setHeader("Location", clientRedirectUri.build().toString());      } +  } +   +  private static JsonNode parseSL20ResultFromResponse(final HttpEntity resp) throws Exception { +    if (resp != null && resp.getContent() != null) { +      final String rawSL20Resp = EntityUtils.toString(resp); +      final JsonNode sl20Resp = mapper.getMapper().readTree(rawSL20Resp); + +      // TODO: check sl20Resp type like && sl20Resp.isJsonObject() +      if (sl20Resp != null) { +        return sl20Resp; + +      } else { +        throw new SlCommandoParserException("SL2.0 can NOT parse to a JSON object"); +      } + +    } else { +      throw new SlCommandoParserException("Can NOT find content in http response"); +    }    }  } diff --git a/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/utils/SL20JsonExtractorUtils.java b/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/utils/SL20JsonExtractorUtils.java index 40ea0430..bed25c0c 100644 --- a/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/utils/SL20JsonExtractorUtils.java +++ b/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/utils/SL20JsonExtractorUtils.java @@ -8,12 +8,6 @@ import java.util.List;  import java.util.Map;  import java.util.Map.Entry; -import org.apache.http.Header; -import org.apache.http.HttpEntity; -import org.apache.http.HttpResponse; -import org.apache.http.client.utils.URIBuilder; -import org.apache.http.util.EntityUtils; -import org.jose4j.base64url.Base64Url;  import org.slf4j.Logger;  import org.slf4j.LoggerFactory; @@ -299,84 +293,6 @@ public class SL20JsonExtractorUtils {    } -  /** -   * Extract generic transport container from httpResponse. -   * -   * @param httpResp Http response object -   * @return JSON with SL2.0 response -   * @throws SlCommandoParserException In case of an error -   */ -  public static JsonNode getSL20ContainerFromResponse(final HttpResponse httpResp) throws SlCommandoParserException { -    try { -      JsonNode sl20Resp = null; -      if (httpResp.getStatusLine().getStatusCode() == 303 || httpResp.getStatusLine().getStatusCode() == 307) { -        final Header[] locationHeader = httpResp.getHeaders("Location"); -        if (locationHeader == null) { -          throw new SlCommandoParserException("Find Redirect statuscode but not Location header"); -        } - -        final String sl20RespString = new URIBuilder(locationHeader[0].getValue()).getQueryParams().get(0).getValue(); -        sl20Resp = mapper.getMapper().readTree(Base64Url.decode(sl20RespString)); - -      } else if (httpResp.getStatusLine().getStatusCode() == 200) { -        if (httpResp.getEntity().getContentType() == null) { -          throw new SlCommandoParserException("SL20 response contains NO ContentType"); -        } - -        if (!httpResp.getEntity().getContentType().getValue().startsWith("application/json")) { -          throw new SlCommandoParserException( -              "SL20 response with a wrong ContentType: " + httpResp.getEntity().getContentType().getValue()); -        } -        sl20Resp = parseSL20ResultFromResponse(httpResp.getEntity()); - -      } else if (httpResp.getStatusLine().getStatusCode() == 500 || httpResp.getStatusLine().getStatusCode() == 401 -          || httpResp.getStatusLine().getStatusCode() == 400) { -        log.info( -            "SL20 response with http-code: " + httpResp.getStatusLine().getStatusCode() + ". Search for error message"); - -        try { -          sl20Resp = parseSL20ResultFromResponse(httpResp.getEntity()); - -        } catch (final Exception e) { -          log.warn("SL20 response contains no valid JSON", e); -          throw new SlCommandoParserException("SL20 response with http-code: " -              + httpResp.getStatusLine().getStatusCode() + " AND NO valid JSON errormsg", e); - -        } - -      } else { -        throw new SlCommandoParserException( -            "SL20 response with http-code: " + httpResp.getStatusLine().getStatusCode()); -      } - -      log.info("Find JSON object in http response"); -      return sl20Resp; - -    } catch (final Exception e) { -      throw new SlCommandoParserException("SL20 response parsing FAILED! Reason: " + e.getMessage(), e); - -    } -  } - -  private static JsonNode parseSL20ResultFromResponse(final HttpEntity resp) throws Exception { -    if (resp != null && resp.getContent() != null) { -      final String rawSL20Resp = EntityUtils.toString(resp); -      final JsonNode sl20Resp = mapper.getMapper().readTree(rawSL20Resp); - -      // TODO: check sl20Resp type like && sl20Resp.isJsonObject() -      if (sl20Resp != null) { -        return sl20Resp; - -      } else { -        throw new SlCommandoParserException("SL2.0 can NOT parse to a JSON object"); -      } - -    } else { -      throw new SlCommandoParserException("Can NOT find content in http response"); -    } - -  } -    private static JsonNode getAndCheck(final JsonNode input, final String keyID, final boolean isRequired)        throws SlCommandoParserException {      final JsonNode internal = input.get(keyID); | 
