// Package googleoauth implements an http.Handler that has two main purposes
// listed below:

// (1) Uses OAuth 2.0 to authenticate with Google and then renders a page that
//     displays all the blessings that were provided for that Google user.
//     The client calls the /listblessings route which redirects to listblessingscallback which
//     renders the list.
// (2) Performs the oauth flow for seeking a blessing using the identity tool
//     located at veyron/tools/identity.
//     The seek blessing flow works as follows:
//     (a) Client (identity tool) hits the /seekblessings route.
//     (b) /seekblessings performs google oauth with a redirect to /seekblessingscallback.
//     (c) Client specifies desired caveats in the form that /seekblessingscallback displays.
//     (d) Submission of the form sends caveat information to /sendmacaroon.
//     (e) /sendmacaroon sends a macaroon with blessing information to client
//         (via a redirect to an HTTP server run by the tool).
//     (f) Client invokes bless rpc with macaroon.
//
// The GoogleIDToken is currently validated by sending an HTTP request to
// googleapis.com.  This adds a round-trip and service may be denied by
// googleapis.com if this handler becomes a breakout success and receives tons
// of traffic.  If either is a concern, the GoogleIDToken can be validated
// without an additional HTTP request.
// See: https://developers.google.com/accounts/docs/OAuth2Login#validatinganidtoken
package googleoauth

import (
	"bytes"
	"encoding/base64"
	"encoding/json"
	"fmt"
	"io/ioutil"
	"net"
	"net/http"
	"net/url"
	"path"
	"strings"
	"time"

	"code.google.com/p/goauth2/oauth"

	"veyron.io/veyron/veyron/services/identity/auditor"
	"veyron.io/veyron/veyron/services/identity/blesser"
	"veyron.io/veyron/veyron/services/identity/revocation"
	"veyron.io/veyron/veyron/services/identity/util"
	"veyron.io/veyron/veyron2"
	"veyron.io/veyron/veyron2/security"
	"veyron.io/veyron/veyron2/vlog"
	"veyron.io/veyron/veyron2/vom"
)

const (
	clientIDCookie   = "VeyronHTTPIdentityClientID"
	revocationCookie = "VeyronHTTPIdentityRevocationID"

	ListBlessingsRoute         = "listblessings"
	listBlessingsCallbackRoute = "listblessingscallback"
	revokeRoute                = "revoke"
	SeekBlessingsRoute         = "seekblessings"
	addCaveatsRoute            = "addcaveat"
	sendMacaroonRoute          = "sendmacaroon"
)

type HandlerArgs struct {
	// The Veyron runtime to use
	R veyron2.Runtime
	// The Key that is used for creating and verifying macaroons.
	// This needs to be common between the handler and the MacaroonBlesser service.
	MacaroonKey []byte
	// URL at which the hander is installed.
	// e.g. http://host:port/google/
	// This is where the handler is installed and where redirect requests
	// from Google will come to.
	Addr string
	// client_id and client_secret registered with the Google Developer
	// Console for API access.
	ClientID, ClientSecret string
	// Prefix for the audit log from which data will be sourced.
	// (auditor.ReadAuditLog).
	Auditor string
	// The RevocationManager is used to revoke blessings granted with a revocation caveat.
	// If this is empty then revocation caveats will not be added to blessings, and instead
	// Expiry Caveats of duration BlessingDuration will be added.
	RevocationManager *revocation.RevocationManager
	// The object name of the discharger service.
	DischargerLocation string
	// MacaroonBlessingService is the object name to which macaroons create by this HTTP
	// handler can be exchanged for a blessing.
	MacaroonBlessingService string
	// If non-empty, only email addressses from this domain will be blessed.
	DomainRestriction string
	// BlessingDuration is the duration that blessings granted will be valid for
	// if RevocationManager is nil.
	BlessingDuration time.Duration
}

func (a *HandlerArgs) oauthConfig(redirectSuffix string) *oauth.Config {
	return &oauth.Config{
		ClientId:     a.ClientID,
		ClientSecret: a.ClientSecret,
		RedirectURL:  redirectURL(a.Addr, redirectSuffix),
		Scope:        "email",
		AuthURL:      "https://accounts.google.com/o/oauth2/auth",
		TokenURL:     "https://accounts.google.com/o/oauth2/token",
	}
}

func redirectURL(baseURL, suffix string) string {
	if !strings.HasSuffix(baseURL, "/") {
		baseURL += "/"
	}
	return baseURL + suffix
}

