在使用Go的App Engine上,正确使用OAuth2的方法

时间:2015-06-12 11:21:53

标签: google-app-engine go oauth-2.0 google-oauth

过去几天我一直在努力解决这个问题,并且在没有喜悦的情况下跟踪了许多示例和文档,我希望得到一些帮助。

以下内容提供了Google授权页面,但随后返回handleOAuth2Callback页面失败,并显示以下错误:

  

错误:发布https://accounts.google.com/o/oauth2/token:不是应用   引擎上下文

我做错了什么?

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)
}

1 个答案:

答案 0 :(得分:1)

我当前的解决方案,包括记录登录用户的显示名称和Google云端硬盘中的所有文件 - 如果您发现任何错误或改进,请发表评论:

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)
    }
}