OAuth authentication using Device Code Flow

With Basic Authentication going away within a few days now, I take a look at another way to do OAuth authentication. The Device Code Flow, is a method that’s very useful, check it out:

https://youtu.be/okdq_65ZcDA

With basic authentication being deprecated for Business Central, connecting to web services (OData, SOAP) now requires OAuth authentication. While there are several OAuth methods available, this video demonstrates the Device Code Flow — a user-based authentication method that avoids the complexity of redirect callbacks. Erik walks through the entire process, from Azure portal configuration to a raw C# implementation that clearly illustrates how the protocol works under the hood.

What is Device Code Flow?

Device Code Flow is an OAuth authentication method designed for scenarios where handling redirect callbacks is difficult or impossible. Instead of redirecting the user’s browser to a callback URL, the application displays a code and a URL. The user opens that URL in any browser, enters the code, and completes the sign-in. Meanwhile, the application polls Microsoft’s token endpoint until authentication is confirmed.

You may have already seen this flow in action — Visual Studio Code uses it when connecting to a Business Central cloud sandbox.

While this approach is specific to Microsoft’s identity platform, it’s not limited to Business Central. It works for any Microsoft service that requires a Microsoft login.

Setting Up the Azure App Registration

Before writing any code, you need to configure an app registration in the Azure portal. Here’s what Erik set up for his demo:

  1. Create an App Registration — Erik created one called “YouTube BC Demo” and noted the Application (Client) ID.
  2. Assign API Permissions — Added permissions for Business Central.
  3. No secrets required — Unlike the service-to-service (side-to-side) flow, Device Code Flow does not require a client secret.
  4. No redirect URIs — No callback URLs need to be configured.
  5. Enable public client flows — Under Authentication → Advanced settings, toggle “Allow public client flows” to Yes. This setting specifically includes the “no keyboard device code flow” option that makes this scenario possible.

How the Flow Works

The Device Code Flow involves two main phases:

Phase 1: Request a Device Code

The application sends a POST request to Microsoft’s device code endpoint:

POST https://login.microsoftonline.com/common/oauth2/v2.0/devicecode

Parameters:
  client_id = {your-app-registration-client-id}
  scope = https://api.businesscentral.dynamics.com/.default

Using common as the tenant ID means the tenant is determined by whoever logs in. The response from Microsoft includes:

  • user_code — The code the user enters in the browser
  • device_code — An internal code the application uses when polling for the token
  • verification_uri — The URL the user should open (https://microsoft.com/devicelogin)
  • expires_in — How long the code is valid
  • interval — How often the application should poll for a result
  • message — A human-readable message to display to the user (e.g., “To sign in, use a web browser to open the page microsoft.com/devicelogin and enter the code…”)

Phase 2: Poll for the Token

The application enters a polling loop, periodically sending POST requests to the token endpoint:

POST https://login.microsoftonline.com/common/oauth2/v2.0/token

Parameters:
  tenant = common
  grant_type = urn:ietf:params:oauth:grant-type:device_code
  client_id = {your-app-registration-client-id}
  scope = https://api.businesscentral.dynamics.com/.default
  device_code = {device-code-from-phase-1}

While the user hasn’t completed sign-in yet, Microsoft returns a 400 Bad Request — this is normal and expected. The application simply waits the specified interval (approximately 5 seconds) and tries again. Once the user completes authentication in the browser, the next poll returns a 200 OK with a full token response, including:

  • access_token — The bearer token needed for API calls
  • token_type — “Bearer”
  • scope — The granted permissions (e.g., User.Read, Financials.ReadWrite.All)
  • expires_in — Token lifetime in seconds

The Demo Walkthrough

Erik demonstrated the complete flow using a C# console application:

  1. The program starts and displays: “To sign in, use a web browser to open the page microsoft.com/devicelogin and enter the code XXXXXXX”
  2. Opening the link in a browser and entering the code presents the Microsoft login page
  3. After confirming the sign-in, the console — which had been showing “waiting” with a countdown — immediately receives the bearer token
  4. The application is now ready to make authenticated web service calls to Business Central

A Note on Implementation

Erik deliberately wrote this implementation without any helper libraries (no MSAL, no NuGet packages) to clearly demonstrate how the protocol works at the HTTP level. However, he recommends using established libraries like Microsoft Authentication Library (MSAL) in production code — they handle edge cases, token caching, and refresh tokens for you.

Real-World Usage: Simple Object Designer

Erik also showed a practical example of Device Code Flow in his Simple Object Designer tool. This tool needs to download Business Central symbols, which requires authenticating from within Business Central to Business Central’s backend. Since handling redirect callbacks from within BC is problematic, Device Code Flow provides a clean solution. The tool displays the sign-in message, the user authenticates in a browser, and the symbol download begins automatically.

Supporting AL Code

The project includes a simple AL codeunit for managing client credentials. Note that in a real application, you should use proper secret management rather than hardcoded values:

codeunit 50102 "AL Secret"
{
    procedure getclientid(): Text
    begin
        exit('secret santa');
    end;

    procedure getclientsecret(): Text
    begin
        exit('enter your own');
    end;
}

The app configuration in app.json shows this was built for Business Central runtime 2.0:

{
  "id": "c24c8b76-1ae7-4b5f-8ef7-d71571e90f8f",
  "name": "BCOauth2",
  "publisher": "Erik Hougaard",
  "version": "1.0.0.0",
  "platform": "13.0.0.0",
  "application": "13.0.0.0",
  "showMyCode": true,
  "runtime": "2.0"
}

When to Use Device Code Flow

Device Code Flow is particularly useful when:

  • You need to authenticate as a user (not as an application)
  • You cannot handle redirect callbacks in your environment
  • You’re working on input-constrained devices or restricted environments
  • You need to authenticate from within Business Central to external services

For service-to-service scenarios where no user interaction is needed, consider the Client Credentials (side-to-side) flow instead, which Erik covers in a separate video.

Summary

Device Code Flow offers a straightforward way to get OAuth tokens for user-based authentication without dealing with redirect URIs. The setup is minimal — just an Azure app registration with public client flows enabled and the appropriate API permissions. The two-phase process (request a code, then poll for a token) is simple to implement and works reliably in environments where traditional OAuth redirect flows are impractical. While raw HTTP requests illustrate the mechanics well, production implementations should leverage MSAL or similar libraries for robustness and maintainability.