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
- Go to Azure Portal → Azure Active Directory → App registrations
- Click New registration
- Give it a name (e.g., “CRM‑Automation‑ServiceAccount”)
- Set Supported account types to “Single tenant”
- 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
- Go to Power Platform Admin Center
- Select your environment
- Go to Settings → Users + permissions → Application users
- Click New app user
- Select your Azure AD app registration
- 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/tokenContent-Type: application/x-www-form-urlencodedclient_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,lastnameAuthorization: Bearer <token>Accept: application/json
Example: Create a Contact
Code
POST https://yourorg.crm.dynamics.com/api/data/v9.2/contactsContent-Type: application/jsonAuthorization: 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