In this video, I show how to use Site-2-Site OAuth authentication to access Business Central web services from C#. All done without using fancy libraries but instead writing code that’s transparent enough to easily translate into other languages, check it out:

With basic authentication being deprecated for Business Central cloud web services, developers need to transition to OAuth. While many guides rely on large authentication libraries, this video demonstrates that site-to-site (S2S) OAuth authentication can be accomplished in under 40 lines of C# code — no magic libraries required. Erik walks through the entire process from Azure app registration to making authenticated API calls against Business Central.
Understanding the Authentication Options
With basic authentication going away for Business Central in the cloud, you’re left with two OAuth-based options:
- User (Delegated) OAuth — A user authenticates interactively, you get a token, and proceed. This uses delegated permissions.
- Site-to-Site (Application) OAuth — No user interaction required. An application authenticates directly using a client ID and secret. This is the replacement for scenarios where you previously stored a username and password for automated processes.
For automated integrations, background services, and any scenario where you don’t want to involve a login procedure, site-to-site OAuth is the way to go.
Step 1: Register an App in Azure Portal
In Business Central, every action is performed by a user. With site-to-site authentication, there is no interactive user — the application itself becomes the user. To set this up, navigate to Azure Portal → App Registrations and click New registration.
- Give the app a name (e.g., “YouTube”).
- Select Accounts in this organizational directory only (your tenant).
- Click Register.
Once registered, you’ll see the Application (client) ID. Think of this as your username — copy it and save it somewhere.
Configure API Permissions
OAuth introduces a concept of two levels of permissions. Before Business Central’s own permission system kicks in, there’s a gatekeeper at the Azure level that determines which Microsoft services this application is allowed to access.
- Go to API Permissions → Add a permission.
- Find and select Dynamics 365 Business Central.
- Choose Application permissions (not Delegated — that’s for user-based OAuth).
- Select app_access (API read/write all).
- Click Grant admin consent to finalize the permissions.
Create a Client Secret
The client secret serves as the password for your application.
- Navigate to Certificates & secrets.
- Click New client secret, give it a description, and set an expiry (e.g., 6 months).
- Important: Copy the secret Value immediately (not the Secret ID). The value will be partially hidden with dots after you navigate away, so copy it using the copy button right away.
At this point, you have three pieces of information: the Client ID (username), the Client Secret (password), and the Tenant ID.
Step 2: Configure Business Central
Back in Business Central, search for Azure Active Directory Applications (you can’t create this kind of user from the regular Users page). Create a new entry and paste the Client ID into the corresponding field.
The Description field is critically important and somewhat misleading. Whatever you enter here becomes the effective username within Business Central. It’s the value returned by UserId in AL code, and it populates the “Created By” and “Modified By” system fields. So treat this as the BC username, not just a description.
Finally, assign permissions to this application user. You can give it permission sets for all companies. Note that you cannot assign the SUPER permission set, but you can assign SUPER (DATA), which is close enough for most integration scenarios.
Step 3: Write the Code
Now for the C# code. Erik’s approach deliberately avoids authentication libraries like MSAL to show exactly what’s happening under the hood — and to demonstrate that you really don’t need megabytes of DLLs for this.
Define Your Constants
string clientId = "your-application-client-id";
string clientSecret = "your-client-secret-value";
string tenantId = "your-tenant-id";
Request an Access Token
Instead of passing credentials directly with each API call (as with basic auth), you first make a POST request to Microsoft’s OAuth token endpoint to obtain a bearer token.
string url = $"https://login.microsoftonline.com/{tenantId}/oauth2/v2.0/token";
HttpClient client = new HttpClient();
string stringContent =
"grant_type=client_credentials" +
"&scope=https://api.businesscentral.dynamics.com/.default" +
"&client_id=" + HttpUtility.UrlEncode(clientId) +
"&client_secret=" + HttpUtility.UrlEncode(clientSecret);
StringContent content = new StringContent(stringContent);
content.Headers.ContentType = new MediaTypeHeaderValue("application/x-www-form-urlencoded");
var response = await client.PostAsync(url, content);
Four values are sent in the POST body:
- grant_type —
client_credentials(indicates site-to-site authentication) - scope —
https://api.businesscentral.dynamics.com/.default(what you’re requesting access to) - client_id — Your application’s client ID
- client_secret — Your application’s secret value
Extract the Bearer Token
The response comes back as JSON containing the token type, expiration, and the access token itself.
if (response.IsSuccessStatusCode)
{
JObject result = JObject.Parse(await response.Content.ReadAsStringAsync());
string? bearerToken = result["access_token"]?.ToString();
}
Call the Business Central API
With the bearer token in hand, you can now make authenticated requests to Business Central. Instead of the old Basic base64(username:password) authorization header, you use Bearer {token}.
string url2 = "https://api.businesscentral.dynamics.com/v2.0/{your-environment}/api/v2.0/{your-endpoint}";
HttpClient testClient = new HttpClient();
testClient.DefaultRequestHeaders.Add("Authorization", "Bearer " + bearerToken);
var result2 = await testClient.GetAsync(url2);
if (result2.IsSuccessStatusCode)
{
Console.WriteLine(await result2.Content.ReadAsStringAsync());
}
The comparison to basic authentication is straightforward: where you previously set the Authorization header to Basic {base64-encoded username:password}, you now set it to Bearer {token}.
The Complete Picture
Here’s a summary of the entire flow:
- Azure App Registration: Register an app, note the Client ID (username) and create a Client Secret (password). Grant it API permission to access Business Central.
- Business Central Setup: Create an Azure AD Application entry with the Client ID, set the description (which becomes the BC username), and assign appropriate permission sets.
- Get the Token: POST to
https://login.microsoftonline.com/{tenantId}/oauth2/v2.0/tokenwith the grant type, scope, client ID, and client secret. Extract theaccess_tokenfrom the JSON response. - Make API Calls: Pass the token in the
Authorization: Bearer {token}header with each request to Business Central.
Conclusion
Site-to-site OAuth authentication doesn’t have to be intimidating. The entire process — from obtaining a token to making an authenticated API call — fits in under 40 lines of C# code with no third-party authentication libraries. This approach is transparent, easy to understand, and straightforward to replicate in any programming language. While authentication libraries like MSAL have their place, if all you need is a simple site-to-site integration, a few lines of raw HTTP calls will get you there without adding megabytes of dependencies to your project.