Facebook graph api 使用golang.org/x/oauth2进行golang Facebook身份验证

Facebook graph api 使用golang.org/x/oauth2进行golang Facebook身份验证,facebook-graph-api,go,oauth-2.0,Facebook Graph Api,Go,Oauth 2.0,我正在尝试使用golang.org/x/oauth2包编写一个简单的程序。但我似乎无法用代码交换访问令牌。下面的错误有点误导,因为它说已经使用了授权代码,但我每次调用登录对话框时都会看到一个新代码。我是刚来golang的新手,可能犯了一个基本的错误,任何提示都会非常有用:) 我从上一个get请求中得到以下错误- {“错误”:{“消息”:“此授权代码已被使用。”,“类型”:“OAutheException”,“代码”:100} 我遵循以下两条指南: Facebook登录流- 最新goauth文件

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

我从上一个get请求中得到以下错误-

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

我遵循以下两条指南: Facebook登录流-

最新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))
}
主程序包
进口(
“fmt”
“io/ioutil”
“日志”
“net/http”
“网络/网址”
“字符串”
“golang.org/x/oauth2”
“golang.org/x/oauth2/facebook”
)
变量(
oauthConf=&oauth2.Config{
客户ID:“您的客户ID”,
ClientSecret:“你的客户的秘密”,
重定向URL:“您的\u重定向\u URL\u回调”,
作用域:[]字符串{“public_profile”},
端点:facebook.Endpoint,
}
oauthStateString=“thisshouldberandom”
)
常量htmlIndex=`
使用登录
`
func handleMain(w http.ResponseWriter,r*http.Request){
w、 Header().Set(“内容类型”,“文本/html;字符集=utf-8”)
w、 WriteHeader(http.StatusOK)
w、 写入([]字节(htmlIndex))
}
func handleFacebookLogin(w http.ResponseWriter,r*http.Request){
Url,err:=Url.Parse(oauthConf.Endpoint.AuthURL)
如果错误!=零{
致命(“解析:,错误)
}
参数:=url.Values{}
parameters.Add(“client_id”,oauthConf.ClientID)
parameters.Add(“scope”,strings.Join(oauthConf.Scopes,”))
parameters.Add(“redirect_uri”,oauthConf.RedirectURL)
参数。添加(“响应类型”、“代码”)
parameters.Add(“state”,oauthStateString)
Url.RawQuery=parameters.Encode()
url:=url.String()
重定向(w,r,url,http.StatusTemporaryRedirect)
}
func handleFacebookCallback(w http.ResponseWriter,r*http.Request){
状态:=r.FormValue(“状态”)
if state!=oauthStateString{
fmt.Printf(“无效的oauth状态,应为“%s”,得到“%s”\n”,oauthStateString,状态)
重定向(w,r,“/”,http.StatusTemporaryRedirect)
返回
}
代码:=r.FormValue(“代码”)
令牌,err:=oauthConf.Exchange(oauth2.NoContext,代码)
如果错误!=零{
fmt.Printf(“oauthConf.Exchange()失败,错误为“%s”\n”)
重定向(w,r,“/”,http.StatusTemporaryRedirect)
返回
}
resp,err:=http.Get(“https://graph.facebook.com/me?access_token=" +
queryscape(token.AccessToken))
如果错误!=零{
fmt.Printf(“获取:%s\n”,错误)
重定向(w,r,“/”,http.StatusTemporaryRedirect)
返回
}
延迟响应主体关闭()
响应,err:=ioutil.ReadAll(resp.Body)
如果错误!=零{
fmt.Printf(“ReadAll:%s\n”,错误)
重定向(w,r,“/”,http.StatusTemporaryRedirect)
返回
}
log.Printf(“parseResponseBody:%s\n”,字符串(响应))
重定向(w,r,“/”,http.StatusTemporaryRedirect)
}
func main(){
http.HandleFunc(“/”,handleMain)
http.HandleFunc(“/login”,handleFacebookLogin)
http.HandleFunc(“/oauth2callback”,handleFacebookCallback)
fmt.Print(“已开始在上运行http://localhost:9090\n“)
log.Fatal(http.ListenAndServe(“:9090”,nil))
}

您对oauth2软件包的使用与!中记录的API不匹配@帕德拉尔,你解决了这个问题吗?我在寻找同样的答案!您可以调用
url:=oauthConf.AuthCodeURL(oauthStateString)
Great suggestion,而不是自己在
handleFacebookLogin
中构建
url。我的帖子有点老了,但很好的更新。感谢您提供了这个很棒的input.log.Fatal:(:(:)当您在handleFacebookLogin中手动构建URL时,没有使用客户端机密。
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))
}