From dedad9f071d81a2b6bf980d5f48d7997cae160af Mon Sep 17 00:00:00 2001 From: Nick Craig-Wood Date: Fri, 5 Jan 2024 12:43:19 +0000 Subject: [PATCH] onedrive: fix "unauthenticated: Unauthenticated" errors when uploading Before this change, sometimes when uploading files the onedrive servers return 401 Unauthorized errors with the text "unauthenticated: Unauthenticated". This is because we are sending the Authorization header with the request and it says in the docs that we shouldn't. https://learn.microsoft.com/en-us/graph/api/driveitem-createuploadsession?view=graph-rest-1.0#remarks > If you include the Authorization header when issuing the PUT call, > it may result in an HTTP 401 Unauthorized response. Only send the > Authorization header and bearer token when issuing the POST during > the first step. Don't include it when you issue the PUT call. This patch fixes the problem by doing the PUT request with an unauthenticated client. Fixes #7405 See: https://forum.rclone.org/t/onedrive-unauthenticated-when-trying-to-copy-sync-but-can-use-lsd/41149/ See: https://forum.rclone.org/t/onedrive-unauthenticated-issue/43792/ --- backend/onedrive/onedrive.go | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/backend/onedrive/onedrive.go b/backend/onedrive/onedrive.go index 5d8c68d03..291ce3435 100644 --- a/backend/onedrive/onedrive.go +++ b/backend/onedrive/onedrive.go @@ -27,6 +27,7 @@ import ( "github.com/rclone/rclone/fs/config/configstruct" "github.com/rclone/rclone/fs/config/obscure" "github.com/rclone/rclone/fs/fserrors" + "github.com/rclone/rclone/fs/fshttp" "github.com/rclone/rclone/fs/hash" "github.com/rclone/rclone/fs/operations" "github.com/rclone/rclone/fs/walk" @@ -688,6 +689,7 @@ type Fs struct { ci *fs.ConfigInfo // global config features *fs.Features // optional features srv *rest.Client // the connection to the OneDrive server + unAuth *rest.Client // no authentication connection to the OneDrive server dirCache *dircache.DirCache // Map of directory path to directory id pacer *fs.Pacer // pacer for API calls tokenRenewer *oauthutil.Renew // renew the token on expiry @@ -946,8 +948,9 @@ func NewFs(ctx context.Context, name, root string, m configmap.Mapper) (fs.Fs, e TokenURL: authEndpoint[opt.Region] + tokenPath, } + client := fshttp.NewClient(ctx) root = parsePath(root) - oAuthClient, ts, err := oauthutil.NewClient(ctx, name, m, oauthConfig) + oAuthClient, ts, err := oauthutil.NewClientWithBaseClient(ctx, name, m, oauthConfig, client) if err != nil { return nil, fmt.Errorf("failed to configure OneDrive: %w", err) } @@ -961,6 +964,7 @@ func NewFs(ctx context.Context, name, root string, m configmap.Mapper) (fs.Fs, e driveID: opt.DriveID, driveType: opt.DriveType, srv: rest.NewClient(oAuthClient).SetRoot(rootURL), + unAuth: rest.NewClient(client).SetRoot(rootURL), pacer: fs.NewPacer(ctx, pacer.NewDefault(pacer.MinSleep(minSleep), pacer.MaxSleep(maxSleep), pacer.DecayConstant(decayConstant))), hashType: QuickXorHashType, } @@ -2245,7 +2249,7 @@ func (o *Object) uploadFragment(ctx context.Context, url string, start int64, to Options: options, } _, _ = chunk.Seek(skip, io.SeekStart) - resp, err = o.fs.srv.Call(ctx, &opts) + resp, err = o.fs.unAuth.Call(ctx, &opts) if err != nil && resp != nil && resp.StatusCode == http.StatusRequestedRangeNotSatisfiable { fs.Debugf(o, "Received 416 error - reading current position from server: %v", err) pos, posErr := o.getPosition(ctx, url)