// Copyright (C) 2015 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;

import static com.google.gerrit.httpd.ProjectBasicAuthFilter.authenticationFailedMsg;
import static java.nio.charset.StandardCharsets.UTF_8;
import static javax.servlet.http.HttpServletResponse.SC_UNAUTHORIZED;

import com.google.common.base.MoreObjects;
import com.google.common.base.Strings;
import com.google.common.collect.Iterables;
import com.google.common.flogger.FluentLogger;
import com.google.gerrit.extensions.auth.oauth.OAuthLoginProvider;
import com.google.gerrit.extensions.registration.DynamicItem;
import com.google.gerrit.extensions.registration.DynamicMap;
import com.google.gerrit.extensions.registration.DynamicMap.Entry;
import com.google.gerrit.reviewdb.client.Account;
import com.google.gerrit.server.AccessPath;
import com.google.gerrit.server.account.AccountCache;
import com.google.gerrit.server.account.AccountException;
import com.google.gerrit.server.account.AccountManager;
import com.google.gerrit.server.account.AccountState;
import com.google.gerrit.server.account.AuthRequest;
import com.google.gerrit.server.account.AuthResult;
import com.google.gerrit.server.config.GerritServerConfig;
import com.google.inject.Inject;
import com.google.inject.Singleton;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.util.Locale;
import java.util.NoSuchElementException;
import java.util.Optional;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpServletResponseWrapper;
import org.apache.commons.codec.binary.Base64;
import org.eclipse.jgit.lib.Config;

/**
 * Authenticates the current user with an OAuth2 server.
 *
 * @see <a href="https://tools.ietf.org/rfc/rfc6750.txt">RFC 6750</a>
 */
@Singleton
class ProjectOAuthFilter implements Filter {
  private static final FluentLogger logger = FluentLogger.forEnclosingClass();

  private static final String REALM_NAME = "Gerrit Code Review";
  private static final String AUTHORIZATION = "Authorization";
  private static final String BASIC = "Basic ";
  private static final String GIT_COOKIE_PREFIX = "git-";

  private final DynamicItem<WebSession> session;
  private final DynamicMap<OAuthLoginProvider> loginProviders;
  private final AccountCache accountCache;
  private final AccountManager accountManager;
  private final String gitOAuthProvider;
  private final boolean userNameToLowerCase;

  private String defaultAuthPlugin;
  private String defaultAuthProvider;

  @Inject
  ProjectOAuthFilter(
      DynamicItem<WebSession> session,
      DynamicMap<OAuthLoginProvider> pluginsProvider,
      AccountCache accountCache,
      AccountManager accountManager,
      @GerritServerConfig Config gerritConfig) {
    this.session = session;
    this.loginProviders = pluginsProvider;
    this.accountCache = accountCache;
    this.accountManager = accountManager;
    this.gitOAuthProvider = gerritConfig.getString("auth", null, "gitOAuthProvider");
    this.userNameToLowerCase = gerritConfig.getBoolean("auth", null, "userNameToLowerCase", false);
  }

  @Override
  public void init(FilterConfig config) throws ServletException {
    if (Strings.isNullOrEmpty(gitOAuthProvider)) {
      pickOnlyProvider();
    } else {
      pickConfiguredProvider();
    }
  }

  @Override
  public void destroy() {}

  @Override
  public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
      throws IOException, ServletException {
    HttpServletRequest req = (HttpServletRequest) request;
    Response rsp = new Response((HttpServletResponse) response);
    if (verify(req, rsp)) {
      chain.doFilter(req, rsp);
    }
  }

