Google日历API invalid_grant获取令牌(Golang)

huangapple go评论89阅读模式
英文:

Google Calendar API invalid_grant getting token (Golang)

问题

我正在尝试获取访问令牌,以便使用Oauth2对用户进行身份验证。我主要使用了在谷歌的HOW-TO页面上找到的代码来使用golang与日历API。问题是,每当我尝试获取令牌时,谷歌都会返回以下错误:

响应: {
 "error" : "invalid_grant"
}

错误信息为 oauth2: cannot fetch token: 400 Bad Request

正如我所说,我使用了一些从谷歌的howto中获取的代码,只是稍作修改以适应我的需求。

//某处...
authURL = config.AuthCodeURL("state-token", oauth2.AccessTypeOffline)

//另外某处...
func getClient(ctx context.Context, config *oauth2.Config, code string) *http.Client {
	cacheFile := tokenCacheFile()

	tok, err := tokenFromFile(cacheFile)
	if err != nil {
		log.Printf("Google auth code not cached. Obtaining from the web...")
		tok, err = getTokenFromWeb(code) //这里返回了一个错误
		if err == nil {
			log.Printf("Got token!")
			saveToken("calendar-go-quickstart.json", tok)
		} else { //当出现错误时不保存令牌
			log.Printf("Couldn't get OAUTH2 token! %s", err)
		}
	}
	return config.Client(ctx, tok)
}

错误发生在 "getTokenFromWeb(code)" 这一行(如果我理解正确,code 必须是一个 随机字符串,无论其值如何,在整个过程中它只需要保持一致)。
这是有问题的代码:

func getTokenFromWeb(code string) (*oauth2.Token, error) {
	tok, err := config.Exchange(context.Background(), code)
	return tok, err
}

执行后,我看到的是这个错误。甚至在尝试 复制粘贴谷歌自己的 示例代码时,我得到了 完全相同的错误
有什么想法吗?我真的找不到在线解决方案。

额外细节:使用IRIS Web框架;使用最新版本的谷歌日历API;使用最新版本的Golang;我在Google Cloud控制台上创建了一个OAuth2的客户端ID;网站具有受信任的SSL证书;它监听端口80(HTTP)和4433(HTTPS)。

英文:

I'm trying to retrieve an access token, in order to authenticate users using Oauth2. I'm using mostly code found on google's HOW-TO page for using the Calendar API with golang. The problem is that whenever I try to obtain a token, google sends back this:

Response: {
 "error" : "invalid_grant"
}

With the error oauth2: cannot fetch token: 400 Bad Request

As I said, I'm using some code got from google's howto, just slightly modified to fit my needs.

//Somewhere...
authURL = config.AuthCodeURL("state-token", oauth2.AccessTypeOffline)

//Somewhere else...
func getClient(ctx context.Context, config *oauth2.Config, code string) *http.Client {
	cacheFile := tokenCacheFile()

	tok, err := tokenFromFile(cacheFile)
	if err != nil {
		log.Printf("Google auth code not cached. Obtaining from the web...")
		tok, err = getTokenFromWeb(code) //This returns an error
		if err == nil {
			log.Printf("Got token!")
			saveToken("calendar-go-quickstart.json", tok)
		} else { //Prevent saving token when error
			log.Printf("Couldn't get OAUTH2 token! %s", err)
		}
	}
	return config.Client(ctx, tok)
}

The error occurs at "getTokenFromWeb(code)" (if I understood correctly, code must be some random string, no matter its value, it just needs to be the same during the whole process).
This is the problematic code:

func getTokenFromWeb(code string) (*oauth2.Token, error) {
	tok, err := config.Exchange(context.Background(), code)
	return tok, err
}

After executing, what I see is that error. I even get the exact same error when trying to copy-paste google's own example code!<br/>
Any idea? I really can't find a solution online.

Extra details: using IRIS web framework; using the latest version of google calendar api; using the latest version of Golang; I've created a client ID for OAuth2 on Google Cloud Console; The website has got a trusted SSL cert; it listens on port 80 (HTTP) and 4433 (HTTPS);

答案1

得分: 1

这是谷歌的示例代码:

// getTokenFromWeb 使用 Config 请求一个 Token。
// 它返回获取到的 Token。
func getTokenFromWeb(config *oauth2.Config) *oauth2.Token {
authURL := config.AuthCodeURL("state-token", oauth2.AccessTypeOffline)
fmt.Printf("在浏览器中打开以下链接,然后输入授权码:\n%v\n", authURL)

var code string
if _, err := fmt.Scan(&code); err != nil {
log.Fatalf("无法读取授权码 %v", err)
}
...
}

code 是用户在访问显示的链接后获得的授权码。fmt.Scan() 将扫描用户输入的内容。

如果你代表不同的用户行事,你需要类似这个示例的操作。
如果你只是代表自己行事,你应该能够在没有授权码的情况下进行身份验证。

无论哪种方式,code 不能是一个随机字符串。

英文:

Here is Google's example:

// getTokenFromWeb uses Config to request a Token.
// It returns the retrieved Token.
func getTokenFromWeb(config *oauth2.Config) *oauth2.Token {
  authURL := config.AuthCodeURL(&quot;state-token&quot;, oauth2.AccessTypeOffline)
  fmt.Printf(&quot;Go to the following link in your browser then type the &quot;+
&quot;authorization code: \n%v\n&quot;, authURL)

  var code string
  if _, err := fmt.Scan(&amp;code); err != nil {
    log.Fatalf(&quot;Unable to read authorization code %v&quot;, err)
  }
  ...
}

code is an authorization code given to the user after visiting the displayed link. fmt.Scan() is going to scan the input from the user.

If you're going to be acting on a different user's behalf, you will have to do something similar to this example.
If you're only acting as yourself, you should be able to authenticate as yourself without the code.

Either way, code cannot be a random string.

huangapple
  • 本文由 发表于 2017年8月4日 03:58:49
  • 转载请务必保留本文链接:https://go.coder-hub.com/45493523.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定