// Copyright 2009 Google Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package com.google.enterprise.secmgr.modules;

import static com.google.enterprise.secmgr.saml.OpenSamlUtil.getMetadataSignaturePolicyRule;
import static com.google.enterprise.secmgr.saml.OpenSamlUtil.initializeLocalEntity;
import static com.google.enterprise.secmgr.saml.OpenSamlUtil.initializePeerEntity;
import static com.google.enterprise.secmgr.saml.OpenSamlUtil.makeAction;
import static com.google.enterprise.secmgr.saml.OpenSamlUtil.makeArtifactResolve;
import static com.google.enterprise.secmgr.saml.OpenSamlUtil.makeAuthnRequest;
import static com.google.enterprise.secmgr.saml.OpenSamlUtil.makeAuthzDecisionQuery;
import static com.google.enterprise.secmgr.saml.OpenSamlUtil.makeSamlMessageContext;
import static com.google.enterprise.secmgr.saml.OpenSamlUtil.makeStaticSecurityPolicyResolver;
import static com.google.enterprise.secmgr.saml.OpenSamlUtil.makeSubject;
import static com.google.enterprise.secmgr.saml.OpenSamlUtil.peerSupportsSignatureVerification;
import static com.google.enterprise.secmgr.saml.OpenSamlUtil.runDecoder;
import static com.google.enterprise.secmgr.saml.OpenSamlUtil.runEncoder;
import static org.opensaml.common.xml.SAMLConstants.SAML20P_NS;
import static org.opensaml.common.xml.SAMLConstants.SAML2_REDIRECT_BINDING_URI;
import static org.opensaml.common.xml.SAMLConstants.SAML2_SOAP11_BINDING_URI;

import com.google.common.base.Preconditions;
import com.google.common.collect.Maps;
//import com.google.enterprise.secmgr.authncontroller.AuthnSession;
import com.google.enterprise.secmgr.common.AuthzStatus;
import com.google.enterprise.secmgr.common.HttpUtil;
//import com.google.enterprise.secmgr.common.ServletBase;
import com.google.enterprise.secmgr.http.HttpClientInterface;
import com.google.enterprise.secmgr.http.HttpExchange;
import com.google.enterprise.secmgr.saml.HTTPSOAP11MultiContextDecoder;
import com.google.enterprise.secmgr.saml.HTTPSOAP11MultiContextEncoder;
import com.google.enterprise.secmgr.saml.HttpExchangeToInTransport;
import com.google.enterprise.secmgr.saml.HttpExchangeToOutTransport;
import com.google.enterprise.secmgr.saml.MetadataEditor;
import com.google.enterprise.secmgr.saml.SamlLogUtil;

import org.joda.time.DateTime;
import org.opensaml.common.SAMLObject;
import org.opensaml.common.binding.SAMLMessageContext;
import org.opensaml.common.xml.SAMLConstants;
import org.opensaml.saml2.binding.decoding.HTTPPostDecoder;
import org.opensaml.saml2.binding.decoding.HTTPSOAP11Decoder;
import org.opensaml.saml2.binding.encoding.HTTPRedirectDeflateEncoder;
import org.opensaml.saml2.binding.encoding.HTTPSOAP11Encoder;
import org.opensaml.saml2.core.Action;
import org.opensaml.saml2.core.ArtifactResolve;
import org.opensaml.saml2.core.ArtifactResponse;
import org.opensaml.saml2.core.Assertion;
import org.opensaml.saml2.core.AuthnRequest;
import org.opensaml.saml2.core.AuthzDecisionQuery;
import org.opensaml.saml2.core.AuthzDecisionStatement;
import org.opensaml.saml2.core.DecisionTypeEnumeration;
import org.opensaml.saml2.core.NameID;
import org.opensaml.saml2.core.Response;
import org.opensaml.saml2.core.Statement;
import org.opensaml.saml2.core.StatusCode;
import org.opensaml.saml2.metadata.ArtifactResolutionService;
import org.opensaml.saml2.metadata.AssertionConsumerService;
import org.opensaml.saml2.metadata.AuthzService;
import org.opensaml.saml2.metadata.EntityDescriptor;
import org.opensaml.saml2.metadata.SPSSODescriptor;
import org.opensaml.saml2.metadata.SingleSignOnService;
import org.opensaml.util.URLBuilder;
import org.opensaml.ws.message.encoder.MessageEncoder;
import org.opensaml.ws.message.encoder.MessageEncodingException;
import org.opensaml.ws.security.provider.MandatoryAuthenticatedMessageRule;
import org.opensaml.ws.security.provider.MandatoryIssuerRule;
import org.opensaml.ws.transport.http.HTTPInTransport;
import org.opensaml.ws.transport.http.HTTPOutTransport;
import org.opensaml.ws.transport.http.HttpServletRequestAdapter;
import org.opensaml.ws.transport.http.HttpServletResponseAdapter;
import org.opensaml.xml.security.credential.Credential;
import org.opensaml.xml.util.Pair;

