drw85135 2015-06-12 11:21
浏览 52

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

I have been trying for the last few days to solve this, and having followed many of the examples and documentation out there without joy, I would like some assistance.

The following gives the Google authorization page, but then fails on returning to the handleOAuth2Callback page with the following error:

ERROR: Post https://accounts.google.com/o/oauth2/token: not an App Engine context

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)
}
  • 写回答

1条回答 默认 最新

  • douche1936 2015-06-18 13:59
    关注

    My current solution, including logging the logged in users display name and all the files in their Google Drive - please comment if you see any errors 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)
        }
    }
    
    评论

报告相同问题?

悬赏问题

  • ¥15 mmocr的训练错误,结果全为0
  • ¥15 python的qt5界面
  • ¥15 无线电能传输系统MATLAB仿真问题
  • ¥50 如何用脚本实现输入法的热键设置
  • ¥20 我想使用一些网络协议或者部分协议也行,主要想实现类似于traceroute的一定步长内的路由拓扑功能
  • ¥30 深度学习,前后端连接
  • ¥15 孟德尔随机化结果不一致
  • ¥15 apm2.8飞控罗盘bad health,加速度计校准失败
  • ¥15 求解O-S方程的特征值问题给出边界层布拉休斯平行流的中性曲线
  • ¥15 谁有desed数据集呀