  private boolean verify(HttpServletRequest req, Response rsp) throws IOException {
    AuthInfo authInfo = null;

    // first check if there is a BASIC authentication header
    String hdr = req.getHeader(AUTHORIZATION);
    if (hdr != null && hdr.startsWith(BASIC)) {
      authInfo = extractAuthInfo(hdr, encoding(req));
      if (authInfo == null) {
        rsp.sendError(SC_UNAUTHORIZED);
        return false;
      }
    } else {
      // if there is no BASIC authentication header, check if there is
      // a cookie starting with the prefix "git-"
      Cookie cookie = findGitCookie(req);
      if (cookie != null) {
        authInfo = extractAuthInfo(cookie);
        if (authInfo == null) {
          rsp.sendError(SC_UNAUTHORIZED);
          return false;
        }
      } else {
        // if there is no authentication information at all, it might be
        // an anonymous connection, or there might be a session cookie
        return true;
      }
    }

    // if there is authentication information but no secret => 401
    if (Strings.isNullOrEmpty(authInfo.tokenOrSecret)) {
      rsp.sendError(SC_UNAUTHORIZED);
      return false;
    }

    Optional<AccountState> who =
        accountCache.getByUsername(authInfo.username).filter(a -> a.getAccount().isActive());
    if (!who.isPresent()) {
      logger.atWarning().log(
          authenticationFailedMsg(authInfo.username, req)
              + ": account inactive or not provisioned in Gerrit");
      rsp.sendError(SC_UNAUTHORIZED);
      return false;
    }

    Account account = who.get().getAccount();
    AuthRequest authRequest = AuthRequest.forExternalUser(authInfo.username);
    authRequest.setEmailAddress(account.getPreferredEmail());
    authRequest.setDisplayName(account.getFullName());
    authRequest.setPassword(authInfo.tokenOrSecret);
    authRequest.setAuthPlugin(authInfo.pluginName);
    authRequest.setAuthProvider(authInfo.exportName);

    try {
      AuthResult authResult = accountManager.authenticate(authRequest);
      WebSession ws = session.get();
      ws.setUserAccountId(authResult.getAccountId());
      ws.setAccessPathOk(AccessPath.GIT, true);
      ws.setAccessPathOk(AccessPath.REST_API, true);
      return true;
    } catch (AccountException e) {
      logger.atWarning().withCause(e).log(authenticationFailedMsg(authInfo.username, req));
      rsp.sendError(SC_UNAUTHORIZED);
      return false;
    }
  }

  /**
   * Picks the only installed OAuth provider. If there is a multiude of providers available, the
   * actual provider must be determined from the authentication request.
   *
   * @throws ServletException if there is no {@code OAuthLoginProvider} installed at all.
   */
  private void pickOnlyProvider() throws ServletException {
    try {
      Entry<OAuthLoginProvider> loginProvider = Iterables.getOnlyElement(loginProviders);
      defaultAuthPlugin = loginProvider.getPluginName();
      defaultAuthProvider = loginProvider.getExportName();
    } catch (NoSuchElementException e) {
      throw new ServletException("No OAuth login provider installed");
    } catch (IllegalArgumentException e) {
      // multiple providers found => do not pick any
    }
  }

  /**
   * Picks the {@code OAuthLoginProvider} configured with <tt>auth.gitOAuthProvider</tt>.
   *
   * @throws ServletException if the configured provider was not found.
   */
  private void pickConfiguredProvider() throws ServletException {
    int splitPos = gitOAuthProvider.lastIndexOf(':');
    if (splitPos < 1 || splitPos == gitOAuthProvider.length() - 1) {
      // no colon at all or leading/trailing colon: malformed providerId
      throw new ServletException(
          "OAuth login provider configuration is"
              + " invalid: Must be of the form pluginName:providerName");
    }
    defaultAuthPlugin = gitOAuthProvider.substring(0, splitPos);
    defaultAuthProvider = gitOAuthProvider.substring(splitPos + 1);
    OAuthLoginProvider provider = loginProviders.get(defaultAuthPlugin, defaultAuthProvider);
    if (provider == null) {
      throw new ServletException(
          "Configured OAuth login provider " + gitOAuthProvider + " wasn't installed");
    }
  }

