Skip to main content

Notifications

Announcements

No record found.

Microsoft Dynamics CRM (Archived)

Server to Server Authentication and API communication with CRM

Posted on by Microsoft Employee

Hello Guys!

I have a usecase to call CRM APIs from my Nodejs client with non-interactive login. For this I have a client key and secret generated after registering my App on Azure Active Directory. I am successful in generating access token, but anytime I attempt to access data (via a Microsoft OData client or straight Web API HTTP requests), I always receive a 401, despite the inclusion of my access token in the authorization header. Here is my Nodejs client:

var adal = require('adal-node');
var azure = require('azure');
var express = require('express');
var https = require('https');
var app = express();


var AuthenticationContext = adal.AuthenticationContext;

var authorityHostUrl = 'login.microsoftonline.com';
var tenant = 'xxxx.onmicrosoft.com';
var authorityUrl = authorityHostUrl + '/' + tenant;
var clientId = 'xxxx';
var clientSecret = 'xxxx'
var resource = 'https://xxxx.crm.dynamics.com';

var context = new AuthenticationContext(authorityUrl);

var accessToken;
var credentials;

context.acquireTokenWithClientCredentials(resource, clientId, clientSecret, function(err, tokenResponse) {
if (err) {
console.log('well that didn\'t work: ' + err.stack);
} else {
console.log("======================SUCCESS=======================");

accessToken=tokenResponse.accessToken;

console.log(accessToken);
}
});

app.get('/accounts', function(req, res) {

var token = "Bearer " + accessToken;
console.log(token);

var options = {
host: 'xxxx.crm.dynamics.com',
path: '/api/data/v8.2/accounts?$select=name,address1_city&$top=10',
headers: {
'Authorization': token,
'Accept': 'application/json',
'Content-Type':'application/json; charset=utf-8',
'OData-MaxVersion':'4.0',
'OData-Version':'4.0'
}
};

callback = function(response) {
console.log("Callback Invoked");
var str = '';

//another chunk of data has been recieved, so append it to `str`
response.on('data', function (chunk) {
str += chunk;
console.log("Data ====>"+str);
});

//the whole response has been recieved, so we just print it out here
response.on('end', function () {
console.log("Complete Data ====>"+str);
console.log(str);
});
}

console.log(options);
https.request(options, callback).end();

});

app.listen(3000);

