Securing a .NET 8 Web API with Auth0 Using the Client Credentials Flow

Securing a .NET 8 Web API with Auth0 Using the Client Credentials Flow

Securing a .NET 8 Web API with Auth0 Using the Client Credentials Flow

In this blog post, we’ll walk through how to secure a .NET 8 Web API using Auth0 for authentication, specifically focusing on the Client Credentials flow. This setup is ideal for machine-to-machine communication, where one service needs to securely access another without user interaction.

Introduction

When building modern web APIs, securing endpoints is a critical requirement. One of the most effective ways to secure your API is by using OAuth 2.0 with JWT tokens. Auth0 simplifies this process by providing a robust identity management solution that handles authentication and authorization for your applications.

In this guide, we’ll create a .NET 8 Web API, configure it to use Auth0 for securing endpoints, and demonstrate how to obtain and use JWT tokens via the Client Credentials flow.

Prerequisites

  • A basic understanding of .NET and C#.
  • .NET 8 SDK installed on your machine.
  • An Auth0 account (you can sign up here).

Step 1: Create a New .NET 8 Web API

Start by creating a new .NET 8 Web API project.

dotnet new webapi -n Auth0WebApi
cd Auth0WebApi

This command creates a new Web API project in a folder named Auth0WebApi.

Step 2: Set Up Auth0

Create an API in Auth0

  1. Log in to the Auth0 dashboard.
  2. Navigate to the APIs section and click Create API.
  3. Fill in the details:
  • Name: My API
  • Identifier: https://myapi.com
  • Signing Algorithm: RS256
  1. Save the API.

Create a Machine-to-Machine Application

  1. In the Applications section, create a new application and choose “Machine to Machine Applications”.
  2. Name the application (e.g., My Machine-to-Machine App).
  3. Grant it access to the API you created by selecting the API and choosing the appropriate scopes (e.g., read:weather).
  4. Take note of the Client ID and Client Secret.

Step 3: Configure the .NET 8 Web API

Add Necessary NuGet Packages

In your terminal, navigate to the project directory and add the required NuGet packages:

dotnet add package Microsoft.AspNetCore.Authentication.JwtBearer
dotnet add package Swashbuckle.AspNetCore

Configure appsettings.json

Open appsettings.json and add the following configuration:

{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
},
"AllowedHosts": "*",
"Auth0": {
"Domain": "your-tenant.auth0.com",
"ClientId": "YOUR_CLIENT_ID",
"ClientSecret": "YOUR_CLIENT_SECRET",
"Audience": "https://myapi.com"
}
}

Replace your-tenant.auth0.com, YOUR_CLIENT_ID, YOUR_CLIENT_SECRET, and https://myapi.com with your actual Auth0 domain, client ID, client secret, and API identifier.

Update Program.cs

Modify Program.cs to include JWT Bearer authentication, authorization, and Swagger configuration:

using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.IdentityModel.Tokens;
using Microsoft.OpenApi.Models;
var builder = WebApplication.CreateBuilder(args);
// Add services to the container.
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen(c =>
{
c.SwaggerDoc("v1", new OpenApiInfo { Title = "My API", Version = "v1" });
c.AddSecurityDefinition("oauth2", new OpenApiSecurityScheme
{
Type = SecuritySchemeType.OAuth2,
Flows = new OpenApiOAuthFlows
{
ClientCredentials = new OpenApiOAuthFlow
{
TokenUrl = new Uri($"https://{builder.Configuration["Auth0:Domain"]}/oauth/token"),
Scopes = new Dictionary<string, string>
{
{ "read:weather", "Read weather information" }
}
}
}
});
c.AddSecurityRequirement(new OpenApiSecurityRequirement
{
{
new OpenApiSecurityScheme
{
Reference = new OpenApiReference
{
Type = ReferenceType.SecurityScheme,
Id = "oauth2"
}
},
new List<string> { "read:weather" }
}
});
});
// Configure JWT Bearer authentication
builder.Services.AddAuthentication(options =>
{
options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
})
.AddJwtBearer(options =>
{
options.Authority = $"https://{builder.Configuration["Auth0:Domain"]}/";
options.Audience = builder.Configuration["Auth0:Audience"];
options.TokenValidationParameters = new TokenValidationParameters
{
ValidateIssuerSigningKey = true,
ValidateIssuer = true,
ValidIssuer = $"https://{builder.Configuration["Auth0:Domain"]}/",
ValidateAudience = true,
ValidAudience = builder.Configuration["Auth0:Audience"],
ValidateLifetime = true,
};
});
builder.Services.AddAuthorization();
var app = builder.Build();
// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment())
{
app.UseSwagger();
app.UseSwaggerUI(c =>
{
c.SwaggerEndpoint("/swagger/v1/swagger.json", "My API v1");
c.OAuthClientId(builder.Configuration["Auth0:ClientId"]);
c.OAuthClientSecret(builder.Configuration["Auth0:ClientSecret"]);
c.OAuthAppName("My API - Swagger");
});
}
app.UseHttpsRedirection();
app.UseAuthentication();
app.UseAuthorization();
var summaries = new[]
{
"Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching"
};
app.MapGet("/weatherforecast", () =>
{
var forecast = Enumerable.Range(1, 5).Select(index =>
new WeatherForecast
(
DateOnly.FromDateTime(DateTime.Now.AddDays(index)),
Random.Shared.Next(-20, 55),
summaries[Random.Shared.Next(summaries.Length)]
))
.ToArray();
return forecast;
})
.WithName("GetWeatherForecast")
.WithOpenApi()
.RequireAuthorization(); // Secures the endpoint
app.Run();
record WeatherForecast(DateOnly Date, int TemperatureC, string? Summary)
{
public int TemperatureF => 32 + (int)(TemperatureC / 0.5556);
}

Step 4: Obtain an Access Token

To test the API, you’ll need to obtain a JWT token from Auth0 using the Client Credentials flow. Use the following cURL command:

curl --request POST \
--url https://your-tenant.auth0.com/oauth/token \
--header 'content-type: application/json' \
--data '{"client_id":"YOUR_CLIENT_ID","client_secret":"YOUR_CLIENT_SECRET","audience":"https://myapi.com","grant_type":"client_credentials"}'

Replace the placeholders with your actual values.

Step 5: Test the API

  1. Run the application:
   dotnet run
  1. Open Swagger UI:
  • Go to https://localhost:5001 in your browser.
  1. Authorize in Swagger:
  • Click the Authorize button.
  • Enter the JWT token you obtained from Auth0.
  1. Test the /weatherforecast endpoint:
  • After authorizing, you can test the endpoint to see the secured API in action.

Conclusion

By following this guide, you’ve successfully secured a .NET 8 Web API using Auth0 with the Client Credentials flow. This setup ensures that only authorized clients can access your API, making it a secure choice for machine-to-machine communication.

Auth0 provides a powerful and flexible solution for handling authentication and authorization, allowing you to focus on building features for your application while ensuring security.

Further Reading

Feel free to ask questions or share your experience with implementing this solution in the comments below!


This blog post provides a comprehensive guide to setting up and securing a .NET 8 Web API using Auth0. It should serve as a useful resource for developers looking to integrate OAuth 2.0 and JWT authentication into their applications.

Leave a Reply

Your email address will not be published. Required fields are marked *