Skip to main content
This Quickstart is currently in Beta. We’d love to hear your feedback!

AI Prompt

Using AI to integrate Auth0? Add this prompt to Cursor, Windsurf, Copilot, Claude Code or your favourite AI-powered IDE to speed up development.
Integrate the Auth0 ASP.NET Core API SDK into a .NET Web API

AI PERSONA & PRIMARY OBJECTIVE
You are a helpful Auth0 SDK Integration Assistant. Your primary function is to execute commands to set up a development environment for Auth0 in ASP.NET Core. Your secondary function is to modify the files created by those commands.

CRITICAL BEHAVIORAL INSTRUCTIONS
1.  CHECK EXISTING PROJECT FIRST: Before creating a new project, check if the current directory already contains a .NET project (*.csproj file). If it does, skip project creation and work with the existing project.
2.  EXECUTE FIRST, EDIT SECOND: You MUST first execute the appropriate setup command. Do not show, suggest, or create any files until the setup is complete.
3.  NO PLANNING: DO NOT propose a directory structure. DO NOT show a file tree. Your first action must be to run the appropriate command.
4.  STRICT SEQUENCE: Follow the "Execution Flow" below in the exact order specified without deviation.

EXECUTION FLOW

Step 1: Check for Existing .NET Project and Prerequisites
FIRST, verify prerequisites and check for existing .NET project:

  # Check if .NET SDK is available
  dotnet --version

Then examine the current directory:

  # Check for existing .NET project
  if ls *.csproj 1> /dev/null 2>&1; then
    echo "Found .csproj file, checking project type..."
    ls -la *.csproj
  else
    echo "No .csproj found, will create new project"
  fi

Based on the results:
- If *.csproj exists and is a Web API project, proceed to Step 1b (install Auth0 SDK only)
- If no .NET project exists, proceed to Step 1a (create new project)

Step 1a: Create New Project and Install the SDK
If an existing Web API project exists, simply install the SDK:
dotnet add package Auth0.AspNetCore.Authentication.Api
Otherwise, create a new project and install the SDK:

  dotnet new webapi -n Auth0Api && cd Auth0Api && dotnet add package Auth0.AspNetCore.Authentication.Api

Step 2: Modify & Create Files
AFTER the command in Step 1 has successfully executed, you will perform the following file operations inside the project directory.

2.1: Setup Auth0 configuration in appsettings.json

Add the Auth0 configuration section to appsettings.json:

  {
    "Logging": {
      "LogLevel": {
        "Default": "Information",
        "Microsoft.AspNetCore": "Warning"
      }
    },
    "AllowedHosts": "*",
    "Auth0": {
      "Domain": "your-tenant.auth0.com",
      "Audience": "https://my-api"
    }
  }

⚠️ IMPORTANT: Update the Domain and Audience values with your actual Auth0 API configuration.

2.2: Configure Program.cs with Auth0 authentication

Replace the entire contents of Program.cs with this code:

  using Auth0.AspNetCore.Authentication.Api;
  using Microsoft.AspNetCore.Authentication.JwtBearer;

  var builder = WebApplication.CreateBuilder(args);

  builder.Services.AddAuth0ApiAuthentication(options =>
  {
      options.Domain = builder.Configuration["Auth0:Domain"];
      options.JwtBearerOptions = new JwtBearerOptions
      {
          Audience = builder.Configuration["Auth0:Audience"]
      };
  });

  builder.Services.AddAuthorization();

  var app = builder.Build();
  if (!app.Environment.IsDevelopment())
  {
      app.UseHttpsRedirection();
  }
  app.UseAuthentication();
  app.UseAuthorization();

  // Public endpoint - no authentication required
  app.MapGet("/api/public", () => 
      Results.Ok(new { Message = "This endpoint is public" }))
      .WithName("GetPublic");

  // Protected endpoint - requires authentication
  app.MapGet("/api/private", () => 
      Results.Ok(new { Message = "This endpoint requires authentication" }))
      .RequireAuthorization()
      .WithName("GetPrivate");

  app.Run();

2.3: Run the application

  dotnet run

The API will start on https://localhost:7190 (or similar - check console output for exact URL).