// URL used to verify google tokens.
// (From https://developers.google.com/accounts/docs/OAuth2Login#validatinganidtoken
// and https://developers.google.com/accounts/docs/OAuth2UserAgent#validatetoken)
const verifyURL = "https://www.googleapis.com/oauth2/v1/tokeninfo?"

// NewHandler returns an http.Handler that expects to be rooted at args.Addr
// and can be used to use OAuth 2.0 to authenticate with Google, mint a new
// identity and bless it with the Google email address.
func NewHandler(args HandlerArgs) (http.Handler, error) {
	csrfCop, err := util.NewCSRFCop()
	if err != nil {
		return nil, fmt.Errorf("NewHandler failed to create csrfCop: %v", err)
	}
	return &handler{
		args:    args,
		csrfCop: csrfCop,
	}, nil
}

type handler struct {
	args    HandlerArgs
	csrfCop *util.CSRFCop
}

func (h *handler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	switch path.Base(r.URL.Path) {
	case ListBlessingsRoute:
		h.listBlessings(w, r)
	case listBlessingsCallbackRoute:
		h.listBlessingsCallback(w, r)
	case revokeRoute:
		h.revoke(w, r)
	case SeekBlessingsRoute:
		h.seekBlessings(w, r)
	case addCaveatsRoute:
		h.addCaveats(w, r)
	case sendMacaroonRoute:
		h.sendMacaroon(w, r)
	default:
		util.HTTPBadRequest(w, r, nil)
	}
}

func (h *handler) listBlessings(w http.ResponseWriter, r *http.Request) {
	csrf, err := h.csrfCop.NewToken(w, r, clientIDCookie, nil)
	if err != nil {
		vlog.Infof("Failed to create CSRF token[%v] for request %#v", err, r)
		util.HTTPServerError(w, fmt.Errorf("failed to create new token: %v", err))
		return
	}
	http.Redirect(w, r, h.args.oauthConfig(listBlessingsCallbackRoute).AuthCodeURL(csrf), http.StatusFound)
}

func (h *handler) listBlessingsCallback(w http.ResponseWriter, r *http.Request) {
	if err := h.csrfCop.ValidateToken(r.FormValue("state"), r, clientIDCookie, nil); err != nil {
		vlog.Infof("Invalid CSRF token: %v in request: %#v", err, r)
		util.HTTPBadRequest(w, r, fmt.Errorf("Suspected request forgery: %v", err))
		return
	}
	email, err := exchangeAuthCodeForEmail(h.args.oauthConfig(listBlessingsCallbackRoute), r.FormValue("code"))
	if err != nil {
		util.HTTPBadRequest(w, r, err)
		return
	}

	type tmplentry struct {
		Blessee        security.PublicID
		Start, End     time.Time
		Blessed        security.PublicID
		RevocationTime time.Time
		Token          string
	}
	tmplargs := struct {
		Log                chan tmplentry
		Email, RevokeRoute string
	}{
		Log:         make(chan tmplentry),
		Email:       email,
		RevokeRoute: revokeRoute,
	}
	if entrych, err := auditor.ReadAuditLog(h.args.Auditor, email); err != nil {
		vlog.Errorf("Unable to read audit log: %v", err)
		util.HTTPServerError(w, fmt.Errorf("unable to read audit log"))
		return
	} else {
		go func(ch chan tmplentry) {
			defer close(ch)
			for entry := range entrych {
				if entry.Method != "Bless" || len(entry.Arguments) < 2 {
					continue
				}
				var tmplentry tmplentry
				var blessEntry revocation.BlessingAuditEntry
				blessEntry, err = revocation.ReadBlessAuditEntry(entry)
				tmplentry.Blessee = blessEntry.Blessee
				tmplentry.Blessed = blessEntry.Blessed
				tmplentry.Start = blessEntry.Start
				tmplentry.End = blessEntry.End
				if err != nil {
					vlog.Errorf("Unable to read bless audit entry: %v", err)
					continue
				}
				if blessEntry.RevocationCaveat != nil {
					if revocationTime := h.args.RevocationManager.GetRevocationTime(blessEntry.RevocationCaveat.ID()); revocationTime != nil {
						tmplentry.RevocationTime = *revocationTime
					} else {
						caveatID := base64.URLEncoding.EncodeToString([]byte(blessEntry.RevocationCaveat.ID()))
						if tmplentry.Token, err = h.csrfCop.NewToken(w, r, revocationCookie, caveatID); err != nil {
							vlog.Infof("Failed to create CSRF token[%v] for request %#v", err, r)
							util.HTTPServerError(w, fmt.Errorf("failed to create new token: %v", err))
							return
						}
					}
				}
				ch <- tmplentry
			}
		}(tmplargs.Log)
	}
	w.Header().Set("Context-Type", "text/html")
	// This MaybeSetCookie call is needed to ensure that a cookie is created. Since the
	// header cannot be changed once the body is written to, this needs to be called first.
	if _, err = h.csrfCop.MaybeSetCookie(w, r, revocationCookie); err != nil {
		vlog.Infof("Failed to set CSRF cookie[%v] for request %#v", err, r)
		util.HTTPServerError(w, err)
		return
	}
	if err := tmplViewBlessings.Execute(w, tmplargs); err != nil {
		vlog.Errorf("Unable to execute audit page template: %v", err)
		util.HTTPServerError(w, err)
	}
}

