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