go - 无法让 Oauth2 TokenSource 刷新从存储中检索到的令牌
问题描述
用户授权 Google Calendar 后,NodeJS 服务将Code、AccessToken 和 RefreshToken保存到存储中。
尝试使用相同的令牌访问使用 Go 编写的不同后端服务的用户日历。当 AccessToken 有效时,数据是可访问的,但是当 AccessToken 过期时,无法获取 config.Exchange() 或 config.TokenSource() 以提供新的令牌,即使令牌有效,在尝试访问事件时也是如此,得到错误:
错误 401:凭据无效,authError 退出状态 1
tok, err := config.TokenSource(ctx, token).Token() // token is previous valid token
if err != nil {
log.Fatalf("Unable to retrieve token from web: %v", err)
}
还尝试用代码交换新令牌,但无济于事
400 错误请求响应:{“error”:“invalid_grant”,“error_description”:“格式错误的身份验证代码。” }
tok, err := config.Exchange(context.TODO(), in)
if err != nil {
log.Fatalf("Unable to retrieve token from web: %v", err)
}
尝试使用 calendar.NewService 访问
srv, _ := calendar.NewService(ctx, option.WithTokenSource(config.TokenSource(ctx, tok)))
如何获得可以离线访问的令牌,而无需用户干预来自其他服务?
更新:将令牌存储到 Redis - RedisJSON 但仍不会获得新的 AccessToken。这是我传递有效令牌的完整功能。它仅在 AccessToken 到期之前有效。
func GetGoogleCalendarEvents(token *oauth2.Token, userid string) *calendar.Events {
tok := &oauth2.Token{}
var config *oauth2.Config
ctx := context.Background()
b, err := ioutil.ReadFile("credentials.json")
if err != nil {
log.Fatalf("Unable to read client secret file: %v", err)
}
config, err = google.ConfigFromJSON(b, calendar.CalendarScope) //calendar.CalendarScope)
if err != nil {
log.Fatalf("Unable to parse client secret file to config: %v", err)
}
tok = token
if token.Expiry.Before(time.Now()) {
tokenSource := config.TokenSource(ctx, token) //oauth2.NoContext
newToken, err := tokenSource.Token()
if err != nil {
log.Fatalln(err)
}
if tok.AccessToken != newToken.AccessToken {
SetAuthCredToCache(userid, tok)
tok = newToken
fmt.Println(newToken)
}
}
fmt.Println(tok.Expiry, tok.Valid(), tok.Type(), tok.RefreshToken, tok.TokenType)
srv, _ := calendar.NewService(ctx, option.WithTokenSource(config.TokenSource(ctx, tok)))
t := time.Now().Format(time.RFC3339)
events, err := srv.Events.List("primary").ShowDeleted(true).
SingleEvents(true).TimeMin(t).OrderBy("startTime").Do()
if err != nil {
log.Fatalf("Unable to retrieve next ten of the user's events: %v", err)
}
return events
}
解决方案
这是一个解组问题。
从 Node 保存令牌时,它将到期时间序列化为“expiry_date”,而 Go Token 的 json 表示形式为“expiry”。将对象的其余部分解组为 oauth2.Token 对象并向该对象添加到期时间解决了该问题。
推荐阅读
- ocaml - 摆脱变体构造函数
- php - 如何防止用户创建新标签?
- docker - 如何使用 Ubuntu18.04 在 Dockerfile 上启用 systemd
- php - WordPress的主域不断重定向到子域
- python - (Npyscreen)如何在拾取小部件中实现功能?
- c# - 打开 Xml 样式颜色未正确显示
- vue.js - 如何取消 vue.js 中文件的上传进度?
- c# - 当 XML 具有多个同名元素时,如何将其表示为类
- r - 在 ShinyApp 中使用下载处理程序下载数据时出现问题
- android - Firebase Api Key 可用于其他应用程序(反编译的 APK)