import java.io.IOException;
import java.net.URI;
import java.net.URL;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.logging.Logger;

import javax.annotation.concurrent.GuardedBy;
import javax.annotation.concurrent.ThreadSafe;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * A library implementing most of the functionality of a SAML service provider.
 * This library knows how to send an authentication request via the redirect
 * binding, and to receive a response via either artifact or POST binding.
 */
@ThreadSafe
public class SamlClient {
  private static final Logger LOGGER = Logger.getLogger(SamlClient.class.getName());

  private final EntityDescriptor localEntity;
  private final EntityDescriptor peerEntity;
  private final String providerName;
  private final Credential signingCredential;
  private final HttpClientInterface httpClient;
  private final int timeout;

  @GuardedBy("requestIdLock")
  private String requestId;
  private static final Object requestIdLock = new Object();

  /**
   * Create an instance of the client library.
   *
   * @param localEntity Metadata for the the local entity (the service provider
   *        using this library).
   * @param peerEntity Metadata for the peer entity (the SAML IdP).
   * @param providerName Descriptive name of the service provider.
   * @param signingCredential A credential to use for signing the outgoing
   *        request.  May be null if signing isn't needed.
   * @param httpClient An HTTP client to use for resolving any artifact returned
   *        from the IdP.  May be null if the artifact binding isn't being used.
   */
  public SamlClient(EntityDescriptor localEntity, EntityDescriptor peerEntity,
      String providerName, Credential signingCredential, HttpClientInterface httpClient) {
    this.localEntity = localEntity;
    this.peerEntity = peerEntity;
    this.providerName = providerName;
    this.signingCredential = signingCredential;
    this.httpClient = httpClient;
    timeout = -1;
  }

  /**
   * Create an instance of the client library.
   *
   * @param localEntity Metadata for the the local entity (the service provider
   *        using this library).
   * @param peerEntity Metadata for the peer entity (the SAML IdP).
   * @param providerName Descriptive name of the service provider.
   * @param signingCredential A credential to use for signing the outgoing
   *        request.  May be null if signing isn't needed.
   * @param httpClient An HTTP client to use for resolving any artifact returned
   *        from the IdP.  May be null if the artifact binding isn't being
   * @param timeout The http socket timeout value in milliseconds.
   *        -1 means to use the httpClient default timeout.
   */
  public SamlClient(EntityDescriptor localEntity, EntityDescriptor peerEntity,
      String providerName, Credential signingCredential, HttpClientInterface httpClient,
      int timeout) {
    this.localEntity = localEntity;
    this.peerEntity = peerEntity;
    this.providerName = providerName;
    this.signingCredential = signingCredential;
    this.httpClient = httpClient;
    this.timeout = timeout;
  }

  /**
   * Get the metadata for this client's local entity.
   *
   * @return The entity descriptor for the local entity.
   */
  public EntityDescriptor getLocalEntity() {
    return localEntity;
  }

  /**
   * Get the metadata for this client's peer entity.
   *
   * @return The entity descriptor for the peer entity.
   */
  public EntityDescriptor getPeerEntity() {
    return peerEntity;
  }

  /**
   * Get the message ID of the most recent request.
   *
   * @return The message ID of the most recent request, never null.
   */
  public String getRequestId() {
    synchronized (requestIdLock) {
      Preconditions.checkNotNull(requestId);
      return requestId;
    }
  }

  /**
   * Get the metadata for this client's local POST assertion consumer service.
   *
   * @return The assertion consumer service descriptor.
   */
  public AssertionConsumerService getPostAssertionConsumerService() {
    return getAssertionConsumerService(MetadataEditor.SAML_BINDING_HTTP_POST);
  }

