A Modern Guide to Using OAuth 2.0 with C# and Visual Studio Code

Many years ago, I wrote an article on the basics of OAuth and while it was helpful, it is now quite outdated. A lot has changed in the past 14 years! OAuth 2.0 has become the de facto standard for securing APIs and authorizing users in modern applications.

The older article I wrote used a SoundCloud example and older libraries, this updated guide walks you through implementing OAuth 2.0 in C# using Visual Studio Code, with modern libraries and best practices.

Whether you're building a console app, a web API, or integrating with services like Google or Microsoft Graph, this guide will help you get started with a clean and simple implementation.


Prerequisites

Before we dive in, make sure you have the following:

Let's get started!


Step 1: Create a New Console App

Open your terminal and run:

dotnet new console -n OAuthDemo
cd OAuthDemo

Step 2: Install Required Packages

We'll use Microsoft.Identity.Client for handling OAuth flows:

dotnet add package Microsoft.Identity.Client
dotnet add package Microsoft.Extensions.Configuration

Step 3: Configure Your OAuth Settings

Create a appsettings.json file to store your credentials:

{
  "OAuth": {
    "ClientId": "your-client-id",
    "TenantId": "your-tenant-id",
    "Authority": "https://login.microsoftonline.com/your-tenant-id",
    "Scopes": [ "https://graph.microsoft.com/.default" ],
    "ClientSecret": "your-client-secret"
  }
}
🔍 What is tenant-id? >This is the unique identifier (GUID) for your Azure Active Directory (AAD) tenant. You can find it in the Azure portal under Azure Active Directory > Overview. Alternatively, you can use your domain name (e.g., contoso.onmicrosoft.com) in place of the GUID. This might be different depending on your OAuth provider.

Step 4: Authenticate and Acquire Token

Here's a simple example using MSAL to get an access token:

using Microsoft.Identity.Client;
using Microsoft.Extensions.Configuration;

var config = new ConfigurationBuilder()
    .AddJsonFile("appsettings.json")
    .Build();

var clientId = config["OAuth:ClientId"];
var tenantId = config["OAuth:TenantId"];
var authority = config["OAuth:Authority"];
var scopes = config.GetSection("OAuth:Scopes").Get<string[]>();

var app = ConfidentialClientApplicationBuilder.Create(clientId)
    .WithAuthority(authority)
    .WithClientSecret(config["OAuth:ClientSecret"])
    .Build();

var result = await app.AcquireTokenForClient(scopes).ExecuteAsync();
Console.WriteLine($"Access Token: {result.AccessToken}");

Step 5: Make an Authenticated API Call

Use HttpClient to call a protected resource:

using System.Net.Http;
using System.Net.Http.Headers;

using var httpClient = new HttpClient();
httpClient.DefaultRequestHeaders.Authorization = 
    new AuthenticationHeaderValue("Bearer", result.AccessToken);

var response = await httpClient.GetAsync("https://graph.microsoft.com/v1.0/users");
var content = await response.Content.ReadAsStringAsync();
Console.WriteLine(content);
✅ Testing Endpoint: https://graph.microsoft.com/v1.0/users >This endpoint returns a list of users in your Azure AD tenant. To use it, ensure your app registration has Application permissions like User.Read.All and that you've granted admin consent.

If all works as expected, you should see a response similar to the following:

{
  "@odata.context": "https://graph.microsoft.com/v1.0/$metadata#users",
  "value": [
    {
      "businessPhones": [],
      "displayName": "Dean Hume",
      "givenName": "Dean",
      "jobTitle": null,
      "mail": null,
      "mobilePhone": null,
      "officeLocation": null,
      "preferredLanguage": "en",
      "surname": "Hume",
      "userPrincipalName": "email.com#EXT#@email.onmicrosoft.com",
      "id": "id-response-goes-here"
    }
  ]
}

*Optional: Set up an Entra ID test OAuth App

This is an optional step as you might be wanting to use your own OAuth provider, however, I wanted to be sure that my code worked and I set up an App in Azure's Entra ID that I could test with.

If you'd like to do the same, I recommend checking out these resources:

Conclusion

OAuth 2.0 doesn't have to be intimidating. With modern libraries like MSAL and tools like Visual Studio Code, you can securely authenticate and access APIs with just a few lines of code.

If you'd like to see an example of this code in action, please head over to the Github repo that I created to accompany this article.