oauthutil: raise fatal error if token expired without refresh token (#5252)

This commit is contained in:
Alex Chen 2021-04-18 12:04:13 +08:00 committed by GitHub
parent 3544e09e95
commit 31a8211afa
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
1 changed files with 24 additions and 8 deletions

View File

@ -15,6 +15,7 @@ import (
"github.com/rclone/rclone/fs" "github.com/rclone/rclone/fs"
"github.com/rclone/rclone/fs/config" "github.com/rclone/rclone/fs/config"
"github.com/rclone/rclone/fs/config/configmap" "github.com/rclone/rclone/fs/config/configmap"
"github.com/rclone/rclone/fs/fserrors"
"github.com/rclone/rclone/fs/fshttp" "github.com/rclone/rclone/fs/fshttp"
"github.com/rclone/rclone/lib/random" "github.com/rclone/rclone/lib/random"
"github.com/skratchdot/open-golang/open" "github.com/skratchdot/open-golang/open"
@ -166,9 +167,11 @@ type TokenSource struct {
expiryTimer *time.Timer // signals whenever the token expires expiryTimer *time.Timer // signals whenever the token expires
} }
// If token has expired then first try re-reading it from the config // If token has expired then first try re-reading it (and its refresh token)
// file in case a concurrently running rclone has updated it already // from the config file in case a concurrently running rclone has updated them
func (ts *TokenSource) reReadToken() bool { // already.
// Returns whether either of the two tokens has been reread.
func (ts *TokenSource) reReadToken() (changed bool) {
tokenString, found := ts.m.Get(config.ConfigToken) tokenString, found := ts.m.Get(config.ConfigToken)
if !found || tokenString == "" { if !found || tokenString == "" {
fs.Debugf(ts.name, "Failed to read token out of config file") fs.Debugf(ts.name, "Failed to read token out of config file")
@ -180,14 +183,23 @@ func (ts *TokenSource) reReadToken() bool {
fs.Debugf(ts.name, "Failed to parse token out of config file: %v", err) fs.Debugf(ts.name, "Failed to parse token out of config file: %v", err)
return false return false
} }
if !newToken.Valid() { if !newToken.Valid() {
fs.Debugf(ts.name, "Loaded invalid token from config file - ignoring") fs.Debugf(ts.name, "Loaded invalid token from config file - ignoring")
return false } else {
fs.Debugf(ts.name, "Loaded fresh token from config file")
changed = true
} }
fs.Debugf(ts.name, "Loaded fresh token from config file") if newToken.RefreshToken != "" && newToken.RefreshToken != ts.token.RefreshToken {
ts.token = newToken fs.Debugf(ts.name, "Loaded new refresh token from config file")
ts.tokenSource = nil // invalidate since we changed the token changed = true
return true }
if changed {
ts.token = newToken
ts.tokenSource = nil // invalidate since we changed the token
}
return changed
} }
// Token returns a token or an error. // Token returns a token or an error.
@ -212,6 +224,10 @@ func (ts *TokenSource) Token() (*oauth2.Token, error) {
if !ts.token.Valid() { if !ts.token.Valid() {
if ts.reReadToken() { if ts.reReadToken() {
changed = true changed = true
} else if ts.token.RefreshToken == "" {
return nil, fserrors.FatalError(
fmt.Errorf("token expired and there's no refresh token - manually refresh with \"rclone config reconnect %s:\"", ts.name),
)
} }
} }