Skip to content

Commit

Permalink
rclone authorize: Send and receive extra config options to fix oauth
Browse files Browse the repository at this point in the history
Before this change any backends which required extra config in the
oauth phase (like the `region` for zoho) didn't work with `rclone
authorize`.

This change serializes the extra config and passes it to `rclone
authorize` and returns new config items to be set from rclone
authorize.

`rclone authorize` will still accept its previous configuration
parameters for use with old rclones.

Fixes rclone#5178
  • Loading branch information
ncw committed Apr 8, 2021
1 parent 9d5c5bf commit f52ae75
Show file tree
Hide file tree
Showing 2 changed files with 54 additions and 13 deletions.
24 changes: 19 additions & 5 deletions fs/config/authorize.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ import (
func Authorize(ctx context.Context, args []string, noAutoBrowser bool) error {
ctx = suppressConfirm(ctx)
switch len(args) {
case 1, 3:
case 1, 2, 3:
default:
return errors.Errorf("invalid number of arguments: %d", len(args))
}
Expand All @@ -40,7 +40,13 @@ func Authorize(ctx context.Context, args []string, noAutoBrowser bool) error {
inM[ConfigAuthNoBrowser] = "true"
}

if len(args) == 3 {
// Add extra parameters if supplied
if len(args) == 2 {
err := inM.Decode(args[1])
if err != nil {
return err
}
} else if len(args) == 3 {
inM[ConfigClientID] = args[1]
inM[ConfigClientSecret] = args[2]
}
Expand All @@ -52,13 +58,21 @@ func Authorize(ctx context.Context, args []string, noAutoBrowser bool) error {
outM := configmap.Simple{}
m.ClearSetters()
m.AddSetter(outM)
m.AddGetter(outM, configmap.PriorityNormal)

ri.Config(ctx, name, m)

// Print code if we are doing a manual auth
fmt.Printf("Paste the following into your remote machine --->\n%s\n<---End paste\n", outM["token"])
// Print the code for the user to paste
out := outM["token"]

fs.Debugf(nil, "Set parameters %q", outM)
// If received a config blob, then return one
if len(args) == 2 {
out, err = outM.Encode()
if err != nil {
return err
}
}
fmt.Printf("Paste the following into your remote machine --->\n%s\n<---End paste\n", out)

return nil
}
43 changes: 35 additions & 8 deletions lib/oauthutil/oauthutil.go
Original file line number Diff line number Diff line change
Expand Up @@ -447,19 +447,46 @@ Execute the following on the machine with the web browser (same rclone
version recommended):
`)
if changed {
fmt.Printf("\trclone authorize %q -- %q %q\n", id, oauthConfig.ClientID, oauthConfig.ClientSecret)
// Find the configuration
ri, err := fs.Find(id)
if err != nil {
return errors.Wrap(err, "oauthutil authorize")
}
// Find the overridden options
inM := ri.Options.NonDefault(m)
delete(inM, config.ConfigToken) // delete token as we are refreshing it
for k, v := range inM {
fs.Debugf(nil, "sending %s = %q", k, v)
}
// Encode them into a string
mCopyString, err := inM.Encode()
if err != nil {
return errors.Wrap(err, "oauthutil authorize encode")
}
// Write what the user has to do
if len(mCopyString) > 0 {
fmt.Printf("\trclone authorize %q %q\n", id, mCopyString)
} else {
fmt.Printf("\trclone authorize %q\n", id)
}
fmt.Println("\nThen paste the result below:")
code := config.ReadNonEmptyLine("result> ")
token := &oauth2.Token{}
err := json.Unmarshal([]byte(code), token)
if err != nil {
return err
// Read the updates to the config
var outM configmap.Simple
for {
outM = configmap.Simple{}
code := config.ReadNonEmptyLine("result> ")
err = outM.Decode(code)
if err == nil {
break
}
fmt.Printf("Couldn't decode response - try again (make sure you are using a matching version of rclone on both sides: %v\n", err)
}
return PutToken(name, m, token, true)
// Save the config updates
for k, v := range outM {
m.Set(k, v)
fs.Debugf(nil, "received %s = %q", k, v)
}
return nil
}
}

Expand Down

0 comments on commit f52ae75

Please sign in to comment.