*This post is locked for comments

  • Community Member Profile Picture
    Community Member Microsoft Employee on at
    RE: Server to Server Authentication and API communication with CRM

    Hello Amit,

    Have you got any solution to this problem? I am facing exactly the same issue. I am able to get access_token from token endpoint. But getting "HTTP Error 401 - Unauthorized: Access is denied" while trying to access any Dynamics resource say, mydomain.crm.dynamics.com/.../accounts$select=name

  • Community Member Profile Picture
    Community Member Microsoft Employee on at
    RE: Server to Server Authentication and API communication with CRM

    I only tried with Native Application.

  • Community Member Profile Picture
    Community Member Microsoft Employee on at
    RE: Server to Server Authentication and API communication with CRM

    I am trying to create a multi tenant application, hence the oauth authorization endpoint for admin_consent was login.microsoftonline.com/.../authorize

  • Community Member Profile Picture
    Community Member Microsoft Employee on at
    RE: Server to Server Authentication and API communication with CRM

    Hi Gilmar,

    I did the following:

    1. Created an azure app of type "WEB APPLICATION AND/OR WEB API"
    2. Created a user and assigned crm license to it.
    3. Changed the user to application user in CRM > Security > User
    4. Assigned the application Id of my app to the application user
    5. Cloned system Admin role and named it as applciationUserRole and assigned to application user.
    6. Logged in CRM as system Admin User and granted access to the app as admin_consent.
    7. Noted Application User Username and Password.
    8. Removed CRM License from user.
    9. Ran the Java client to get the accessToken. The client is failing saying "error_description":"AADSTS70002: The request body must contain the following parameter: 'client_secret or client_assertion'.\r\nTrace ID: 5d2241fa-70a6-402d-8804-d6a66dae3200\r\nCorrelation ID: f1d7cf5d-47ff-4722-8532-1c937b975970\r\nTimestamp: 2017-09-27 19:15:55Z","error":"invalid_client"

    Note:

    1. I marked my azure app as web application and/or web api type.(Is it mandatory to have app as native)
    2. When I tried authenticationContext.acquireToken(crmURL, clientCredential, new AuthenticationCallBackImpl()), I get an accessToken but am not able to user it as it gives 401.
  • Community Member Profile Picture
    Community Member Microsoft Employee on at
    RE: Server to Server Authentication and API communication with CRM
    1. Create an Application account in AD

    • Under Azure Active Directory/Users and Groups/All Users click “New User”.

    • This user is given a temporary password. Copy it, it will be used later on. If you forget to copy, you can always come back later and reset the password which will give you another temporary password.

      1. Register a new Native Application in Azure Portal.

      • Go to https://portal.azure.com

      • Under Azure Active Directory/App Registrations, click New Application Registration and fill in the form with the information like in the following figure.

      • PS: The Redirect URL is not important so don't worry if the url does not make sense.

      • Click on the registered Application and you should see ApplicationID.

      • Copy the Application ID for later use.

        1. Add Dynamics CRM Online to the Registered Application.

        • Under Under Azure Active Directory/App Registrations, click on the registered app we just created.

        • Click “Required Permissions”, “Add”, “Select API”, then select “Dynamics CRM Online”

        • Check “Delegated Permissions” Checkbox then click “select”, “done”

        • After you added the permission, you have to click “Grant Permissions”

          1. Create a MSCRM Application User.

          • Open MSCRM Online.

          • Under Settings/Security/Users change the view to “Application Users”

          • Click “New”

          • Change Form to “Application User”

            1. Fill in the form.

            • PS: The Application ID field is the GUID you copied on step 2.4. Its the GUID of our registered Application in Azure.

            • Inform ApplicationID and user information from the user you created in AD

            • Click Manage Roles and Select a custom role. It does not accept SysAdmin roles.

              1. Login in Azure with the user you created

              • go to https://portal.azure.com

              • if already logged in, logout.

              • Login with user you created and inform the temporary password.

              • A new password will be asked. Inform it.

              1. Temporarily add Dynamics CRM Online license to the Applicatio User.

              • Go to http://portal.office.com and log-in with an administrator user.

              • Go to User/Active Users and select the user App User.

              • Edit Product Licenses and Add Dynamics CRM Online License.

              • PS: This license is required only once. On the last step of this instruction document we will remove the license from this user.

                1. Manually Build this URL and use it once. It will be necessary to activate your registered application.

                • 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}

                • Replace the Fields Accordingly

                  • talent-id: the Azure active Directory id from Azure Portal/Azure Active Directory/Properties/Directory ID

                  • application-id: the application id of our registered application.

                  • Url-redirect: the url we informed on step 2.2

                  • crm-url: your full Dynamics 365 url

                  • new-guid: a generated GUID, like 7D17C069-0000-0000-0000-000000000001

                  1. Administrator gives privilege to Application to call MSCRM.

                  • Go to https://portal.azure.com and if you are logged in just logout.

                  • Go to the url from step 7.2

                  • Login as an Administrator user.

                  • PS: You will be redirected to http://appurl page with a code parameter. Just ignore it. Now the Application has access to CRM.

                    1. Remove Dynamics CRM Online license from teh App User.

                    • Go to http://portal.office.com and log-in with an administrator user and remove the license from that app user.

                    1. Use Adal4J lib and login with the Application user credentials

                      this is an example using Groovy

                    @Grab('com.microsoft.azure:adal4j:+')

                    @Grab('org.codehaus.groovy.modules.http-builder:http-builder:+')

                    @Grab('com.auth0:java-jwt:+')

                    import com.microsoft.aad.adal4j.AuthenticationCallback

                    import com.microsoft.aad.adal4j.AuthenticationContext

                    import com.microsoft.aad.adal4j.AuthenticationResult

                    import com.microsoft.aad.adal4j.*

                    import com.nimbusds.jwt.JWTParser

                    import com.nimbusds.jwt.SignedJWT

                    import groovyx.net.http.*

                    import groovyx.net.http.ContentType.*

                    import groovyx.net.http.Method.*

                    AuthenticationContext authenticationContext = new AuthenticationContext('https://login.microsoftonline.com/common', false, java.util.concurrent.Executors.newSingleThreadExecutor());

                    authenticationContext.acquireToken('https://CRM URL HERE', 'applicationIDHere', 'USERNAME', 'PASSWORD', new AuthenticationCallback() {

                    @Override

                    public void onSuccess(AuthenticationResult result) {

                    def token = result.getAccessToken();

                    println token;

                    SignedJWT jwt = JWTParser.parse(token)

                    println jwt.getPayload().toJSONObject()

                    println result.getExpiresOnDate().getTime() - 10000; //ten secs earlier

                    url = new URL("https://CRM URL API HERE/api/data/v8.2/WhoAmI()")

                    jsonContent = url.getText(requestProperties: ["Authorization": "Bearer ${token}"]);

                    println jsonContent

                    System.exit(0);

                    }

                    @Override

                    public void onFailure(Throwable exc) {

                    println exc

                    System.exit(0);

                    }

                    });

                  1. Community Member Profile Picture
                    Community Member Microsoft Employee on at
                    RE: Server to Server Authentication and API communication with CRM

                    It was not privileges. I had to assign a license to the Application User, run the URL to grant access to him then remove the license.

                    From then on it didn't deny access to the Application user and the user has no license assigned.

                  2. Community Member Profile Picture
                    Community Member Microsoft Employee on at
                    RE: Server to Server Authentication and API communication with CRM

                    Hi Gilmar Purin,
                    Can you help me out in getting a accessToken for the application user? As for the accessToken getting 401 on api call, have you assigned the required privileges to your application user.

                  3. Community Member Profile Picture
                    Community Member Microsoft Employee on at
                    RE: Server to Server Authentication and API communication with CRM

                    Hi were you able to figure this out? 

                    I have the same problem. I'm able to use an Application User and get the Token but I'm not able to call the WebAPI using this token.

                    Always get 401.

                    thanks.

                  4. Community Member Profile Picture
                    Community Member Microsoft Employee on at
                    RE: Server to Server Authentication and API communication with CRM

                    Thanks Gopalan. In the link that you have shared,  check step 2 of "Run the web application" section. We need to explicitly re-route the user to login page to enter credentials of Dynamics. Is there any way to do this authentication in background?

                  5. Gopalan Bhuvanesh Profile Picture
                    Gopalan Bhuvanesh 11,397 on at
                    RE: Server to Server Authentication and API communication with CRM

                    Is this the client application you are talking about?

                    mscrmshop.blogspot.in/.../crm-web-api-and-cors-support.html

                  Under review

                  Thank you for your reply! To ensure a great experience for everyone, your content is awaiting approval by our Community Managers. Please check back later.

                  Helpful resources

                  Quick Links

                  December Spotlight Star - Muhammad Affan

                  Congratulations to a top community star!

                  Top 10 leaders for November!

                  Congratulations to our November super stars!

                  Tips for Writing Effective Suggested Answers

                  Best practices for providing successful forum answers ✍️

                  Leaderboard

                  #1
                  André Arnaud de Calavon Profile Picture

                  André Arnaud de Cal... 291,280 Super User 2024 Season 2

                  #2
                  Martin Dráb Profile Picture

                  Martin Dráb 230,214 Most Valuable Professional

                  #3
                  nmaenpaa Profile Picture

                  nmaenpaa 101,156

                  Leaderboard

                  Featured topics

                  Product updates

                  Dynamics 365 release plans