// The serviceproviders URL MAY be relative & IdP URL MAY be absolute.
  // But not if the latest specs are followed.
  private boolean consumerUrlsMatch(ExchangeContent idpContent, String spAssertionConsumerURL) {
    // if header != null ..

    if (idpContent.getResponseParts().getHeader() != null) {
      // Extract the assertionConsumerURL from an IdP response header.
      String idpAssertionConsumerURL =
          ExtractField.extractAssertionConsumerURL(idpContent.getResponseParts().getHeader());

      if (idpAssertionConsumerURL.equals(spAssertionConsumerURL)
          || idpAssertionConsumerURL.endsWith(spAssertionConsumerURL)) return true;
    }
    return false;
  }
  /**
   * Send a GET request to an SP. Receive an AuthnRequest in the spContent.
   *
   * @param spURL
   * @param paosClient
   * @return
   */
  private ExchangeContent getRequestToSP(URL spURL, PaosClient paosClient) {

    // Create a new, empty SP ExchangeContent.
    ExchangeContent spContent = new ExchangeContent(null, null);

    // Send a PAOS GET request to the given SP endpoint.
    spContent = paosClient.sendHttpGETRequest(spURL, spContent);

    if (verbose) {
      System.out.println(
          "AuthnRequest from SP: \n"
              + new String(
                  ParseHelper.anythingToXMLString(spContent.getResponseParts().getBody())));
    }

    return spContent;
  }
  /**
   * Return a SOAP Envelope Body that contains the Response the IdP sent, if there is one.
   *
   * <p>Returns null if the IdP returned no response at all. Nothing.
   *
   * @return
   */
  private Body getResponseBody(
      ExchangeContent spContent, IDPEntry idpEntry, PaosClient paosClient, ClientOptions options) {

    String spAssertionConsumerURL = "";
    ExchangeContent idpContent = null;
    Envelope idpEnvelope = null;
    URL idpURL = null;

    // Extract idplist from authnrequest and check if the SP supports
    // the one that was chosen. If not, complain.
    idpURL = determineIdP(spContent.getResponseParts().getHeader(), idpEntry);

    spAssertionConsumerURL =
        ExtractField.extractAssertionConsumerURL(spContent.getResponseParts().getHeader());

    // If no matching idp was found from the list the SP sent...
    if (idpURL == null) {
      logger.info("The SP did not indicate support for the chosen IdP.");
      idpURL = getURL(idpEntry.getLoc()); // Get an assertion from the IdP
      // and let the SP trust an
      // unknown IdP.
    }

    // Create the envelope with the AuthnRequest that will be sent to the
    // IdP
    idpEnvelope = EnvelopeCreator.createIdpEnvelope(spContent.getResponseParts());

    // Get the Assertion from the IdP (send AuthnRequest to IdP)
    idpContent = getAssertion(paosClient, idpEnvelope, idpURL, options);

    // If the IdP sent back anything at all as a response:
    if (idpContent != null) {
      // Check assertionConsumerURL. If it does not match, send a SOAP
      // fault to the SP/endpoint
      if (consumerUrlsMatch(idpContent, spAssertionConsumerURL)) {
        return idpContent.getResponseParts().getBody();
      } else {
        logger.debug("AssertionConsumerURLs from AuthnRequest and Response did not match.");
        logger.debug("Returning a SOAP fault message to the endpoint.");
        return EnvelopeCreator.createSoapFaultBody("AssertionConsumerURLs did not match.");
      }
    } // else the paosclient has complained about this.
    return null;
  }
  /**
   * Access some resource at a SP. Returns an ExchangeContent object that contains the response that
   * was sent from the IdP.
   *
   * @param spHost
   * @param spPort
   * @param spUri
   * @throws Exception
   */
  public ExchangeContent accessResource(
      ClientOptions options, IDPEntry idpEntry, HttpClient httpClient) {

    PaosClient paosClient = null;

    ExchangeContent spContent = null;
    URL assertionConsumerEndpoint = null;

    // Set parameters from options in args.
    setParameters(options);

    // Create a Paos HttpClient.
    paosClient = new PaosClient(httpClient);

    // Get the AuthnRequest from the SP
    spContent = getRequestToSP(options.getSpURL(), paosClient);

    if (spContent.getResponseParts() != null) {
      String spAssertionConsumer =
          ExtractField.extractAssertionConsumerURL(spContent.getResponseParts().getHeader());

      // Check if we received an AuthnRequest as a response.
      // validate(spContent.getEnvelope.getbody.getUnknownXMLObjects);

      // Get the SOAP Envelope Body from the IdP that contains the
      // response or a soap fault.
      Body body = getResponseBody(spContent, idpEntry, paosClient, options);

      if (body != null) {
        if (verbose) {
          System.out.println("Received from idp: \n" + ParseHelper.anythingToXMLString(body));
        }

        logger.debug("Received from idp: \n" + ParseHelper.anythingToXMLString(body));
      }

      // Build the envelope you want to send.
      Envelope assertionEnvelope = EnvelopeCreator.createSpResponseEnvelope(body);

      // Build an empty exchangeContent with the envelope
      ExchangeContent assertionContent = new ExchangeContent(assertionEnvelope, null);

      // Turn the assertionConsumer string into an URL
      assertionConsumerEndpoint = getURL(spAssertionConsumer);

      // Add the sp session cookie back
      assertionContent.setCookieField(spContent.getCookieField());

      // Send the exchangeContent.
      assertionContent = paosClient.send(assertionConsumerEndpoint, assertionContent);

      String envelopeString = ParseHelper.anythingToXMLString(assertionEnvelope);

      System.out.println("Sending envelope to SP endpoint: " + options.getSpEndpoint());
      System.out.println(envelopeString);
      logger.info("Sent to SP: \n" + envelopeString);

      if (assertionContent.getOtherResponse() != null) {
        System.out.println("Response received from SP: \n");
        System.out.println(new String(assertionContent.getOtherResponse()));
      }

      // This return is unnecessary in a normal SP exchange.
      return assertionContent;
    }
    logger.debug("The SP did not respond to the GET request.");
    return null; // :(
  }