  /**
   * Get the metadata for this client's local ARTIFACT assertion consumer service.
   *
   * @return The assertion consumer service descriptor.
   */
  public AssertionConsumerService getArtifactAssertionConsumerService() {
    return getAssertionConsumerService(MetadataEditor.SAML_BINDING_HTTP_ARTIFACT);
  }

  private AssertionConsumerService getAssertionConsumerService(String binding) {
    for (AssertionConsumerService acs :
             localEntity.getSPSSODescriptor(SAML20P_NS).getAssertionConsumerServices()) {
      if (binding.equals(acs.getBinding())) {
        return acs;
      }
    }
    throw new IllegalArgumentException("No assertion consumer with binding " + binding);
  }

  /**
   * Send an AuthnRequest message to the IdP via the redirect protocol.
   *
   * @param response The HTTP response message that will be filled with the encoded redirect.
   * @throws IOException if errors occur during the encoding.
   */
  public void sendAuthnRequest(HTTPOutTransport outTransport)
      throws IOException {
    SAMLMessageContext<SAMLObject, AuthnRequest, NameID> context = makeSamlMessageContext();

    SPSSODescriptor sp = localEntity.getSPSSODescriptor(SAML20P_NS);
    initializeLocalEntity(context, localEntity, sp);
    initializePeerEntity(context, peerEntity, peerEntity.getIDPSSODescriptor(SAML20P_NS),
        SingleSignOnService.DEFAULT_ELEMENT_NAME,
        SAML2_REDIRECT_BINDING_URI);

    // Generate the request
    AuthnRequest authnRequest =
        makeAuthnRequest(context.getOutboundMessageIssuer(), new DateTime());
    authnRequest.setProviderName(providerName);
    authnRequest.setIsPassive(false);
    if (signingCredential != null) {
      authnRequest.setAssertionConsumerServiceURL(
          sp.getDefaultAssertionConsumerService().getLocation());
      authnRequest.setProtocolBinding(
          sp.getDefaultAssertionConsumerService().getBinding());
      // Must sign the message in order for ACS URL to be trusted by peer.
      context.setOutboundSAMLMessageSigningCredential(signingCredential);
    }
    authnRequest.setDestination(context.getPeerEntityEndpoint().getLocation());
    context.setOutboundSAMLMessage(authnRequest);

    // Remember the request ID for later.
    synchronized (requestIdLock) {
      requestId = authnRequest.getID();
    }

    // Not needed:
    //context.setRelayState();

    // Send the request via redirect to the user agent
    //ServletBase.initResponse(response);
    context.setOutboundMessageTransport(outTransport);
    runEncoder(new RedirectEncoder(), context);
  }

  /**
   * Decode a SAML response sent via the POST binding.
   *
   * @param request The HTTP request containing the encoded response.
   * @return The decoded response, or null if there was an error decoding the message.  In
   *     this case, a log file entry is generated, so the caller doesn't need to know the
   *     details of the failure.
   * @throws IOException for various errors related to session and metadata.
   */
  /*
  // Commented out to prevent pulling in AuthnSession.
  public Response decodePostResponse(HttpServletRequest request)
      throws IOException {
    AuthnSession session = AuthnSession.getInstance(request);
    if (session == null) {
      return null;
    }
    SAMLMessageContext<Response, SAMLObject, NameID> context =
        makeSamlMessageContext();

    initializeLocalEntity(context, localEntity, localEntity.getSPSSODescriptor(SAML20P_NS));
    initializePeerEntity(context, peerEntity, peerEntity.getIDPSSODescriptor(SAML20P_NS),
        SingleSignOnService.DEFAULT_ELEMENT_NAME,
        SAML2_REDIRECT_BINDING_URI);

    if (!peerSupportsSignatureVerification(context)) {
      LOGGER.warning("SAML POST peer not configured for signature verification");
      return null;
    }

    // Create a security policy to check the response signature.  Works only
    // with certificates that are stored in the metadata.
    context.setSecurityPolicyResolver(
        makeStaticSecurityPolicyResolver(
            getMetadataSignaturePolicyRule(request),
            // Requires an <Issuer>:
            new MandatoryIssuerRule(),
            // Requires that the message be authenticated:
            new MandatoryAuthenticatedMessageRule()));

    context.setInboundMessageTransport(new HttpServletRequestAdapter(request));
    if (!runDecoder(new HTTPPostDecoder(), context, session, "client identity provider")) {
      return null;
    }

    Response samlResponse = context.getInboundSAMLMessage();
    Preconditions.checkNotNull(samlResponse, "Decoded SAML response is null");
    return samlResponse;
  }*/

