I am trying to use AAD delegated permission Bearer tokens for a Visio VSTO addin to create SharePoint Online pages using CSOM. Initially I was able to get this working entering username / password following Modern Authentication with CSOM for Net Standard
However, I would like for the user to select an existing AAD account. When I attempt to use the following code the Bearer token "aud" claim is consistently set to "00000003-0000-0000-c000-000000000000" which is the Graph API. Whilst a ClientContext object is returned I am getting a HTTP 401 Unauthorized error when performing a page lookup.
The code is as follows
//
// Get Client App
//
var ClientApp = (PublicClientApplication)PublicClientApplicationBuilder.Create(<AAD App ID>)
.WithDefaultRedirectUri()
.WithTenantId(<AAD Tenant ID>)
.WithAuthority(AzureCloudInstance.AzurePublic, <AAD Tenant ID>)
.Build();
//
// Prompt for user to select preferred AAD account
// The returned JWT Bearer Token "aud" claim is 00000003-0000-0000-c000-000000000000
//
var Token = ClientApp.AcquireTokenInteractive(scopes)
.WithPrompt(Prompt.SelectAccount)
.WithParentActivityOrWindow(GetActiveWindow())
.ExecuteAsync()
.GetAwaiter()
.GetResult();
//
// Get client Context
//
var ClientContext = AuthenticationManager.GetAzureADAccessTokenAuthenticatedContext(<SharePoint Site URL>, Token.AccessToken);
//
// Using the Client Context to query the Site results in HTTP 401
//
ClientContext.Load(ClientContext.Web, p => p.Title, t => t.Description);
ClientContext.ExecuteQuery();
Looking at the code for the AuthenticationManager class in the above link I can see that the AAD Bearer request is passing the following resource request parameter to the SharePoint online URL:
var body = $"resource={resource}&client_id={clientId}&grant_type=password&username={HttpUtility.UrlEncode(username)}&password={HttpUtility.UrlEncode(password)}";
So it seems that AAD is setting the Bearer token "aud" claim based upon this parameter. However, when I try and add this parameter using 'WithExtraQueryParameters' I am getting the following error: "AADSTS901002: The 'resource' request parameter is not supported"
Ok, I figured out the problem. The scope needs to be prefixed with the resource:
string[] scopes = { "https://<domain>.sharepoint.com/AllSites.Write", "user.read" }
Then retrieve the token
this.Token = await ClientApp.AcquireTokenInteractive(scopes)
.WithPrompt(Prompt.SelectAccount)
.WithParentActivityOrWindow(GetActiveWindow())
.ExecuteAsync();