func (h *handler) revoke(w http.ResponseWriter, r *http.Request) {
	w.Header().Set("Content-Type", "application/json")
	const (
		success = `{"success": "true"}`
		failure = `{"success": "false"}`
	)
	if h.args.RevocationManager == nil {
		vlog.Infof("no provided revocation manager")
		w.Write([]byte(failure))
		return
	}

	content, err := ioutil.ReadAll(r.Body)
	if err != nil {
		vlog.Infof("Failed to parse request: %s", err)
		w.Write([]byte(failure))
		return
	}
	var requestParams struct {
		Token string
	}
	if err := json.Unmarshal(content, &requestParams); err != nil {
		vlog.Infof("json.Unmarshal failed : %s", err)
		w.Write([]byte(failure))
		return
	}

	var caveatID string
	if caveatID, err = h.validateRevocationToken(requestParams.Token, r); err != nil {
		vlog.Infof("failed to validate token for caveat: %s", err)
		w.Write([]byte(failure))
		return
	}
	if err := h.args.RevocationManager.Revoke(caveatID); err != nil {
		vlog.Infof("Revocation failed: %s", err)
		w.Write([]byte(failure))
		return
	}

	w.Write([]byte(success))
	return
}

func (h *handler) validateRevocationToken(Token string, r *http.Request) (string, error) {
	var encCaveatID string
	if err := h.csrfCop.ValidateToken(Token, r, revocationCookie, &encCaveatID); err != nil {
		return "", fmt.Errorf("invalid CSRF token: %v in request: %#v", err, r)
	}
	caveatID, err := base64.URLEncoding.DecodeString(encCaveatID)
	if err != nil {
		return "", fmt.Errorf("decode caveatID failed: %v", err)
	}
	return string(caveatID), nil
}

type seekBlessingsMacaroon struct {
	RedirectURL, State string
}

func validLoopbackURL(u string) (*url.URL, error) {
	netURL, err := url.Parse(u)
	if err != nil {
		return nil, fmt.Errorf("invalid url: %v", err)
	}
	// Remove the port from the netURL.Host.
	host, _, err := net.SplitHostPort(netURL.Host)
	// Check if its localhost or loopback ip
	if host == "localhost" {
		return netURL, nil
	}
	urlIP := net.ParseIP(host)
	if urlIP.IsLoopback() {
		return netURL, nil
	}
	return nil, fmt.Errorf("invalid loopback url")
}

func (h *handler) seekBlessings(w http.ResponseWriter, r *http.Request) {
	if _, err := validLoopbackURL(r.FormValue("redirect_url")); err != nil {
		vlog.Infof("seekBlessings failed: invalid redirect_url: %v", err)
		util.HTTPBadRequest(w, r, fmt.Errorf("invalid redirect_url: %v", err))
		return
	}
	outputMacaroon, err := h.csrfCop.NewToken(w, r, clientIDCookie, seekBlessingsMacaroon{
		RedirectURL: r.FormValue("redirect_url"),
		State:       r.FormValue("state"),
	})
	if err != nil {
		vlog.Infof("Failed to create CSRF token[%v] for request %#v", err, r)
		util.HTTPServerError(w, fmt.Errorf("failed to create new token: %v", err))
		return
	}
	http.Redirect(w, r, h.args.oauthConfig(addCaveatsRoute).AuthCodeURL(outputMacaroon), http.StatusFound)
}

type addCaveatsMacaroon struct {
	ToolRedirectURL, ToolState, Email string
}

