// UserInfo uses the token source to query the provider's user info endpoint. func (p *Provider) UserInfo(ctx context.Context, tokenSource oauth2.TokenSource) (*UserInfo, error) { if p.userInfoURL == "" { return nil, errors.New("oidc: user info endpoint is not supported by this provider") } req, err := http.NewRequest("GET", p.userInfoURL, nil) if err != nil { return nil, fmt.Errorf("oidc: create GET request: %v", err) } token, err := tokenSource.Token() if err != nil { return nil, fmt.Errorf("oidc: get access token: %v", err) } token.SetAuthHeader(req) resp, err := ctxhttp.Do(ctx, clientFromContext(ctx), req) if err != nil { return nil, err } defer resp.Body.Close() body, err := ioutil.ReadAll(resp.Body) if err != nil { return nil, err } if resp.StatusCode != http.StatusOK { return nil, fmt.Errorf("%s: %s", resp.Status, body) } var userInfo UserInfo if err := json.Unmarshal(body, &userInfo); err != nil { return nil, fmt.Errorf("oidc: failed to decode userinfo: %v", err) } userInfo.claims = body return &userInfo, nil }
func main() { const OOB = "urn:ietf:wg:oauth:2.0:oob" conf := &oauth2.Config{ ClientID: "881077086782-039l7vctubc7vrvjmubv6a7v0eg96sqg.apps.googleusercontent.com", // proj: inbox-fewer // https://developers.google.com/identity/protocols/OAuth2InstalledApp // says: "The client ID and client secret obtained // from the Developers Console are embedded in the // source code of your application. In this context, // the client secret is obviously not treated as a // secret." ClientSecret: "y9Rj5-KheyZSFyjCH1dCBXWs", Endpoint: google.Endpoint, RedirectURL: OOB, Scopes: []string{gmail.MailGoogleComScope}, } cacheDir := filepath.Join(userCacheDir(), "inboxfewer") gmailTokenFile := filepath.Join(cacheDir, "gmail.token") slurp, err := ioutil.ReadFile(gmailTokenFile) var ts oauth2.TokenSource if err == nil { f := strings.Fields(strings.TrimSpace(string(slurp))) if len(f) == 2 { ts = conf.TokenSource(context.Background(), &oauth2.Token{ AccessToken: f[0], TokenType: "Bearer", RefreshToken: f[1], Expiry: time.Unix(1, 0), }) if _, err := ts.Token(); err != nil { log.Printf("Cached token invalid: %v", err) ts = nil } } } if ts == nil { authCode := conf.AuthCodeURL("state") log.Printf("Go to %v", authCode) io.WriteString(os.Stdout, "Enter code> ") bs := bufio.NewScanner(os.Stdin) if !bs.Scan() { os.Exit(1) } code := strings.TrimSpace(bs.Text()) t, err := conf.Exchange(context.Background(), code) if err != nil { log.Fatal(err) } os.MkdirAll(cacheDir, 0700) ioutil.WriteFile(gmailTokenFile, []byte(t.AccessToken+" "+t.RefreshToken), 0600) ts = conf.TokenSource(context.Background(), t) } client := oauth2.NewClient(context.Background(), ts) svc, err := gmail.New(client) if err != nil { log.Fatal(err) } readGithubConfig() fc := &FewerClient{ svc: svc.Users, } n := 0 if err := fc.ForeachThread("in:inbox", func(t *gmail.Thread) error { if err := fc.PopulateThread(t); err != nil { return err } topic := fc.ClassifyThread(t) n++ log.Printf("Thread %d (%v) = %T %v", n, t.Id, topic, topic) if topic == nil { return nil } if stale, err := topic.IsStale(); err != nil { return err } else if stale { log.Printf(" ... archiving") return fc.ArchiveThread(t.Id) } return nil }); err != nil { log.Fatal(err) } }