OneDrive config auth failure - body must contain scope

What is the problem you are having with rclone?

Hello,

I'm trying to complete OneDrive config using custom client ID. It successfully redirects to the browser and I see

Success!
All done. Please go back to rclone.

But the command output says

2022/08/03 17:06:55 Fatal error: failed to get token: invalid character '<' looking for beginning of value

I reran with rclone config -vv --dump responses --log-file /tmp/rclone.log and see a REQUEST URL that contains a scope http parameter

https://login.microsoftonline.com/da6.../oauth2/v2.0/authorize?access_type=offline&client_id=ec14...&redirect_uri=http%3A%2F%2Flocalhost%3A53682%2F&response_type=code&scope=Files.Read+Files.ReadWrite+Files.Read.All+Files.ReadWrite.All+Sites.Read.All+offline_access&state=YLzwO9gv4r1LtI3xsMeCig

But burried in the JSON response I see it claiming that scope should be part of the BODY.

$Config={
	"iErrorDesc": 0,
	"iErrorTitle": 0,
	"strMainMessage": "We received a bad request.",
	"strAdditionalMessage": "",
	"strServiceExceptionMessage": "AADSTS900144: The request body must contain the following parameter: \u0026#39;scope\u0026#39;.",
	"strTraceId": "ce627b70-6e47-4bdc-84ec-dc911249d700",
	"iErrorCode": 900144,
	"iHttpErrorCode": 400,
...

I found a possibly related post here: http - oauth2 error AADSTS90014: The request body must contain the following parameter: 'grant_type' - Stack Overflow where one respondent says

You shouldn't send grant_type neither in params nor in headers. Those should be sent in body params then only it will work.

Not sure if that's the real root cause, but looking for help (obviously). Thanks in advance.

Run the command 'rclone version' and share the full output of the command.

rclone v1.59.0
- os/version: darwin 12.3.1 (64 bit)
- os/kernel: 21.4.0 (x86_64)
- os/type: darwin
- os/arch: amd64
- go/version: go1.18.3
- go/linking: dynamic
- go/tags: cmount

Which cloud storage system are you using? (eg Google Drive)

onedrive

The command you were trying to run (eg rclone copy /tmp remote:tmp)

rclone config

The rclone config contents with secrets removed.

[onedrive-kmarx]
type = onedrive
client_id = ec1...
client_secret = e2f...
# Manually added to try and work around "Error: Auth Error; No code returned by remote server"
# per https://rclone.org/onedrive/
auth_url = https://login.microsoftonline.com/da6.../oauth2/v2.0/authorize
token_url = https://login.microsoftonline.com/da6.../oauth2/v2.0/authorize

A log from the command with the -vv flag

2022/08/03 16:23:48 DEBUG : rclone: Version "v1.59.0" starting with parameters ["rclone" "config" "-vv" "--log-file" "/tmp/rclone.log"]
2022/08/03 16:23:48 DEBUG : Using config file from "/Users/kmarx/.config/rclone/rclone.conf"
2022/08/03 16:23:55 DEBUG : onedrive-kmarx: config in: state="*all", result=""
2022/08/03 16:23:55 DEBUG : onedrive-kmarx: config out: out=&{State:*all-set,0,false Option:ec1... OAuth:<nil> Error: Result:}, err=<nil>
2022/08/03 16:23:55 DEBUG : onedrive-kmarx: config: reading config parameter "client_id"
2022/08/03 16:23:56 DEBUG : onedrive-kmarx: config in: state="*all-set,0,false", result="ec1..."
2022/08/03 16:23:56 DEBUG : onedrive-kmarx: config out: out=&{State:*all,1,false Option:<nil> OAuth:<nil> Error: Result:}, err=<nil>
2022/08/03 16:23:56 DEBUG : onedrive-kmarx: config in: state="*all,1,false", result=""
2022/08/03 16:23:56 DEBUG : onedrive-kmarx: config out: out=&{State:*all-set,1,false Option:e2f... OAuth:<nil> Error: Result:}, err=<nil>
2022/08/03 16:23:56 DEBUG : onedrive-kmarx: config: reading config parameter "client_secret"
2022/08/03 16:23:57 DEBUG : onedrive-kmarx: config in: state="*all-set,1,false", result="e2f..."
2022/08/03 16:23:57 DEBUG : onedrive-kmarx: config out: out=&{State:*all,2,false Option:<nil> OAuth:<nil> Error: Result:}, err=<nil>
2022/08/03 16:23:57 DEBUG : onedrive-kmarx: config in: state="*all,2,false", result=""
2022/08/03 16:23:57 DEBUG : onedrive-kmarx: config out: out=&{State:*all,3,false Option:<nil> OAuth:<nil> Error: Result:}, err=<nil>
2022/08/03 16:23:57 DEBUG : onedrive-kmarx: config in: state="*all,3,false", result=""
2022/08/03 16:23:57 DEBUG : onedrive-kmarx: config out: out=&{State:*all,4,false Option:<nil> OAuth:<nil> Error: Result:}, err=<nil>
2022/08/03 16:23:57 DEBUG : onedrive-kmarx: config in: state="*all,4,false", result=""
2022/08/03 16:23:57 DEBUG : onedrive-kmarx: config out: out=&{State:*all,5,false Option:<nil> OAuth:<nil> Error: Result:}, err=<nil>
2022/08/03 16:23:57 DEBUG : onedrive-kmarx: config in: state="*all,5,false", result=""
2022/08/03 16:23:57 DEBUG : onedrive-kmarx: config out: out=&{State:*all-set,5,false Option:global OAuth:<nil> Error: Result:}, err=<nil>
2022/08/03 16:23:57 DEBUG : onedrive-kmarx: config: reading config parameter "region"
2022/08/03 16:23:58 DEBUG : onedrive-kmarx: config in: state="*all-set,5,false", result="global"
2022/08/03 16:23:58 DEBUG : onedrive-kmarx: config out: out=&{State:*all,6,false Option:<nil> OAuth:<nil> Error: Result:}, err=<nil>
2022/08/03 16:23:58 DEBUG : onedrive-kmarx: config in: state="*all,6,false", result=""
2022/08/03 16:23:58 DEBUG : onedrive-kmarx: config out: out=&{State:*all,7,false Option:<nil> OAuth:<nil> Error: Result:}, err=<nil>
2022/08/03 16:23:58 DEBUG : onedrive-kmarx: config in: state="*all,7,false", result=""
2022/08/03 16:23:58 DEBUG : onedrive-kmarx: config out: out=&{State:*all,8,false Option:<nil> OAuth:<nil> Error: Result:}, err=<nil>
2022/08/03 16:23:58 DEBUG : onedrive-kmarx: config in: state="*all,8,false", result=""
2022/08/03 16:23:58 DEBUG : onedrive-kmarx: config out: out=&{State:*all,9,false Option:<nil> OAuth:<nil> Error: Result:}, err=<nil>
2022/08/03 16:23:58 DEBUG : onedrive-kmarx: config in: state="*all,9,false", result=""
2022/08/03 16:23:58 DEBUG : onedrive-kmarx: config out: out=&{State:*all,10,false Option:<nil> OAuth:<nil> Error: Result:}, err=<nil>
2022/08/03 16:23:58 DEBUG : onedrive-kmarx: config in: state="*all,10,false", result=""
2022/08/03 16:23:58 DEBUG : onedrive-kmarx: config out: out=&{State:*all,11,false Option:<nil> OAuth:<nil> Error: Result:}, err=<nil>
2022/08/03 16:23:58 DEBUG : onedrive-kmarx: config in: state="*all,11,false", result=""
2022/08/03 16:23:58 DEBUG : onedrive-kmarx: config out: out=&{State:*all,12,false Option:<nil> OAuth:<nil> Error: Result:}, err=<nil>
2022/08/03 16:23:58 DEBUG : onedrive-kmarx: config in: state="*all,12,false", result=""
2022/08/03 16:23:58 DEBUG : onedrive-kmarx: config out: out=&{State:*all,13,false Option:<nil> OAuth:<nil> Error: Result:}, err=<nil>
2022/08/03 16:23:58 DEBUG : onedrive-kmarx: config in: state="*all,13,false", result=""
2022/08/03 16:23:58 DEBUG : onedrive-kmarx: config out: out=&{State:*all,14,false Option:<nil> OAuth:<nil> Error: Result:}, err=<nil>
2022/08/03 16:23:58 DEBUG : onedrive-kmarx: config in: state="*all,14,false", result=""
2022/08/03 16:23:58 DEBUG : onedrive-kmarx: config out: out=&{State:*all,15,false Option:<nil> OAuth:<nil> Error: Result:}, err=<nil>
2022/08/03 16:23:58 DEBUG : onedrive-kmarx: config in: state="*all,15,false", result=""
2022/08/03 16:23:58 DEBUG : onedrive-kmarx: config out: out=&{State:*all,16,false Option:<nil> OAuth:<nil> Error: Result:}, err=<nil>
2022/08/03 16:23:58 DEBUG : onedrive-kmarx: config in: state="*all,16,false", result=""
2022/08/03 16:23:58 DEBUG : onedrive-kmarx: config out: out=&{State:*all,17,false Option:<nil> OAuth:<nil> Error: Result:}, err=<nil>
2022/08/03 16:23:58 DEBUG : onedrive-kmarx: config in: state="*all,17,false", result=""
2022/08/03 16:23:58 DEBUG : onedrive-kmarx: config out: out=&{State:*all,18,false Option:<nil> OAuth:<nil> Error: Result:}, err=<nil>
2022/08/03 16:23:58 DEBUG : onedrive-kmarx: config in: state="*all,18,false", result=""
2022/08/03 16:23:58 DEBUG : onedrive-kmarx: config out: out=&{State:*all,19,false Option:<nil> OAuth:<nil> Error: Result:}, err=<nil>
2022/08/03 16:23:58 DEBUG : onedrive-kmarx: config in: state="*all,19,false", result=""
2022/08/03 16:23:58 DEBUG : onedrive-kmarx: config out: out=&{State:*all,20,false Option:<nil> OAuth:<nil> Error: Result:}, err=<nil>
2022/08/03 16:23:58 DEBUG : onedrive-kmarx: config in: state="*all,20,false", result=""
2022/08/03 16:23:58 DEBUG : onedrive-kmarx: config out: out=&{State:*all-advanced Option:false OAuth:<nil> Error: Result:}, err=<nil>
2022/08/03 16:23:58 DEBUG : onedrive-kmarx: config: reading config parameter "config_fs_advanced"
2022/08/03 16:24:03 DEBUG : onedrive-kmarx: config in: state="*all-advanced", result="false"
2022/08/03 16:24:03 DEBUG : onedrive-kmarx: config out: out=&{State:*postconfig Option:<nil> OAuth:<nil> Error: Result:}, err=<nil>
2022/08/03 16:24:03 DEBUG : onedrive-kmarx: config in: state="*postconfig", result=""
2022/08/03 16:24:03 DEBUG : onedrive-kmarx: config in: state="", result=""
2022/08/03 16:24:03 DEBUG : onedrive-kmarx: config out: out=&{State:*oauth,choose_type,, Option:<nil> OAuth:<nil> Error: Result:}, err=<nil>
2022/08/03 16:24:03 DEBUG : onedrive-kmarx: config out: out=&{State:*oauth,choose_type,, Option:<nil> OAuth:<nil> Error: Result:}, err=<nil>
2022/08/03 16:24:03 DEBUG : onedrive-kmarx: config in: state="*oauth,choose_type,,", result=""
2022/08/03 16:24:03 DEBUG : onedrive-kmarx: config out: out=&{State:*oauth-confirm,choose_type,, Option:<nil> OAuth:<nil> Error: Result:}, err=<nil>
2022/08/03 16:24:03 DEBUG : onedrive-kmarx: config in: state="*oauth-confirm,choose_type,,", result=""
2022/08/03 16:24:03 DEBUG : onedrive-kmarx: config out: out=&{State:*oauth-islocal,choose_type,, Option:true OAuth:<nil> Error: Result:}, err=<nil>
2022/08/03 16:24:03 DEBUG : onedrive-kmarx: config: reading config parameter "config_is_local"
2022/08/03 16:24:07 DEBUG : onedrive-kmarx: config in: state="*oauth-islocal,choose_type,,", result="true"
2022/08/03 16:24:07 DEBUG : onedrive-kmarx: config out: out=&{State:*oauth-do,choose_type,, Option:<nil> OAuth:<nil> Error: Result:}, err=<nil>
2022/08/03 16:24:07 DEBUG : onedrive-kmarx: config in: state="*oauth-do,choose_type,,", result=""
2022/08/03 16:24:07 NOTICE: Make sure your Redirect URL is set to "http://localhost:53682/" in your custom config.
2022/08/03 16:24:07 DEBUG : Starting auth server on 127.0.0.1:53682
2022/08/03 16:24:07 NOTICE: If your browser doesn't open automatically go to the following link: http://127.0.0.1:53682/auth?state=r8ceul7TUSg0QYmp-2hDYA
2022/08/03 16:24:07 NOTICE: Log in and authorize rclone for access
2022/08/03 16:24:07 NOTICE: Waiting for code...
2022/08/03 16:24:07 DEBUG : Redirecting browser to: https://login.microsoftonline.com/da6.../oauth2/v2.0/authorize?access_type=offline&client_id=ec1...&redirect_uri=http%3A%2F%2Flocalhost%3A53682%2F&response_type=code&scope=Files.Read+Files.ReadWrite+Files.Read.All+Files.ReadWrite.All+Sites.Read.All+offline_access&state=r8ceul7TUSg0QYmp-2hDYA
2022/08/03 16:24:08 DEBUG : Received GET request on auth server to "/"
2022/08/03 16:24:08 NOTICE: Got code
2022/08/03 16:24:08 DEBUG : Closing auth server
2022/08/03 16:24:08 DEBUG : Closed auth server with error: accept tcp 127.0.0.1:53682: use of closed network connection
2022/08/03 16:24:08 DEBUG : onedrive-kmarx: config out: out=<nil>, err=failed to get token: invalid character '<' looking for beginning of value
Error: failed to get token: invalid character '<' looking for beginning of value
Usage:
  rclone config [flags]
  rclone config [command]

Available Commands:
  create      Create a new remote with name, type and options.
  delete      Delete an existing remote.
  disconnect  Disconnects user from remote
  dump        Dump the config file as JSON.
  file        Show path of configuration file in use.
  password    Update password in an existing remote.
  paths       Show paths used for configuration, cache, temp etc.
  providers   List in JSON format all the providers and options.
  reconnect   Re-authenticates user with remote.
  show        Print (decrypted) config file, or the config for a single remote.
  touch       Ensure configuration file exists.
  update      Update options in an existing remote.
  userinfo    Prints info about logged in user of remote.

Flags:
  -h, --help   help for config

Additional help topics:
  rclone config edit       Enter an interactive configuration session.

Use "rclone [command] --help" for more information about a command.
Use "rclone help flags" for to see the global flags.
Use "rclone help backends" for a list of supported services.

2022/08/03 16:24:08 Fatal error: failed to get token: invalid character '<' looking for beginning of value

Hello there, have you tried creating it without using a client id?

Hi and thanks very much for the reply. Pardon my ignorance but I'm a bit paranoid about granting permissions using the globally accessible rclone app client id and secret

Permissions requested
rclone
App info
This application is not published by Microsoft or your organization.
This app would like to:

Read your files
Have full access to your files
Read all files that you have access to
Have full access to all files you have access to
Read items in all site collections
Maintain access to data you have given it access to
View your basic profile

That's why I created my own "app" using the https://rclone.org/onedrive/ " Creating Client ID for OneDrive Business" steps.

It looks like I can revoke those permissions anytime via the https://portal.azure.com/#view/Microsoft_AAD_RegisteredApps/ApplicationsListBlade site. But I'm nervous about exposing sensitive information on my OneDrive account even momentarily.

My (again naive) understanding is that the underlying handshaking would be the same anyway, but just using the generic rclone client_id and secret. Would the proposed test really be expected to behave differently?

It's like letting any 3rd party app use your account. Only the thing you've configured can use it. You are not giving anyone else but the app rclone.conf you've configured. I don't use MS in this case, but Google will show up listed as a 3rd party App that has access to my drive regardless if I use the rclone client ID/secret or my own.

Regardless if you use your own client ID or secret, you can revoke the 3rd party access at anytime by just removing it.

I don't have the MS screens but should be a very similar process.

Hi. Thanks for the explanation. I went ahead and tried using rclone's id/secret and get the same error about the scope needing to be in the BODY.

Furthermore, MS does have a similar screen as Google.

[update: Paranoid alleviated a bit. It's apparently a known app in our "Enterprise applications". I'm simplifying this post and removing the confusing screenshot so as to keep focus on the main issue of getting rclone config working]

Still stuck on the rclone config and apparent issue with the scope params. Thanks!

Can you run rclone config -vv --dump bodies and post the output here? You can redirect the log to a file with --log-file rclone.log.

This will contain confidential info, so I suggest you redact any long strings of base64/hex numbers with XXX.

Hi @ncw and thanks for the help. I did run the command with the beautifully named --dump bodies option and did some redacting. But I can't paste the results here due to forum message size limits:

Body is limited to 32000 characters; you entered 331077.

Is there some portion of the log dump that you don't need to have included so that I can edit it down?

Thanks much!

Can you put it on pastebin or a GitHub gist or share it with me somehow nick@craig-wood.com

Hi @ncw, just keeping this thread in sync: I was finally able to send you the dump bodies log file to the email you kindly posted. And/or can also now put in Pastebin if that works better for you. Thanks again

I've got that. Funny that microsoft send back an entire HTML page!

The summary of that is

AADSTS900144: The request body must contain the following parameter: 'scope'.

As you said above!

Rclone passes the scope in the initial GET request it sends to the browser

2022/08/05 12:20:31 DEBUG : Redirecting browser to: Sign in to your account

Microsoft returns back with the code - we can see that here

2022/08/05 12:20:32 NOTICE: Got code

However it is when we try to exchange the code for a token that it goes wrong.

I don't know why Microsoft needs the scope here - we've given it already and none of the other providers need it here!

This seems the most relevant stack overflow answer I could find

But it relates to using a custom ID.

So you could try that?

I've made an rclone which does add the scopes to the request which you can also try

v1.60.0-beta.6408.74a0800a4.fix-onedrive-oauth on branch fix-onedrive-oauth (uploaded in 15-30 mins)

I'd like to have some justification for this, but I tried it with onedrive and it seemed to work...

Very nice find on the s/o article. I didn't see that (but probably wouldn't have known what to do with it anyway since it seems to be about config via ms UI screens).