func (h *handler) addCaveats(w http.ResponseWriter, r *http.Request) {
	var inputMacaroon seekBlessingsMacaroon
	if err := h.csrfCop.ValidateToken(r.FormValue("state"), r, clientIDCookie, &inputMacaroon); err != nil {
		util.HTTPBadRequest(w, r, fmt.Errorf("Suspected request forgery: %v", err))
		return
	}
	email, err := exchangeAuthCodeForEmail(h.args.oauthConfig(addCaveatsRoute), r.FormValue("code"))
	if err != nil {
		util.HTTPBadRequest(w, r, err)
		return
	}
	if len(h.args.DomainRestriction) > 0 && !strings.HasSuffix(email, "@"+h.args.DomainRestriction) {
		util.HTTPBadRequest(w, r, fmt.Errorf("blessings for name %q are not allowed due to domain restriction", email))
		return
	}
	outputMacaroon, err := h.csrfCop.NewToken(w, r, clientIDCookie, addCaveatsMacaroon{
		ToolRedirectURL: inputMacaroon.RedirectURL,
		ToolState:       inputMacaroon.State,
		Email:           email,
	})
	if err != nil {
		vlog.Infof("Failed to create caveatForm token[%v] for request %#v", err, r)
		util.HTTPServerError(w, fmt.Errorf("failed to create new token: %v", err))
		return
	}
	tmplargs := struct {
		CaveatMap               map[string]caveatInfo
		Macaroon, MacaroonRoute string
	}{caveatMap, outputMacaroon, sendMacaroonRoute}
	w.Header().Set("Context-Type", "text/html")
	if err := tmplSelectCaveats.Execute(w, tmplargs); err != nil {
		vlog.Errorf("Unable to execute bless page template: %v", err)
		util.HTTPServerError(w, err)
	}
}

func (h *handler) sendMacaroon(w http.ResponseWriter, r *http.Request) {
	var inputMacaroon addCaveatsMacaroon
	if err := h.csrfCop.ValidateToken(r.FormValue("macaroon"), r, clientIDCookie, &inputMacaroon); err != nil {
		util.HTTPBadRequest(w, r, fmt.Errorf("Suspected request forgery: %v", err))
		return
	}
	caveats, err := h.caveats(r)
	if err != nil {
		util.HTTPBadRequest(w, r, fmt.Errorf("failed to extract caveats: ", err))
		return
	}
	buf := &bytes.Buffer{}
	m := blesser.BlessingMacaroon{
		Creation: time.Now(),
		Caveats:  caveats,
		Name:     inputMacaroon.Email,
	}
	if err := vom.NewEncoder(buf).Encode(m); err != nil {
		util.HTTPServerError(w, fmt.Errorf("failed to encode BlessingsMacaroon: ", err))
		return
	}
	// Construct the url to send back to the tool.
	baseURL, err := validLoopbackURL(inputMacaroon.ToolRedirectURL)
	if err != nil {
		util.HTTPBadRequest(w, r, fmt.Errorf("invalid ToolRedirectURL: ", err))
		return
	}
	params := url.Values{}
	params.Add("macaroon", string(util.NewMacaroon(h.args.MacaroonKey, buf.Bytes())))
	params.Add("state", inputMacaroon.ToolState)
	params.Add("object_name", h.args.MacaroonBlessingService)
	baseURL.RawQuery = params.Encode()
	http.Redirect(w, r, baseURL.String(), http.StatusFound)
}

func (h *handler) caveats(r *http.Request) ([]security.Caveat, error) {
	if err := r.ParseForm(); err != nil {
		return nil, err
	}
	var caveats []security.Caveat
	var caveat security.Caveat
	var err error

	userProvidedExpiryCaveat := false

	for i, cavName := range r.Form["caveat"] {
		if cavName == "none" {
			continue
		}
		if cavName == "ExpiryCaveat" {
			userProvidedExpiryCaveat = true
		}
		args := strings.Split(r.Form[cavName][i], ",")
		cavInfo, ok := caveatMap[cavName]
		if !ok {
			return nil, fmt.Errorf("unable to create caveat %s: caveat does not exist", cavName)
		}
		caveat, err := cavInfo.New(args...)
		if err != nil {
			return nil, fmt.Errorf("unable to create caveat %s(%v): cavInfo.New failed: %v", cavName, args, err)
		}
		caveats = append(caveats, caveat)
	}

	// TODO(suharshs): have a checkbox in the form that says "include revocation caveat".
	if h.args.RevocationManager != nil {
		revocationCaveat, err := h.args.RevocationManager.NewCaveat(h.args.R.Identity().PublicID(), h.args.DischargerLocation)
		if err != nil {
			return nil, err
		}
		caveat, err = security.NewCaveat(revocationCaveat)
	} else if !userProvidedExpiryCaveat {
		caveat, err = security.ExpiryCaveat(time.Now().Add(h.args.BlessingDuration))
	}
	if err != nil {
		return nil, err
	}
	// revocationCaveat need to be prepended for extraction in ReadBlessAuditEntry.
	caveats = append([]security.Caveat{caveat}, caveats...)

	return caveats, nil
}

