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!
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);
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("state-token", oauth2.AccessTypeOffline)
fmt.Printf("Go to the following link in your browser then type the "+
"authorization code:
%v
", authURL)
var code string
if _, err := fmt.Scan(&code); err != nil {
log.Fatalf("Unable to read authorization code %v", 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.