Anyway, full disclosure: When I tried @JWHero123's suggestion of running the config w/out using a custom client id, I left in the two lines for

auth_url = https://login.microsoftonline.com/myTenantId/oauth2/v2.0/authorize
token_url = https://login.microsoftonline.com/myTenantId/oauth2/v2.0/token

Before trying your fix for the Body#scope behavior, I redid the default client ID test with the above lines removed and it seems to work fine(!). Apologies for not doing this right in the first place. So, with no custom id, I can do rclone ls kmarx-onedrive:/someDir, and do copy commands, etc.

I wanted to now circle back to the custom client id case for this thread, but can't seem to reproduce the missing scope behavior. Instead, I still get the "All done" screen in a browser, but rclone exits and the log file has

2022/08/06 11:22:34 NOTICE: Got code

But then when it does the POST:

2022/08/06 11:22:34 DEBUG : POST /MY-TENANT-ID/oauth2/v2.0/token HTTP/1.1

It gets this:

Host: login.microsoftonline.com^M
User-Agent: rclone/v1.59.0^M
Content-Length: 1070^M
Authorization: XXXX
Content-Type: application/x-www-form-urlencoded^M
Accept-Encoding: gzip^M
^M
code=0.ARMAG-XREDACTEDX&grant_type=authorization_code&redirect_uri=http%3A%2F%2Flocalhost%3A53682%2F
2022/08/06 11:22:34 DEBUG : >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
2022/08/06 11:22:34 DEBUG : <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
2022/08/06 11:22:34 DEBUG : HTTP RESPONSE (req 0xc0000e2400)
2022/08/06 11:22:34 DEBUG : HTTP/1.1 401 Unauthorized^M
...

And rclone exits with no further output and the command line. That's obviously not what I was getting before.

I just now downloaded your latest changes for the scope issue, and get the same 401 behavior. I suspect I'm doing something (else) stupid here.

I can probably live with not using the custom client id. I'd sort of prefer getting that to work though - maybe just out of stubbornness at this point - and am more than happy to keep working on it if you have continued interest.

That is a little unfriendly! I'd expect to see something printed?

OK

Microsoft auth is really complicated and I'm not an expert at it. I suspect you haven't clicked enough buttons in the control panel, but I don't know which ones you should be clicking! Do you need to enable the rclone app you created in your tenant maybe?

Nothing printed. A bit sad, yes. But all the help I'm getting here more than makes up for it :slight_smile: .

The 401 thing is vexing. I didn't change anything from before when I was getting the body#scope issue. I did go back into the custom app in azure and couldn't see anything obvious the ui/config. (Although the word obvious doesn't really apply to anything in there for me.) My only guess is that perhaps something got locked down since my earlier attempts. I admit that's a stretch.

I'm happy to post screenshots of what I see in there if that would help. Perhaps I should just delete the azure app I created for this (per https://tip.rclone.org/onedrive/#getting-your-own-client-id-and-key) and try again.

I'll maybe take a crack at that later/tomorrow (I just checked the time and realized it's Sunday!).

The fact that you got through the key exchange probably means your app is OK.

I suspect it is permissions of the app to use in your enterprise that is the problem, so I'd focus on that.

Well, it turns out that way back when getting the default id working (see message 10 on 8/6) it smashed my custom id config (since I didn't know/think to create it as a new remote). When re-doing the custom id config, I stupidly used the client secret ID instead of the client secret value. That was the cause of the 401 distractions.

Today I re-created a new client secret and ran config with vanilla rclone install, and - um - it works fine. That is, it works fine without your mods addressing the original issue of this thread

AADSTS900144: The request body must contain the following parameter: 'scope'.

Since I can't reproduce this, I can't test your fix for it either.

Not sure what changed, but all my missteps certainly make me question my own possible user error. Let me know if there's anything you'd like to pursue or follow up on.

Glad you got it working :slightly_smiling_face:

Oauth is very complicated and there are lot of very obscure failure modes.

I'm just glad I didn't have to put yet another provider workaround on the oauth code!

Yup. I wish I had a better resolution to close this thread with, other than that I make a lot of mistakes. I sure appreciate all your help and efforts in any case.

One follow up on the silent command line failures, such as the 401 or even the body/scope thing. It has the feel of some logic path whereby the POST response isn't being checked for errors.

Anyway, I consider the topic resolved for now. Thanks again!

1 Like