Search code examples
pythonazureazure-ad-msaldynamics-business-central

Why do I always get 'The server has rejected the client credentials.' when I call business central api?


Here is my MSAL authentication:

@app.route('/get-microsoft-data', methods=('GET', 'POST'))
def get_microsoft_token():
    public_app = ConfidentialClientApplication(
        client_id="<client_id>", authority="https://login.microsoftonline.com/<tenant_id>",
        client_credential="<client_secret>"
    )
    
    result = None
    result = public_app.acquire_token_silent(["https://api.businesscentral.dynamics.com/.default"], account=None)

    if not result:
        print("No suitable token exists in cache. Let's get a new one from AAD.")
        result = public_app.acquire_token_for_client(scopes=["https://api.businesscentral.dynamics.com/.default"])
        
    if "access_token" in result:
        global microsoft_token
        microsoft_token = result["access_token"]

    return redirect('/') 

This is my call to business central api:

@app.route('/send-data-to-microsoft', methods=('GET', 'POST'))
def send_data_to_microsoft():
    print(microsoft_token)
    
    headers = {
        "Authorization": "Bearer " + microsoft_token
    }
    
    r = requests.get("https://api.businesscentral.dynamics.com/v1.0/<tenant_domain>/sandbox/api/v1.0/companies", headers=headers)
    print(r.json())
    return redirect('/')

And this is the error I'm getting when I call /send-data-to-microsoft:

{'error': {'code': 'Authentication_InvalidCredentials', 'message': 'The server has rejected the client credentials.  CorrelationId:  ff4d9d32-db03-4c2a-bf77-2e6186d4988c.'}}

This is the doc for what I want: https://learn.microsoft.com/en-us/dynamics-nav/api-reference/v1.0/api/dynamics_companies_get

This is the list of valid endpoints for business central: https://learn.microsoft.com/en-us/dynamics-nav/api-reference/v1.0/endpoints-apis-for-dynamics


Solution

  • Client credential flow is NOT supported here. The supported Authentication methods for Dynamics 365 BC are only these 2 options based on the official document:

    • Basis Authentication
    • AAD authentication

    If you want to call D365 BC API with a method which doesn't require user interaction, you should choose Basis Authentication.

    The steps to do it are:

    1. To set up basic authentication, log into your tenant, and in the Search field, enter Users and then select the relevant link.
    2. Select the user to add access for, and on the User Card page, in the Web Service Access Key field, generate a key.
    3. Copy the generated key and use it as the password for the username.

    And then you could refer to Exploring the APIs with Postman and basic authentication.