Created
November 28, 2016 17:05
-
-
Save evanj/e415d808dbb6c2a0bd866cd9d17ef5aa to your computer and use it in GitHub Desktop.
Go Google Oauth2 example using the tokeninfo endpoint
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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