// 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.auth.oauth;

import static javax.servlet.http.HttpServletResponse.SC_UNAUTHORIZED;

import com.google.common.base.Strings;
import com.google.gerrit.extensions.auth.oauth.OAuthServiceProvider;
import com.google.gerrit.extensions.auth.oauth.OAuthToken;
import com.google.gerrit.extensions.auth.oauth.OAuthUserInfo;
import com.google.gerrit.extensions.auth.oauth.OAuthVerifier;
import com.google.gerrit.extensions.registration.DynamicItem;
import com.google.gerrit.extensions.restapi.Url;
import com.google.gerrit.httpd.CanonicalWebUrl;
import com.google.gerrit.httpd.WebSession;
import com.google.gerrit.reviewdb.client.Account;
import com.google.gerrit.server.account.AccountException;
import com.google.gerrit.server.account.AccountManager;
import com.google.gerrit.server.account.AuthResult;
import com.google.gwtorm.server.OrmException;
import com.google.inject.Inject;
import com.google.inject.servlet.SessionScoped;

import org.apache.commons.codec.binary.Base64;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;

import javax.servlet.ServletRequest;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@SessionScoped
/* OAuth protocol implementation */
class OAuthSession {
  private static final Logger log = LoggerFactory.getLogger(OAuthSession.class);
  private static final SecureRandom randomState = newRandomGenerator();
  private final String state;
  private final DynamicItem<WebSession> webSession;
  private final AccountManager accountManager;
  private final CanonicalWebUrl urlProvider;
  private OAuthServiceProvider serviceProvider;
  private OAuthToken token;
  private OAuthUserInfo user;
  private String redirectToken;

  @Inject
  OAuthSession(DynamicItem<WebSession> webSession,
      AccountManager accountManager,
      CanonicalWebUrl urlProvider) {
    this.state = generateRandomState();
    this.webSession = webSession;
    this.accountManager = accountManager;
    this.urlProvider = urlProvider;
  }

  boolean isLoggedIn() {
    return token != null && user != null;
  }

  boolean isOAuthFinal(HttpServletRequest request) {
    return Strings.emptyToNull(request.getParameter("code")) != null;
  }

  boolean login(HttpServletRequest request, HttpServletResponse response,
      OAuthServiceProvider oauth) throws IOException {
    if (isLoggedIn()) {
      return true;
    }

    log.debug("Login " + this);

    if (isOAuthFinal(request)) {
      if (!checkState(request)) {
        response.sendError(HttpServletResponse.SC_NOT_FOUND);
        return false;
      }

      log.debug("Login-Retrieve-User " + this);
      token = oauth.getAccessToken(new OAuthVerifier(request.getParameter("code")));

      user = oauth.getUserInfo(token);

      if (isLoggedIn()) {
        log.debug("Login-SUCCESS " + this);
        authenticateAndRedirect(request, response);
        return true;
      } else {
        response.sendError(SC_UNAUTHORIZED);
        return false;
      }
    } else {
      log.debug("Login-PHASE1 " + this);
      redirectToken = request.getRequestURI();
      // We are here in content of filter.
      // Due to this Jetty limitation:
      // https://bz.apache.org/bugzilla/show_bug.cgi?id=28323
      // we cannot use LoginUrlToken.getToken() method,
      // because it relies on getPathInfo() and it is always null here.
      redirectToken = redirectToken.substring(
          request.getContextPath().length());
      response.sendRedirect(oauth.getAuthorizationUrl() +
          "&state=" + state);
      return false;
    }
  }

  private void authenticateAndRedirect(HttpServletRequest req,
      HttpServletResponse rsp) throws IOException {
    com.google.gerrit.server.account.AuthRequest areq =
        new com.google.gerrit.server.account.AuthRequest(user.getExternalId());
    AuthResult arsp;
    try {
      String claimedIdentifier = user.getClaimedIdentity();
      Account.Id actualId = accountManager.lookup(user.getExternalId());
      if (!Strings.isNullOrEmpty(claimedIdentifier)) {
        Account.Id claimedId = accountManager.lookup(claimedIdentifier);
        if (claimedId != null && actualId != null) {
          if (claimedId.equals(actualId)) {
            // Both link to the same account, that's what we expected.
            log.debug("OAuth2: claimed identity equals current id");
          } else {
            // This is (for now) a fatal error. There are two records
            // for what might be the same user.
            //
            log.error("OAuth accounts disagree over user identity:\n"
                + "  Claimed ID: " + claimedId + " is " + claimedIdentifier
                + "\n" + "  Delgate ID: " + actualId + " is "
                + user.getExternalId());
            rsp.sendError(HttpServletResponse.SC_FORBIDDEN);
            return;
          }
        } else if (claimedId != null && actualId == null) {
          // Claimed account already exists: link to it.
          //
          log.info("OAuth2: linking claimed identity to {}",
              claimedId.toString());
          try {
            accountManager.link(claimedId, areq);
          } catch (OrmException e) {
            log.error("Cannot link: " +  user.getExternalId()
                + " to user identity:\n"
                + "  Claimed ID: " + claimedId + " is " + claimedIdentifier);
            rsp.sendError(HttpServletResponse.SC_FORBIDDEN);
            return;
          }
        }
      } else {
        log.debug("OAuth2: claimed identity is empty");
      }
      areq.setUserName(user.getUserName());
      areq.setEmailAddress(user.getEmailAddress());
      areq.setDisplayName(user.getDisplayName());
      arsp = accountManager.authenticate(areq);
    } catch (AccountException e) {
      log.error("Unable to authenticate user \"" + user + "\"", e);
      rsp.sendError(HttpServletResponse.SC_FORBIDDEN);
      return;
    }

    webSession.get().login(arsp, true);
    String suffix = redirectToken.substring(
        OAuthWebFilter.GERRIT_LOGIN.length() + 1);
    StringBuilder rdr = new StringBuilder(urlProvider.get(req));
    rdr.append(Url.decode(suffix));
    rsp.sendRedirect(rdr.toString());
  }

  void logout() {
    token = null;
    user = null;
    redirectToken = null;
    serviceProvider = null;
  }

  private boolean checkState(ServletRequest request) {
    String s = Strings.nullToEmpty(request.getParameter("state"));
    if (!s.equals(state)) {
      log.error("Illegal request state '" + s + "' on OAuthProtocol " + this);
      return false;
    }
    return true;
  }

  private static SecureRandom newRandomGenerator() {
    try {
      return SecureRandom.getInstance("SHA1PRNG");
    } catch (NoSuchAlgorithmException e) {
      throw new IllegalArgumentException(
          "No SecureRandom available for GitHub authentication", e);
    }
  }

  private static String generateRandomState() {
    byte[] state = new byte[32];
    randomState.nextBytes(state);
    return Base64.encodeBase64URLSafeString(state);
  }

  @Override
  public String toString() {
    return "OAuthSession [token=" + token + ", user=" + user + "]";
  }

  public void setServiceProvider(OAuthServiceProvider provider) {
    this.serviceProvider = provider;
  }

  public OAuthServiceProvider getServiceProvider() {
    return serviceProvider;
  }
}
