Search code examples
c#asp.net-mvcoauth-2.0azure-active-directorydynamics-crm

Getting access token using email address and app password from oauth2/token


We are using compulsory two factor authentication for our email addresses under our Active Directory.

I have an app that requires a service account, so we created app password for that service account. We acquire access token using following end point -

https://login.windows.net/{tenant_id}/oauth2/token

It works perfectly fine for credentials without two factor authentication and normal password but not for accounts with two factor auth and app password

If we enter app password it returns this error -

AADSTS70002: Error validating credentials. AADSTS50126: Invalid username or password enter image description here

How can I get it working?


Solution

  • It looks like you are trying to use the Resource Owner Password Credentials Grant, which is in general not recommended (it doesn't support MFA among other things) Instead of using that flow, see if the client credential flow (where you can use an application ID + secret or certificate) fits your needs

    In the case of CRM Online, it does support the concept of “application user”. You declare the application in AAD with a secret or a certificate. Then you go to CRM Online and add that “application user” with a custom security role.

    enter image description here

    Then you can use code like this to access CRM web services.

    add-type -path "Microsoft.IdentityModel.Clients.ActiveDirectory.dll"
    add-type -path "Microsoft.Xrm.Sdk.dll"
    $resourceAppIdURI = "https://ORG.crm2.dynamics.com"
    $authority = "https://login.windows.net/TENANT.onmicrosoft.com" 
    $credential=New-Object Microsoft.IdentityModel.Clients.ActiveDirectory.ClientCredential("b1d83e4e-bc77-4919-8791-5408746265c1","<SECRET>")
    $authContext = New-Object "Microsoft.IdentityModel.Clients.ActiveDirectory.AuthenticationContext" -ArgumentList $authority,$false
    $authResult = $authContext.AcquireToken($resourceAppIdURI, $credential)
    $sdkService=new-object Microsoft.Xrm.Sdk.WebServiceClient.OrganizationWebProxyClient("https://ORG.crm2.dynamics.com/xrmservices/2011/organization.svc/web?SdkClientVersion=8.2",$false)
    $sdkService.HeaderToken=$authResult.accesstoken
    $OrganizationRequest=new-object Microsoft.Xrm.Sdk.OrganizationRequest
    $OrganizationRequest.RequestName="WhoAmI"
    $sdkService.Execute($OrganizationRequest)