Using this config in the https://github.com/Azure-Samples/ms-identity-python-webapp worked for me. The scope must include the CDS organization/environment API URL.
CLIENT_SECRET = "**********************************"
AUTHORITY = "https://login.microsoftonline.com/common"
CLIENT_ID = "3641e71b-ad98-4489-8423-f77532d0a5d5"
REDIRECT_PATH = "/getAToken"
ENDPOINT = 'https://graph.microsoft.com/v1.0/users'
CDS_ENDPOINT = "https://REPLACE_WITH_ORG_NAME.api.crm.dynamics.com/api/data/v9.0/msmrw_guides?$select=msmrw_name&$expand=msmrw_guide_Annotations"
# cds environment / crm org, MUST be a part of the scope
SCOPE = ["https://REPLACE_WITH_ORG_NAME.api.crm.dynamics.com/user_impersonation"]
SESSION_TYPE = "filesystem"
ADAL issue Pyhton bearer token issue
I am authenticating non-interactively with a client id and secret for my REST application that interacts with the Common Data Service. Testing first in Postman I am able to perform both read and write operations using my credentials successfully.
When implementing the REST API in Python I can only perform Read operations through the Azure AD Authentication Library (ADAL) with version adal==1.2.2. I am using the same credentials from my Postman environment in Python through a config file, an example is further below. I also tested this Python ADAL generated token in Postman to verify that I can make get requests since I noticed the token strings are different between the one I generate in Python and one I generate in Postman. When making a post request I get the error shown even further below. My guess is I need logic in python to somehow tell ADAL the user requesting the token is allowed write permissions.
Code and Postman error
import adal
from .config import *
class AzureAuth:
bearerToken = ""
def __init__(self):
authCtx = adal.AuthenticationContext(AUTHORITY_URL)
tokenResponse = authCtx.acquire_token_with_client_credentials(RESOURCE, CLIENT_ID, CLIENT_SECRET)
self.bearerToken = tokenResponse["accessToken"]
Here's an example of what my config.py looks like.
AUTHORITY_URL=""
CDS_API_URL=""
CLIENT_ID=""
CLIENT_SECRET=""
REDIRECT_URI=""
RESOURCE="" # like "https://your_cds_environment.api.crm.dynamics.com/"
TENANT="" # like "https://login.microsoftonline.com/put_your_tenant"
Error thrown in Postman when I copy paste the Python token into a Postman post request.
{
"error": {
"code": "0x80048306",
"message": "{\"CallerPrincipal\":{\"PrincipalId\":\"96b856f4-134c-e911-a823-000d3a1d5de8\",\"Type\":8,\"IsUserPrincipal\":true,\"IsTeamPrincipal\":false,\"TypeName\":\"user\"},\"OwnerPrincipal\":{\"PrincipalId\":\"96b856f4-134c-e911-a823-000d3a1d5de8\",\"Type\":8,\"IsUserPrincipal\":true,\"IsTeamPrincipal\":false,\"TypeName\":\"user\"},\"CallerInfo\":{\"IsSystemUser\":false,\"IsSupportUser\":false,\"IsAdministrator\":false,\"IsCustomizer\":false,\"IsDisabled\":false,\"IsIntegrationUser\":false,\"Privileges\":null,\"Teams\":null,\"Roles\":null},\"ObjectId\":\"00000000-0000-0000-0000-000000000000\",\"ObjectTypeCode\":10410,\"ObjectBusinessUnitId\":\"1abfdddc-8140-e911-a823-000d3a1a25b8\",\"OrganizationId\":\"08907b95-ee84-4861-b141-b584fecc774d\",\"EntityName\":\"msmrw_guide\",\"EntityOwnershipTypeMask\":1,\"EntityPrivileges\":[{\"Id\":\"915a1feb-2a56-4a8c-bea0-3256728785e5\",\"ObjectTypeCode\":10410,\"Name\":\"prvCreatemsmrw_guide\",\"AccessRight\":32,\"PrivilegeType\":0,\"CanBeBasic\":true,\"CanBeLocal\":true,\"CanBeDeep\":true,\"CanBeGlobal\":true,\"CanBeEntityReference\":true,\"CanBeParentEntityReference\":true},{\"Id\":\"6415b9e2-24c4-408a-a830-85c21ab8ac72\",\"ObjectTypeCode\":10410,\"Name\":\"prvReadmsmrw_guide\",\"AccessRight\":1,\"PrivilegeType\":1,\"CanBeBasic\":true,\"CanBeLocal\":true,\"CanBeDeep\":true,\"CanBeGlobal\":true,\"CanBeEntityReference\":true,\"CanBeParentEntityReference\":true},{\"Id\":\"229dfe7f-1394-47fe-84d4-8d5d7747cbd2\",\"ObjectTypeCode\":10410,\"Name\":\"prvWritemsmrw_guide\",\"AccessRight\":2,\"PrivilegeType\":2,\"CanBeBasic\":true,\"CanBeLocal\":true,\"CanBeDeep\":true,\"CanBeGlobal\":true,\"CanBeEntityReference\":true,\"CanBeParentEntityReference\":true},{\"Id\":\"d6624737-6846-49c7-bfef-25f6f482e297\",\"ObjectTypeCode\":10410,\"Name\":\"prvDeletemsmrw_guide\",\"AccessRight\":65536,\"PrivilegeType\":3,\"CanBeBasic\":true,\"CanBeLocal\":true,\"CanBeDeep\":true,\"CanBeGlobal\":true,\"CanBeEntityReference\":true,\"CanBeParentEntityReference\":true},{\"Id\":\"4f4fa37d-b977-4acf-a05a-d003ac32fc44\",\"ObjectTypeCode\":10410,\"Name\":\"prvAssignmsmrw_guide\",\"AccessRight\":524288,\"PrivilegeType\":4,\"CanBeBasic\":true,\"CanBeLocal\":true,\"CanBeDeep\":true,\"CanBeGlobal\":true,\"CanBeEntityReference\":true,\"CanBeParentEntityReference\":true},{\"Id\":\"09e5b82f-5cd8-46ea-a7ae-acbc472ae2b2\",\"ObjectTypeCode\":10410,\"Name\":\"prvSharemsmrw_guide\",\"AccessRight\":262144,\"PrivilegeType\":5,\"CanBeBasic\":true,\"CanBeLocal\":true,\"CanBeDeep\":true,\"CanBeGlobal\":true,\"CanBeEntityReference\":true,\"CanBeParentEntityReference\":true},{\"Id\":\"93b7f403-fc9b-442b-b602-9ba347ddda26\",\"ObjectTypeCode\":10410,\"Name\":\"prvAppendmsmrw_guide\",\"AccessRight\":4,\"PrivilegeType\":6,\"CanBeBasic\":true,\"CanBeLocal\":true,\"CanBeDeep\":true,\"CanBeGlobal\":true,\"CanBeEntityReference\":true,\"CanBeParentEntityReference\":true},{\"Id\":\"776967fe-67f4-4b3d-908a-dfb4306d2372\",\"ObjectTypeCode\":10410,\"Name\":\"prvAppendTomsmrw_guide\",\"AccessRight\":16,\"PrivilegeType\":7,\"CanBeBasic\":true,\"CanBeLocal\":true,\"CanBeDeep\":true,\"CanBeGlobal\":true,\"CanBeEntityReference\":true,\"CanBeParentEntityReference\":true}],\"RightsToCheck\":\"CreateAccess\",\"RoleAccessRights\":\"None\",\"PoaAccessRights\":\"None\",\"HsmAccessRights\":\"None\",\"Messages\":[\"PrincipalHasOwnerPrincipalWithAtLeastBasicPrivilegeDepth = False\",\"EntityUserGroupRights = None\",\"MinimumPrivilegeDepthRequired = Local\",\"GrantedRights = None\",\"SecLib::AccessCheckEx2 failed. Owner Data: roleCount=1, privilegeCount=0, accessMode=4; Principal Data: roleCount=1, privilegeCount=0, accessMode=4\"],\"IsHsmEnabled\":false,\"IsOwnerDirectReport\":false,\"IsDirectReportInOwningTeam\":false,\"IsReadAccessFromIndirectReport\":false}",
"innererror": {
"message": "{\"CallerPrincipal\":{\"PrincipalId\":\"96b856f4-134c-e911-a823-000d3a1d5de8\",\"Type\":8,\"IsUserPrincipal\":true,\"IsTeamPrincipal\":false,\"TypeName\":\"user\"},\"OwnerPrincipal\":{\"PrincipalId\":\"96b856f4-134c-e911-a823-000d3a1d5de8\",\"Type\":8,\"IsUserPrincipal\":true,\"IsTeamPrincipal\":false,\"TypeName\":\"user\"},\"CallerInfo\":{\"IsSystemUser\":false,\"IsSupportUser\":false,\"IsAdministrator\":false,\"IsCustomizer\":false,\"IsDisabled\":false,\"IsIntegrationUser\":false,\"Privileges\":null,\"Teams\":null,\"Roles\":null},\"ObjectId\":\"00000000-0000-0000-0000-000000000000\",\"ObjectTypeCode\":10410,\"ObjectBusinessUnitId\":\"1abfdddc-8140-e911-a823-000d3a1a25b8\",\"OrganizationId\":\"08907b95-ee84-4861-b141-b584fecc774d\",\"EntityName\":\"msmrw_guide\",\"EntityOwnershipTypeMask\":1,\"EntityPrivileges\":[{\"Id\":\"915a1feb-2a56-4a8c-bea0-3256728785e5\",\"ObjectTypeCode\":10410,\"Name\":\"prvCreatemsmrw_guide\",\"AccessRight\":32,\"PrivilegeType\":0,\"CanBeBasic\":true,\"CanBeLocal\":true,\"CanBeDeep\":true,\"CanBeGlobal\":true,\"CanBeEntityReference\":true,\"CanBeParentEntityReference\":true},{\"Id\":\"6415b9e2-24c4-408a-a830-85c21ab8ac72\",\"ObjectTypeCode\":10410,\"Name\":\"prvReadmsmrw_guide\",\"AccessRight\":1,\"PrivilegeType\":1,\"CanBeBasic\":true,\"CanBeLocal\":true,\"CanBeDeep\":true,\"CanBeGlobal\":true,\"CanBeEntityReference\":true,\"CanBeParentEntityReference\":true},{\"Id\":\"229dfe7f-1394-47fe-84d4-8d5d7747cbd2\",\"ObjectTypeCode\":10410,\"Name\":\"prvWritemsmrw_guide\",\"AccessRight\":2,\"PrivilegeType\":2,\"CanBeBasic\":true,\"CanBeLocal\":true,\"CanBeDeep\":true,\"CanBeGlobal\":true,\"CanBeEntityReference\":true,\"CanBeParentEntityReference\":true},{\"Id\":\"d6624737-6846-49c7-bfef-25f6f482e297\",\"ObjectTypeCode\":10410,\"Name\":\"prvDeletemsmrw_guide\",\"AccessRight\":65536,\"PrivilegeType\":3,\"CanBeBasic\":true,\"CanBeLocal\":true,\"CanBeDeep\":true,\"CanBeGlobal\":true,\"CanBeEntityReference\":true,\"CanBeParentEntityReference\":true},{\"Id\":\"4f4fa37d-b977-4acf-a05a-d003ac32fc44\",\"ObjectTypeCode\":10410,\"Name\":\"prvAssignmsmrw_guide\",\"AccessRight\":524288,\"PrivilegeType\":4,\"CanBeBasic\":true,\"CanBeLocal\":true,\"CanBeDeep\":true,\"CanBeGlobal\":true,\"CanBeEntityReference\":true,\"CanBeParentEntityReference\":true},{\"Id\":\"09e5b82f-5cd8-46ea-a7ae-acbc472ae2b2\",\"ObjectTypeCode\":10410,\"Name\":\"prvSharemsmrw_guide\",\"AccessRight\":262144,\"PrivilegeType\":5,\"CanBeBasic\":true,\"CanBeLocal\":true,\"CanBeDeep\":true,\"CanBeGlobal\":true,\"CanBeEntityReference\":true,\"CanBeParentEntityReference\":true},{\"Id\":\"93b7f403-fc9b-442b-b602-9ba347ddda26\",\"ObjectTypeCode\":10410,\"Name\":\"prvAppendmsmrw_guide\",\"AccessRight\":4,\"PrivilegeType\":6,\"CanBeBasic\":true,\"CanBeLocal\":true,\"CanBeDeep\":true,\"CanBeGlobal\":true,\"CanBeEntityReference\":true,\"CanBeParentEntityReference\":true},{\"Id\":\"776967fe-67f4-4b3d-908a-dfb4306d2372\",\"ObjectTypeCode\":10410,\"Name\":\"prvAppendTomsmrw_guide\",\"AccessRight\":16,\"PrivilegeType\":7,\"CanBeBasic\":true,\"CanBeLocal\":true,\"CanBeDeep\":true,\"CanBeGlobal\":true,\"CanBeEntityReference\":true,\"CanBeParentEntityReference\":true}],\"RightsToCheck\":\"CreateAccess\",\"RoleAccessRights\":\"None\",\"PoaAccessRights\":\"None\",\"HsmAccessRights\":\"None\",\"Messages\":[\"PrincipalHasOwnerPrincipalWithAtLeastBasicPrivilegeDepth = False\",\"EntityUserGroupRights = None\",\"MinimumPrivilegeDepthRequired = Local\",\"GrantedRights = None\",\"SecLib::AccessCheckEx2 failed. Owner Data: roleCount=1, privilegeCount=0, accessMode=4; Principal Data: roleCount=1, privilegeCount=0, accessMode=4\"],\"IsHsmEnabled\":false,\"IsOwnerDirectReport\":false,\"IsDirectReportInOwningTeam\":false,\"IsReadAccessFromIndirectReport\":false}",
"type": "System.ServiceModel.FaultException`1[[Microsoft.Xrm.Sdk.OrganizationServiceFault, Microsoft.Xrm.Sdk, Version=9.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35]]",
"stacktrace": " at Microsoft.Crm.Extensibility.OrganizationSdkServiceInternal.CreateInternal(Entity entity, InvocationContext invocationContext, CallerOriginToken callerOriginToken, WebServiceType serviceType, Boolean checkAdminMode, Dictionary`2 optionalParameters)\r\n at Microsoft.Crm.Extensibility.OData.CrmODataExecutionContext.CreateOrganizationResponse(Entity entity)\r\n at Microsoft.Crm.Extensibility.OData.CrmODataServiceDataProvider.CreateEdmEntity(CrmODataExecutionContext context, String edmEntityName, EdmEntityObject entityObject, Boolean isUpsert)\r\n at Microsoft.Crm.Extensibility.OData.EntityController.PostEntitySetImplementation(String& entitySetName, EdmEntityObject entityObject)\r\n at Microsoft.PowerApps.CoreFramework.ActivityLoggerExtensions.Execute[TResult](ILogger logger, EventId eventId, ActivityType activityType, Func`1 func, IEnumerable`1 additionalCustomProperties)\r\n at Microsoft.Xrm.Telemetry.XrmTelemetryExtensions.Execute[TResult](ILogger logger, XrmTelemetryActivityType activityType, Func`1 func)\r\n at lambda_method(Closure , Object , Object[] )\r\n at System.Web.Http.Controllers.ReflectedHttpActionDescriptor.ActionExecutor.<>c__DisplayClass10.<GetExecutor>b__9(Object instance, Object[] methodParameters)\r\n at System.Web.Http.Controllers.ReflectedHttpActionDescriptor.ExecuteAsync(HttpControllerContext controllerContext, IDictionary`2 arguments, CancellationToken cancellationToken)\r\n--- End of stack trace from previous location where exception was thrown ---\r\n at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()\r\n at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)\r\n at System.Web.Http.Controllers.ApiControllerActionInvoker.<InvokeActionAsyncCore>d__0.MoveNext()\r\n--- End of stack trace from previous location where exception was thrown ---\r\n at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()\r\n at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)\r\n at System.Web.Http.Controllers.ActionFilterResult.<ExecuteAsync>d__2.MoveNext()\r\n--- End of stack trace from previous location where exception was thrown ---\r\n at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()\r\n at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)\r\n at System.Web.Http.Dispatcher.HttpControllerDispatcher.<SendAsync>d__1.MoveNext()"
}
}
}
These are the fields I file out in Postman when requesting a token and the values for these fields, I removed the secret for security.
These are the permissions my app uses.
According to the code and picture you provided, in the postman, you use the OAuth 2.0 code grant flow to require Azure AD access token. The way is getting access on behalf of a user. The token is user token. But in your application, you use the method acquire_token_with_client_credentials to require Azure AD access token. It means that you use OAuth 2.0 Client Credentials Grant Flow to require Azure AD access token. The way is getting access without a user. The token is app token. They are different.
Besides, according to the error, you do not have enough privilege and you need to configure the permissions. It means that if you still want to use OAuth 2.0 Client Credentials Grant Flow to require access token, you need to provide enough privilege for the service principal(the AD application ) you use. Or you change your code to use OAuth 2.0 code grant flow to require access token. For more details about how to change, please refer to the sample