// Copyright (C) 2009 The Android Open Source Project
//
// 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.gerrit.httpd.auth.openid;

import com.google.gerrit.common.PageLinks;
import com.google.gerrit.common.auth.SignInMode;
import com.google.gerrit.common.auth.openid.DiscoveryResult;
import com.google.gerrit.common.auth.openid.OpenIdProviderPattern;
import com.google.gerrit.common.auth.openid.OpenIdService;
import com.google.gerrit.common.auth.openid.OpenIdUrls;
import com.google.gerrit.httpd.WebSession;
import com.google.gerrit.reviewdb.client.Account;
import com.google.gerrit.server.IdentifiedUser;
import com.google.gerrit.server.UrlEncoded;
import com.google.gerrit.server.account.AccountException;
import com.google.gerrit.server.account.AccountManager;
import com.google.gerrit.server.account.AuthMethod;
import com.google.gerrit.server.config.AuthConfig;
import com.google.gerrit.server.config.CanonicalWebUrl;
import com.google.gerrit.server.config.ConfigUtil;
import com.google.gerrit.server.config.GerritServerConfig;
import com.google.gwtjsonrpc.common.AsyncCallback;
import com.google.gwtorm.client.KeyUtil;
import com.google.inject.Inject;
import com.google.inject.Provider;
import com.google.inject.Singleton;

import org.eclipse.jgit.lib.Config;
import org.openid4java.consumer.ConsumerException;
import org.openid4java.consumer.ConsumerManager;
import org.openid4java.consumer.VerificationResult;
import org.openid4java.discovery.DiscoveryException;
import org.openid4java.discovery.DiscoveryInformation;
import org.openid4java.message.AuthRequest;
import org.openid4java.message.Message;
import org.openid4java.message.MessageException;
import org.openid4java.message.MessageExtension;
import org.openid4java.message.ParameterList;
import org.openid4java.message.ax.AxMessage;
import org.openid4java.message.ax.FetchRequest;
import org.openid4java.message.ax.FetchResponse;
import org.openid4java.message.pape.PapeMessage;
import org.openid4java.message.pape.PapeRequest;
import org.openid4java.message.pape.PapeResponse;
import org.openid4java.message.sreg.SRegMessage;
import org.openid4java.message.sreg.SRegRequest;
import org.openid4java.message.sreg.SRegResponse;
import org.openid4java.util.HttpClientFactory;
import org.openid4java.util.ProxyProperties;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.List;
import java.util.concurrent.TimeUnit;

import javax.annotation.Nullable;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@Singleton
class OpenIdServiceImpl implements OpenIdService {
  private static final Logger log =
      LoggerFactory.getLogger(OpenIdServiceImpl.class);

  static final String RETURN_URL = "OpenID";

  private static final String P_MODE = "gerrit.mode";
  private static final String P_TOKEN = "gerrit.token";
  private static final String P_REMEMBER = "gerrit.remember";
  private static final String P_CLAIMED = "gerrit.claimed";
  private static final int LASTID_AGE = 365 * 24 * 60 * 60; // seconds

  private static final String OPENID_MODE = "openid.mode";
  private static final String OMODE_CANCEL = "cancel";

  private static final String SCHEMA_EMAIL =
      "http://schema.openid.net/contact/email";
  private static final String SCHEMA_FIRSTNAME =
      "http://schema.openid.net/namePerson/first";
  private static final String SCHEMA_LASTNAME =
      "http://schema.openid.net/namePerson/last";

  private final Provider<WebSession> webSession;
  private final Provider<IdentifiedUser> identifiedUser;
  private final Provider<String> urlProvider;
  private final AccountManager accountManager;
  private final ConsumerManager manager;
  private final List<OpenIdProviderPattern> allowedOpenIDs;

  /** Maximum age, in seconds, before forcing re-authentication of account. */
  private final int papeMaxAuthAge;

