diff --git a/backend/box/box.go b/backend/box/box.go index 4f38955eb..659ecf7de 100644 --- a/backend/box/box.go +++ b/backend/box/box.go @@ -202,7 +202,9 @@ func refreshJWTToken(ctx context.Context, jsonFile string, boxSubType string, na signingHeaders := getSigningHeaders(boxConfig) queryParams := getQueryParams(boxConfig) client := fshttp.NewClient(ctx) - err = jwtutil.Config("box", name, tokenURL, *claims, signingHeaders, queryParams, privateKey, m, client) + // When using OAuth2.0 with JWT Box appears to expire their tokens earlier than expected. + // To counter this, we manually set the token to expire 2 minutes earlier than expected + err = jwtutil.Config("box", name, tokenURL, *claims, signingHeaders, queryParams, privateKey, m, client, 2*time.Minute) return err } diff --git a/lib/jwtutil/jwtutil.go b/lib/jwtutil/jwtutil.go index 43ae3f4bb..f99b0e43e 100644 --- a/lib/jwtutil/jwtutil.go +++ b/lib/jwtutil/jwtutil.go @@ -32,7 +32,7 @@ func RandomHex(n int) (string, error) { } // Config configures rclone using JWT -func Config(id, name, url string, claims jwt.Claims, headerParams map[string]interface{}, queryParams map[string]string, privateKey *rsa.PrivateKey, m configmap.Mapper, client *http.Client) (err error) { +func Config(id, name, url string, claims jwt.Claims, headerParams map[string]interface{}, queryParams map[string]string, privateKey *rsa.PrivateKey, m configmap.Mapper, client *http.Client, earlyExpire time.Duration) (err error) { jwtToken := jwt.NewWithClaims(jwt.SigningMethodRS256, claims) for key, value := range headerParams { jwtToken.Header[key] = value @@ -93,7 +93,7 @@ func Config(id, name, url string, claims jwt.Claims, headerParams map[string]int } e := result.ExpiresIn if e != 0 { - token.Expiry = time.Now().Add(time.Duration(e) * time.Second) + token.Expiry = time.Now().Add(time.Duration(e)*time.Second - earlyExpire) } return oauthutil.PutToken(name, m, token, true) } diff --git a/lib/oauthutil/oauthutil.go b/lib/oauthutil/oauthutil.go index 2f3d5278f..b1a525ae5 100644 --- a/lib/oauthutil/oauthutil.go +++ b/lib/oauthutil/oauthutil.go @@ -18,7 +18,6 @@ import ( "github.com/rclone/rclone/fs" "github.com/rclone/rclone/fs/config" "github.com/rclone/rclone/fs/config/configmap" - "github.com/rclone/rclone/fs/fserrors" "github.com/rclone/rclone/fs/fshttp" "github.com/rclone/rclone/lib/random" "github.com/skratchdot/open-golang/open" @@ -266,11 +265,13 @@ func (ts *TokenSource) Token() (*oauth2.Token, error) { if !ts.token.Valid() { if ts.reReadToken() { 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), - ) - } + } //else if ts.token.RefreshToken == "" { + // FIXME need to detect JWT here + // Box authentication OAuth2.0 with JWT does not provide refresh tokens + // return nil, fserrors.FatalError( + // fmt.Errorf("token expired and there's no refresh token - manually refresh with \"rclone config reconnect %s:\"", ts.name), + //) + //} } // Make a new token source if required