SharePoint API: Can't authenticate 'Sites.FullControl.All' in client_credential flow - active-directory

I've have an App that would like to access SharePoint API.
I've registered it in AD, and gave it the following permissions:
But when I ask it to be authenticated with the following scopes
- https://graph.microsoft.com/User.Read.All
- https://graph.microsoft.com/Group.Read.All
- https://graph.microsoft.com/Sites.Read.All
- https://graph.microsoft.com/Calendars.Read.Shared
- https://graph.microsoft.com/MailboxSettings.Read
- https://graph.microsoft.com/Files.Read.All
- https://graph.microsoft.com/Directory.Read.All
- https://graph.microsoft.com/AuditLog.Read.All
- https://graph.microsoft.com/AuditLog.Read.All
- offline_access
- https://manage.office.com/ActivityFeed.Read
- https://microsoft.sharepoint-df.com/Sites.FullControl.All
- https://microsoft.sharepoint-df.com/Sites.Read.All
- https://microsoft.sharepoint-df.com/User.Read.All
I get this error:
invalid_client&error_description=AADSTS650053:
enter code here`The application 'XXX' asked for scope
'Sites.FullControl.All' that doesn't exist on the resource
'00000003-0000-0ff1-ce00-000000000000'.
Contact the app vendor.
What does this mean that it that doesn't exist on the resource?
With all the other scopes (except SharePoint's) it all works fine

Looks like the Sites.FullControl.All has moved to the Graph API section but trying to add it in the Azure portal results in a different error saying that permission is not currently supported (see on screenshot below).
In my test application, I succeeded using AllSites.FullControl (AllSites as a single word, no periods) and then listing all sites on SharePoint Online tenant with MSAL for .NET.
var app = PublicClientApplicationBuilder.Create(MyAppId)
.WithAuthority("https://login.microsoftonline.com/common", false)
.WithDefaultRedirectUri()
.Build();
return await app
.AcquireTokenInteractive(new string[] { "https://tenantxx.sharepoint.com/.default" })
.WithParentActivityOrWindow(parentWindow) // optional, used to center the browser on the window
.WithPrompt(Prompt.SelectAccount)
.ExecuteAsync();
API Permissions in the Azure portal:

I ran into this same thing. It took a while but this was my clue: How to Access Sharepoint Online API with v1 Azure AD Application and Client Credentials
Using client secret, I could get a token but it would fail. Using a certificate, I was able to successfully authenticate.

Related

How to set up access to Azure blob storage from React app (deployed in Azure web app) with credentials from browser?

I got stuck on trying to access Azure blob storage from React app (thus from browser) with credentials.
And firstly I want to admit, that I am newbie in Azure, so maybe I misunderstood some basic concepts...
My current situation and goal:
I am developing React app (lets say MyReactApp). This app uses some files from Azure blob storage (lets say MyBlobStorage) -> it reads, creates and deletes blobs.
I started to develop it on my local and for this dev purpose I was connecting to MyBlobStorage with SAS - this worked perfectly.
MyReactApp is browser only, so it does not have any backend.
After finishing local development, I deployed it as Azure web app with SAS. What have I done:
created App service (lets say MyAppService)
register app in Azure Active Directory and use it as Identity Provider in MyAppService
After this the app works from Azure url perfectly too.
But my app on Azure should fulfill 2 conditions:
User has to log in with AAD account before access to MyReactApp
App itself must get rid of SAS (because it is not secure as it can be obtained from browser) and use some Azure credentials to connect to Azure blob storage
First condition - user log in:
I enabled "easy" logging in MyAppService -> Authentication and chose users, who can have access.
in Authentication section of app in AAD I set up Web type Redirect Uri as /.auth/login/aad/callback
Still everything works great - the user, who is assigned to the app, can log in and work with the app - so far so good, but now the problem comes
Second condition - I wanted to get rid of the SAS to access MyBlobStorage and use DefaultAzureCredentials:
I turned on managed identity for MyAppService and add it as Storage Blob Data Contributor for MyBlobStorage
I obtained user_impersonation and User.Read Api permissions for my app
I removed SAS and tried to add DefaultAzureCredentials to my code -> but it seems, that they can't be used in browser and only option is InteractiveBrowserCredentails
so I tried to use InteractiveBrowserCredentails like this:
this.interactiveBrowserCredential = new InteractiveBrowserCredential({
tenantId: "<appTenant>", // got from app registration on AAD
clientId: "<appClient>", // got from app registration on AAD
redirectUri: <MyAppServiceURi>/.auth/login/aad/callback // the same as in Azure AAD app,
});
this.blobSC = new BlobServiceClient(Constants.STORAGE_PATH, this.interactiveBrowserCredential);
My current result:
This shows login popup after getting to the page and after another signing in it results in error:
AADSTS9002326: Cross-origin token redemption is permitted only for the
'Single-Page Application' client-type.
I googled it of course and according to some answers I tried to change the Web type of redirect URI to SPA.
I tried it, but some other error showed up:
AADSTS9002325: Proof Key for Code Exchange is required for
cross-origin authorization code redemption.
Surprisingly this should be solved by changing from SPA to Web type...:) So I am trapped...
My expected result
In ideal world, I want to connect MyReactApp to MyBlobStorage without popup and with some secret credentials, just to say something like this.blobSC = new BlobServiceClient(Constants.STORAGE_PATH, credentials);
and be able to work with blobs.
Is it possible to access blob storage from browser without errors of course and ideally without popup, which needs another log in for user?
My complementary questions
Can I use somehow the logging info from the user (from his "easy" AAD logging)? I can get his info with GET call to /.auth/me, maybe it can be utilized, so I can use his info to access the blobs?
The solution should be working on localhost too (I tried to add http://localhost:3000/ to redirect uri, but without success), can it be done?
Thank you all, who read the whole story!

Error "invalid_client" when trying to get a token from Microsoft API

I'm trying to develop a drive solution (Onedrive) in a windev program.
I created an application in Microsoft Azure and created a secret key.
When doing the first request https://login.live.com/oauth20_authorize.srf?client_id={client_id}&scope={scope} &response_type=code&redirect_uri={redirect_uri} I'm redirected on the connection page.
Once I'm connected I get a code back as https://login.live.com/oauth20_authorize.srf?code={code}.
But when I ask for a token posting this request : POST https://login.live.com/oauth20_token.srf Content-Type: application/x-www-form-urlencoded client_id={client_id}&redirect_uri={redirect_uri}&client_secret={client_secret} &code={code}&grant_type=authorization_code
I get this back
{ "error":"invalid_client", "error_description":"The client does not exist or is not enabled for consumers. If you are the application developer, configure a new application through the App Registrations in the Azure Portal at https:\/\/go.microsoft.com\/fwlink\/?linkid=2083908.", "correlation_id":"471e800c-69b4-43c6-a03f-a1f7e9512e6b" }
Thank you for your help.
This error means you are using a Microsoft Account to login your client app, but it is not enabled for that.
To change the setting for an existing AD App, navigate to the Manifest blade of it in the portal, find the signInAudience attribute, set it with AzureADandPersonalMicrosoftAccount or PersonalMicrosoftAccount.

Swaggerbuckle with AAD --Error AADSTS500013: Resource identifier is not provided

I'm trying to use AzureAD to get a token in swagger and test my .netCore2.1 API with it.(using Swashbuckle.AspNetCore 4.0.1)
To do this I completed the following steps
1. Created a Web API project(asp.net Core2.1)
2. Register an Azure AD (AAD) app for the Web API
3. Updated the Web API project to use Azure AD authentication
4. Register an AAD app for the Swagger web site https://localhost:5001/swagger
5. Granted permissions for the Swagger AAD app to access the Web API AAD app
6. Generated a Client Secret for the Swagger AAD app
7. Enabled OAuth2 implicit flow on the Swagger AAD app
8. Added Swagger to the Web API project
When I authenticate, I am getting the following error.
Error AADSTS500013: Resource identifier is not provided .
When I click authorize
I am getting error AADSTS500013: Resource identifier is not provided.
My WebAPI project's startup.cs file goes here
Please help me understand which resource Identifier I am missing here or how to resolve this error.
Or any pointers on how to use Swaggerbuckle with ASP.NET Core webAPI, especially with AAD authenticated WebAPI ?
UPDATES
I copied my webAPI's APPID URI from azure portal. ie Dashboard>>Microsoft - App registrations>>MY_API_APP>>Settings>>Properties>>App ID URI
But I am still getting the same error when I try to authenticate
Error AADSTS500013: Resource identifier is not provided
Usually resource identifier which uniquely identifies your application. You can easily found your resource Identifier Like below:
When logged into the Azure portal, Azure Active Directory > App Registrations > [App Name] > Settings> Properties, then it's the App ID URI
See the screen shot:
In the orignal OAuth 2.0 specification, there is no resource parameter in the authorization request. It use scope parameter. The authorization and token endpoints allow the client to specify the scope of the access request using the "scope" request parameter.
As document explains, when Azure AD implement the OAuth 2.0(1.0 endpoint), the resource is used to specify the access_token you request for which resource. And the Azure AD will issue the token which the scp based on the permission you config on the portal for the resource.
And in the v2.0 endpoint, the Azure AD also use the scope to support the dynamic permission request. More detail you can have a look here.
Usual Reason for Error
Make sure you have configured below steps accordingly.
Like below:
Application Manifest
Reply URI
Request Endpoint
For V1.0 refer this URI https://login.microsoft.com//oauth2/authorize
For V2.0 refer this URI https://login.microsoft.com//oauth2/v2.0/authorize
Application Consent
Need to confirm your application required resource access permission you could refer here
I believe this step can lead you to sort out your problem.
With Azure AD V1.0 app you need set resource to identify which api you want to access during the authentication&access token requests :
Code flow :
https://learn.microsoft.com/en-us/azure/active-directory/develop/v1-protocols-oauth-code
Implicit flow :
https://learn.microsoft.com/en-us/azure/active-directory/develop/v1-oauth2-implicit-grant-flow
In Swashbuckle.AspNetCore 4.0.1 , you need to config the resource as parameter if you want to get access token for accessing your web api :
app.UseSwaggerUI(options =>
{
options.SwaggerEndpoint("/swagger/v1/swagger.json", "MySite API V1");
options.OAuthClientId("19c73866-562f-482a-bafb-89d9fe9b0aaa");
options.OAuthAppName("Swagger Api Calls");
// add resource
options.OAuthAdditionalQueryStringParams(new Dictionary<string, string>() { { "resource", "f479db30-9b62-431b-98c2-bcaae52203cf" } });
});
For us Nan Yu's response got us one step closer.
We added the resource in the AdditionalQuerystringParams like so:
options.OAuthAdditionalQueryStringParams(new Dictionary<string, string>() { { "resource", "{ResourceIDHere}" } });
We are now able to get passed the Auth step in Swagger, but trying routes out doesn't seem to pass the token to the api called and so we get a 401 Error.
change { "scope", API_AppID_URI} to { "resource", API_AppID_URI}

Get SharePoint Office 365 data using Client Id

I am accessing SharePoint online list data using the following code but i get the following error.
The remote server returned an error: (403) Forbidden.
The web forms application is running in Azure and uses Azure authentication. I would like to use the same credentials for authentication
string siteUrl = "[url]";
string aadAppId = "[appid]";
string clientSecret = "[redacted]";
OfficeDevPnP.Core.AuthenticationManager authManager = new OfficeDevPnP.Core.AuthenticationManager();
ClientContext context = authManager.GetAzureADNativeApplicationAuthenticatedContext(siteUrl, aadAppId, appurl, null, AzureEnvironment.Production);
if (context != null)
{
Web web = context.Web;
context.Load(web);
context.ExecuteQuery();
}
I do not want to access the SharePoint using the user credentials.
I have enabled AAD Azure authentication on the web app. The web app authenticates with Azure credentials.
On the CORS setting i have also set the Domain Url to "https://domainname.sharepoint.com";
In the manage permissions section of AAD app I have given the app Permission to read and write sharepoint list and web data.
You example is attempting to retrieve a token as a native client application, which is an app that cannot keep a secret and cannot authenticate by itself. (That's why you'll notice you never use clientSecret.)
If you want to use OfficePnP, you can try one of the AuthenticationManager.GetAzureADAppOnlyAuthenticatedContext methods to authenticate in the app-only context. Note that they all require a certificate for authentication, rather than a secret.

Microsoft Graph appRoleAssignment direct queries not supported?

I've been using these github documentation pages: Page1, Page2, I've implemented adal on the app that I'm using and I'm just logging the token on the console so that I can just copy-paste the token into postman and try requests faster.
I've been trying a get request as mentioned on the documentation to.
https://graph.microsoft.com/beta/appRoleAssignments/{Object Id of AD App} or { App ID of AD App }
But also attempted various other routes based on the documention. I'm getting 'resource not found' for all of the other ones and 'direct queries to this resource type are not supported' for the one above.
Brosed a few related stackoverflow threads and went into github issues to see anything related to approlesassignment resource type but no luck.
EDIT: Token is obtained in Angular app using package adal-angular4 (it is however an angular6 application and the package has been updated to work with Angular 6)
After a lot of struggling, I managed to get the necessary info via Azure Enterprise App API, not th endpoints mentioned above.
This is how the GET request looks like:
https://graph.microsoft.com/beta/servicePrincipals/{ID}/appRoleAssignments/
ID in the context above is "Object ID" of the Azure AD App under 'ENTERPRISE APPS', taking the one from under 'enterprise apps' is critical.
You'll find it in:
In Azure > Active Directory > Enterprise Apps > Your App > Properties
Now you just need bearer authentication token in the header for Microsoft Graph and the right permissions, I think Read/write all directory data should be good enough.

Resources