func main() { if len(os.Args) == 1 { fmt.Println("Usage: gauthtoken REFRESH_TOKEN") os.Exit(1) } conf := oauth2.Config{ ClientID: "32555940559.apps.googleusercontent.com", ClientSecret: "ZmssLNjJy2998hD4CTg2ejr2", Endpoint: google.Endpoint, RedirectURL: "oob", } refreshToken := &oauth2.Token{ AccessToken: "", RefreshToken: os.Args[1], Expiry: time.Now().UTC(), } token, err := conf.TokenSource(oauth2.NoContext, refreshToken).Token() if err != nil { log.Fatalln(err) } fmt.Println(token.AccessToken) }
// CallbackHandler handles OAuth2 redirection URI requests by parsing the auth // code and state, comparing with the state value from the ctx, and obtaining // an OAuth2 Token. func CallbackHandler(config *oauth2.Config, success, failure ctxh.ContextHandler) ctxh.ContextHandler { if failure == nil { failure = gologin.DefaultFailureHandler } fn := func(ctx context.Context, w http.ResponseWriter, req *http.Request) { authCode, state, err := parseCallback(req) if err != nil { ctx = gologin.WithError(ctx, err) failure.ServeHTTP(ctx, w, req) return } ownerState, err := StateFromContext(ctx) if err != nil { ctx = gologin.WithError(ctx, err) failure.ServeHTTP(ctx, w, req) return } if state != ownerState || state == "" { ctx = gologin.WithError(ctx, ErrInvalidState) failure.ServeHTTP(ctx, w, req) return } // use the authorization code to get a Token token, err := config.Exchange(ctx, authCode) if err != nil { ctx = gologin.WithError(ctx, err) failure.ServeHTTP(ctx, w, req) return } ctx = WithToken(ctx, token) success.ServeHTTP(ctx, w, req) } return ctxh.ContextHandlerFunc(fn) }
func handleCallback(w http.ResponseWriter, r *http.Request, config *oauth2.Config, profilesURL, code string) { token, err := config.Exchange(oauth2.NoContext, code) if err != nil { http.Error(w, err.Error(), http.StatusInternalServerError) return } client := config.Client(oauth2.NoContext, token) response, err := client.Get(profilesURL) if err != nil { http.Error(w, err.Error(), http.StatusInternalServerError) return } defer response.Body.Close() rawBody, err := ioutil.ReadAll(response.Body) if err != nil { http.Error(w, err.Error(), http.StatusInternalServerError) return } s, _ := session.Manager.SessionStart(w, r) defer s.SessionRelease(w) s.Set("id_token", token.Extra("id_token")) s.Set("access_token", token.AccessToken) s.Set("profile", string(rawBody)) http.Redirect(w, r, "/user", http.StatusMovedPermanently) }
func handleOAuth2Callback(config *oauth2.Config, s sessions.Session, w http.ResponseWriter, r *http.Request) { providedState := extractPath(r.URL.Query().Get("state")) //fmt.Printf("Got state from request %s\n", providedState) //verify that the provided state is the state we generated //if it is not, then redirect to the error page originalState := s.Get(keyState) //fmt.Printf("Got state from session %s\n", originalState) if providedState != originalState { //http.Redirect(w, r, PathError, http.StatusFound) //return } //next := s.Get(keyNextPage).(string) //fmt.Printf("Got a next page from the session: %s\n", next) next := "" code := r.URL.Query().Get("code") t, err := config.Exchange(oauth2.NoContext, code) if err != nil { // Pass the error message, or allow dev to provide its own // error handler. fmt.Println("There is some error in the code exchange") http.Redirect(w, r, PathError, http.StatusFound) return } // Store the credentials in the session. val, _ := json.Marshal(t) s.Set(KeyToken, maskval(val)) http.Redirect(w, r, next, http.StatusFound) }
func tokenFromWeb(ctx context.Context, config *oauth2.Config) *oauth2.Token { randState := fmt.Sprintf("st%d", time.Now().UnixNano()) tokenOnce.Do(func() { http.HandleFunc("/oauth/", func(rw http.ResponseWriter, req *http.Request) { if req.FormValue("state") != randState { log.Printf("State doesn't match: req = %#v", req) http.Error(rw, "", 500) return } if code := req.FormValue("code"); code != "" { fmt.Fprintf(rw, "<h1>Success</h1>Authorized.") rw.(http.Flusher).Flush() ch <- code return } log.Printf("no code") http.Error(rw, "", 500) }) }) config.RedirectURL = "http://localhost:8383/oauth/" authURL := config.AuthCodeURL(randState) go openURL(authURL) log.Printf("Authorize this app at: %s", authURL) code := <-ch log.Printf("Got code: %s", code) token, err := config.Exchange(ctx, code) if err != nil { log.Fatalf("Token exchange error: %v", err) } return token }
func (c *client) newUserToken(ctx context.Context, config *oauth2.Config, userID string) (*oauth2.Token, error) { stateBytes := make([]byte, 32) _, err := rand.Read(stateBytes) if err != nil { log.Fatalf("Unable to read random bytes: %v", err) return nil, err } state := fmt.Sprintf("%x", stateBytes) authURL := config.AuthCodeURL(state, oauth2.AccessTypeOffline) authcode, err := c.GiveTokenPermissions(authURL) if err != nil { log.Fatalf("Error when getting token permissions: %v", err) return nil, err } token, err := c.HandleOAuthCode(authcode) if err != nil { log.Fatalf("Error when handling OAuth Code error: %v", err) return nil, err } c.SaveToken(userID, token) // save token to datastore return token, nil }
// Config does the initial creation of the token func Config(name string, config *oauth2.Config) error { // See if already have a token tokenString := fs.ConfigFile.MustValue(name, "token") if tokenString != "" { fmt.Printf("Already have a token - refresh?\n") if !fs.Confirm() { return nil } } // Generate a URL for the user to visit for authorization. authUrl := config.AuthCodeURL("state") fmt.Printf("Go to the following link in your browser\n") fmt.Printf("%s\n", authUrl) fmt.Printf("Log in, then type paste the token that is returned in the browser here\n") // Read the code, and exchange it for a token. fmt.Printf("Enter verification code> ") authCode := fs.ReadLine() token, err := config.Exchange(oauth2.NoContext, authCode) if err != nil { return fmt.Errorf("Failed to get token: %v", err) } return putToken(name, token) }
// getTokenFromWeb uses Config to request a Token. // It returns the retrieved Token. func getTokenFromWeb(config *oauth2.Config) *oauth2.Token { ch := make(chan string) http.HandleFunc("/auth", func(rw http.ResponseWriter, req *http.Request) { if code := req.FormValue("code"); code != "" { fmt.Fprintf(rw, "<h1>Success</h1>Authorized.") rw.(http.Flusher).Flush() ch <- code return } log.Printf("no code") http.Error(rw, "", 500) }) authURL := config.AuthCodeURL("state-token", oauth2.AccessTypeOffline) go openUrl(authURL) log.Printf("Authorize this app at: %s", authURL) code := <-ch log.Printf("received code") tok, err := config.Exchange(oauth2.NoContext, code) if err != nil { log.Fatalf("Unable to retrieve token from web %v", err) } return tok }
// facebookHandler is a ContextHandler that gets the OAuth2 Token from the ctx // to get the corresponding Facebook User. If successful, the user is added to // the ctx and the success handler is called. Otherwise, the failure handler // is called. func facebookHandler(config *oauth2.Config, success, failure ctxh.ContextHandler) ctxh.ContextHandler { if failure == nil { failure = gologin.DefaultFailureHandler } fn := func(ctx context.Context, w http.ResponseWriter, req *http.Request) { token, err := oauth2Login.TokenFromContext(ctx) if err != nil { ctx = gologin.WithError(ctx, err) failure.ServeHTTP(ctx, w, req) return } httpClient := config.Client(ctx, token) facebookService := newClient(httpClient) user, resp, err := facebookService.Me() err = validateResponse(user, resp, err) if err != nil { ctx = gologin.WithError(ctx, err) failure.ServeHTTP(ctx, w, req) return } ctx = WithUser(ctx, user) success.ServeHTTP(ctx, w, req) } return ctxh.ContextHandlerFunc(fn) }
func exchangeToken(ctx context.Context, config *oauth2.Config, code string) *oauth2.Token { token, err := config.Exchange(ctx, code) if err != nil { glog.Fatalf("Token exchange error: %v", err) } return token }
// NewRefreshTokenSource returns a token source that obtains its initial token // based on the provided config and the refresh token. func NewRefreshTokenSource(config *oauth2.Config, refreshToken string) oauth2.TokenSource { var noInitialToken *oauth2.Token = nil return oauth2.ReuseTokenSource(noInitialToken, config.TokenSource( oauth2.NoContext, // TODO: maybe accept a context later. &oauth2.Token{RefreshToken: refreshToken}, )) }
func (p *Engine) _google(code string) (*User, error) { var cfg oauth2.Config if err := p.Dao.Get("google.oauth", &cfg); err != nil { return nil, err } tok, err := cfg.Exchange(oauth2.NoContext, code) if err != nil { return nil, err } cli := cfg.Client(oauth2.NoContext, tok) res, err := cli.Get("https://www.googleapis.com/oauth2/v1/userinfo?alt=json") if err != nil { return nil, err } defer res.Body.Close() var gu GoogleUser dec := json.NewDecoder(res.Body) if err := dec.Decode(&gu); err != nil { return nil, err } return p.Dao.AddUser(gu.ID, "google", gu.Email, gu.Name, gu.Link, gu.Picture) }
// googleHandler is a ContextHandler that gets the OAuth2 Token from the ctx // to get the corresponding Google Userinfoplus. If successful, the user info // is added to the ctx and the success handler is called. Otherwise, the // failure handler is called. func googleHandler(config *oauth2.Config, success, failure ctxh.ContextHandler) ctxh.ContextHandler { if failure == nil { failure = gologin.DefaultFailureHandler } fn := func(ctx context.Context, w http.ResponseWriter, req *http.Request) { token, err := oauth2Login.TokenFromContext(ctx) if err != nil { ctx = gologin.WithError(ctx, err) failure.ServeHTTP(ctx, w, req) return } httpClient := config.Client(ctx, token) googleService, err := google.New(httpClient) if err != nil { ctx = gologin.WithError(ctx, err) failure.ServeHTTP(ctx, w, req) return } userInfoPlus, err := googleService.Userinfo.Get().Do() err = validateResponse(userInfoPlus, err) if err != nil { ctx = gologin.WithError(ctx, err) failure.ServeHTTP(ctx, w, req) return } ctx = WithUser(ctx, userInfoPlus) success.ServeHTTP(ctx, w, req) } return ctxh.ContextHandlerFunc(fn) }
/* This auth function is a bootstrap until better integration with gcloud auth can be provided. To use, set (and export) the environment variable GCLOUD_APIS_REFRESH_TOKEN to a valid refresh token, which can usually be acquired via $(gcloud auth print-refresh-token). In the future, gcloud_apis will be able to fetch credential information from the same place as gcloud, and will be usable without setting this environment variable. */ func getAuthenticatedClient() (*http.Client, error) { conf := oauth2.Config{ ClientID: "32555940559.apps.googleusercontent.com", ClientSecret: "ZmssLNjJy2998hD4CTg2ejr2", Endpoint: oauth2.Endpoint{ AuthURL: "https://accounts.google.com/o/oauth2/auth", TokenURL: "https://accounts.google.com/o/oauth2/token", }, Scopes: []string{"https://www.googleapis.com/auth/cloud-platform"}, } var ts oauth2.TokenSource refreshToken := os.Getenv("GCLOUD_APIS_REFRESH_TOKEN") if refreshToken == "" { ts = cliTokenSource{} } else { token := &oauth2.Token{ RefreshToken: refreshToken, } ts = conf.TokenSource(oauth2.NoContext, token) } oauth2Transport := &oauth2.Transport{ Source: ts, } client := &http.Client{ Transport: gcloudTransport{oauth2Transport}, } return client, nil }
// Ref: https://github.com/google/google-api-go-client/blob/master/examples/calendar.go // Copyright 2014 The Go Authors. All rights reserved. func tokenFromWeb(ctx context.Context, config *oauth2.Config) (*oauth2.Token, error) { ch := make(chan string) randState := fmt.Sprintf("st%d", time.Now().UnixNano()) ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { if r.URL.Path == "/favicon.ico" { w.WriteHeader(http.StatusNotFound) return } if r.FormValue("state") != randState { w.WriteHeader(http.StatusInternalServerError) return } if code := r.FormValue("code"); code != "" { w.Write([]byte("<h1>Success</h1>Authorized.")) w.(http.Flusher).Flush() ch <- code return } // no code w.WriteHeader(http.StatusInternalServerError) })) defer ts.Close() config.RedirectURL = ts.URL authURL := config.AuthCodeURL(randState) fmt.Println("Access to %s", authURL) code := <-ch return config.Exchange(ctx, code) }
func ExecuteFlow(ctx context.Context, config *oauth2.Config, options ...Option) (*oauth2.Token, error) { o := processOpts(options) configCopy := *config config = &configCopy code := make(chan string) l, err := net.Listen("tcp", o.addr) if err != nil { return nil, err } defer l.Close() config.RedirectURL = fmt.Sprintf("http://%s/", l.Addr().String()) go http.Serve(l, http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { fmt.Fprint(w, closeMessage) code <- r.FormValue("code") // send code to OAuth flow })) url := config.AuthCodeURL("", oauth2.AccessTypeOffline) if o.noBrowser { fmt.Fprintln(os.Stderr, visitMessage) } else if err := openURL(url); err != nil { fmt.Fprintln(os.Stderr, visitMessage) } else { fmt.Fprintln(os.Stderr, openedMessage) } fmt.Fprintf(os.Stderr, "\n%s\n\n", url) fmt.Fprintln(os.Stderr, resumeMessage) return config.Exchange(ctx, <-code) }
func GetTokenFromCode(config *oauth2.Config, code string) (*oauth2.Token, error) { token, err := config.Exchange(oauth2.NoContext, code) if err != nil { return nil, err } return token, nil }
func handleOAuth2Callback(config *oauth2.Config, s sessions.Session, w http.ResponseWriter, r *http.Request) { providedState := extractPath(r.URL.Query().Get("state")) //verify that the provided state is the state we generated //if it is not, then redirect to the error page originalState := s.Get(keyState) if providedState != originalState { http.Redirect(w, r, PathError, http.StatusFound) return } next := s.Get(keyNextPage).(string) code := r.URL.Query().Get("code") t, err := config.Exchange(oauth2.NoContext, code) if err != nil { // Pass the error message, or allow dev to provide its own // error handler. http.Redirect(w, r, PathError, http.StatusFound) return } // Store the credentials in the session. val, _ := json.Marshal(t) s.Set(keyToken, val) http.Redirect(w, r, next, http.StatusFound) }
func getClient(config *oauth2.Config, code string) (*drive.Service, error) { if config == nil { return nil, errors.New("Google Drive is not configured") } token := &oauth2.Token{AccessToken: code} return drive.New(config.Client(context.Background(), token)) }
// TokenOAuthClient returns an oauth2 client for a specific token func (c *client) TokenOAuthClient(ctx context.Context, config *oauth2.Config, userToken *oauth2.Token) (client *http.Client, err error) { if !userToken.Valid() { // if user token is expired userToken = &oauth2.Token{RefreshToken: userToken.RefreshToken} } return config.Client(ctx, userToken), err }
// Your credentials should be obtained from the Google // Developer Console (https://console.developers.google.com). func OauthURL(conf *oauth2.Config) string { // Redirect user to Google's consent page to ask for permission // for the scopes specified above. url := conf.AuthCodeURL("state") log.Debugf("\nVisit the URL for the auth dialog: %v\n", url) return url }
// getClient uses a Context and Config to retrieve a Token // then generate a Client. It returns the generated Client. func getSheetClient(ctx context.Context, authConfig *oauth2.Config) *http.Client { tok, err := tokenFromFile(config.SheetCredentials) if err != nil { tok = getTokenFromWeb(authConfig) saveToken(config.SheetCredentials, tok) } return authConfig.Client(ctx, tok) }
// NewClientTokenTLS returns a client at the specified url that // authenticates all outbound requests with the given token and // tls.Config if provided. func NewClientTokenTLS(uri, token string, c *tls.Config) Client { config := new(oauth2.Config) auther := config.Client(oauth2.NoContext, &oauth2.Token{AccessToken: token}) if c != nil { auther.Transport.(*oauth2.Transport).Base = &http.Transport{TLSClientConfig: c} } return &client{auther, uri} }
func createClient(cfg *oauth2.Config) (*http.Client, error) { tok, err := getToken(cfg) if err != nil { return nil, err } return cfg.Client(context.Background(), tok), nil }
// authorize performs user authorization flow, asking for permissions grant. func authorize(conf *oauth2.Config) (*oauth2.Token, error) { aurl := conf.AuthCodeURL("unused", oauth2.AccessTypeOffline) fmt.Printf("Authorize me at following URL, please:\n\n%s\n\nCode: ", aurl) var code string if _, err := fmt.Scan(&code); err != nil { return nil, err } return conf.Exchange(context.Background(), code) }
// Token refreshes the token by using a new client credentials request. // tokens received this way do not include a refresh token // Token returns a token or an error. // Token must be safe for concurrent use by multiple goroutines. // The returned Token must not be modified. func (c *tokenSource) Token() (*oauth2.Token, error) { config := oauth2.Config{ ClientID: c.conf.ClientID, ClientSecret: c.conf.ClientSecret, Endpoint: c.conf.Endpoint, Scopes: c.conf.Scopes, } return config.PasswordCredentialsToken(c.ctx, c.conf.Username, c.conf.Password) }
// GetClient uses a Context and Config to retrieve a Token // then generate a Client. It returns the generated Client. func GetClient(ctx context.Context, config *oauth2.Config) *http.Client { cacheFile := tokenCacheFile() tok, err := tokenFromFile(cacheFile) if err != nil { tok = getTokenFromWeb(config) saveToken(cacheFile, tok) } return config.Client(ctx, tok) }
// getClient uses a Context and Config to retrieve a Token // then generate a Client. It returns the generated Client. func getClient(ctx context.Context, config *oauth2.Config) *http.Client { cacheFile := filepath.Join("./.credentials", url.QueryEscape("gmail_token.json")) token, err := tokenFromFile(cacheFile) if err != nil { log.Fatalf("Unable to retrieve token from cached credential file. %v", err) } return config.Client(ctx, token) }
func (c *googinitCmd) RunCommand(args []string) error { var ( err error clientId string clientSecret string oauthConfig *oauth2.Config ) if c.storageType != "drive" && c.storageType != "cloud" { return cmdmain.UsageError("Invalid storage type: must be drive for Google Drive or cloud for Google Cloud Storage.") } clientId, clientSecret = getClientInfo() switch c.storageType { case "drive": oauthConfig = &oauth2.Config{ Scopes: []string{drive.Scope}, Endpoint: google.Endpoint, ClientID: clientId, ClientSecret: clientSecret, RedirectURL: oauthutil.TitleBarRedirectURL, } case "cloud": oauthConfig = &oauth2.Config{ Scopes: []string{storage.ScopeReadWrite}, Endpoint: google.Endpoint, ClientID: clientId, ClientSecret: clientSecret, RedirectURL: oauthutil.TitleBarRedirectURL, } } token, err := oauth2.ReuseTokenSource(nil, &oauthutil.TokenSource{ Config: oauthConfig, AuthCode: func() string { fmt.Fprintf(cmdmain.Stdout, "Get auth code from:\n\n") fmt.Fprintf(cmdmain.Stdout, "%v\n\n", oauthConfig.AuthCodeURL("", oauth2.AccessTypeOffline, oauth2.ApprovalForce)) return prompt("Enter auth code:") }, }).Token() if err != nil { return fmt.Errorf("could not acquire token: %v", err) } fmt.Fprintf(cmdmain.Stdout, "\nYour Google auth object:\n\n") enc := json.NewEncoder(cmdmain.Stdout) authObj := map[string]string{ "client_id": clientId, "client_secret": clientSecret, "refresh_token": token.RefreshToken, } enc.Encode(authObj) fmt.Fprint(cmdmain.Stdout, "\n\nFor server-config.json, your 'googlecloudstorage' value (update with your bucket name and path):\n\n") fmt.Fprintf(cmdmain.Stdout, "%s:%s:%s:bucketName[/optional/dir]\n", clientId, clientSecret, token.RefreshToken) return nil }
// overrideCredentials sets the ClientID and ClientSecret from the // config file if they are not blank func overrideCredentials(name string, config *oauth2.Config) { ClientID := fs.ConfigFile.MustValue(name, ConfigClientID) if ClientID != "" { config.ClientID = ClientID } ClientSecret := fs.ConfigFile.MustValue(name, ConfigClientSecret) if ClientSecret != "" { config.ClientSecret = ClientSecret } }