PhuocLe - Microsoft Dynamics CRM

Dynamics 365 Online S2S Authentication - Full Explain Apr/02/2017


Server-to-Server (S2S) authentication (only support Dynamics 365 online) was great, it use ClientId/SecretKey to authentication (instead use UserName/Password) and it use without Dynamics 365 license.
 
But everybody have problem when use CllientId/SecretKey, the main problem is HTTP Error 401 - Unauthorized: Access is denied
 
I headache this problem more than 3 days, and now, I succeed authentication with ClientId/SecretKey.
 
This post I will fully explain you how I can achieve it.
 
Important noted: do the correct order step by step here
1. Register App with Azure Active Directory
After you register App, save these value here to use it later
a. Application ID
b. Url redirect
c. SecretKey
 
Save Application ID for use later.
 
Save Redirect URI for use later
 
Save SecretKey for use later. Rember the SecretKey only show once.
 
Note: When register App use:  
  • Application Type = Native and
  • Assign Permission to Dynamics CRM Online
2. Create new Office365 user
We call this user as ApplicationUser
a. Assign CRM Online license
b. Role: Dynamics 365 Service Administrator
Create new Office 365 user with Dynamics 365 license and role
 
3. Create a custom security role and assgin to ApplicationUser
Open Dynamics 365 by CRM Administrator account
a. Clone a System Administrator security role to new ApplicationUserRole
b. Assign ApplicationUserRole to ApplicationUser user
Clone System Administrator role to ApplicationUserRole
 
Assign ApplicationUserRole to ApplicationUser
 
c. Open Application User form for this ApplicationUser
i. Change form from User to Application User (if not change)
ii. Update field Application ID from step 1.a (Application ID)
iii. Save and go back to Enabled Users
Update Application ID for ApplicationUser
 
d. Change view to Application Users and check field Application ID URI for ApplicationUser empty
Make sure Application ID URI of ApplicationUser is emtpy
 
4. Remove Dyanmics 365 license
Back to 365 admin and remove license from ApplicationUser you already do in step 2
S2S Authentication no need a license, if you assign license to ApplicationUser it not work.
 
5. Manually build url and use it once
The syntax url here
https://login.microsoftonline.com/{talent-id}/oauth2/authorize?client_id={application-id}&response_type=code&redirect_uri={url-redirect}&response_mode=query&resource={crm-url}&state={new-guid}
  • talent-id: your azure active directory id. Azure portal -> Azure Active Directory -> Properties -> Directory ID
  • application-id: step 1.a
  • url-redirect: step 1.b
  • crm-ur: your full Dynamics 365 url, E.g.: https://phuoc2017mar26.crm.dynamics.com
  • new-guid: generator a new GUID
My final manually url here: 
https://login.microsoftonline.com/12b5c856-99c8-4268-b99f-b5bfd02ae0f3/oauth2/authorize?client_id=2015d711-986e-4728-87d5-228994e190ba&response_type=code&redirect_uri=http://myapplicationusers.com&response_mode=query&resource=https://phuoc2017mar26.crm.dynamics.com&state=5cebc804-b7d6-4e26-b850-ed45708f37fa
6. Grant ApplicationUser to App
  • Use the manually url build on step 5. Open IE private window and paste the url to IE address bar
  • Process first time login (and only do it once) with the ApplicationUser you create in step 2, it redirect to url-redirect. Leave it and close your IE browser.
First and only once login to grant permission to ApplicationUser
 
7. Check Application ID URI
Goback to Application Users view and check the Application ID URI (step 3.e.1) now have value same value with Applcation ID.
  • The key I found here, if this field NULL, 401 return.
  • Only this way update this field (step 5)
Application ID URI updated
 
8. Build console application
a. Create a console application
b. Use code below and now you can see WhoAmI
Note: you can use authenticationResult.AccessToken for WebAPI call in the header request
class Program
{
    static private Uri GetServiceUrl(string organizationUrl)
    {
        return new Uri(organizationUrl + @"/xrmservices/2011/organization.svc/web?SdkClientVersion=8.2");
    }