  /**
   * Decode a SAML response sent via the artifact binding.
   *
   * @param request The HTTP request containing the artifact.
   * @return The decoded response, or null if there was an error decoding the message.  In
   *     this case, a log file entry is generated, so the caller doesn't need to know the
   *     details of the failure.
   * @throws IOException for various errors related to session and metadata, or for the
   *     artifact resolution interchange.
   */
  public Response decodeArtifactResponse(URI requestUri, HTTPInTransport inTransport)
      throws IOException {
    // The OpenSAML HTTPArtifactDecoder isn't implemented, so we must manually decode the
    // artifact.
    String query = requestUri.getQuery();
    String artifact = null;
    for (String kvPair : query.split("&")) {
      String[] kv = kvPair.split("=", 2);
      if (kv.length != 2) {
        continue;
      }
      if (!"SAMLart".equals(kv[0])) {
        continue;
      }
      artifact = kv[1];
      break;
    }
    if (artifact == null) {
      LOGGER.warning("No artifact in message");
      return null;
    }

    SAMLObject message = resolveArtifact(inTransport, artifact);
    if (!(message instanceof Response)) {
      LOGGER.warning("Unable to resolve artifact");
    }
    return (Response) message;
  }

  /**
   * Resolve a SAML artifact.
   *
   * @param session The authentication session.
   * @param request The HTTP request containing the artifact, to identify the artifact
   *     resolution service to use.
   * @param artifact The artifact to resolve.
   * @return The SAML object that the artifact resolves to.
   * @throws IOException
   */
  private SAMLObject resolveArtifact(HTTPInTransport inTransport,
      String artifact)
      throws IOException {
    // Establish the SAML message context.
    SAMLMessageContext<ArtifactResponse, ArtifactResolve, NameID> context =
        makeSamlMessageContext();

    initializeLocalEntity(context, localEntity, localEntity.getSPSSODescriptor(SAML20P_NS));
    initializePeerEntity(context, peerEntity, peerEntity.getIDPSSODescriptor(SAML20P_NS),
        ArtifactResolutionService.DEFAULT_ELEMENT_NAME,
        SAML2_SOAP11_BINDING_URI);

    // Generate the request.
    context.setOutboundSAMLMessage(
        makeArtifactResolve(localEntity.getEntityID(), new DateTime(), artifact));

    // Encode the request.
    HttpExchange exchange =
        httpClient.postExchange(new URL(context.getPeerEntityEndpoint().getLocation()), null);
    try {
      HttpExchangeToOutTransport out = new HttpExchangeToOutTransport(exchange);
      try {
        context.setOutboundMessageTransport(out);
        context.setRelayState(inTransport.getHeaderValue("RelayState"));
        runEncoder(new HTTPSOAP11Encoder(), context);
      } finally {
        out.finish();
      }
    } finally {
      exchange.close();
    }

    if (timeout != -1) {
       exchange.setTimeout(timeout);
    }

    // Do HTTP exchange.
    int status = exchange.exchange();
    if (status != HttpServletResponse.SC_OK) {
      LOGGER.warning("Incorrect HTTP status: " + status);
      return null;
    }

    // Decode the response.
    context.setInboundMessageTransport(new HttpExchangeToInTransport(exchange));
    try {
      runDecoder(new HTTPSOAP11Decoder(), context);
    } catch (IOException e) {
      LOGGER.warning("IOException: " + e.getMessage());
      return null;
    }

    // Return the decoded response.
    ArtifactResponse artifactResponse = context.getInboundSAMLMessage();
    Preconditions.checkNotNull(artifactResponse, "Decoded SAML response is null");
    return artifactResponse.getMessage();
  }

