From f1226f19b259f9e0a5cb80389fe7f2c92d60233f Mon Sep 17 00:00:00 2001 From: Nick Craig-Wood Date: Sat, 12 Sep 2015 14:17:39 +0100 Subject: [PATCH] drive, googlecloudstorage: optionally use auto config for the oauth token --- amazonclouddrive/amazonclouddrive.go | 6 ++-- docs/content/drive.md | 23 ++++++++++--- docs/content/googlecloudstorage.md | 24 +++++++++++--- oauthutil/oauthutil.go | 49 +++++++++++++++++++--------- 4 files changed, 73 insertions(+), 29 deletions(-) diff --git a/amazonclouddrive/amazonclouddrive.go b/amazonclouddrive/amazonclouddrive.go index 00ed959e8..b440179af 100644 --- a/amazonclouddrive/amazonclouddrive.go +++ b/amazonclouddrive/amazonclouddrive.go @@ -31,8 +31,6 @@ import ( const ( rcloneClientID = "amzn1.application-oa2-client.6bf18d2d1f5b485c94c8988bb03ad0e7" rcloneClientSecret = "k8/NyszKm5vEkZXAwsbGkd6C3NrbjIqMg4qEhIeF14Szub2wur+/teS3ubXgsLe9//+tr/qoqK+lq6mg8vWkoA==" - bindAddress = "127.0.0.1:53682" - redirectURL = "http://" + bindAddress + "/" folderKind = "FOLDER" fileKind = "FILE" assetKind = "ASSET" @@ -54,7 +52,7 @@ var ( }, ClientID: rcloneClientID, ClientSecret: fs.Reveal(rcloneClientSecret), - RedirectURL: redirectURL, + RedirectURL: oauthutil.RedirectURL, } ) @@ -64,7 +62,7 @@ func init() { Name: "amazon cloud drive", NewFs: NewFs, Config: func(name string) { - err := oauthutil.ConfigWithWebserver(name, acdConfig, bindAddress) + err := oauthutil.Config(name, acdConfig) if err != nil { log.Fatalf("Failed to configure token: %v", err) } diff --git a/docs/content/drive.md b/docs/content/drive.md index 7e16414d2..f65e10923 100644 --- a/docs/content/drive.md +++ b/docs/content/drive.md @@ -1,7 +1,7 @@ --- title: "Google drive" description: "Rclone docs for Google drive" -date: "2015-05-10" +date: "2015-09-12" --- Google Drive @@ -39,10 +39,16 @@ client_id> Google Application Client Secret - leave blank to use rclone's. client_secret> Remote config -Go to the following link in your browser -https://accounts.google.com/o/oauth2/auth?access_type=&approval_prompt=&client_id=XXXXXXXXXXXX.apps.googleusercontent.com&redirect_uri=urn%3XXXXX%3Awg%3Aoauth%3XX.0%3Aoob&response_type=code&scope=https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fdrive&state=state -Log in, then type paste the token that is returned in the browser here -Enter verification code> X/XXXXXXXXXXXXXXXXXX-XXXXXXXXX.XXXXXXXXX-XXXXX_XXXXXXX_XXXXXXX +Use auto config? + * Say Y if not sure + * Say N if you are working on a remote or headless machine +y) Yes +n) No +y/n> y +If your browser doesn't open automatically go to the following link: http://127.0.0.1:53682/auth +Log in and authorize rclone for access +Waiting for code... +Got code -------------------- [remote] client_id = @@ -55,6 +61,13 @@ d) Delete this remote y/e/d> y ``` +Note that rclone runs a webserver on your local machine to collect the +token as returned from Google if you use auto config mode. This only +runs from the moment it opens your browser to the moment you get back +the verification code. This is on `http://127.0.0.1:53682/` and this +it may require you to unblock it temporarily if you are running a host +firewall, or use manual mode. + You can then use it like this, List directories in top level of your drive diff --git a/docs/content/googlecloudstorage.md b/docs/content/googlecloudstorage.md index 6f15fe8d6..5de71ffbb 100644 --- a/docs/content/googlecloudstorage.md +++ b/docs/content/googlecloudstorage.md @@ -1,7 +1,7 @@ --- title: "Google Cloud Storage" description: "Rclone docs for Google Cloud Storage" -date: "2014-07-17" +date: "2015-09-12" --- Google Cloud Storage @@ -70,10 +70,17 @@ Choose a number from below, or type in your own value 5) publicReadWrite bucket_acl> 2 Remote config -Go to the following link in your browser -https://accounts.google.com/o/oauth2/auth?access_type=&approval_prompt=&client_id=XXXXXXXXXXXX.apps.googleusercontent.com&redirect_uri=urn%3Aietf%3Awg%3Aoauth%3A2.0%3Aoob&response_type=code&scope=https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fdevstorage.full_control&state=state -Log in, then type paste the token that is returned in the browser here -Enter verification code> x/xxxxxxxxxxxxxxxxxxxxxxxxxxxx.xxxxxxxxxxxxxxxxxxxxxx_xxxxxxxx +Remote config +Use auto config? + * Say Y if not sure + * Say N if you are working on a remote or headless machine +y) Yes +n) No +y/n> y +If your browser doesn't open automatically go to the following link: http://127.0.0.1:53682/auth +Log in and authorize rclone for access +Waiting for code... +Got code -------------------- [remote] type = google cloud storage @@ -90,6 +97,13 @@ d) Delete this remote y/e/d> y ``` +Note that rclone runs a webserver on your local machine to collect the +token as returned from Google if you use auto config mode. This only +runs from the moment it opens your browser to the moment you get back +the verification code. This is on `http://127.0.0.1:53682/` and this +it may require you to unblock it temporarily if you are running a host +firewall, or use manual mode. + This remote is called `remote` and can now be used like this See all the buckets in your project diff --git a/oauthutil/oauthutil.go b/oauthutil/oauthutil.go index 3fb851b1a..696a683b1 100644 --- a/oauthutil/oauthutil.go +++ b/oauthutil/oauthutil.go @@ -15,13 +15,21 @@ import ( "golang.org/x/oauth2" ) -// configKey is the key used to store the token under -const configKey = "token" +const ( + // configKey is the key used to store the token under + configKey = "token" -// TitleBarRedirectURL is the OAuth2 redirect URL to use when the authorization -// code should be returned in the title bar of the browser, with the page text -// prompting the user to copy the code and paste it in the application. -const TitleBarRedirectURL = "urn:ietf:wg:oauth:2.0:oob" + // TitleBarRedirectURL is the OAuth2 redirect URL to use when the authorization + // code should be returned in the title bar of the browser, with the page text + // prompting the user to copy the code and paste it in the application. + TitleBarRedirectURL = "urn:ietf:wg:oauth:2.0:oob" + + // BindAddress is binding for local webserver when active + bindAddress = "127.0.0.1:53682" + + // RedirectURL is redirect to local webserver when active + RedirectURL = "http://" + bindAddress + "/" +) // oldToken contains an end-user's tokens. // This is the data you must store to persist authentication. @@ -144,8 +152,8 @@ func NewClient(name string, config *oauth2.Config) (*http.Client, error) { // Config does the initial creation of the token // -// It runs an internal webserver to receive the results -func ConfigWithWebserver(name string, config *oauth2.Config, bindAddress string) error { +// It may run an internal webserver to receive the results +func Config(name string, config *oauth2.Config) error { // See if already have a token tokenString := fs.ConfigFile.MustValue(name, "token") if tokenString != "" { @@ -155,6 +163,22 @@ func ConfigWithWebserver(name string, config *oauth2.Config, bindAddress string) } } + // Detect whether we should use internal web server + useWebServer := false + switch config.RedirectURL { + case RedirectURL: + 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\n") + useWebServer = fs.Confirm() + // 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) @@ -170,7 +194,7 @@ func ConfigWithWebserver(name string, config *oauth2.Config, bindAddress string) bindAddress: bindAddress, authUrl: authUrl, } - if bindAddress != "" { + if useWebServer { server.code = make(chan string, 1) go server.Start() defer server.Stop() @@ -183,7 +207,7 @@ func ConfigWithWebserver(name string, config *oauth2.Config, bindAddress string) fmt.Printf("Log in and authorize rclone for access\n") var authCode string - if bindAddress != "" { + if useWebServer { // Read the code, and exchange it for a token. fmt.Printf("Waiting for code...\n") authCode = <-server.code @@ -204,11 +228,6 @@ func ConfigWithWebserver(name string, config *oauth2.Config, bindAddress string) return putToken(name, token) } -// Config does the initial creation of the token -func Config(name string, config *oauth2.Config) error { - return ConfigWithWebserver(name, config, "") -} - // Local web server for collecting auth type authServer struct { state string