    static void Main(string[] args)
    {
        var organizationUrl = "https://phuoc2017mar26.crm.dynamics.com";
        var aadInstance = "https://login.microsoftonline.com/";
        var tenantID = "12b5c856-99c8-4268-b99f-b5bfd02ae0f3";
        var clientId = "2015d711-986e-4728-87d5-228994e190ba";
        var appKey = "your-private-secret-key-here";
        var clientcred = new ClientCredential(clientId, appKey);
        var authenticationContext = new AuthenticationContext(aadInstance + tenantID);
        var authenticationResult = authenticationContext.AcquireToken(organizationUrl, clientcred);
        var requestedToken = authenticationResult.AccessToken;
        using (var sdkService = new OrganizationWebProxyClient(GetServiceUrl(organizationUrl), false))
        {
            sdkService.HeaderToken = requestedToken;
            var request = new OrganizationRequest()
            {
                RequestName = "WhoAmI"
            };
            var response = sdkService.Execute(new WhoAmIRequest()) as WhoAmIResponse;
            Console.WriteLine(response.UserId);
            Console.ReadKey();
        }
    }
}

Run the code and I get the result here

I get UserID GUID of ApplicationUser we already grant permission to App

Now in your 3rd app, you can access CRM by use ClientId/SecretKey (without use UserName/Password) and no need Dynamics 365 license. 

GREAT !!!!!!!
 
Some mistakes
  • Don’t assign Application ID to user.
  • Don’t create a custom security role and assign to application user, everybody always use default System Administrator role and assign to application user.
  • Build correct url above but login with another user that have assign Application ID, or login with user don’t assign application key
  • Forgot remove license from user before use url above.
  • Manually url not match with url-redirect when register application in Azure Active Directory
  • Don't do correct order I list here
Finally your target
  • Application User should in Application Users view
  • Application User should have 3 field (not blank)
    • Application ID
    • Application ID URI
    • Azure AD Object ID
  • Application User should remove Dynamics 365 license
  • Application User must have a custom security role

Hope this post working for you.


Category: CRM
wrote: May/16/2017

We followed your steps and it works! I cannot believe how complicated it is to push a lead from server to server with Dynamics. Thank you anyway for helping solve this.

Sander avatar Sander
wrote: Jun/14/2017

Wow.. so much blogs so much info but none explains it like you do. Took me a day to find your blog. Took me 5 minutes to actually be able to read the crm data through s2s clientid/secret combi. I got 401 all the way; for me the trick was the cloning of the admin role.. suddenly the url of the app user was updated with the client id and my 401 disappeared.

Thnx a million for posting this walktrhough!!

Sander

Srinivasa Rao Asapu avatar Srinivasa Rao Asapu
wrote: Jul/19/2017

The HTTP request is unauthorized with client authentication scheme 'Anonymous'. The authentication header received from the server was 'Bearer authorization_uri=https://login.windows.net/xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx, resource_id=https://xxxxxxxxxxxxxxxxxx.crm.dynamics.com/'

Srinivasa Rao Asapu avatar Srinivasa Rao Asapu
wrote: Jul/19/2017

The HTTP request is unauthorized with client authentication scheme 'Anonymous'. The authentication header received from the server was 'Bearer authorization_uri=https://login.windows.net/xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx, resource_id=https://xxxxxxxxxxxxxxxxxx.crm.dynamics.com/'

Srinivasa Rao Asapu avatar Srinivasa Rao Asapu
wrote: Jul/19/2017

The HTTP request is unauthorized with client authentication scheme 'Anonymous'. The authentication header received from the server was 'Bearer authorization_uri=https://login.windows.net/xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx, resource_id=https://xxxxxxxxxxxxxxxxxx.crm.dynamics.com/'

E. avatar E.
wrote: Sep/12/2017

Great post: it contains a lot of information that are missing from Microsoft's own documentation. Thanks a lot!

wrote: Sep/12/2017

Thanks for a useful post.

I was getting error Principal user (Id={guid...}, type=8) is missing prvReadAccount when trying to use this token.

I found that by enabling the licence again for that account it started working OK.

I was on the 1 month free trial and the licence type was 'Dynamics 365 Customer Engagement Plan Enterprise Edition'

Enter your comment

Your Name (*)
Your Email (*)
Website (*)

Search

About Me

Connect

Projects

Categories

MB2

Tags

RSS