  @Inject
  OpenIdServiceImpl(final Provider<WebSession> cf,
      final Provider<IdentifiedUser> iu,
      @CanonicalWebUrl @Nullable final Provider<String> up,
      @GerritServerConfig final Config config, final AuthConfig ac,
      final AccountManager am) throws ConsumerException, MalformedURLException {

    if (config.getString("http", null, "proxy") != null) {
      final URL proxyUrl = new URL(config.getString("http", null, "proxy"));
      String username = config.getString("http", null, "proxyUsername");
      String password = config.getString("http", null, "proxyPassword");

      final String userInfo = proxyUrl.getUserInfo();
      if (userInfo != null) {
        int c = userInfo.indexOf(':');
        if (0 < c) {
          username = userInfo.substring(0, c);
          password = userInfo.substring(c + 1);
        } else {
          username = userInfo;
        }
      }

      final ProxyProperties proxy = new ProxyProperties();
      proxy.setProxyHostName(proxyUrl.getHost());
      proxy.setProxyPort(proxyUrl.getPort());
      proxy.setUserName(username);
      proxy.setPassword(password);
      HttpClientFactory.setProxyProperties(proxy);
    }

    webSession = cf;
    identifiedUser = iu;
    urlProvider = up;
    accountManager = am;
    manager = new ConsumerManager();
    allowedOpenIDs = ac.getAllowedOpenIDs();
    papeMaxAuthAge = (int) ConfigUtil.getTimeUnit(config, //
        "auth", null, "maxOpenIdSessionAge", -1, TimeUnit.SECONDS);
  }

  @SuppressWarnings("unchecked")
  public void discover(final String openidIdentifier, final SignInMode mode,
      final boolean remember, final String returnToken,
      final AsyncCallback<DiscoveryResult> cb) {
    if (!isAllowedOpenID(openidIdentifier)) {
      cb.onSuccess(new DiscoveryResult(DiscoveryResult.Status.NOT_ALLOWED));
      return;
    }

    final State state;
    state = init(openidIdentifier, mode, remember, returnToken);
    if (state == null) {
      cb.onSuccess(new DiscoveryResult(DiscoveryResult.Status.NO_PROVIDER));
      return;
    }

    final AuthRequest aReq;
    try {
      aReq = manager.authenticate(state.discovered, state.retTo.toString());
      aReq.setRealm(state.contextUrl);

      if (requestRegistration(aReq)) {
        final SRegRequest sregReq = SRegRequest.createFetchRequest();
        sregReq.addAttribute("fullname", true);
        sregReq.addAttribute("email", true);
        aReq.addExtension(sregReq);

        final FetchRequest fetch = FetchRequest.createFetchRequest();
        fetch.addAttribute("FirstName", SCHEMA_FIRSTNAME, true);
        fetch.addAttribute("LastName", SCHEMA_LASTNAME, true);
        fetch.addAttribute("Email", SCHEMA_EMAIL, true);
        aReq.addExtension(fetch);
      }

      if (0 <= papeMaxAuthAge) {
        final PapeRequest pape = PapeRequest.createPapeRequest();
        pape.setMaxAuthAge(papeMaxAuthAge);
        aReq.addExtension(pape);
      }
    } catch (MessageException e) {
      log.error("Cannot create OpenID redirect for " + openidIdentifier, e);
      cb.onSuccess(new DiscoveryResult(DiscoveryResult.Status.ERROR));
      return;
    } catch (ConsumerException e) {
      log.error("Cannot create OpenID redirect for " + openidIdentifier, e);
      cb.onSuccess(new DiscoveryResult(DiscoveryResult.Status.ERROR));
      return;
    }

    cb.onSuccess(new DiscoveryResult(aReq.getDestinationUrl(false), //
        aReq.getParameterMap()));
  }

  private boolean requestRegistration(final AuthRequest aReq) {
    if (AuthRequest.SELECT_ID.equals(aReq.getIdentity())) {
      // We don't know anything about the identity, as the provider
      // will offer the user a way to indicate their identity. Skip
      // any database query operation and assume we must ask for the
      // registration information, in case the identity is new to us.
      //
      return true;

    }

    // We might already have this account on file. Look for it.
    //
    try {
      return accountManager.lookup(aReq.getIdentity()) == null;
    } catch (AccountException e) {
      log.warn("Cannot determine if user account exists", e);
      return true;
    }
  }

