如何使用GoogleAPI交换OAUTH令牌(Go)
这里是我到目前为止得到的返回“400错误”的结果。我做错什么了吗?我不明白为什么不工作,因为请求非常简单如何使用GoogleAPI交换OAUTH令牌(Go),oauth,go,google-oauth,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 recei
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
我建议使用“一次性代码流”,如下所述: 要利用Google+登录的所有好处,您必须使用混合服务器端流程,其中用户使用JavaScript API客户端在客户端授权您的应用程序,您向服务器发送一个特殊的一次性授权代码。您的服务器交换此一次性使用代码,以从Google获取自己的访问权限并刷新令牌,以便服务器能够进行自己的API调用,这可以在用户脱机时完成。与纯服务器端流和向服务器发送访问令牌相比,此一次性代码流具有安全优势 因为代码只需使用一次,就不太可能破坏用户帐户 客户端代码非常简单,请遵循下面的示例 对于服务器端,我建议使用包而不是
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
包
可以使用以下函数将一次性代码交换为可重用令牌:
最后,您在步骤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))
}
缺少一些错误处理,但您知道了。您的程序中有一个硬编码的访问代码。这些是一次性使用的,那么您是否已经使用过代币?您是对的。。。我以为“代码”实际上是刷新令牌。对。代码是在用户对服务进行身份验证时通过用户的web浏览器传递到重定向URL的代码。您使用该一次性代码创建多用途访问令牌。google.NewConfig中的重定向URL值是多少???答案来自2014年。。。我建议您检查文档,它可能已经更改了好几次
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))
}