Go Oauth 認證

先設定API

Google api setup

server.go

package main

import (
   "fmt"
   "io/ioutil"
   "net/http"
   "golang.org/x/oauth2"
   "golang.org/x/oauth2/google"
)

var (
   googleOauthConfig *oauth2.Config
   // TODO: randomize it
   oauthStateString = "pseudo-random"
)

func init() {
   googleOauthConfig = &oauth2.Config{
      RedirectURL:  "http://localhost:10080/oauth/callback",
      // ClientID:     os.Getenv("GOOGLE_CLIENT_ID"),
      // ClientSecret: os.Getenv("GOOGLE_CLIENT_SECRET"),
      ClientID:     "9999xxxx852494768188-fj7mdktcfbd9r7oq1neeb3tk9o6tg0sm.apps.googleusercontent.com",
      ClientSecret: "gFmZsNbf7vm1aJE9BBu5s4Tf9999x",
      Scopes:       []string{"https://www.googleapis.com/auth/userinfo.email"},
      Endpoint:     google.Endpoint,
   }
}

func main() {
   http.HandleFunc("/", handleMain)
   http.HandleFunc("/login", handleGoogleLogin)
   http.HandleFunc("/callback", handleGoogleCallback)
   fmt.Println(http.ListenAndServe(":3090", nil))
}

func handleMain(w http.ResponseWriter, r *http.Request) {
   var htmlIndex = `<html>
<body>
   <a href="/oauth/login">Google Log In</a>
</body>
</html>`

   fmt.Fprintf(w, htmlIndex)
}

func handleGoogleLogin(w http.ResponseWriter, r *http.Request) {
   url := googleOauthConfig.AuthCodeURL(oauthStateString)
   http.Redirect(w, r, url, http.StatusTemporaryRedirect)
}

func handleGoogleCallback(w http.ResponseWriter, r *http.Request) {
   content, err := getUserInfo(r.FormValue("state"), r.FormValue("code"))
   if err != nil {
      fmt.Println(err.Error())
      http.Redirect(w, r, "/", http.StatusTemporaryRedirect)
      return
   }

   fmt.Fprintf(w, "Content: %s\n", content)
}

func getUserInfo(state string, code string) ([]byte, error) {
   if state != oauthStateString {
      return nil, fmt.Errorf("invalid oauth state")
   }

   token, err := googleOauthConfig.Exchange(oauth2.NoContext, code)
   if err != nil {
      return nil, fmt.Errorf("code exchange failed: %s", err.Error())
   }

   response, err := http.Get("https://www.googleapis.com/oauth2/v2/userinfo?access_token=" + token.AccessToken)
   if err != nil {
      return nil, fmt.Errorf("failed getting user info: %s", err.Error())
   }

   defer response.Body.Close()
   contents, err := ioutil.ReadAll(response.Body)
   if err != nil {
      return nil, fmt.Errorf("failed reading response body: %s", err.Error())
   }

   return contents, nil