Skip to content

Instantly share code, notes, and snippets.

@evanj
Created November 28, 2016 17:05
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save evanj/e415d808dbb6c2a0bd866cd9d17ef5aa to your computer and use it in GitHub Desktop.
Save evanj/e415d808dbb6c2a0bd866cd9d17ef5aa to your computer and use it in GitHub Desktop.
Go Google Oauth2 example using the tokeninfo endpoint
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()
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment