401 Unauthorized on Dataverse Web API post method - azure-active-directory

I am using Dataverse via the Web API to access data from a server. This works very well in itself. All unlocked tables/entities can be accessed via the corresponding URL using GET method and also return valid results. That means the access and the authentication via security token works.
However, when I call the POST-Method to exactly the same table/entity, I get an error message back:
__checkpoint ⇢ 401 UNAUTHORIZED from POST https://ANONYM.crm4.dynamics.com/api/data/v9.2/
The role assigned to the application user actually has explicit write permissions to the table.
The post looks like this:
POST /api/data/v9.2/ANONYMtime-acquisitions HTTP/1.1
user-agent: ReactorNetty/1.1.2
host: ANONYM.crm4.dynamics.com
ACCEPT: */*
content-type: application/json
content-length: 282
{"cr2a0_id":0,"cr2a0_Abweichung":7.5,"cr2a0_Datum":"Sat Feb 01 00:00:00 CET 2020","cr2a0_Ist-
Arbeitszeit":7.5,"cr2a0_Mitarbeiter":"ANONYM","cr2a0_Pause":0. 0,"cr2a0_Soll-
Arbeitszeit":0.0,"cr2a0_Wochentag":"ANONYM","cr2a0_Beginn":"09:00","cr2a0_Ende":"16:30",
"cr2a0_Info":""}
I would have expected that the writing access also works. What else could be the reason for this?

I tried to reproduce the same in my environment and got the same error like below:
I created an Azure AD Application and added API permission:
I generated the auth-code by using below endpoint:
https://login.microsoftonline.com/TenantID/oauth2/v2.0/authorize?
&client_id=ClientID
&response_type=code
&redirect_uri=redirectUri
&response_mode=query
&scope=https://admin.services.crm.dynamics.com/user_impersonation
&state=12345
I generated the access token by using below parameters:
GET https://login.microsoftonline.com/TenantID/oauth2/v2.0/token
client_id:ClientID
client_secret:ClientSecret
scope:https://admin.services.crm.dynamics.com/user_impersonation
grant_type:authorization_code
redirect_uri:redirectURi
code:code
By using the above access token I am able to make the GET request successfully as below:
If still the issue occurs, make sure to assign Security role like below:
And check the version of the CRM like below:
To make a POST query, refer the below blog:
Dynamics CRM 365 WEB API Common Errors and Resolution – xrm CRM Dynamics by Bipin Kumar

Related

Invalid_grant when requesting Access token MS Graph

thanks for reading this.
I've a problem obtaining an access token for MS Graph using Postman. I've been reading similar posts on stackoverflow, but so far, without success. In the following I added some screenshots that contain (I believe) all the information needed for this process.
Screenshot of application permissions: https://i.stack.imgur.com/4lyM2.png
The link I use to obtain an access-code:
https://login.microsoftonline.com/{Tenant ID}/oauth2/v2.0/authorize?
client_id=3ef3343a-ab22-4c50-12ae2a2d7c67
&response_type=code
&redirect_uri=https://localhost:8080
&response_mode=query
&scope=offline_access%20user.read
&state=12345
3)After following this link I give permission and receive a code, which I use in the following postman call: https://i.stack.imgur.com/ZJv2b.png
I had no problem obtaining the access token without a user, but unfortunately, I need more than just the application permissions. I hope someone can help me!
Thanks for your time!
You need to delete the "code=" in code of postman call, it looks like "OAAABAAAAiL9Kn.....". code is just the value of "code" from /authorize endpoint. The others all looks correct.
UPDATE:
I tried with the steps in your issue, it worked well.
Permissions:
Get authorization code:
https://login.microsoftonline.com/{tenant-id}/oauth2/v2.0/authorize?
client_id={client-id}
&response_type=code
&redirect_uri=https://localhost:44300/
&response_mode=query
&scope=offline_access%20user.read
&state=12345
Receive the code:
https://localhost:44300/?code=0.ATcATqvJ...vv1MbCO6MN_uCAA&state=12345&session_state=7ac58b8f-b2af-45fa-be4b-0b2c2a003e2e
Code is 0.ATcATqvJ...vv1MbCO6MN_uCAA from the pervious.
Request in Postman:
You cannot generate a single token both Delegated (with a user) and Application (without a user). You'll need to make two separate requests.
For generating a Delegated token, you first need to retrieve an Authorization Code (i.e. the authrorization_code grant). This is done by redirecting the user to the following address (line breaks are for readability only)
https://login.microsoftonline.com/common/oauth2/v2.0/authorize?
client_id=[APPLICATION ID]&
response_type=code&
redirect_uri=[REDIRECT URI]&
scope=[SCOPE]
This will return an Authorization Code to the address you specified in the redirect_uri parameter (note that this address must also be included in your app registration). You then take this code an POST it to the /token endpoint like this:
https://login.microsoftonline.com/common/oauth2/v2.0/token
Content-Type: application/x-www-form-urlencoded
grant_type=authorization_code&
code=[AUTHORIZATION CODE]&
client_id=[APPLICATION ID]&
client_secret=[PASSWORD]&
scope=[SCOPE]&
redirect_uri=[REDIRECT URI]
For Application tokens, you simply skip the authorization code step and POST to the /token endpoint directly:
https://login.microsoftonline.com/{tenantDomain}/oauth2/v2.0/token
Content-Type: application/x-www-form-urlencoded
grant_type=client_credentials&
client_id=[APPLICATION ID]&
client_secret=[PASSWORD]&
scope=https://graph.microsoft.com/.default

HTTP/1.1 403 Forbidden while create upload session

I am trying to upload a file to Sharepoint. I Got the Accesstoken based on the client id and tenant id given by the application and able to do it.
'client_id='||'xxxx'||'&scope='||'https%3A%2F%2Fgraph.microsoft.com%2F.default'||'&client_secret='||'xxxxxx'||'&grant_type='||'client_credentials'
Token as follows :
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
Based on the token i am trying to create an upload session and it is saying http1.1 403 forbidden. I have the known site id and Drive (Item id).
HTTPResponseHeader X-Original-HTTP-Status-Line:CHARACTER:HTTP/1.1 403
Forbidden X-Original-HTTP-Status-Code:INTEGER:403 Cache-Control:CHARACTER:private
Content-Type:CHARACTER:application/json request-id:CHARACTER:1f6e2c51-5061-41c0-be0d-ee38a2c2a533
client-request-id:CHARACTER:1f6e2c51-5061-41c0-be0d-ee38a2c2a533 x-ms-ags-
diagnostic:CHARACTER:{"ServerInfo":{"DataCenter":"South Central US","Slice":"SliceC","Ring":"3","ScaleUnit":"000","RoleInstance":"AGSFE_IN_11"}}
Strict-Transport-Security:CHARACTER:max-age=31536000
Date:CHARACTER:Fri, 19 Jun 2020 17:23:53 GMT Content-Length:CHARACTER:256
Application had given permissions to Sites.readwrite.All provided admin consent as well. Any help is Appreciated.
So there's a couple of things here:
To use the Microsoft Graph APIs to create an upload session to write a file to SharePoint using the site/library as a drive with an app only permission (client_credentials) you need to request the at least the Sites.ReadWriteAll scope for the Microsoft Graph resource https://graph.microsoft.com: https://learn.microsoft.com/en-us/graph/api/driveitem-createuploadsession?view=graph-rest-1.0
Instead of requesting the https://graph.microsoft.com/.default scope try using 'https://graph.microsoft.com/Sites.ReadWriteAll`

Azure AD app with Application.ReadWrite.OwnedBy cannot add more owners to apps it created

I have an AAD app that creates other AAD apps. The first app (creator) has right Application.ReadWrite.OwnedBy and is able to update display names of the apps it created but it is not able to add more owners on those apps. Does it need more privileges to do that?
HTTP request updating the created-app display name (succeeds):
PATCH https://graph.windows.net/72f988bf-86f1-41af-91ab-2d7cd011db47/applications/a1236923-6de6-4e78-87dd-494d621fc20c?api-version=1.6 HTTP/1.1
Authorization: Bearer eyJ0eXAi...
Content-Type: application/json; charset=utf-8
Host: graph.windows.net
Content-Length: 45
Expect: 100-continue
{
"displayName": "test"
}
HTTP request adding an owner to the created-app (fails):
POST https://graph.windows.net/72f988bf-86f1-41af-91ab-2d7cd011db47/applications/a1236923-6de6-4e78-87dd-494d621fc20c/$links/owners?api-version=1.6 HTTP/1.1
Authorization: Bearer eyJ0eXAi...
Content-Type: application/json; charset=utf-8
Host: graph.windows.net
Content-Length: 122
Expect: 100-continue
{
"url": "https://graph.windows.net/72f988bf-86f1-41af-91ab-2d7cd011db47/users/ac990eb3-b25a-4e06-ade5-41c7613693ff"
}
HTTP/1.1 403 Forbidden
request-id: 9be47e62-abcd-4768-926f-ffd62544e696
client-request-id: 149115f6-c9b7-4dd4-a267-711a40c51f23
...
{"odata.error":{"code":"Authorization_RequestDenied","message":{"lang":"en","value":"Insufficient privileges to complete the operation."}}}
I verified that the creator app does indeed have Application.ReadWrite.OwnedBy in the roles array of the JWT Bearer token.
I also verified that the creator app is present in the owner list of the created app by calling GET https://graph.windows.net/72f988bf-86f1-41af-91ab-2d7cd011db47/applications/a1236923-6de6-4e78-87dd-494d621fc20c/owners/64898a3a-2fb1-45f0-a514-e83fabbc01f2.
In general, in order to add an owner, the calling app (and the calling user, in the case of delegated permissions, though in this case it's an app only) needs to have the permission to read the object of the owner being added, as well as the permission to read and write to the object which is being given a new owner.
Thus, in order for an app to add a User object as an owner to an Application object that the calling app is itself an owner of, the app needs (at least) Directory.Read.All (to read the new owner's User object), and Application.ReadWrite.OwnedBy (to be able to write to the Application object's list of owners).
According to your error message, you do not have enough privileges. As far as I known, if you want to assign user to AAD Application with Application privileges, you need to have these privileges : Application.ReadWrite.OwnedBy and Directory.Read.All, Application.ReadWrite.All and Directory.Read.All.
Besides, Microsoft strongly recommends that you use Microsoft Graph instead of Azure AD Graph API to access Azure Active Directory resources. For more details, please refer to the article. If you want to use Microsoft graph api to assign user to AAD Application, please refer to the document.

Microsoft Store collection REST API, Create Azure AD access tokens returns 404

I'm following the Tutorial "Manage product entitlements from a service" here,
Am getting stuck on step 3, where calls to request an access token return a 404 error.
Step1: In Azure Portal,
Created new WebApp, gave it a name & accepted all the defaults.
Selected the default AD directory and registered the app (used the
APP URL as the login URL).
Grabbed the AP ID _APP_ID_ and created app key _APP_SECRET_.
Updated manifest, replaced identifierURIs as described.
"identifierUris" : [
"https://onestore.microsoft.com",
"https://onestore.microsoft.com/b2b/keys/create/collections",
"https://onestore.microsoft.com/b2b/keys/create/purchase"
],
Step2: In MS DevCenter
Added _APP_ID_ to "Services-> Product collections and purchases -> Client ID".
Step3: Testing using Postman
I pulled the Azure AD Tenant ID _TENANT_ID_ from the PortalDiagnostics.json.
Using the provided sample, I used postman to post as follows:
POST https://login.microsoftonline.com/_TENANT_ID_/oauth2/token HTTP/1.1
Host: login.microsoftonline.com
Content-Type: application/x-www-form-urlencoded; charset=utf-8
grant_type=client_credentials
&client_id=_APP_ID_
&client_secret=_APP_SECRET_
&resource=https://onestore.microsoft.com
Host and content type are set in the headers, remainder is posted as raw text in the body.
POSTMAN with headers & body
POSTMAN headers
POSTMAN body
As you can see, the result is a 404 with no body, making this a little tough to trouble shoot.
Question:
Have I missed something obvious in steps 1 & 2?
Should I be able to test this with POSTMAN?
I'd appreciate any pointers; I can't find any other tutorials to cross reference.
So in this case the problem was a rogue HTTP/1.1 at the end of the URL + some unencoded content in the form data. Using Postman's x-www-form-urlencoded tab helped for that since it encodes all the fields for you.

Can service/daemon app use 'common' instead of 'tenant-id' when obtaining token from Azure AD v2.0 endpoint

I am developing a daemon app that can perform actions on user inboxes in multiple tenants. Once an admin from a tenant gives the app the required permissions, it should be able to access users inboxes in that tenant. I am doing the following now.
Get consent from admin
https://login.microsoftonline.com/common/adminconsent?client_id={client-id}&redirect_uri=https%3A%2F%2Fredirect.test.com
Global Admin from a tenant (e.g. myutils.onmcirosoft.com) gives required permission.
Get access token by using common instead of tenant-id
curl -X POST _https://login.microsoftonline.com/common/oauth2/v2.0/token --data "grant_type=client_credentials&client_id={client-id}&client_secret={clientsecret}&scope=https://graph.microsoft.com/.default
It gives a access token.
Access messages of admin#myutils.onmicrosoft.com using the token obtained in step 3.
curl -X GET -H "Authorization: Bearer <token>" https://graph.microsoft.com/v1.0/users/admin#myutils.onmicrosoft.com/messages
Above curl request gives the following 404 response:
HTTP/1.1 404 Not Found
Cache-Control: private
Transfer-Encoding: chunked
Content-Type: text/plain
request-id: e602ada7-6efd-4e18-a979-63c02b9f3c76
client-request-id: e602ada7-6efd-4e18-a979-63c02b9f3c76
x-ms-ags-diagnostic: {"ServerInfo":{"DataCenter":"West US","Slice":"SliceB","ScaleUnit":"000","Host":"AGSFE_IN_22","ADSiteName":"WST"}}
Duration: 1537.3097
Date: Tue, 19 Sep 2017 09:31:08 GMT
In step 3 if I replace common with tenant-id of myutils.onmicrosoft.com it is working.
Is common supported with Azure AD v2.0 endpoint? This link says common is not supported for v1 endpoint. Is it the same for v2.0 endpoint as well?
Just to expand on Nan Yo's answer, the reason you need the tenant-id is due to Graph API itself being a multi-tenant.
Without a tenant-id, Graph would have no way of knowing which tenant to route your calls too. For example,/users returns a list of users but without a tenant-id there is no way to determine which tenant it should pull the users from.
When you use authorization_code or implicit grants, it uses the user's credentials to determine which tenant calls should be routed too. With client_credentials you don't have those credentials to pull those routing queues from.
You can however determine the tenant id during Admin Consent. Along with the admin_consent result, it also returns the tenant. For a multi-tenant service you would need to store that id to use when obtaining a token prior to making a call to Graph.
When using the client credentials flow in Azure AD V2.0, you need to specify the actual tenant that you want a token for. Otherwise , even you get an access token , you will find no application roles include in the access token . An access token will issued from one tenant and could access resource of that tenant , it is impossible to use one access token to query resources of multi tenants .
Please acquiring your token not from /common/oauth/v2.0/token endpoint , use /{tenent-id}/oauth2/v2.0/token endpoint with the tenant id .
Please click here for more details .

Resources