oauth - 如何使用 Google API 交换 OAUTH token ( Go )

标签 oauth go google-oauth

这是我到目前为止返回“400 错误”的结果。难道我做错了什么?我无法弄清楚为什么不起作用,因为请求非常简单

package main

import (
    "code.google.com/p/goauth2/oauth"
    "fmt"
    "log"
)

func main() {
    cachefile := "cache.json"
    code := "4/xxxxx.8uFT5Z0slpMbJvIeHux6iLY_9k7ajw" //the code received from the URL redirect
    // Set up a configuration.
    config := &oauth.Config{
        ClientId:     "xx.apps.googleusercontent.com",
        ClientSecret: "cWP3HudD3XmaP33j8",
        RedirectURL:  "https://crm.com/sender/gmail/auth/callBack",
        Scope:        "https://www.googleapis.com/auth/gmail.compose",
        AuthURL:      "https://accounts.google.com/o/oauth2/auth",
        TokenURL:     "https://accounts.google.com/o/oauth2/token",
        AccessType:   "offline",
        TokenCache:   oauth.CacheFile(cachefile),
    }

    // Set up a Transport using the config.
    transport := &oauth.Transport{Config: config}
    token, err := config.TokenCache.Token()
    if err != nil {
        token, err = transport.Exchange(code)
        if err != nil {
            log.Fatal("Exchange:", err)
        }
    }
    // (The Exchange method will automatically cache the token.)

    transport.Token = token
    fmt.Println(token)
}

结果

Exchange:OAuthError: updateToken: Unexpected HTTP status 400 Bad Request

最佳答案

我建议使用“一次性代码流”,如所述in the documentation :

To take advantage of all of the benefits of Google+ Sign-In you must use a hybrid server-side flow where a user authorizes your app on the client side using the JavaScript API client and you send a special one-time authorization code to your server. Your server exchanges this one-time-use code to acquire its own access and refresh tokens from Google for the server to be able to make its own API calls, which can be done while the user is offline. This one-time code flow has security advantages over both a pure server-side flow and over sending access tokens to your server.

由于代码只能使用一次,因此破坏用户帐户的可能性较小。

客户端代码非常简单,按照示例in step 3 .

对于服务器端,我建议使用包 oauth2而不是 goauth2

$ go get code.google.com/p/google-api-go-client/plus/v1
$ go get github.com/golang/oauth2
$ go get google.golang.org/appengine

出于某种原因,oauth2 包还需要 appengine 包。

可以使用函数 NewTransportWithCode 将一次性代码交换为可重复使用的 token 。 :

func exchangeCode(code string) (*oauth2.Token, *oauth2.Transport, error) {
    config, err := google.NewConfig(&oauth2.Options{
        ClientID:     CLIENT_ID,
        ClientSecret: CLIENT_SECRET,
        RedirectURL:  "postmessage",
        Scopes:       []string{"https://www.googleapis.com/auth/plus.login"},
    })
    if err != nil {
        return &oauth2.Token{}, &oauth2.Transport{}, err
    }

    transport, err := config.NewTransportWithCode(code)
    if err != nil {
        return &oauth2.Token{}, &oauth2.Transport{}, err
    }

    token := transport.Token()
    return token, transport, nil
}

最后,您在第 3 步中创建的代码可以将一次代码提交给监听在 /oauth2 的处理程序:

func oauth2Handler(w http.ResponseWriter, r *http.Request) {
    // TODO Check request has...
    // - Method: POST
    // - Content-Type: application/octet-stream; charset=utf-8
    // - CSRF Token http://goo.gl/mNCjJm

    body, err := ioutil.ReadAll(r.Body)
    defer r.Body.Close()
    if err != nil {
        http.Error(w, err.Error(), http.StatusInternalServerError)
        return
    }

    code := string(body[:])
    token, transport, err := exchangeCode(code)
    if err != nil {
        http.Error(w, err.Error(), http.StatusInternalServerError)
        return
    }

    // From here you can use the transport
    client := http.Client{Transport: transport}
    service, err := plus.New(&client)
    if err != nil {
        return nil, err
    }

    // https://www.googleapis.com/plus/v1/people/me
    person, err := service.People.Get("me").Do()
    // ...
}

func main() {
    http.HandleFunc("/oauth2", oauth2Handler)
    log.Fatal(http.ListenAndServe(":8000", nil))
}

缺少一些错误处理,但您明白了。

关于oauth - 如何使用 Google API 交换 OAUTH token ( Go ),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25379038/

相关文章:

go - 使用 go get 获取第三方许可证

google-app-engine - 在使用 Go 的 App Engine 上,使用 OAuth2 的正确方法

android - Google Drive API 的 Google OAuth 2.0 和调试 key

oauth-2.0 - Google API刷新 token 限制

post - Twitter-获取请求 token 响应 401 - POST

php - One Drive API - 获取访问 token 时出错

golang 异步缓冲 channel 挂起

Go函数参数

laravel - 在没有 session 的情况下使用 Laravel Socialite 和 jwt-auth

ios - 混合移动应用程序中的 Salesforce Connected App OAuth 流程