  /**
   * Send a single SAML-standard authorization request.
   *
   * @param urlString The URL for which access is being authorized.
   * @param username The username to test for access.
   * @return The authorization status.
   * @throws IOException if there are any I/O errors during authorization.
   */
  public AuthzStatus sendAuthzRequest(String urlString, String username)
      throws IOException {
    Preconditions.checkNotNull(urlString);
    Preconditions.checkNotNull(username);

    SAMLMessageContext<Response, AuthzDecisionQuery, NameID> context = makeAuthzContext();
    HttpExchange exchange = makeAuthzExchange(context);
    try {

      HttpExchangeToOutTransport out = new HttpExchangeToOutTransport(exchange);
      setupAuthzQuery(context, urlString, username, new DateTime(), out, new HTTPSOAP11Encoder());
      out.finish();

      // Do HTTP exchange
      int status = exchange.exchange();
      if (!HttpUtil.isGoodHttpStatus(status)) {
        throw new IOException("Incorrect HTTP status: " + status);
      }

      // Decode the response
      HttpExchangeToInTransport in = new HttpExchangeToInTransport(exchange);
      context.setInboundMessageTransport(in);
      runDecoder(new HTTPSOAP11Decoder(), context);

    } finally {
      exchange.close();
    }

    DecodedAuthzResponse response = decodeAuthzResponse(context.getInboundSAMLMessage(), username);
    if (response == null) {
      return AuthzStatus.INDETERMINATE;
    }
    if (!urlString.equals(response.resource)) {
      throw new IOException("Wrong resource received (expected '" + urlString
          + "'): '" + response.resource + "'");
    }
    return response.status;
  }

  /**
   * Send a (nonstandard) multiple SAML authorization request.
   *
   * @param urlStrings The URLs for which access is being authorized.
   * @param username The username to test for access.
   * @return The authorization responses.
   * @throws IOException if there are any I/O errors during authorization.
   */
  public AuthzResult sendMultiAuthzRequest(Collection<String> urlStrings,
      String username)
      throws IOException {
    Preconditions.checkNotNull(urlStrings);
    Preconditions.checkNotNull(username);

    if (urlStrings.isEmpty()) {
      return AuthzResult.makeIndeterminate(urlStrings);
    }

    // Establish the SAML message context.
    SAMLMessageContext<Response, AuthzDecisionQuery, NameID> context = makeAuthzContext();

    HTTPSOAP11MultiContextEncoder encoder = new HTTPSOAP11MultiContextEncoder();
    HttpExchange exchange = makeAuthzExchange(context);
    try {
      HttpExchangeToOutTransport out = new HttpExchangeToOutTransport(exchange);
      DateTime now = new DateTime();

      for (String urlString : urlStrings) {
        setupAuthzQuery(context, urlString, username, now, out, encoder);
      }
      try {
        encoder.finish();
      } catch (MessageEncodingException e) {
        throw new IOException(e);
      }
      out.finish();

      // Do HTTP exchange
      int status = exchange.exchange();
      if (!HttpUtil.isGoodHttpStatus(status)) {
        throw new IOException("Incorrect HTTP status: " + status);
      }

      // Decode the responses
      HttpExchangeToInTransport in = new HttpExchangeToInTransport(exchange);
      context.setInboundMessageTransport(in);
      HTTPSOAP11MultiContextDecoder decoder = new HTTPSOAP11MultiContextDecoder();

      AuthzResult.Builder builder = AuthzResult.builder(urlStrings);
      while (true) {
        try {
          runDecoder(decoder, context);
        } catch (IndexOutOfBoundsException e) {
          // normal indication that there are no more messages to decode
          break;
        }
        DecodedAuthzResponse response
            = decodeAuthzResponse(context.getInboundSAMLMessage(), username);
        if (response != null) {
          if (urlStrings.contains(response.resource)) {
            builder.put(response.resource, response.status);
          } else {
            LOGGER.warning("Unknown resource received: '" + response.resource + "'");
          }
        }
      }
      return builder.build();

    } finally {
      exchange.close();
    }
  }

  private SAMLMessageContext<Response, AuthzDecisionQuery, NameID> makeAuthzContext() {
    // Establish the SAML message context.
    SAMLMessageContext<Response, AuthzDecisionQuery, NameID> context = makeSamlMessageContext();
    initializeLocalEntity(context, localEntity);
    initializePeerEntity(context, peerEntity,
        peerEntity.getPDPDescriptor(SAMLConstants.SAML20P_NS),
        AuthzService.DEFAULT_ELEMENT_NAME,
        SAML2_SOAP11_BINDING_URI);
    return context;
  }

  private HttpExchange makeAuthzExchange(
      SAMLMessageContext<Response, AuthzDecisionQuery, NameID> context)
      throws IOException {
    return httpClient.postExchange(new URL(context.getPeerEntityEndpoint().getLocation()), null);
  }

