// Copyright 2015 The Vanadium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package oauth

import (
	"encoding/json"
	"fmt"
	"golang.org/x/oauth2"
	"net/http"
	"os"

	"v.io/x/lib/vlog"
)

// googleOAuth implements the OAuthProvider interface with google oauth 2.0.
type googleOAuth struct {
	// client_id and client_secret registered with the Google Developer
	// Console for API access.
	clientID, clientSecret   string
	scope, authURL, tokenURL string
	// URL used to verify google tokens.
	// (From https://developers.google.com/accounts/docs/OAuth2Login#validatinganidtoken
	// and https://developers.google.com/accounts/docs/OAuth2UserAgent#validatetoken)
	verifyURL string
}

func NewGoogleOAuth(configFile string) (OAuthProvider, error) {
	clientID, clientSecret, err := getOAuthClientIDAndSecret(configFile)
	if err != nil {
		return nil, err
	}
	return &googleOAuth{
		clientID:     clientID,
		clientSecret: clientSecret,
		scope:        "email",
		authURL:      "https://accounts.google.com/o/oauth2/auth",
		tokenURL:     "https://accounts.google.com/o/oauth2/token",
		verifyURL:    "https://www.googleapis.com/oauth2/v1/tokeninfo?",
	}, nil
}

func (g *googleOAuth) AuthURL(redirectUrl, state string) string {
	return g.oauthConfig(redirectUrl).AuthCodeURL(state)
}

// 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 (g *googleOAuth) ExchangeAuthCodeForEmail(authcode string, url string) (string, error) {
	config := g.oauthConfig(url)
	t, err := config.Exchange(oauth2.NoContext, authcode)
	if err != nil {
		return "", fmt.Errorf("failed to exchange authorization code for token: %v", err)
	}

	if !t.Valid() {
		return "", fmt.Errorf("oauth2 token invalid")
	}
	// 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.
	idToken, ok := t.Extra("id_token").(string)
	if !ok {
		return "", fmt.Errorf("no GoogleIDToken found in OAuth token")
	}
	// 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
	tinfo, err := http.Get(g.verifyURL + "id_token=" + idToken)
	if err != nil {
		return "", fmt.Errorf("failed to talk to GoogleIDToken verifier (%q): %v", g.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)
	}
	// We check both "verified_email" and "email_verified" here because the token response sometimes
	// contains one and sometimes contains the other.
	if !gtoken.VerifiedEmail && !gtoken.EmailVerified {
		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
}

// GetEmailAndClientName uses Google's tokeninfo API to verify that the token has been issued
// for one of the provided 'accessTokenClients' and if so returns the email and client name
// from the tokeninfo obtained.
func (g *googleOAuth) GetEmailAndClientName(accessToken string, accessTokenClients []AccessTokenClient) (string, string, error) {
	if len(accessTokenClients) == 0 {
		return "", "", fmt.Errorf("no expected AccessTokenClients specified")
	}
	// As per https://developers.google.com/accounts/docs/OAuth2UserAgent#validatetoken
	// we obtain the 'info' for the token via an HTTP roundtrip to Google.
	tokeninfo, err := http.Get(g.verifyURL + "access_token=" + accessToken)
	if err != nil {
		return "", "", fmt.Errorf("unable to use token: %v", err)
	}
	if tokeninfo.StatusCode != http.StatusOK {
		return "", "", fmt.Errorf("unable to verify access token, OAuth2 TokenInfo endpoint responded with StatusCode: %v", tokeninfo.StatusCode)
	}
	// tokeninfo contains a JSON-encoded struct
	var token struct {
		IssuedTo      string `json:"issued_to"`
		Audience      string `json:"audience"`
		UserID        string `json:"user_id"`
		Scope         string `json:"scope"`
		ExpiresIn     int64  `json:"expires_in"`
		Email         string `json:"email"`
		VerifiedEmail bool   `json:"verified_email"`
		EmailVerified bool   `json:"email_verified"`
		AccessType    string `json:"access_type"`
	}
	if err := json.NewDecoder(tokeninfo.Body).Decode(&token); err != nil {
		return "", "", fmt.Errorf("invalid JSON response from Google's tokeninfo API: %v", err)
	}
	var client AccessTokenClient
	audienceMatch := false
	for _, c := range accessTokenClients {
		if token.Audience == c.ClientID {
			client = c
			audienceMatch = true
			break
		}
	}
	if !audienceMatch {
		vlog.Infof("Got access token [%+v], wanted one of client ids %v", token, accessTokenClients)
		return "", "", fmt.Errorf("token not meant for this purpose, confused deputy? https://developers.google.com/accounts/docs/OAuth2UserAgent#validatetoken")
	}
	// We check both "verified_email" and "email_verified" here because the token response sometimes
	// contains one and sometimes contains the other.
	if !token.VerifiedEmail && !token.EmailVerified {
		return "", "", fmt.Errorf("email not verified")
	}
	return token.Email, client.Name, nil
}

func (g *googleOAuth) oauthConfig(redirectUrl string) *oauth2.Config {
	return &oauth2.Config{
		ClientID:     g.clientID,
		ClientSecret: g.clientSecret,
		RedirectURL:  redirectUrl,
		Scopes:       []string{g.scope},
		Endpoint: oauth2.Endpoint{
			AuthURL:  g.authURL,
			TokenURL: g.tokenURL,
		},
	}
}

func getOAuthClientIDAndSecret(configFile string) (clientID, clientSecret string, err error) {
	f, err := os.Open(configFile)
	if err != nil {
		return "", "", fmt.Errorf("failed to open %q: %v", configFile, err)
	}
	defer f.Close()
	clientID, clientSecret, err = ClientIDAndSecretFromJSON(f)
	if err != nil {
		return "", "", fmt.Errorf("failed to decode JSON in %q: %v", configFile, err)
	}
	return clientID, clientSecret, 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"`
	EmailVerified bool   `json:"email_verified"`
}