type caveatInfo struct {
	New         func(args ...string) (security.Caveat, error)
	Placeholder string
}

// caveatMap is a map from Caveat name to caveat information.
// To add to this map append
// key = "CaveatName"
// New = func that returns instantiation of specific caveat wrapped in security.Caveat.
// Placeholder = the placeholder text for the html input element.
var caveatMap = map[string]caveatInfo{
	"ExpiryCaveat": {
		New: func(args ...string) (security.Caveat, error) {
			if len(args) != 1 {
				return security.Caveat{}, fmt.Errorf("must pass exactly one duration string.")
			}
			dur, err := time.ParseDuration(args[0])
			if err != nil {
				return security.Caveat{}, fmt.Errorf("parse duration failed: %v", err)
			}
			return security.ExpiryCaveat(time.Now().Add(dur))
		},
		Placeholder: "i.e. 2h45m. Valid time units are ns, us (or µs), ms, s, m, h.",
	},
	"MethodCaveat": {
		New: func(args ...string) (security.Caveat, error) {
			if len(args) < 1 {
				return security.Caveat{}, fmt.Errorf("must pass at least one method")
			}
			return security.MethodCaveat(args[0], args[1:]...)
		},
		Placeholder: "Comma-separated method names.",
	},
	"PeerBlessingsCaveat": {
		New: func(args ...string) (security.Caveat, error) {
			if len(args) < 1 {
				return security.Caveat{}, fmt.Errorf("must pass at least one blessing pattern")
			}
			var patterns []security.BlessingPattern
			for _, arg := range args {
				patterns = append(patterns, security.BlessingPattern(arg))
			}
			return security.PeerBlessingsCaveat(patterns[0], patterns[1:]...)
		},
		Placeholder: "Comma-separated blessing patterns.",
	},
}

// exchangeAuthCodeForEmail exchanges the authorization code (which must
// have been obtained with scope=email) for an OAuth token and then uses Google's
// tokeninfo API to extract the email address from that token.
func exchangeAuthCodeForEmail(config *oauth.Config, authcode string) (string, error) {
	t, err := (&oauth.Transport{Config: config}).Exchange(authcode)
	if err != nil {
		return "", fmt.Errorf("failed to exchange authorization code for token: %v", err)
	}
	// Ideally, would validate the token ourselves without an HTTP roundtrip.
	// However, for now, as per:
	// https://developers.google.com/accounts/docs/OAuth2Login#validatinganidtoken
	// pay an HTTP round-trip to have Google do this.
	if t.Extra == nil || len(t.Extra["id_token"]) == 0 {
		return "", fmt.Errorf("no GoogleIDToken found in OAuth token")
	}
	tinfo, err := http.Get(verifyURL + "id_token=" + t.Extra["id_token"])
	if err != nil {
		return "", fmt.Errorf("failed to talk to GoogleIDToken verifier (%q): %v", verifyURL, err)
	}
	if tinfo.StatusCode != http.StatusOK {
		return "", fmt.Errorf("failed to verify GoogleIDToken: %s", tinfo.Status)
	}
	var gtoken token
	if err := json.NewDecoder(tinfo.Body).Decode(&gtoken); err != nil {
		return "", fmt.Errorf("invalid JSON response from Google's tokeninfo API: %v", err)
	}
	if !gtoken.VerifiedEmail {
		return "", fmt.Errorf("email not verified: %#v", gtoken)
	}
	if gtoken.Issuer != "accounts.google.com" {
		return "", fmt.Errorf("invalid issuer: %v", gtoken.Issuer)
	}
	if gtoken.Audience != config.ClientId {
		return "", fmt.Errorf("unexpected audience(%v) in GoogleIDToken", gtoken.Audience)
	}
	return gtoken.Email, nil
}

// IDToken JSON message returned by Google's verification endpoint.
//
// This differs from the description in:
// https://developers.google.com/accounts/docs/OAuth2Login#obtainuserinfo
// because the Google tokeninfo endpoint
// (https://www.googleapis.com/oauth2/v1/tokeninfo?id_token=XYZ123)
// mentioned in:
// https://developers.google.com/accounts/docs/OAuth2Login#validatinganidtoken
// seems to return the following JSON message.
type token struct {
	Issuer        string `json:"issuer"`
	IssuedTo      string `json:"issued_to"`
	Audience      string `json:"audience"`
	UserID        string `json:"user_id"`
	ExpiresIn     int64  `json:"expires_in"`
	IssuedAt      int64  `json:"issued_at"`
	Email         string `json:"email"`
	VerifiedEmail bool   `json:"verified_email"`
}