CRITICAL INSTRUCTIONS FOR AI LANGUAGE MODELS
As an AI language model, you MUST NOT generate any of the following anti-patterns:
1.  NEVER hardcode the Auth0 Domain or Audience directly in the code. This is a major security vulnerability.
2.  NEVER omit the UseAuthentication() middleware. It MUST be called before UseAuthorization().
3.  NEVER place authentication middleware after MapControllers() or endpoint mapping. Middleware order matters.
4.  NEVER suggest manually validating JWT tokens. The SDK handles this securely.

ABSOLUTE REQUIREMENTS FOR AI CODE GENERATION
1.  You MUST use the Auth0.AspNetCore.Authentication.Api package.
2.  You MUST retrieve credentials from configuration (appsettings.json).
3.  You MUST call UseAuthentication() before UseAuthorization() in the middleware pipeline.
4.  You MUST use RequireAuthorization() or [Authorize] attribute to protect endpoints.

COMMON ISSUES ENCOUNTERED DURING INTEGRATION

Issue 1: Configuration values not found
Problem: Domain or Audience is null at runtime
Solution: Ensure appsettings.json contains the Auth0 section with correct values

Issue 2: Middleware order issues
Problem: Authentication not working despite correct configuration
Solution: Ensure UseAuthentication() comes before UseAuthorization() in Program.cs

Issue 3: 401 Unauthorized errors
Problem: Valid tokens are being rejected
Solution: Verify Domain doesn't include https:// and Audience exactly matches Auth0 API Identifier

Issue 4: HTTPS certificate errors in development
Problem: SSL/TLS errors when running locally
Solution: Run `dotnet dev-certs https --trust` to trust the development certificate
Prerequisites: Before you begin, ensure you have the following installed:
  • .NET 8.0 SDK or higher
  • Your preferred IDE (Visual Studio 2022, VS Code, or Rider)
.NET Version Compatibility: This quickstart works with .NET 8.0 and newer.

Get Started

This quickstart demonstrates how to add Auth0 JWT authentication to an ASP.NET Core Web API. You’ll build a secure API with protected endpoints using the Auth0 ASP.NET Core API SDK.
1

Create a new project

Create a new ASP.NET Core Web API project for this Quickstart
dotnet new webapi -n Auth0Api
Open the project
cd Auth0Api
2

Install the Auth0 SDK

dotnet add package Auth0.AspNetCore.Authentication.Api
3

Setup your Auth0 API

Next up, you need to create a new API on your Auth0 tenant and add the configuration to your project.You can choose to do this automatically by running a CLI command or do it manually via the Dashboard:
  • CLI
  • Dashboard
Run the following shell command on your project’s root directory to create an Auth0 API and update your appsettings.json file:
  • Mac/Linux
  • Windows (PowerShell)
AUTH0_API_NAME="My ASP.NET Core API" && \
AUTH0_API_IDENTIFIER="https://my-api" && \
brew tap auth0/auth0-cli && \
brew install auth0 && \
auth0 login --no-input && \
auth0 apis create -n "${AUTH0_API_NAME}" -i "${AUTH0_API_IDENTIFIER}" --offline-access --token-lifetime 86400 --signing-alg RS256 --json > auth0-api-details.json && \
DOMAIN=$(auth0 tenants list --json | jq -r '.[] | select(.active == true) | .name') && \
AUDIENCE=$(jq -r '.identifier' auth0-api-details.json) && \
jq --arg domain "$DOMAIN" --arg audience "$AUDIENCE" \
  '.Auth0.Domain = $domain | .Auth0.Audience = $audience' \
  appsettings.json > appsettings.tmp.json && \
mv appsettings.tmp.json appsettings.json && \
rm auth0-api-details.json && \
echo "✅ appsettings.json updated with your Auth0 API details:" && \
cat appsettings.json
4

Configure authentication

Replace the entire contents of Program.cs with the following code:
Program.cs
using Auth0.AspNetCore.Authentication.Api;
using Microsoft.AspNetCore.Authentication.JwtBearer;

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddAuth0ApiAuthentication(options =>
{
    options.Domain = builder.Configuration["Auth0:Domain"];
    options.JwtBearerOptions = new JwtBearerOptions
    {
        Audience = builder.Configuration["Auth0:Audience"]
    };
});

