After a user authorizes Google Calendar, the NodeJS service saves the Code, AccessToken and RefreshToken to a storage.
Trying to use the same token to access the users' calendar using different backend service written in Go. When the AccessToken is valid, the data is accessible, but when AccessToken expires unable to get the config.Exchange() or config.TokenSource() to give a new token which works, even though the token is valid, when trying to access events, get error :
Error 401: Invalid Credentials, authError exit status 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)
}
Also tried to exchange code for a new token but doesn't help
400 Bad Request Response: { "error": "invalid_grant", "error_description": "Malformed auth code." }
tok, err := config.Exchange(context.TODO(), in)
if err != nil {
log.Fatalf("Unable to retrieve token from web: %v", err)
}
Trying to access using calendar.NewService
srv, _ := calendar.NewService(ctx, option.WithTokenSource(config.TokenSource(ctx, tok)))
How to get a token which can access offline without user intervention from another service ?
Update: Storing token to Redis - RedisJSON but still won't get a new AccessToken. This is the complete function where I am passing a valid Token. It works only before AccessToken expiry.
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
}