Skip to content

Instantly share code, notes, and snippets.

@neverlock
Forked from evanj/google_oauth.go
Created April 18, 2020 16:26
Show Gist options
  • Save neverlock/c8bc04c172007c69d6c4504f894475d3 to your computer and use it in GitHub Desktop.
Save neverlock/c8bc04c172007c69d6c4504f894475d3 to your computer and use it in GitHub Desktop.

Revisions

  1. Evan Jones created this gist Nov 28, 2016.
    104 changes: 104 additions & 0 deletions google_oauth.go
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,104 @@
    package main

    import (
    "fmt"
    "io/ioutil"
    "log"
    "net/http"
    "os"

    "golang.org/x/oauth2"
    "golang.org/x/oauth2/google"

    "google.golang.org/appengine"
    )

    // TODO: This must be randomized per request
    const todoBadStateImplementation = "9bd752171ba8fd0590fe5c26c5f03c23"

    var oauthConfig = oauth2.Config{
    ClientID: "TODO",
    ClientSecret: "TODO",
    Endpoint: google.Endpoint,
    Scopes: []string{"email"},
    RedirectURL: "http://localhost:8080/oauth_callback",
    }

    func init() {
    http.HandleFunc("/", handler)
    http.HandleFunc("/start", startOauth)
    http.HandleFunc("/oauth_callback", oauthCallback)
    }

    func handler(w http.ResponseWriter, r *http.Request) {
    w.Header().Set("Content-Type", "text/plain;charset=utf-8")

    ctx := appengine.NewContext(r)
    fmt.Fprintln(w, "REQUEST ID:", appengine.RequestID(ctx))
    fmt.Fprintln(w)

    fmt.Fprintln(w, "HEADERS:")
    for k, values := range r.Header {
    fmt.Fprintln(w, k, ":")
    for _, s := range values {
    fmt.Fprintln(w, " ", s)
    }
    }
    fmt.Fprintln(w)

    fmt.Fprintln(w, "ENVIRONMENT:")
    for _, s := range os.Environ() {
    fmt.Fprintln(w, s)
    }
    }

    func startOauth(w http.ResponseWriter, r *http.Request) {
    url := oauthConfig.AuthCodeURL(todoBadStateImplementation)
    log.Println("startOauth: redirecting to", url)
    http.Redirect(w, r, url, http.StatusFound)
    }

    func oauthCallback(w http.ResponseWriter, r *http.Request) {
    errorString := r.FormValue("error")
    if errorString != "" {
    panic(errorString)
    }

    stateString := r.FormValue("state")
    if stateString != todoBadStateImplementation {
    panic("state does not match")
    }

    // things look like they might be valid! Let's get the token
    code := r.FormValue("code")
    ctx := appengine.NewContext(r)
    token, err := oauthConfig.Exchange(ctx, code)
    if err != nil {
    panic(err)
    }

    // it worked! get the tokeninfo
    log.Printf("access_token: %s refresh_token: %s", token.AccessToken, token.RefreshToken)
    tokeninfoUrl := "https://www.googleapis.com/oauth2/v3/tokeninfo?access_token=" + token.AccessToken
    log.Println("URL: ", tokeninfoUrl)
    resp, err := http.Get(tokeninfoUrl)
    if err != nil {
    panic(err)
    }
    data, err := ioutil.ReadAll(resp.Body)
    err2 := resp.Body.Close()
    if err != nil {
    panic(err)
    }
    if err2 != nil {
    panic(err2)
    }

    w.Header().Set("Content-Type", "text/plain;charset=utf-8")
    fmt.Fprintln(w, "Tokeninfo:")
    w.Write(data)
    }

    func main() {
    appengine.Main()
    }