/**
   * Overrideable method to determine which credentials to use to grant a proxy granting ticket.
   * Default is to use the pgtUrl.
   *
   * @param request the HttpServletRequest object.
   * @return the credentials or null if there was an error or no credentials provided.
   */
  protected Credential getServiceCredentialsFromRequest(final HttpServletRequest request) {
    final String pgtUrl = request.getParameter("pgtUrl");
    final String authnMethod = getAuthenticationMethodFromRequest(request);

    if (StringUtils.isNotBlank(pgtUrl)) {
      try {
        final URLBuilder builder = new URLBuilder(pgtUrl);
        if (StringUtils.isNotBlank(authnMethod)) {
          builder.getQueryParams().add(new Pair<String, String>(MODEL_AUTHN_METHOD, authnMethod));
        }
        return new HttpBasedServiceCredentials(new URL(builder.buildURL()));
      } catch (final Exception e) {
        logger.error("Error constructing pgtUrl", e);
      }
    }
    return null;
  }
  /**
   * Builds the URL to redirect the client to.
   *
   * @param messagesContext current message context
   * @param endpointURL endpoint URL to send encoded message to
   * @param message Deflated and Base64 encoded message
   * @return URL to redirect client to
   * @throws MessageEncodingException thrown if the SAML message is neither a RequestAbstractType or
   *     Response
   */
  protected String buildRedirectURL(
      SAMLMessageContext messagesContext, String endpointURL, String message)
      throws MessageEncodingException {
    log.debug("Building URL to redirect client to");
    URLBuilder urlBuilder = new URLBuilder(endpointURL);

    List<Pair<String, String>> queryParams = urlBuilder.getQueryParams();
    queryParams.clear();

    if (messagesContext.getOutboundSAMLMessage() instanceof RequestAbstractType) {
      queryParams.add(new Pair<String, String>("SAMLRequest", message));
    } else if (messagesContext.getOutboundSAMLMessage() instanceof StatusResponseType) {
      queryParams.add(new Pair<String, String>("SAMLResponse", message));
    } else {
      throw new MessageEncodingException(
          "SAML message is neither a SAML RequestAbstractType or StatusResponseType");
    }

    String relayState = messagesContext.getRelayState();
    if (checkRelayState(relayState)) {
      queryParams.add(new Pair<String, String>("RelayState", relayState));
    }

    Credential signingCredential = messagesContext.getOuboundSAMLMessageSigningCredential();
    if (signingCredential != null) {
      // TODO pull SecurityConfiguration from SAMLMessageContext? needs to be added
      String sigAlgURI = getSignatureAlgorithmURI(signingCredential, null);
      Pair<String, String> sigAlg = new Pair<String, String>("SigAlg", sigAlgURI);
      queryParams.add(sigAlg);
      String sigMaterial = urlBuilder.buildQueryString();

      queryParams.add(
          new Pair<String, String>(
              "Signature", generateSignature(signingCredential, sigAlgURI, sigMaterial)));
    }

    return urlBuilder.buildURL();
  }