Most Dynamics 365 and Power Platform teams eventually reach the point where they need to call the Dataverse Web API from automated tests, integration services, or CI/CD pipelines. And almost every team hits the same roadblock:

“How do we authenticate without using a human account?”

In this post, we’ll walk through the right way to create a secure, least‑privilege service account using Azure AD and Dataverse’s Application User model. This is the foundation for any automated API work — including the validation approach from the previous blog.

Why Service Accounts Matter for API Access

Before we dive into the how, let’s talk about the why.

1. Human accounts don’t belong in automation

  • They require MFA
  • Passwords expire
  • People leave the organisation
  • They violate least‑privilege principles

2. Service principals are designed for automation

  • No MFA
  • No password expiry
  • Can be scoped to minimal permissions
  • Work perfectly in CI/CD

3. Dataverse has a dedicated “Application User” model

This is the correct, supported way to let an Azure AD app access CRM data.

Overview: How Authentication Works

Here’s the high‑level flow:

Code

Azure AD App Registration (Service Principal)
OAuth Token (Client Credentials)
Dataverse Application User
Dataverse Web API

Your automated test or integration service authenticates using the app registration, and Dataverse recognises it as an Application User with specific permissions.

Step 1 — Create an Azure AD App Registration

This is your service principal — the identity your automation will use.

Steps

  1. Go to Azure Portal → Azure Active Directory → App registrations
  2. Click New registration
  3. Give it a name (e.g., “CRM‑Automation‑ServiceAccount”)
  4. Set Supported account types to “Single tenant”
  5. Register the app

Why this matters

The app registration is what Azure AD trusts. It’s the identity that will request OAuth tokens.

Step 2 — Create a Client Secret or Certificate

Your automation needs a credential.

Option A — Client Secret (simple, but rotate often)

Azure AD → App → Certificates & secrets → New client secret

Option B — Certificate (more secure)

Upload a certificate and use it for authentication.

Best practice

  • Use secrets for dev/test
  • Use certificates for production

Step 3 — Create an Application User in Dataverse

This is the step most people miss.

Dataverse does not automatically recognise your Azure AD app. You must explicitly create an Application User.

Steps

  1. Go to Power Platform Admin Center
  2. Select your environment
  3. Go to Settings → Users + permissions → Application users
  4. Click New app user
  5. Select your Azure AD app registration
  6. Assign a security role

Important

If you don’t assign a role, the API calls will authenticate but fail with:

“Principal user is not assigned a role.”

Step 4 — Assign the Right Security Role

This is where you enforce least privilege.

Common roles

  • Read‑only custom role for validation
  • Integration role for create/update/delete
  • System Administrator only for rare admin automation

Best practice

Create a custom role with exactly the permissions your automation needs.

Step 5 — Authenticate Using OAuth 2.0 Client Credentials

Your automation now requests a token using:

  • Tenant ID
  • Client ID
  • Client Secret or Certificate
  • Scope: https://<org>.crm.dynamics.com/.default

Token Request Example

Code

POST https://login.microsoftonline.com/{tenantId}/oauth2/v2.0/token
Content-Type: application/x-www-form-urlencoded
client_id=xxxx
&client_secret=xxxx
&scope=https://yourorg.crm.dynamics.com/.default
&grant_type=client_credentials

The response contains an access token your code can use.

Step 6 — Call the Dataverse Web API

Once you have a token, you can call any Dataverse endpoint your role allows.

Example: Query a Contact

Code

GET https://yourorg.crm.dynamics.com/api/data/v9.2/contacts?$select=firstname,lastname
Authorization: Bearer <token>
Accept: application/json

Example: Create a Contact

Code

POST https://yourorg.crm.dynamics.com/api/data/v9.2/contacts
Content-Type: application/json
Authorization: Bearer <token>
{
"firstname": "Jamie",
"lastname": "AutomationTest"
}

Step 7 — Using the Service Account in CI/CD

This is where service principals shine.

Where to store secrets

  • Azure DevOps Library
  • GitHub Actions Secrets
  • Key Vault (best practice)

Where to use them

  • Automated tests
  • Integration pipelines
  • Deployment scripts
  • Validation workflows

No MFA. No human login. Fully automated.

Security Best Practices

A few guidelines to keep your service accounts safe:

  • Use least privilege roles
  • Rotate secrets regularly
  • Prefer certificates over secrets
  • Never store secrets in code
  • Use Key Vault for production
  • Monitor sign‑ins for unusual activity

Common Pitfalls and How to Avoid Them

1. “Invalid client”

Usually caused by:

  • Wrong secret
  • Secret expired
  • Wrong tenant ID

2. “Principal user is not assigned a role”

You forgot to assign a Dataverse security role.

3. “Insufficient privileges”

Your role doesn’t include the table you’re querying.

4. “Resource not found”

Your scope is wrong — use the .default scope.

Conclusion: The Foundation for All API‑Driven Automation

Creating a proper service account is the first step toward:

  • Automated CRM validation
  • Integration pipelines
  • Data quality checks
  • Regression testing
  • Background processing
  • Monitoring and observability

Once you have a secure, least‑privilege service principal in place, you can confidently automate anything in Dataverse.

Leave a comment