Authorization not working with Post, Put or Patch in Azure App Service - azure-web-app-service

I have an ASP.NET Core 6 MVC / Web API app I am deploying to Azure which uses the ASP.NET Authentication Framework. It uses cookie authentication with VueJs on the front end.
When I deploy to Azure Web Services, the [Authorize] attribute returns a 401 for all Patch, Put or Post calls. However, for all Get calls, the [Authorize] attribute works fine, and the API call is authenticated.
I've tried removing the [Authorize] attribute and inspected the claims and identity. Again, for all non Get calls, the identity is empty and User.Identity.IsAuthenticated is false.
But if I just change it back to a Get call, then all identity information comes through.
I can't think of any reason why the .NET authentication stack would great a Get call differently than a Post call when deployed on Azure.
Locally on my dev machine, and on a regular IIS deployment everything works fine. I've inspected the http packets, and the identity cookie is being sent by the client.
Any pointers on where to look is appreciated.

I have come across the scenario when using postman to create the users Which uses POST request.
GET https://graph.microsoft.com/v1.0/users
Even for GET , i was getting unauthorized as previously read permissions are not given and invalid bearer tpoken was given
You must be missing receiving auth access token , please add the authorization header in the code which is done In the Configure method in Startup.cs class
app.UseSession();
app.Use(async (context, next) =>
{
var JWToken = context.Session.GetString("Token");
if (!string.IsNullOrEmpty(Token))
{
context.Request.Headers.Add("Authorization", "Bearer " + Token);
}
await next();
});
app.UseAuthentication();
app.UseAuthorization();
check the scope is provided in controller part where [Authorize] attribute is given.
Check Protect a web API with the Microsoft identity platform - Microsoft Entra | Microsoft Learn
I could get the GET request response successfully after giving below permissions
I have these Directory.Read.All and User.Read delegated and application permissions only.
POST request needs write permissions , in my case to create users , it requires User.ReadWrite.All and Directory.ReadWrite.All Application permissions
Create User - Microsoft Graph v1.0 | Microsoft Learn
After giving required permissions and getting admin grant consent .
I could execute the post request successfully and create the users
Please check POST request requirements and permissions needed and make sure they are granted admin consent.It can be permissions with scopes that are granted to particular web api.
Make sure the access token or user interaction is done and permissions required are granted.

Related

Get Azure Webjob History - 403 Token invalid

I am trying to retrieve the web job history of an Azure web job via REST using a .NET backend and the OAuth2 credentials flow (as described here
https://learn.microsoft.com/en-us/rest/api/appservice/web-apps/get-triggered-web-job-history-slot)
How do I need to authenticate correctly?
I retrieve the token as follows:
POST https://login.microsoftonline.com/{MySubscription}/oauth2/v2.0/token
client_id={MyApp}
&grant_type=client_credentials
&scope=https://management.azure.com/.default
&client_secret={myclient_secret}
I get a token back, however I get a 403 error message when I try to retrieve the resource:
GET https://management.azure.com/subscriptions/{MySubscription}/resourceGroups/{MyResource}/providers/Microsoft.Web/sites/{MyApp}/slots/{MySlot}/triggeredwebjobs/{MyWebjob}/history?api-version=2021-02-01
Authorization: Bearer {MyToken}
Client '{MyApp}' with object ID '{MyApp}' is not
authorized to perform the action
'Microsoft.Web/sites/slots/triggeredwebjobs/history/read' using the
scope
'/subscriptions/{MySubscription}/resourceGroups/{MyResource}/providers/Microsoft.Web/sites/{MyApp}/slots/{MySlot}/triggeredwebjobs/{MyWebjob}'
or the scope is invalid. If access was granted recently, please update
your credentials.
What am I doing wrong?
I already added the API-Permission
The "403 Token invalid" error usually occurs if you missed giving permissions to particular scope (Azure Service Management).
By giving this scope it enables you to access https://management.azure.com
To resolve this error, please follow below steps:
Go to Azure Ad ->your application -> API permissions -> Add permission -> Azure Service Management -> delegated permissions ->User impersonation -> Add
After giving these permissions try to retrieve the resource again, there won't be any error.
Since I didn't find a solution that worked with OAuth2 and the Credentials flow, I got it working with Basic Authentication. The username (userName) and password (userPWD) can be taken from the publishing profile of the respective app service.
GET https://{appservicename}.scm.azurewebsites.net/api/triggeredwebjobs/{jobName}/history
Authorization Basic ....

Why aren't the application permissions being added to my MS Graph token?

I'm trying to get a subscription created with the callRecord resource (https://learn.microsoft.com/en-us/graph/api/subscription-post-subscriptions?view=graph-rest-beta&tabs=http)
In the app registration section of the Azure portal, I've created a multi-tenant app with a client secret. That app has permissions for application-level "CallRecords.Read.All" as well as the default delegated "User.Read". The statuses also have a green checkbox for being granted against my organization by an admin.
I am able to get an access token with the following HTTP POST request to https://login.microsoftonline.com/common/oauth2/v2.0/token:
grant_type:authorization_code
scope:https://graph.microsoft.com/.default
client_secret:<client_secret>
client_id:<client_id>
code:<code>
redirect_uri:http://localhost:3000
However, that token is not able to generate a subscription to my callRecord resource. I get a response with this message: "Operation: Create; Exception: [Status Code: Forbidden; Reason: The request is not authorized for this user or application.]"
The message suggests that the app has not been granted admin-level authorization, but in fact it has. This used to work for me. I'm wondering if there has been a regression on the MS Graph side.
Further, when I examine the JWT, I see that the scope is "User.Read profile openid email". There is no mention of the application-level permission (specifically, CallRecords.Read.All)
Thanks.
Because when you use the auth code flow, just the Delegated permission will take effect. So even if you grant the Application permission, the token you got will not include the permission.
From the doc, to call this API Get callRecord, just the Application permission is supported.
To get the token which include the permission, your option is to use the client credential flow.
Note: You need to use <tenant-id> instead of common in this flow.
POST https://login.microsoftonline.com/<tenant-id>/oauth2/v2.0/token
client_id=xxxxxxx
&scope=https://graph.microsoft.com/.default
&client_secret=xxxxxxx
&grant_type=client_credentials
Decode the token in https://jwt.io, the roles includes the CallRecords.Read.All permission:

Asking for user info anonymously Microsoft Graph

In an old application some people in my company were able to get info from Microsoft Graph without signing users in. I've tried to replicate this but I get unauthorized when trying to fetch users. I think the graph might have changed, or I'm doing something wrong in Azure when I register my app.
So in the Azure portal i have registered an application (web app), and granted it permissions to Azure ad and Microsoft graph to read all users full profiles.
Then I do a request
var client = new RestClient(string.Format("https://login.microsoftonline.com/{0}/oauth2/token", _tenant));
var request = new RestRequest();
request.Method = Method.POST;
request.AddParameter("tenant", _tenant);
request.AddParameter("client_id", _clientId);
request.AddParameter("client_secret", _secret);
request.AddParameter("grant_type", "client_credentials");
request.AddParameter("resource", "https://graph.microsoft.com");
request.AddParameter("scope", "Directory.Read.All");
I added the last row (scope) while testing. I still got a token without this but the result is same with or without it.
After I get a token I save it and do this request:
var testClient = new RestClient(string.Format("https://graph.microsoft.com/v1.0/users/{0}", "test#test.onmicrosoft.com")); //I use a real user here in my code ofc.
testRequest = new RestRequest();
testRequest.Method = Method.GET;
testRequest.AddParameter("Authorization", _token.Token);
var testResponse = testClient.Execute(testRequest);
However now I get an error saying unauthorized, Bearer access token is empty.
The errors point me to signing users in and doing the request, however I do not want to sign a user in. As far as i know this was possible before. Have Microsoft changed it to not allow anonymous requests?
If so, is it possible to not redirecting the user to a consent-page? The users are already signed in via Owin. However users may have different access and i want this app to be able to access everything from the azure ad, regardless of wich user is logged in. How is the correct way of doing this nowadays?
Or am I just missing something obvious? The app has been given access to azure and microsoft graph and an admin has granted permissions for the app.
Edit: just to clarify, i tried both "Authorization", "bearer " + _token.Token, and just _token.Token as in the snippet.
Yes, it's still possible to make requests to Graph without a user present using application permissions. You will need to have the tenant admin consent and approve your application.
Edit / answer: Adding the 'Authorization' as a header instead of a parameter did the trick. It works both with 'bearer token' and just 'token'

Authorization_IdentityNotFound Error while accessing graph API

I have searched with the error which I found, Did not find any matching questions. So posting question. Appreciate if some one provides some pointers to proceed.
My goal is to access graph API in my desktop client. I have started using fiddler to experiment.
I have followed instructions provided at https://graph.microsoft.io/en-us/docs/authorization/app_only
registered Web APP using Application Registration portal using my Microsoft work account.
Provided 'Read all users' full profiles in Delegated permissions
Requested token and Used the token in Authorization header to call the graph API, Getting following error.
https://graph.microsoft.com/v1.0/users
119
{
"error": {
"code": "Authorization_IdentityNotFound",
"message": "The identity of the calling application could not be established.",
"innerError": {
"request-id": "4c3a7bc6-e3d8-453c-adc9-5a12fec3b0ee",
"date": "2016-05-11T00:46:23"
}
}
}
In my case, I got the same error after I used Quickstart (step 1), then configured automatically .net sample (step 2), then download the code sample (step 3) as shown in the picture below.
All steps was done successfully except step 3. Microsoft code generate, generate app id, and app secret in project successfully but the tenant was set to common in appsetting.json as seen in image below.
I thought it was a valid thing, but later found out that this caused the issue.
Solution:
I copied the Directory (tenant) ID, than replace common with tenant Id, and it worked. I am not sure if this is a bug in Azure Quickstart code generation.
This sample helped me understand the flows around app-only permissions.
https://blogs.msdn.microsoft.com/tsmatsuz/2016/10/07/application-permission-with-v2-endpoint-and-microsoft-graph/
Key takeaways for me:
Ensure you set up the app and specify the Application Permissions needed
Do have an admin grant the app permission to run against the relevant directory.
Get the relevant token:
Notice the scope in the request below is https://graph.microsoft.com/.default
POST https://login.microsoftonline.com/{tenantname}.onmicrosoft.com/oauth2/v2.0/token
Content-Type: application/x-www-form-urlencoded
grant_type=client_credentials&client_id=6abf3364-0a60-4603-8276-e9abb0d843d6&client_secret=JfgrNM9CcW...&scope=https%3A%2F%2Fgraph.microsoft.com%2F.default
Use the token to request the relevant graph resource, eg:
GET https://graph.microsoft.com/v1.0/users/demouser01#[tenant-name].onmicrosoft.com/drive/root/children
Accept: application/json
Authorization: Bearer eyJ0eXAiOi
For me, I had not given admin consent. This is a critical step. My mistake was in thinking that by granting the app permissions, this was giving admin consent, but its not the same thing.
From step 3 on this site: https://developer.microsoft.com/en-us/graph/docs/concepts/auth_v2_service
I just pasted their call into a browser after filling in the tenant and client id, then signed in, and everything worked.
GET https://login.microsoftonline.com/{tenant}/adminconsent
?client_id=6731de76-14a6-49ae-97bc-6eba6914391e
&state=12345
&redirect_uri=http://localhost/myapp/permissions
while generating new access token, make sure to replace tenant_id with the actual tenant id
https://login.microsoftonline.com/{tenant_id}/oauth2/v2.0/token
You'll find that this document is a better set of instructions for app-only apps.
There are two issues from your description that stand out.
You'll need to make the call with an X509 certificate for app-only flows.
You need to set up app scopes, rather than delegated scopes on your app - delegated scopes are for delegate flows rather than app-only flows.

CAML-query to Sharepoint REST API results in "invalid audience URI"?

We have been successfully using the Sharepoint REST API to retrieve items from lists for a while now, but just recently decided to integrate the ADAL.JS in order to be able to access other Microsoft APIs such as Graph, Azure AD etc.
After successfully authenticating Adal.js automatically adds an
Authorization: Bearer eyJ..
header to the REST calls which works fine after fiddling with permissions a bit. The app is an Angular SPA hosted in Sharepoint so this header isn't necessary but doesn't really matter.
HOWEVER, a few of our REST calls require us to also query the taxonomy and as that isn't supported in the normal Sharepoint REST API, we have to hit the (/_api/web/lists/GetByTitle('ListName')/GetItems endpoint) with a CAML-query as request payload i.e. https://mydomain.sharepoint.com/sites/dev/_api/web/lists/GetByTitle('News')/GetItems
Unfortunatelly, this does not work as the API simply returns
Invalid audience Uri '5exx5cef-x7xx-4xxx-axxx-4xxxx2e40'.
So far my only solution is to modify the actual Adal.JS library to remove this header for this specific endpoint.
So, my questions is - has anyone done CAML-queries against Sharepoint REST APIs using Adal.JS, or ran into a similar problem and can provide any insight?
I suspect it is a configuration issue but am somewhat at loss on what to do.
In this case, you need to force setting the endpoint 'https://mydomain.sharepoint.com' to null. Else, each request to "mydomain.sharepoint.com" will add a graph authorization header which be validated by the SharePoint server. Since the app is registered on the Azure AD rather than SharePoint, it will be considered as a invalid audience.
Here is the workaround for your reference, please let me know if it works on your side.
(function () {
angular.module('app', [
'ngRoute',
'AdalAngular'
]).config(config);
// Configure the routes.
function config($routeProvider, $httpProvider, adalAuthenticationServiceProvider) {
$routeProvider
.when('/', {
templateUrl: 'views/main.html',
controller: 'MainController',
controllerAs: 'main'
})
.otherwise({
redirectTo: '/'
});
// Initialize the ADAL provider with your clientID (found in the Azure Management Portal) and the API URL (to enable CORS requests).
adalAuthenticationServiceProvider.init(
{
clientId: clientId,
// The endpoints here are resources for ADAL to get tokens for.
endpoints: {
'https://graph.microsoft.com': 'https://graph.microsoft.com',
'https://mydomain.sharepoint.com': null
}
},
$httpProvider
);
};
})();

Resources