// 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 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 tokenFromWeb(ctx context.Context, config *oauth2.Config, cfg *config.Config) *oauth2.Token { ch := make(chan string) randState := fmt.Sprintf("st%d", time.Now().UnixNano()) lis, err := net.Listen("tcp", fmt.Sprintf(":%d", cfg.GetYoutubeOAuthPort())) if err != nil { panic(err) } // make our own handler that puts all requests in a wait group. h := http.NewServeMux() // add a close handlefunc to that handler h.HandleFunc("/youtube_callback/", func(rw http.ResponseWriter, req *http.Request) { if req.URL.Path == "/favicon.ico" { http.Error(rw, "", 404) return } if req.FormValue("state") != randState { fmt.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 lis.Close() return } fmt.Printf("no code") http.Error(rw, "", 500) lis.Close() }) //listen and serve until listner is closed go http.Serve(lis, h) // TODO fix this hard-coded localhost thingy config.RedirectURL = fmt.Sprintf("http://127.0.0.1:%d/youtube_callback/", cfg.GetYoutubeOAuthPort()) authURL := config.AuthCodeURL(randState) go openURL(authURL) fmt.Printf("Authorize this app at: %s", authURL) code := <-ch token, err := config.Exchange(ctx, code) if err != nil { fmt.Printf("Token exchange error: %v", err) } return token }
func tokenFromWeb(ctx context.Context, config *oauth2.Config, wf *web.WebFace) *oauth2.Token { ch := make(chan string) randState := fmt.Sprintf("st%d", time.Now().UnixNano()) config.RedirectURL = "http://" + wf.Addr + "/login" { // Auto authURL := config.AuthCodeURL(randState) wf.RedirectHandler = func(rw http.ResponseWriter, req *http.Request) { if req.URL.Path == "/favicon.ico" { http.Error(rw, "", 404) return } if !strings.HasPrefix(req.URL.Path, "/login") { log.Println("Redirect ", req.URL.Path, strings.HasPrefix(req.URL.Path, "/login")) http.Redirect(rw, req, authURL, 302) return } 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 != "" { wf.RedirectHandler = nil http.Redirect(rw, req, "http://"+wf.Addr+"/", 302) ch <- code return } } log.Println("Awaiting Authorize Token") } 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 tokenFromWeb(ctx context.Context, config *oauth2.Config) { randState := fmt.Sprintf("st%d", time.Now().UnixNano()) config.RedirectURL = "http://localhost:3000/after" http.HandleFunc("/", func(rw http.ResponseWriter, req *http.Request) { log.Printf("====> Got: %s", req.URL.Path) if req.URL.Path == "/favicon.ico" { http.Error(rw, "", 404) return } if req.URL.Path == "/" { authURL := config.AuthCodeURL(randState) http.Redirect(rw, req, authURL, http.StatusFound) } if req.FormValue("state") != randState { log.Printf("State doesn't match: %s / %s ", req.FormValue("state"), randState) http.Error(rw, "", 500) return } if code := req.FormValue("code"); code != "" { log.Printf("sending code") token, err := config.Exchange(ctx, code) if err == nil { // encode this thing var tokenBytes bytes.Buffer enc := gob.NewEncoder(&tokenBytes) enc.Encode(token) tokenString := base64.StdEncoding.EncodeToString(tokenBytes.Bytes()) log.Printf(tokenString) } log.Printf("sent code") fmt.Fprintf(rw, "<h1>Success</h1>Authorized.") return } log.Printf("no code") http.Error(rw, "", 500) }) http.ListenAndServe(":3000", nil) }
func auth(cfg *oauth2.Config, fn func(string) error) (*oauth2.Token, error) { ch := make(chan interface{}) l, err := net.Listen("tcp", ":0") if err != nil { return nil, err } defer l.Close() cfg.RedirectURL = urlFor(l.Addr()) if err := fn(cfg.RedirectURL); err != nil { return nil, err } go func() { for { c, err := l.Accept() if err != nil { ch <- err return } code, err := serveConn(c, cfg) if err != nil { ch <- err return } if code == "" { continue } ch <- code return } }() v := <-ch switch t := v.(type) { case error: return nil, t case string: return cfg.Exchange(context.Background(), t) } panic("unreachable") }
func GetAuthCodeURL(conf oauth2.Config, ar *osin.AuthorizeRequest, provider string) string { redirect, err := url.Parse(conf.RedirectURL) if err != nil { return "" } q := redirect.Query() q.Set(ProviderQueryParam, provider) q.Set(RedirectQueryParam, ar.RedirectUri) q.Set(ClientQueryParam, ar.Client.GetId()) q.Set(ScopeQueryParam, ar.Scope) q.Set(StateQueryParam, ar.State) q.Set(TypeQueryParam, string(ar.Type)) redirect.RawQuery = q.Encode() conf.RedirectURL = redirect.String() return conf.AuthCodeURL(ar.State) }
// Get an authorization code by opening up the authorization page in a web // browser. func codeFromWeb(oauthConfig *oauth2.Config) (string, error) { ch := make(chan string) randState := fmt.Sprintf("st%d", time.Now().UnixNano()) // Launch a local web server to receive the authorization code. ts := httptest.NewServer(http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) { if req.URL.Path == "/favicon.ico" { http.Error(rw, "", 404) return } 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>Skicka is now authorized.") rw.(http.Flusher).Flush() ch <- code return } http.Error(rw, "", 500) })) defer ts.Close() oauthConfig.RedirectURL = ts.URL url := oauthConfig.AuthCodeURL(randState) errs := make(chan error) go func() { err := openURL(url) errs <- err }() err := <-errs if err == nil { // The URL open was apparently successful; wait for our server to // receive the code and send it back. code := <-ch return code, nil } return "", err }
/** * This creates a new OAuth configuration and synchronizes concurrent access * to that configuration. * This is expected since ServerHTTP run on their own goroutine * @param path is the path to retrieve CA certificates * @param c is the channel to write to * @see #PopulateCertPool(string) */ func OAuthConfigurationManager(clientid, clientsecret, redirecturl, authurl, tokenurl string, c chan *oauth2.Config) { var logger = NewPrefixed("security#OAuthConfigurationManager") oauthConfig := new(oauth2.Config) oauthConfig.ClientID = clientid oauthConfig.ClientSecret = clientsecret oauthConfig.Scopes = []string{"email"} oauthConfig.RedirectURL = redirecturl oauthConfig.Endpoint = oauth2.Endpoint{ AuthURL: authurl, TokenURL: tokenurl, } for { select { case c <- oauthConfig: logger.Finest("Written OAuthconf : %v", oauthConfig) } } }
func tokenFromWeb(ctx context.Context, config *oauth2.Config) *oauth2.Token { ch := make(chan string) randState := fmt.Sprintf("st%d", time.Now().UnixNano()) ts := httptest.NewServer(http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) { if req.URL.Path == "/favicon.ico" { http.Error(rw, "", 404) return } 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) })) defer ts.Close() config.RedirectURL = ts.URL 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 }
// Config does the initial creation of the token // // It may run an internal webserver to receive the results func Config(name string, config *oauth2.Config) error { overrideCredentials(name, config) // 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 } } // Detect whether we should use internal web server useWebServer := false switch config.RedirectURL { case RedirectURL, RedirectPublicURL, RedirectLocalhostURL: useWebServer = true case TitleBarRedirectURL: fmt.Printf("Use auto config?\n") fmt.Printf(" * Say Y if not sure\n") fmt.Printf(" * Say N if you are working on a remote or headless machine or Y didn't work\n") useWebServer = fs.Confirm() if useWebServer { // copy the config and set to use the internal webserver configCopy := *config config = &configCopy config.RedirectURL = RedirectURL } } // Make random state stateBytes := make([]byte, 16) _, err := rand.Read(stateBytes) if err != nil { return err } state := fmt.Sprintf("%x", stateBytes) authURL := config.AuthCodeURL(state) // Prepare webserver server := authServer{ state: state, bindAddress: bindAddress, authURL: authURL, } if useWebServer { server.code = make(chan string, 1) go server.Start() defer server.Stop() authURL = "http://" + bindAddress + "/auth" } // Generate a URL for the user to visit for authorization. _ = open.Start(authURL) fmt.Printf("If your browser doesn't open automatically go to the following link: %s\n", authURL) fmt.Printf("Log in and authorize rclone for access\n") var authCode string if useWebServer { // Read the code, and exchange it for a token. fmt.Printf("Waiting for code...\n") authCode = <-server.code if authCode != "" { fmt.Printf("Got code\n") } else { return fmt.Errorf("Failed to get code") } } else { // 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) }
// Config does the initial creation of the token // // It may run an internal webserver to receive the results func Config(id, name string, config *oauth2.Config) error { changed := overrideCredentials(name, config) automatic := fs.ConfigFile.MustValue(name, fs.ConfigAutomatic) != "" // 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 } } // Detect whether we should use internal web server useWebServer := false switch config.RedirectURL { case RedirectURL, RedirectPublicURL, RedirectLocalhostURL: useWebServer = true if automatic { break } fmt.Printf("Use auto config?\n") fmt.Printf(" * Say Y if not sure\n") fmt.Printf(" * Say N if you are working on a remote or headless machine\n") auto := fs.Confirm() if !auto { fmt.Printf("For this to work, you will need rclone available on a machine that has a web browser available.\n") fmt.Printf("Execute the following on your machine:\n") if changed { fmt.Printf("\trclone authorize %q %q %q\n", id, config.ClientID, config.ClientSecret) } else { fmt.Printf("\trclone authorize %q\n", id) } fmt.Println("Then paste the result below:") code := "" for code == "" { fmt.Printf("result> ") code = strings.TrimSpace(fs.ReadLine()) } token := &oauth2.Token{} err := json.Unmarshal([]byte(code), token) if err != nil { return err } return putToken(name, token) } case TitleBarRedirectURL: useWebServer = automatic if !automatic { fmt.Printf("Use auto config?\n") fmt.Printf(" * Say Y if not sure\n") fmt.Printf(" * Say N if you are working on a remote or headless machine or Y didn't work\n") useWebServer = fs.Confirm() } if useWebServer { // copy the config and set to use the internal webserver configCopy := *config config = &configCopy config.RedirectURL = RedirectURL } } // Make random state stateBytes := make([]byte, 16) _, err := rand.Read(stateBytes) if err != nil { return err } state := fmt.Sprintf("%x", stateBytes) authURL := config.AuthCodeURL(state) // Prepare webserver server := authServer{ state: state, bindAddress: bindAddress, authURL: authURL, } if useWebServer { server.code = make(chan string, 1) go server.Start() defer server.Stop() authURL = "http://" + bindAddress + "/auth" } // Generate a URL for the user to visit for authorization. _ = open.Start(authURL) fmt.Printf("If your browser doesn't open automatically go to the following link: %s\n", authURL) fmt.Printf("Log in and authorize rclone for access\n") var authCode string if useWebServer { // Read the code, and exchange it for a token. fmt.Printf("Waiting for code...\n") authCode = <-server.code if authCode != "" { fmt.Printf("Got code\n") } else { return errors.New("failed to get code") } } else { // 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 errors.Wrap(err, "failed to get token") } // Print code if we do automatic retrieval if automatic { result, err := json.Marshal(token) if err != nil { return errors.Wrap(err, "failed to marshal token") } fmt.Printf("Paste the following into your remote machine --->\n%s\n<---End paste", result) } return putToken(name, token) }