  private AuthInfo extractAuthInfo(String hdr, String encoding)
      throws UnsupportedEncodingException {
    byte[] decoded = Base64.decodeBase64(hdr.substring(BASIC.length()));
    String usernamePassword = new String(decoded, encoding);
    int splitPos = usernamePassword.indexOf(':');
    if (splitPos < 1 || splitPos == usernamePassword.length() - 1) {
      return null;
    }
    return new AuthInfo(
        usernamePassword.substring(0, splitPos),
        usernamePassword.substring(splitPos + 1),
        defaultAuthPlugin,
        defaultAuthProvider);
  }

  private AuthInfo extractAuthInfo(Cookie cookie) throws UnsupportedEncodingException {
    String username =
        URLDecoder.decode(cookie.getName().substring(GIT_COOKIE_PREFIX.length()), UTF_8.name());
    String value = cookie.getValue();
    int splitPos = value.lastIndexOf('@');
    if (splitPos < 1 || splitPos == value.length() - 1) {
      // no providerId in the cookie value => assume default provider
      // note: a leading/trailing at sign is considered to belong to
      // the access token rather than being a separator
      return new AuthInfo(username, cookie.getValue(), defaultAuthPlugin, defaultAuthProvider);
    }
    String token = value.substring(0, splitPos);
    String providerId = value.substring(splitPos + 1);
    splitPos = providerId.lastIndexOf(':');
    if (splitPos < 1 || splitPos == providerId.length() - 1) {
      // no colon at all or leading/trailing colon: malformed providerId
      return null;
    }
    String pluginName = providerId.substring(0, splitPos);
    String exportName = providerId.substring(splitPos + 1);
    OAuthLoginProvider provider = loginProviders.get(pluginName, exportName);
    if (provider == null) {
      return null;
    }
    return new AuthInfo(username, token, pluginName, exportName);
  }

  private static String encoding(HttpServletRequest req) {
    return MoreObjects.firstNonNull(req.getCharacterEncoding(), UTF_8.name());
  }

  private static Cookie findGitCookie(HttpServletRequest req) {
    Cookie[] cookies = req.getCookies();
    if (cookies != null) {
      for (Cookie cookie : cookies) {
        if (cookie.getName().startsWith(GIT_COOKIE_PREFIX)) {
          return cookie;
        }
      }
    }
    return null;
  }

  private class AuthInfo {
    private final String username;
    private final String tokenOrSecret;
    private final String pluginName;
    private final String exportName;

    private AuthInfo(String username, String tokenOrSecret, String pluginName, String exportName) {
      this.username = userNameToLowerCase ? username.toLowerCase(Locale.US) : username;
      this.tokenOrSecret = tokenOrSecret;
      this.pluginName = pluginName;
      this.exportName = exportName;
    }
  }

  private static class Response extends HttpServletResponseWrapper {
    private static final String WWW_AUTHENTICATE = "WWW-Authenticate";

    Response(HttpServletResponse rsp) {
      super(rsp);
    }

    private void status(int sc) {
      if (sc == SC_UNAUTHORIZED) {
        StringBuilder v = new StringBuilder();
        v.append(BASIC);
        v.append("realm=\"").append(REALM_NAME).append("\"");
        setHeader(WWW_AUTHENTICATE, v.toString());
      } else if (containsHeader(WWW_AUTHENTICATE)) {
        setHeader(WWW_AUTHENTICATE, null);
      }
    }

    @Override
    public void sendError(int sc, String msg) throws IOException {
      status(sc);
      super.sendError(sc, msg);
    }

    @Override
    public void sendError(int sc) throws IOException {
      status(sc);
      super.sendError(sc);
    }

    @Override
    @Deprecated
    public void setStatus(int sc, String sm) {
      status(sc);
      super.setStatus(sc, sm);
    }

    @Override
    public void setStatus(int sc) {
      status(sc);
      super.setStatus(sc);
    }
  }
}
