我正在try 用golang.org/x/oauth2包编写一个简单的程序.但我似乎无法用代码交换访问令牌.下面的错误有点误导,因为它说已经使用了授权代码,但我每次调用登录对话框时都会看到一个新代码.我是刚来golang的新手,可能犯了一个基本的错误,任何提示都会非常有用:)

    clientOptions, err = oauth2.New(
        oauth2.Client("xxxxxx", "22222222222222"),
        oauth2.RedirectURL("http://localhost:3000/auth/cb/fb2"),
        oauth2.Scope("public_profile", "email", "user_friends"),
        oauth2.Endpoint(
            "https://www.facebook.com/dialog/oauth",
            "https://graph.facebook.com/oauth/access_token",
        ),
    )

func handleFBSetupOauth(w http.ResponseWriter, r *http.Request) {
    url := clientOptions.AuthCodeURL("state", "online", "auto")
    fmt.Printf("Visit the URL for the auth dialog: %v", url)

    http.Redirect(w, r, url, http.StatusFound)
}

func handleFBOauthCB(w http.ResponseWriter, r *http.Request) (int, string) {
    var err error

    code := r.FormValue("code")
    if code == "" {
        return 500, "No code!"
    }

    fmt.Printf("code - %s", code)

    t, err := clientOptions.NewTransportFromCode(code)
    if err != nil {
        log.Fatal(err)
    }

    client := http.Client{Transport: t}

    url := "https://graph.facebook.com/oauth/access_token?client_id=xxxxxxx&redirect_uri=http://localhost:3000/auth/cb/fb2&client_secret=22222222&code=" + code + ""

    resp, err := client.Get(url)

我从上一个GET请求中收到以下错误-

{"错误":{"消息":"此授权码已被使用.","类型":"OAutheException","代码":100}

我跟着这两位导游走- Facebook登录流程- https://developers.facebook.com/docs/facebook-login/manually-build-a-login-flow/v2.2

最新goauth文件-

推荐答案

下面是一个简单的例子,让你开始:

package main

import (
  "fmt"
  "io/ioutil"
  "log"
  "net/http"
  "net/url"
  "strings"

  "golang.org/x/oauth2"
  "golang.org/x/oauth2/facebook"
)

var (
  oauthConf = &oauth2.Config{
    ClientID:     "YOUR_CLIENT_ID",
    ClientSecret: "YOUR_CLIENT_SECRET",
    RedirectURL:  "YOUR_REDIRECT_URL_CALLBACK",
    Scopes:       []string{"public_profile"},
    Endpoint:     facebook.Endpoint,
  }
  oauthStateString = "thisshouldberandom"
)

const htmlIndex = `<html><body>
Logged in with <a href="/login">facebook</a>
</body></html>
`

func handleMain(w http.ResponseWriter, r *http.Request) {
  w.Header().Set("Content-Type", "text/html; charset=utf-8")
  w.WriteHeader(http.StatusOK)
  w.Write([]byte(htmlIndex))
}

func handleFacebookLogin(w http.ResponseWriter, r *http.Request) {
  Url, err := url.Parse(oauthConf.Endpoint.AuthURL)
  if err != nil {
    log.Fatal("Parse: ", err)
  }
  parameters := url.Values{}
  parameters.Add("client_id", oauthConf.ClientID)
  parameters.Add("scope", strings.Join(oauthConf.Scopes, " "))
  parameters.Add("redirect_uri", oauthConf.RedirectURL)
  parameters.Add("response_type", "code")
  parameters.Add("state", oauthStateString)
  Url.RawQuery = parameters.Encode()
  url := Url.String()
  http.Redirect(w, r, url, http.StatusTemporaryRedirect)
}

func handleFacebookCallback(w http.ResponseWriter, r *http.Request) {
  state := r.FormValue("state")
  if state != oauthStateString {
    fmt.Printf("invalid oauth state, expected '%s', got '%s'\n", oauthStateString, state)
    http.Redirect(w, r, "/", http.StatusTemporaryRedirect)
    return
  }

  code := r.FormValue("code")

  token, err := oauthConf.Exchange(oauth2.NoContext, code)
  if err != nil {
    fmt.Printf("oauthConf.Exchange() failed with '%s'\n", err)
    http.Redirect(w, r, "/", http.StatusTemporaryRedirect)
    return
  }

  resp, err := http.Get("https://graph.facebook.com/me?access_token=" +
    url.QueryEscape(token.AccessToken))
  if err != nil {
    fmt.Printf("Get: %s\n", err)
    http.Redirect(w, r, "/", http.StatusTemporaryRedirect)
    return
  }
  defer resp.Body.Close()

  response, err := ioutil.ReadAll(resp.Body)
  if err != nil {
    fmt.Printf("ReadAll: %s\n", err)
    http.Redirect(w, r, "/", http.StatusTemporaryRedirect)
    return
  }

  log.Printf("parseResponseBody: %s\n", string(response))

  http.Redirect(w, r, "/", http.StatusTemporaryRedirect)
}

func main() {
  http.HandleFunc("/", handleMain)
  http.HandleFunc("/login", handleFacebookLogin)
  http.HandleFunc("/oauth2callback", handleFacebookCallback)
  fmt.Print("Started running on http://localhost:9090\n")
  log.Fatal(http.ListenAndServe(":9090", nil))
}

Go相关问答推荐

try 用GitHub操作中的release标签更新version. go文件,但失败了

即使HTTP服务器正在使用GO和Protobuf、SQL Server启动,请求也不返回结果

使用Go使用Gorm使用外键对数据进行排序

确定果朗CSV行中的字节数

Go 中带有回调的 MiniDumpWriteDump

如何获取集群外go Kubernetes客户端的当前命名空间?

Json.Unmarshal() 和 gin.BindJson() 之间的区别

将文本文件放入切片然后进行比较

自定义 Fyne 自适应网格布局

Gremlin-Go:树步骤不可序列化

如何判断范围内的字段?

没有任务角色的 AWS CDK ECS 任务定义

具有未导出字段的 struct 类型之间的转换

无法建立连接,因为目标机器主动拒绝它 Golang

没有堆栈跟踪的 go 程序崩溃是什么意思?

如何在 docker 文件中安装 golang 包?

GOLANG 如何使用 http.FileServer 从模板目录加载某个 html 文件

如何使用 context.WithCancel 启动和停止每个会话的心跳?

Go 错误:Is() 和 As() 声称是递归的,是否有任何类型实现错误接口并支持这种递归 - 无错误?

Golang 与 Cassandra db 使用 docker-compose:cannot connect (gocql)