  /** Called by {@link OpenIdLoginServlet} doGet, doPost */
  void doAuth(final HttpServletRequest req, final HttpServletResponse rsp)
      throws Exception {
    if (OMODE_CANCEL.equals(req.getParameter(OPENID_MODE))) {
      cancel(req, rsp);
      return;
    }

    // Process the authentication response.
    //
    final SignInMode mode = signInMode(req);
    final String openidIdentifier = req.getParameter("openid.identity");
    final String claimedIdentifier = req.getParameter(P_CLAIMED);
    final String returnToken = req.getParameter(P_TOKEN);
    final boolean remember = "1".equals(req.getParameter(P_REMEMBER));
    final String rediscoverIdentifier =
        claimedIdentifier != null ? claimedIdentifier : openidIdentifier;
    final State state;

    if (!isAllowedOpenID(rediscoverIdentifier)
        || !isAllowedOpenID(openidIdentifier)
        || (claimedIdentifier != null && !isAllowedOpenID(claimedIdentifier))) {
      cancelWithError(req, rsp, "Provider not allowed");
      return;
    }

    state = init(rediscoverIdentifier, mode, remember, returnToken);
    if (state == null) {
      // Re-discovery must have failed, we can't run a login.
      //
      cancel(req, rsp);
      return;
    }

    final String returnTo = req.getParameter("openid.return_to");
    if (returnTo != null && returnTo.contains("openid.rpnonce=")) {
      // Some providers (claimid.com) seem to embed these request
      // parameters into our return_to URL, and then give us them
      // in the return_to request parameter. But not all.
      //
      state.retTo.put("openid.rpnonce", req.getParameter("openid.rpnonce"));
      state.retTo.put("openid.rpsig", req.getParameter("openid.rpsig"));
    }

    final VerificationResult result =
        manager.verify(state.retTo.toString(), new ParameterList(req
            .getParameterMap()), state.discovered);
    if (result.getVerifiedId() == null /* authentication failure */) {
      if ("Nonce verification failed.".equals(result.getStatusMsg())) {
        // We might be suffering from clock skew on this system.
        //
        log.error("OpenID failure: " + result.getStatusMsg()
            + "  Likely caused by clock skew on this server,"
            + " install/configure NTP.");
        cancelWithError(req, rsp, result.getStatusMsg());

      } else if (result.getStatusMsg() != null) {
        // Authentication failed.
        //
        log.error("OpenID failure: " + result.getStatusMsg());
        cancelWithError(req, rsp, result.getStatusMsg());

      } else {
        // Assume authentication was canceled.
        //
        cancel(req, rsp);
      }
      return;
    }

    final Message authRsp = result.getAuthResponse();
    SRegResponse sregRsp = null;
    FetchResponse fetchRsp = null;

    if (0 <= papeMaxAuthAge) {
      PapeResponse ext;
      boolean unsupported = false;

      try {
        ext = (PapeResponse) authRsp.getExtension(PapeMessage.OPENID_NS_PAPE);
      } catch (MessageException err) {
        // Far too many providers are unable to provide PAPE extensions
        // right now. Instead of blocking all of them log the error and
        // let the authentication complete anyway.
        //
        log.error("Invalid PAPE response " + openidIdentifier + ": " + err);
        unsupported = true;
        ext = null;
      }
      if (!unsupported && ext == null) {
        log.error("No PAPE extension response from " + openidIdentifier);
        cancelWithError(req, rsp, "OpenID provider does not support PAPE.");
        return;
      }
    }

    if (authRsp.hasExtension(SRegMessage.OPENID_NS_SREG)) {
      final MessageExtension ext =
          authRsp.getExtension(SRegMessage.OPENID_NS_SREG);
      if (ext instanceof SRegResponse) {
        sregRsp = (SRegResponse) ext;
      }
    }

    if (authRsp.hasExtension(AxMessage.OPENID_NS_AX)) {
      final MessageExtension ext = authRsp.getExtension(AxMessage.OPENID_NS_AX);
      if (ext instanceof FetchResponse) {
        fetchRsp = (FetchResponse) ext;
      }
    }

    final com.google.gerrit.server.account.AuthRequest areq =
        new com.google.gerrit.server.account.AuthRequest(openidIdentifier);

    if (sregRsp != null) {
      areq.setDisplayName(sregRsp.getAttributeValue("fullname"));
      areq.setEmailAddress(sregRsp.getAttributeValue("email"));

    } else if (fetchRsp != null) {
      final String firstName = fetchRsp.getAttributeValue("FirstName");
      final String lastName = fetchRsp.getAttributeValue("LastName");
      final StringBuilder n = new StringBuilder();
      if (firstName != null && firstName.length() > 0) {
        n.append(firstName);
      }
      if (lastName != null && lastName.length() > 0) {
        if (n.length() > 0) {
          n.append(' ');
        }
        n.append(lastName);
      }
      areq.setDisplayName(n.length() > 0 ? n.toString() : null);
      areq.setEmailAddress(fetchRsp.getAttributeValue("Email"));
    }

    if (claimedIdentifier != null) {
      // The user used a claimed identity which has delegated to the verified
      // identity we have in our AuthRequest above. We still should have a
      // link between the two, so set one up if not present.
      //
      Account.Id claimedId = accountManager.lookup(claimedIdentifier);
      Account.Id actualId = accountManager.lookup(areq.getExternalId());

      if (claimedId != null && actualId != null) {
        if (claimedId.equals(actualId)) {
          // Both link to the same account, that's what we expected.
        } else {
          // This is (for now) a fatal error. There are two records
          // for what might be the same user.
          //
          log.error("OpenID accounts disagree over user identity:\n"
              + "  Claimed ID: " + claimedId + " is " + claimedIdentifier
              + "\n" + "  Delgate ID: " + actualId + " is "
              + areq.getExternalId());
          cancelWithError(req, rsp, "Contact site administrator");
          return;
        }

      } else if (claimedId == null && actualId != null) {
        // Older account, the actual was already created but the claimed
        // was missing due to a bug in Gerrit. Link the claimed.
        //
        final com.google.gerrit.server.account.AuthRequest linkReq =
            new com.google.gerrit.server.account.AuthRequest(claimedIdentifier);
        linkReq.setDisplayName(areq.getDisplayName());
        linkReq.setEmailAddress(areq.getEmailAddress());
        accountManager.link(actualId, linkReq);

      } else if (claimedId != null && actualId == null) {
        // Claimed account already exists, but it smells like the user has
        // changed their delegate to point to a different provider. Link
        // the new provider.
        //
        accountManager.link(claimedId, areq);

      } else {
        // Both are null, we are going to create a new account below.
      }
    }

    try {
      final com.google.gerrit.server.account.AuthResult arsp;
      switch (mode) {
        case REGISTER:
        case SIGN_IN:
          arsp = accountManager.authenticate(areq);

          final Cookie lastId = new Cookie(OpenIdUrls.LASTID_COOKIE, "");
          lastId.setPath(req.getContextPath() + "/");
          if (remember) {
            lastId.setValue(rediscoverIdentifier);
            lastId.setMaxAge(LASTID_AGE);
          } else {
            lastId.setMaxAge(0);
          }
          rsp.addCookie(lastId);
          webSession.get().login(arsp, AuthMethod.COOKIE, remember);
          if (arsp.isNew() && claimedIdentifier != null) {
            final com.google.gerrit.server.account.AuthRequest linkReq =
                new com.google.gerrit.server.account.AuthRequest(
                    claimedIdentifier);
            linkReq.setDisplayName(areq.getDisplayName());
            linkReq.setEmailAddress(areq.getEmailAddress());
            accountManager.link(arsp.getAccountId(), linkReq);
          }
          callback(arsp.isNew(), req, rsp);
          break;

        case LINK_IDENTIY: {
          arsp = accountManager.link(identifiedUser.get().getAccountId(), areq);
          webSession.get().login(arsp, AuthMethod.COOKIE, remember);
          callback(false, req, rsp);
          break;
        }
      }
    } catch (AccountException e) {
      log.error("OpenID authentication failure", e);
      cancelWithError(req, rsp, "Contact site administrator");
    }
  }

