On App Engine using Go, the correct method is to use OAuth2
I have been trying for the last few days to resolve this issue, and without paying attention to many examples and documentation, I would love to help.
Below is the google authorization page but then fails to return to the handleOAuth2Callback page with the following error:
ERROR: Post https://accounts.google.com/o/oauth2/token : Not app Context engine
What am I doing wrong?
import (
"google.golang.org/appengine"
"google.golang.org/appengine/log"
"google.golang.org/cloud"
"golang.org/x/oauth2"
"golang.org/x/oauth2/google"
// "google.golang.org/api/drive/v2"
"html/template"
"net/http"
)
var cached_templates = template.Must(template.ParseGlob("templates/*.html"))
var conf = &oauth2.Config{
ClientID: "my client id",
ClientSecret: "my client secret",
RedirectURL: "http://localhost:10080/oauth2callback",
Scopes: []string{
"https://www.googleapis.com/auth/drive",
"https://www.googleapis.com/auth/userinfo.profile",
},
Endpoint: google.Endpoint,
}
func init() {
http.HandleFunc("/", handleRoot)
http.HandleFunc("/authorize", handleAuthorize)
http.HandleFunc("/oauth2callback", handleOAuth2Callback)
}
func handleRoot(w http.ResponseWriter, r *http.Request) {
err := cached_templates.ExecuteTemplate(w, "notAuthenticated.html", nil)
if err != nil {
http.Error(w, err.Error(), http.StatusNotFound)
}
}
func handleAuthorize(w http.ResponseWriter, r *http.Request) {
c := appengine.NewContext(r)
url := conf.AuthCodeURL("")
http.Redirect(w, r, url, http.StatusFound)
}
func handleOAuth2Callback(w http.ResponseWriter, r *http.Request) {
c := appengine.NewContext(r)
hc := &http.Client{}
ctx := cloud.NewContext(appengine.AppID(c), hc)
log.Infof(c, "Ctx: %v", ctx)
code := r.FormValue("code")
log.Infof(c, "Code: %v", code)
// Exchange the received code for a token
tok, err := conf.Exchange(ctx, code)
// tok, err := conf.Exchange(oauth2.NoContext, code)
if err != nil {
log.Errorf(c, "%v", err)
}
log.Infof(c, "Token: %v", tok)
client := conf.Client(oauth2.NoContext, tok)
log.Infof(c, "Client: %v", client)
}
+3
source to share
1 answer
My current solution, including logging the display names of users and all files in their Google Drive - please comment if you see any bugs or improvements:
import (
"golang.org/x/oauth2"
"golang.org/x/oauth2/google"
"google.golang.org/api/drive/v2"
"google.golang.org/api/plus/v1"
"google.golang.org/appengine"
"google.golang.org/appengine/log"
"html/template"
"net/http"
)
var cached_templates = template.Must(template.ParseGlob("templates/*.html"))
var conf = &oauth2.Config{
ClientID: "my client id", // Replace with correct ClientID
ClientSecret: "my client secret", // Replace with correct ClientSecret
RedirectURL: "http://localhost:10080/oauth2callback",
Scopes: []string{
"https://www.googleapis.com/auth/drive",
"profile",
},
Endpoint: google.Endpoint,
}
func init() {
http.HandleFunc("/", handleRoot)
http.HandleFunc("/authorize", handleAuthorize)
http.HandleFunc("/oauth2callback", handleOAuth2Callback)
}
func handleRoot(w http.ResponseWriter, r *http.Request) {
err := cached_templates.ExecuteTemplate(w, "notAuthenticated.html", nil)
if err != nil {
http.Error(w, err.Error(), http.StatusNotFound)
}
}
func handleAuthorize(w http.ResponseWriter, r *http.Request) {
c := appengine.NewContext(r)
url := conf.AuthCodeURL("")
http.Redirect(w, r, url, http.StatusFound)
}
func handleOAuth2Callback(w http.ResponseWriter, r *http.Request) {
c := appengine.NewContext(r)
code := r.FormValue("code")
tok, err := conf.Exchange(c, code)
if err != nil {
log.Errorf(c, "%v", err)
}
client := conf.Client(c, tok)
// PLUS SERVICE CLIENT
pc, err := plus.New(client)
if err != nil {
log.Errorf(c, "An error occurred creating Plus client: %v", err)
}
person, err := pc.People.Get("me").Do()
if err != nil {
log.Errorf(c, "Person Error: %v", err)
}
log.Infof(c, "Name: %v", person.DisplayName)
// DRIVE CLIENT
dc, err := drive.New(client)
if err != nil {
log.Errorf(c, "An error occurred creating Drive client: %v", err)
}
files, err := dc.Files.List().Do()
for _, value := range files.Items {
log.Infof(c, "Files: %v", value.Title)
}
}
+1
source to share