  private void setupAuthzQuery(SAMLMessageContext<Response, AuthzDecisionQuery, NameID> context,
      String urlString, String username, DateTime instant, HTTPOutTransport out,
      MessageEncoder encoder)
      throws IOException {
    AuthzDecisionQuery query
        = makeAuthzDecisionQuery(
            context.getOutboundMessageIssuer(),
            instant,
            makeSubject(username),
            urlString,
            makeAction(Action.HTTP_GET_ACTION, Action.GHPP_NS_URI));
    LOGGER.info(SamlLogUtil.xmlMessage("AuthzDecisionQuery", query));
    context.setOutboundSAMLMessage(query);
    context.setOutboundMessageTransport(out);
    runEncoder(encoder, context);
  }

  private DecodedAuthzResponse decodeAuthzResponse(Response response, String username)
      throws IOException {
    LOGGER.info(SamlLogUtil.xmlMessage("response", response));

    String statusValue = response.getStatus().getStatusCode().getValue();
    if (!StatusCode.SUCCESS_URI.equals(statusValue)) {
      LOGGER.info("Unsuccessful response received: " + statusValue);
      return null;
    }

    List<Assertion> assertions = response.getAssertions();
    if (assertions.size() != 1) {
      LOGGER.warning("Wrong number of assertions received (expected 1): " + assertions.size());
      return null;
    }
    Assertion assertion = assertions.get(0);

    String responseUsername = assertion.getSubject().getNameID().getValue();
    if (!username.equals(responseUsername)) {
      LOGGER.warning("Wrong username received (expected '" + username + "'): '"
          + responseUsername + "'");
      return null;
    }

    List<Statement> statements = assertion.getStatements();
    if (statements.size() != 1) {
      LOGGER.warning("Wrong number of statements received (expected 1): " + statements.size());
      return null;
    }
    Statement statement = statements.get(0);

    AuthzDecisionStatement authzDecisionStatement = AuthzDecisionStatement.class.cast(statement);
    return new DecodedAuthzResponse(
        authzDecisionStatement.getResource(),
        mapDecision(authzDecisionStatement.getDecision()));
  }

  private static final class DecodedAuthzResponse {
    public final String resource;
    public final AuthzStatus status;

    public DecodedAuthzResponse(String resource, AuthzStatus status) {
      this.resource = resource;
      this.status = status;
    }
  }

  private AuthzStatus mapDecision(DecisionTypeEnumeration decision) {
    if (decision == DecisionTypeEnumeration.PERMIT) {
      return AuthzStatus.PERMIT;
    } else if (decision == DecisionTypeEnumeration.DENY) {
      return AuthzStatus.DENY;
    } else {
      return AuthzStatus.INDETERMINATE;
    }
  }

  /**
   * A tweaked redirect encoder that preserves query parameters from the endpoint URL.
   */
  private static final class RedirectEncoder extends HTTPRedirectDeflateEncoder {

    RedirectEncoder() {
      super();
    }

    @Override
    protected String buildRedirectURL(@SuppressWarnings("rawtypes") SAMLMessageContext context,
        String endpointUrl, String message)
        throws MessageEncodingException {
      String encodedUrl = super.buildRedirectURL(context, endpointUrl, message);

      // Get the query parameters from the endpoint URL.
      List<Pair<String, String>> endpointParams = new URLBuilder(endpointUrl).getQueryParams();
      if (endpointParams.isEmpty()) {
        // If none, we're finished.
        return encodedUrl;
      }

      URLBuilder builder = new URLBuilder(encodedUrl);
      List<Pair<String, String>> samlParams = builder.getQueryParams();

      // Merge the endpoint params with the SAML params.
      Map<String, String> params = Maps.newHashMap();
      for (Pair<String, String> entry : endpointParams) {
        params.put(entry.getFirst(), entry.getSecond());
      }
      for (Pair<String, String> entry : samlParams) {
        params.put(entry.getFirst(), entry.getSecond());
      }

      // Copy the merged params back into the result.
      samlParams.clear();
      for (Map.Entry<String, String> entry : params.entrySet()) {
        samlParams.add(new Pair<String, String>(entry.getKey(), entry.getValue()));
      }
      return builder.buildURL();
    }
  }
}