  private boolean isSignIn(final SignInMode mode) {
    switch (mode) {
      case SIGN_IN:
      case REGISTER:
        return true;
      default:
        return false;
    }
  }

  private static SignInMode signInMode(final HttpServletRequest req) {
    try {
      return SignInMode.valueOf(req.getParameter(P_MODE));
    } catch (RuntimeException e) {
      return SignInMode.SIGN_IN;
    }
  }

  private void callback(final boolean isNew, final HttpServletRequest req,
      final HttpServletResponse rsp) throws IOException {
    String token = req.getParameter(P_TOKEN);
    if (token == null || token.isEmpty() || token.startsWith("/SignInFailure,")) {
      token = PageLinks.MINE;
    }

    final StringBuilder rdr = new StringBuilder();
    rdr.append(urlProvider.get());
    rdr.append('#');
    if (isNew && !token.startsWith(PageLinks.REGISTER + "/")) {
      rdr.append(PageLinks.REGISTER);
    }
    rdr.append(token);
    rsp.sendRedirect(rdr.toString());
  }

  private void cancel(final HttpServletRequest req,
      final HttpServletResponse rsp) throws IOException {
    if (isSignIn(signInMode(req))) {
      webSession.get().logout();
    }
    callback(false, req, rsp);
  }

  private void cancelWithError(final HttpServletRequest req,
      final HttpServletResponse rsp, final String errorDetail)
      throws IOException {
    final SignInMode mode = signInMode(req);
    if (isSignIn(mode)) {
      webSession.get().logout();
    }
    final StringBuilder rdr = new StringBuilder();
    rdr.append(urlProvider.get());
    rdr.append('#');
    rdr.append("SignInFailure");
    rdr.append(',');
    rdr.append(mode.name());
    rdr.append(',');
    rdr.append(errorDetail != null ? KeyUtil.encode(errorDetail) : "");
    rsp.sendRedirect(rdr.toString());
  }