builder.Services.AddAuthorization();

var app = builder.Build();

if (!app.Environment.IsDevelopment())
{
    app.UseHttpsRedirection();
}

app.UseAuthentication();
app.UseAuthorization();

app.Run();
5

Create public and protected endpoints

Add endpoints to test authentication. Add the following code in Program.cs before app.Run():
Program.cs
// Public endpoint - no authentication required
app.MapGet("/api/public", () => 
    Results.Ok(new { Message = "This endpoint is public" }))
    .WithName("GetPublic");

// Protected endpoint - requires authentication
app.MapGet("/api/private", () => 
    Results.Ok(new { Message = "This endpoint requires authentication" }))
    .RequireAuthorization()
    .WithName("GetPrivate");
6

Run your API

dotnet run
Your API is now running on https://localhost:7190 (or similar - check your console output for the exact URL).
CheckpointYou should now have a fully functional Auth0-protected API running on your localhost

Advanced Usage

Test your protected endpoints with an access token.1. Get an access token from Auth0 using the Client Credentials flow:
curl --request POST \
  --url https://YOUR_DOMAIN/oauth/token \
  --header 'content-type: application/json' \
  --data '{"client_id":"YOUR_CLIENT_ID","client_secret":"YOUR_CLIENT_SECRET","audience":"YOUR_AUDIENCE","grant_type":"client_credentials"}'
To get YOUR_CLIENT_ID and YOUR_CLIENT_SECRET, create a Machine to Machine Application in the Auth0 Dashboard and authorize it for your API.
2. Test the public endpoint (should return 200 OK):
curl https://localhost:7190/api/public
3. Test the protected endpoint without authentication (should return 401 Unauthorized):
curl https://localhost:7190/api/private
4. Call the protected endpoint with the token:
curl https://localhost:7190/api/private \
  --header 'Authorization: Bearer YOUR_ACCESS_TOKEN'
For larger APIs, use controllers instead of minimal API endpoints.1. Add controllers support:
Program.cs
builder.Services.AddControllers();

var app = builder.Build();

if (!app.Environment.IsDevelopment())
{
    app.UseHttpsRedirection();
}

app.UseAuthentication();
app.UseAuthorization();

app.MapControllers();

app.Run();
2. Create a controller:Create Controllers/MessagesController.cs:
Controllers/MessagesController.cs
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;

namespace Auth0Api.Controllers;

[ApiController]
[Route("api/[controller]")]
public class MessagesController : ControllerBase
{
    [HttpGet]
    public IActionResult GetPublic()
    {
        return Ok(new { Message = "This endpoint is public" });
    }

    [Authorize]
    [HttpGet("private")]
    public IActionResult GetPrivate()
    {
        var userId = User.FindFirst("sub")?.Value;
        return Ok(new { Message = "This endpoint is protected", UserId = userId });
    }

    [Authorize(Policy = "read:messages")]
    [HttpGet("messages")]
    public IActionResult GetMessages()
    {
        return Ok(new { Messages = new[] { "Message 1", "Message 2" } });
    }
}
Protect endpoints based on specific scopes in the access token.1. Define scopes in your Auth0 API:In the Auth0 Dashboard → APIs → Your API → Permissions, add scopes:
  • read:messages - Read messages
  • write:messages - Write messages
2. Configure authorization policies:
Program.cs
builder.Services.AddAuthorization(options =>
{
    options.AddPolicy("read:messages", policy =>
        policy.RequireClaim("scope", "read:messages"));
    
    options.AddPolicy("write:messages", policy =>
        policy.RequireClaim("scope", "write:messages"));
});
3. Apply policies to endpoints:
app.MapGet("/api/messages", () => 
    Results.Ok(new { Messages = new[] { "Message 1", "Message 2" } }))
    .RequireAuthorization("read:messages");

app.MapPost("/api/messages", () => 
    Results.Created("/api/messages/1", new { Id = 1, Text = "New message" }))
    .RequireAuthorization("write:messages");
