Created
November 1, 2014 07:46
-
-
Save 9nut/1f883d857369a279f289 to your computer and use it in GitHub Desktop.
Sample Go Web Server that handles OAuth2 authentication through Google.
This file contains 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 ( | |
"code.google.com/p/goauth2/oauth" | |
"crypto/tls" | |
"encoding/json" | |
"flag" | |
"io/ioutil" | |
"log" | |
"net/http" | |
"strings" | |
"text/template" | |
) | |
var notAuthenticatedTemplate = template.Must(template.New("").Parse(` | |
<html><body> | |
Please authenticate this app with the Google OAuth provider. | |
<form action="/authorize" method="POST"><input type="submit" value="Ok, authorize this app with my id"/></form> | |
</body></html> | |
`)) | |
var userInfoTemplate = template.Must(template.New("").Parse(` | |
<html><body> | |
This app is now authenticated to access your Google user info. Your details are:<br /> | |
{{.}} | |
</body></html> | |
`)) | |
// variables used during oauth protocol flow of authentication | |
var ( | |
code = "" | |
token = "" | |
) | |
type KeyEnv struct { | |
AKey AppKey `json:"web"` | |
} | |
type AppKey struct { | |
ClientId string `json:"client_id"` | |
ClientSecret string `json:"client_secret"` | |
ClientEmail string `json:"client_email"` | |
AuthURL string `json:"auth_uri"` | |
TokenURL string `json:"token_uri"` | |
RedirectURLs []string `json:"redirect_uris"` | |
ProviderX509 string `json:"auth_provider_x509_cert_url"` | |
JSOrigins []string `json:"javascript_origins"` | |
} | |
var oauthCfg *oauth.Config | |
var ( | |
hostport = flag.String("http", ":443", "host:port") | |
clisec = flag.String("secret", "client_secrets.json", "client secrets JSON file") | |
) | |
//This is the URL that Google has defined so that an authenticated application may obtain the user's info in json format | |
const profileInfoURL = "https://www.googleapis.com/oauth2/v2/userinfo" | |
func main() { | |
var k KeyEnv | |
flag.Parse() | |
appkey, err := ioutil.ReadFile(*clisec) | |
if err != nil { | |
log.Fatal(err) | |
} | |
dec := json.NewDecoder(strings.NewReader(string(appkey))) | |
if err = dec.Decode(&k); err != nil { | |
log.Fatal(err) | |
} | |
oauthCfg = &oauth.Config{ | |
ClientId: k.AKey.ClientId, | |
ClientSecret: k.AKey.ClientSecret, | |
AuthURL: k.AKey.AuthURL, | |
TokenURL: k.AKey.TokenURL, | |
RedirectURL: k.AKey.RedirectURLs[0], | |
Scope: "https://www.googleapis.com/auth/userinfo.email", | |
} | |
http.HandleFunc("/", handleRoot) | |
http.HandleFunc("/authorize", handleAuthorize) | |
//Google will redirect to this page to return your code, so handle it appropriately | |
http.HandleFunc("/oauth2callback", handleOAuth2Callback) | |
log.Println("Listen On: " + *hostport) | |
http.ListenAndServeTLS(*hostport, "cert.pem", "key.pem", nil) | |
} | |
func handleRoot(w http.ResponseWriter, r *http.Request) { | |
notAuthenticatedTemplate.Execute(w, nil) | |
} | |
// Start the authorization process | |
func handleAuthorize(w http.ResponseWriter, r *http.Request) { | |
//Get the Google URL which shows the Authentication page to the user | |
url := oauthCfg.AuthCodeURL("") | |
//redirect user to that page | |
http.Redirect(w, r, url, http.StatusFound) | |
} | |
// Function that handles the callback from the Google server | |
func handleOAuth2Callback(w http.ResponseWriter, r *http.Request) { | |
//Get the code from the response | |
code := r.FormValue("code") | |
t := &oauth.Transport{Config: oauthCfg} | |
// Exchange the received code for a token | |
tok, err := t.Exchange(code) | |
if err != nil { | |
log.Printf("Error exchanging token: %v", err) | |
http.Redirect(w, r, "/", http.StatusFound) | |
return | |
} | |
tokenCache := oauth.CacheFile("./request.token") | |
err = tokenCache.PutToken(tok) | |
if err != nil { | |
log.Fatal("Cache write:", err) | |
} | |
log.Printf("Token is cached in %v\n", tokenCache) | |
// Skip TLS Verify | |
t.Transport = &http.Transport{ | |
TLSClientConfig: &tls.Config{InsecureSkipVerify: true}, | |
} | |
// Make the request. | |
req, err := t.Client().Get(profileInfoURL) | |
if err != nil { | |
log.Fatal("Request Error:", err) | |
} | |
defer req.Body.Close() | |
body, err := ioutil.ReadAll(req.Body) | |
if err != nil { | |
log.Fatal(err) | |
} | |
log.Println(string(body)) | |
userInfoTemplate.Execute(w, string(body)) | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment