I have a mobile app (Flutter) where I'm allowing the user to backup their data to their personal OneDrive, so if they lose their device they can restore data from their OneDrive. I'm using a delegated authentication workflow to access personal / consumer OneDrive using the Microsoft graph REST API, logging in using OAuth, with the scope Files.ReadWrite.All (and offline_access). The problem is that after uploading a file, I cannot then download the contents of the same file, even though it is the same user, the same scopes, the same device, the same app, the same login session. I can't understand why.
Here's the scenario:
I'm using flutter_appauth to request the user to login to their OneDrive account. This launches the OAuth login, which succeeds and returns an access token and refresh token:
final AuthorizationTokenResponse result = await appAuth.authorizeAndExchangeCode( AuthorizationTokenRequest( // This is the Application (client) ID from Azure App Registrations: oauthConfiguration.oauthClientId, // This is my redirect URL, eg "com.someapp://oauthcallback/" oauthConfiguration.oauthRedirectUrl, serviceConfiguration: AuthorizationServiceConfiguration( authorizationEndpoint: 'https://login.microsoftonline.com/common/oauth2/v2.0/authorize', tokenEndpoint: 'https://login.microsoftonline.com/common/oauth2/v2.0/token' ), scopes: ['Files.ReadWrite.All','User.Read','offline_access'], externalUserAgent: ExternalUserAgent.ephemeralAsWebAuthenticationSession, ), );I then use this access token (using flutter_appauth which handles refreshing) to write a file to the user's OneDrive. This succeeds.
I can then see the file in the web version of OneDrive, and GET the metadata for this file, no problem
The problem is that I can't download the file content - I always get
{"error":{"code":"unauthenticated","message":"Unauthenticated"}}
This is what I'm doing to download the file:
await httpClient.get(
Uri.https(
"graph.microsoft.com",
"v1.0/me/drive/root:/path/to/file.txt:/content",
),
headers: {"Authorization": "Bearer $oAuthToken"},
)
I've also tried using the download URL directly (from the @microsoft.graph.downloadUrl field from the file's metadata), this yields the same result.
I'm struggling to understand why this is happening, and what I can do to solve this. I'm using Files.ReadWrite.All scope. I've verified that full read/write access is granted to the app on authentication via the user's Microsoft account privacy page:
I've verified that the App Registration in Azure with the Client ID that I'm using during the OAuth process has the same scopes which are being requested and returned to the app:
I've tried multiple devices, I've tried waiting for a few hours after the files have been uploaded to allow eventual consistency to catch up. I've tried using consumers oauth endpoint instead of common. The only clue I can get is I get this header with the error response:
www-authenticate: Wlid1.1 realm="WindowsLive", fault="BadContextToken", ...
Which suggests for some reason the access token (the same one I'm using to upload the file) is not valid to download the file. To repeat, this is for personal / consumer OneDrive only.