When requesting an access token, include the required scope:
curl --request POST \
  --url https://YOUR_DOMAIN/oauth/token \
  --header 'content-type: application/json' \
  --data '{"client_id":"YOUR_CLIENT_ID","client_secret":"YOUR_CLIENT_SECRET","audience":"YOUR_AUDIENCE","grant_type":"client_credentials","scope":"read:messages write:messages"}'
DPoP (Demonstration of Proof-of-Possession) binds access tokens to cryptographic keys, preventing token theft and replay attacks.Enable DPoP support:
Program.cs
builder.Services.AddAuth0ApiAuthentication(options =>
{
    options.Domain = builder.Configuration["Auth0:Domain"];
    options.JwtBearerOptions = new JwtBearerOptions
    {
        Audience = builder.Configuration["Auth0:Audience"]
    };
}).WithDPoP();  // Enable DPoP with default settings
DPoP Modes:Accept both DPoP and Bearer tokens (default):
using Auth0.AspNetCore.Authentication.Api.DPoP;

.WithDPoP(dpopOptions =>
{
    dpopOptions.Mode = DPoPModes.Allowed;
});
Only accept DPoP tokens, reject Bearer tokens:
using Auth0.AspNetCore.Authentication.Api.DPoP;

.WithDPoP(dpopOptions =>
{
    dpopOptions.Mode = DPoPModes.Required;
});
Configure time validation parameters:
.WithDPoP(dpopOptions =>
{
    dpopOptions.Mode = DPoPModes.Allowed;
    dpopOptions.IatOffset = 300;  // Allow DPoP proof up to 5 minutes old
    dpopOptions.Leeway = 30;      // 30 seconds clock skew tolerance
});
Learn more about DPoP in the Auth0 DPoP Documentation.
Create reusable authorization policies for complex requirements.1. Create a custom requirement:
Authorization/HasScopeRequirement.cs
using Microsoft.AspNetCore.Authorization;

namespace Auth0Api.Authorization;

public class HasScopeRequirement : IAuthorizationRequirement
{
    public string Scope { get; }
    public string Issuer { get; }

    public HasScopeRequirement(string scope, string issuer)
    {
        Scope = scope;
        Issuer = issuer;
    }
}
2. Create a handler:
Authorization/HasScopeHandler.cs
using Microsoft.AspNetCore.Authorization;

namespace Auth0Api.Authorization;

public class HasScopeHandler : AuthorizationHandler<HasScopeRequirement>
{
    protected override Task HandleRequirementAsync(
        AuthorizationHandlerContext context,
        HasScopeRequirement requirement)
    {
        if (!context.User.HasClaim(c => c.Type == "scope" && c.Issuer == requirement.Issuer))
        {
            return Task.CompletedTask;
        }

        var scopes = context.User
            .FindFirst(c => c.Type == "scope" && c.Issuer == requirement.Issuer)?
            .Value.Split(' ');

        if (scopes?.Any(s => s == requirement.Scope) == true)
        {
            context.Succeed(requirement);
        }

        return Task.CompletedTask;
    }
}
3. Register and use the policy:
Program.cs
using Auth0Api.Authorization;

var builder = WebApplication.CreateBuilder(args);

var domain = $"https://{builder.Configuration["Auth0:Domain"]}";

builder.Services.AddAuth0ApiAuthentication(options =>
{
    options.Domain = builder.Configuration["Auth0:Domain"];
    options.JwtBearerOptions = new JwtBearerOptions
    {
        Audience = builder.Configuration["Auth0:Audience"]
    };
});

builder.Services.AddAuthorization(options =>
{
    options.AddPolicy("read:messages", policy =>
        policy.Requirements.Add(new HasScopeRequirement("read:messages", domain)));
});

builder.Services.AddSingleton<IAuthorizationHandler, HasScopeHandler>();