  private State init(final String openidIdentifier, final SignInMode mode,
      final boolean remember, final String returnToken) {
    final List<?> list;
    try {
      list = manager.discover(openidIdentifier);
    } catch (DiscoveryException e) {
      log.error("Cannot discover OpenID " + openidIdentifier, e);
      return null;
    }
    if (list == null || list.isEmpty()) {
      return null;
    }

    final String contextUrl = urlProvider.get();
    final DiscoveryInformation discovered = manager.associate(list);
    final UrlEncoded retTo = new UrlEncoded(contextUrl + RETURN_URL);
    retTo.put(P_MODE, mode.name());
    if (returnToken != null && returnToken.length() > 0) {
      retTo.put(P_TOKEN, returnToken);
    }
    if (remember) {
      retTo.put(P_REMEMBER, "1");
    }
    if (discovered.hasClaimedIdentifier()) {
      retTo.put(P_CLAIMED, discovered.getClaimedIdentifier().getIdentifier());
    }
    return new State(discovered, retTo, contextUrl);
  }

  private boolean isAllowedOpenID(final String id) {
    for (final OpenIdProviderPattern pattern : allowedOpenIDs) {
      if (pattern.matches(id)) {
        return true;
      }
    }
    return false;
  }

  private static class State {
    final DiscoveryInformation discovered;
    final UrlEncoded retTo;
    final String contextUrl;

    State(final DiscoveryInformation d, final UrlEncoded r, final String c) {
      discovered = d;
      retTo = r;
      contextUrl = c;
    }
  }
}
