package main import ( "encoding/json" "fmt" "log" "net/http" "os" "golang.org/x/net/context" "golang.org/x/oauth2" ) // Retrieve a token, saves the token, then returns the generated client. func getClient(config *oauth2.Config) (*http.Client, error) { // The file token.json stores the user's access and refresh tokens, and is // created automatically when the authorization flow completes for the first // time. tokFile := "token.json" tok, err := tokenFromFile(tokFile) if err != nil { tok, err = getTokenFromWeb(config) if err != nil { return nil, err } err = saveToken(tokFile, tok) if err != nil { return nil, err } } return config.Client(context.Background(), tok), nil } // Request a token from the web, then returns the retrieved token. func getTokenFromWeb(config *oauth2.Config) (*oauth2.Token, error) { authURL := config.AuthCodeURL("state-token", oauth2.AccessTypeOffline) log.Printf("Go to the following link in your browser then type the authorization code: \n%v", authURL) var authCode string if _, err := fmt.Scan(&authCode); err != nil { return nil, err } tok, err := config.Exchange(context.TODO(), authCode) if err != nil { return nil, err } return tok, nil } // Retrieves a token from a local file. func tokenFromFile(file string) (*oauth2.Token, error) { f, err := os.Open(file) if err != nil { return nil, err } defer f.Close() tok := &oauth2.Token{} err = json.NewDecoder(f).Decode(tok) return tok, err } // Saves a token to a file path. func saveToken(path string, token *oauth2.Token) error { f, err := os.OpenFile(path, os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0600) if err != nil { return err } defer f.Close() json.NewEncoder(f).Encode(token) return nil }