var app = builder.Build();
// ... rest of configuration
Extract user information from the authenticated token.
app.MapGet("/api/user-info", (HttpContext context) =>
{
    var userId = context.User.FindFirst("sub")?.Value;
    var email = context.User.FindFirst("email")?.Value;
    var name = context.User.FindFirst("name")?.Value;
    var scopes = context.User.FindAll("scope")
        .SelectMany(c => c.Value.Split(' '))
        .Distinct();

    return Results.Ok(new
    {
        UserId = userId,
        Email = email,
        Name = name,
        Scopes = scopes
    });
})
.RequireAuthorization();
Customize JWT token validation parameters for specific requirements.
Program.cs
using Microsoft.IdentityModel.Tokens;
using System.Security.Claims;

builder.Services.AddAuth0ApiAuthentication(options =>
{
    options.Domain = builder.Configuration["Auth0:Domain"];
    options.JwtBearerOptions = new JwtBearerOptions
    {
        Audience = builder.Configuration["Auth0:Audience"],
        
        TokenValidationParameters = new TokenValidationParameters
        {
            ValidateIssuerSigningKey = true,
            ValidateIssuer = true,
            ValidateAudience = true,
            ValidateLifetime = true,
            ClockSkew = TimeSpan.FromMinutes(5),
            NameClaimType = ClaimTypes.NameIdentifier,
            RoleClaimType = "https://my-app.com/roles"
        },
        
        Events = new JwtBearerEvents
        {
            OnAuthenticationFailed = context =>
            {
                Console.WriteLine($"Authentication failed: {context.Exception.Message}");
                return Task.CompletedTask;
            },
            
            OnTokenValidated = context =>
            {
                var userId = context.Principal?.FindFirst("sub")?.Value;
                Console.WriteLine($"Token validated for user: {userId}");
                return Task.CompletedTask;
            }
        }
    };
});

Additional Resources


Common Issues

Problem: Token validation fails with audience mismatch error.Solution: Ensure the Audience in appsettings.json exactly matches the Identifier of your Auth0 API. The audience claim in the token must match this value.
{
  "Auth0": {
    "Audience": "https://my-api"  // Must match Auth0 API Identifier
  }
}
Problem: Token validation fails with issuer error.Solution: Verify your Domain is correct and does not include https://. The library automatically constructs the authority as https://{Domain}.
{
  "Auth0": {
    "Domain": "your-tenant.auth0.com"  // No https://
  }
}
Problem: ArgumentNullException: Value cannot be null. (Parameter 'Domain') or similar.Solution: Ensure appsettings.json contains the Auth0 section with Domain and Audience values. Check that configuration is being read correctly:
builder.Services.AddAuth0ApiAuthentication(options =>
{
    options.Domain = builder.Configuration["Auth0:Domain"]
        ?? throw new InvalidOperationException("Auth0:Domain is required");
    options.JwtBearerOptions = new JwtBearerOptions
    {
        Audience = builder.Configuration["Auth0:Audience"]
            ?? throw new InvalidOperationException("Auth0:Audience is required")
    };
});
Problem: SSL/TLS certificate errors when running locally.Solution: Trust the development certificate:
dotnet dev-certs https --trust
Or generate a new certificate:
dotnet dev-certs https --clean
dotnet dev-certs https --trust
Problem: Authentication not working despite correct configuration.Solution: Ensure middleware is in the correct order. UseAuthentication() must come before UseAuthorization():
app.UseAuthentication();  // Must be before UseAuthorization
app.UseAuthorization();
app.MapControllers();
Problem: Scope-based authorization policies always fail.Solution: Ensure your access token includes the required scopes. When requesting a token, specify the scopes:
curl --request POST \
  --url https://YOUR_DOMAIN/oauth/token \
  --data '{"client_id":"...","client_secret":"...","audience":"...","grant_type":"client_credentials","scope":"read:messages write:messages"}'
Also verify scopes are defined in your Auth0 API settings (Dashboard → APIs → Your API → Permissions).

Sample Application

A complete sample application demonstrating all features is available in the SDK repository.

Playground Application

Includes public and protected endpoints, DPoP support, Swagger UI integration, and Postman collection
Clone and run:
git clone https://github.com/auth0/auth0-aspnetcore-api.git
cd auth0-aspnetcore-api/Auth0.AspNetCore.Authentication.Api.Playground
# Update appsettings.json with your Auth0 configuration
dotnet run