Question: Microsoft Graph .NET SDK on-behalf-of flow returns Access Denied 403 for Sites/Files

I'm trying to implement on-behalf-of user flow for Microsoft Graph API. I'm using Microsoft Graph .NET SDK and I'm encountering Access Denied (status code 403) for my requests. I'm not sure how to correctly set up permissions for users of my organization in Active Azure Directory. I'm trying to implement SharePoint / OneDrive file operations like list files/download/upload etc. with on-behalf-of flow. I want to be able to access any drive/site files and be able to upload/download/list.
The way my application is designed is like this:

But instead of Desktop WPF app, I have next.js website using next-auth. This is how I define my Azure Active Directory provider to sign-in in my next.js application using next-auth:
providers: [
    AzureADProvider({
      clientId: process.env.AZURE_AD_CLIENT_ID, // NextAuth client id in AAD
      clientSecret: process.env.AZURE_AD_CLIENT_SECRET, // NextAuth client secret value in AAD
      tenantId: process.env.AZURE_AD_TENANT_ID, 
      authorization: {
        params: {
          scope: "openid email profile offline_access api://NextAuthAPI/.default",
          prompt: "consent",
        }
      },
    }),
  ]

In my AAD I registered my frontend app and web api as NextAuth and NextAuthAPI, generated client secret for both of them. For the NextAuthAPI (webAPI) I created a scope:

and added these permissions:

For the NextAuth (next.js) app I added this permission:

After signing in my next.js frontend application, I'm able to receive an access token with:
"aud": "api://NextAuthAPI",
"scp": "access_as_user"
....

Then I provide this access_token to the webAPI and create client like this:
var scopes = new[] { "https://graph.microsoft.com/.default" };

var tenantId = "c0dc-------------------5ce7";
var clientId = "087e66-----------------------b5";
var clientSecret = "p5Q8Q-----------------------JddpK";

// using Azure.Identity;
var options = new OnBehalfOfCredentialOptions
{
    AuthorityHost = AzureAuthorityHosts.AzurePublicCloud
};

var oboToken = /* HERE I PASTE ACCESS_TOKEN FROM NEXTJS APP */;

var onBehalfOfCredential = new OnBehalfOfCredential(tenantId, clientId, clientSecret, oboToken, options);

m_GraphClient = new GraphServiceClient(onBehalfOfCredential, scopes);

Now, when I have the m_GraphClient initialized, I'm trying to make some requests. This request works for me:
var response = await m_GraphClient.Me.GetAsync();

But something like this:
var response2 = await m_GraphClient.Sites.GetAllSites.GetAsync();

throws an ODataError exception with status code 403 and message "Access denied".
Packages I use:

Microsoft.Graph 5.11.0 (backend)
Azure.Identity 1.9.0 (backend)
Next.JS 13.4.5-canary.2 (frontend)
next-auth 4.22.1 (frontend)



Answer:
You want to be able to access any drive/site files and be able to upload/download/list. Then on-behalf-of flow isn't suitable for you. OBO flow will generate access token with Delegated API permission, which can't be used to access any others' drive/site files. We need to use access token with Application API permission.
Then in this scenario, we can only use client credential flow so that we can generate access token with Application API permission. First, grant application API permission in Azure portal. For example, we are trying to use this Graph API.

Then in your API application, your code should look like this which used ClientSecretCredential instead of your OnBehalfOfCredential:
var scopes = new[] { "https://graph.microsoft.com/.default" };
var tenantId = "tenant_id";
var clientId = "client_id";
var clientSecret = "client_secret";
var clientSecretCredential = new ClientSecretCredential(
                            tenantId, clientId, clientSecret);
var graphClient = new GraphServiceClient(clientSecretCredential, scopes);