> ## Documentation Index
> Fetch the complete documentation index at: https://translations.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# API Web ASP.NET Core

> Ajoutez l’authentification JWT d’Auth0 à une API Web ASP.NET Core avec des points de terminaison protégés

export const HowToSchema = () => <script type="application/ld+json">
    {'{"@context":"https://schema.org","@type":"HowTo"}'}
  </script>;

<HowToSchema />

<Callout icon="pencil" color="#FFC107" iconType="solid">
  Ce guide de démarrage rapide est actuellement en **bêta**. N’hésitez pas à nous faire part de vos commentaires!
</Callout>

<Accordion title="Utiliser l’IA pour intégrer Auth0" icon="microchip-ai" iconType="solid" defaultOpen>
  Si vous utilisez un assistant IA de codage comme Claude Code, Cursor ou GitHub Copilot, vous pouvez ajouter automatiquement l’authentification Auth0 en quelques minutes à l’aide des [agent skills](https://agentskills.io/home).

  **Installer :**

  ```bash theme={null}
  npx skills add auth0/agent-skills --skill auth0-quickstart --skill auth0-aspnetcore-api
  ```

  **Ensuite, demandez à votre assistant IA :**

  ```text theme={null}
  Add Auth0 JWT authentication to my ASP.NET Core Web API
  ```

  Votre assistant IA créera automatiquement votre API Auth0, récupérera les identifiants, installera le SDK d’authentification API Auth0 pour ASP.NET Core, configurera l’authentification JWT Bearer et mettra en œuvre des points de terminaison d’API protégés. [Documentation complète sur les agent skills →](/fr-CA/docs/quickstart/agent-skills)
</Accordion>

<Note>
  **Prérequis :** Avant de commencer, assurez-vous d’avoir installé ce qui suit :

  * **[.NET 8.0 SDK](https://dotnet.microsoft.com/download/dotnet/8.0)** ou une version ultérieure
  * Votre IDE préféré (Visual Studio 2022, VS Code ou Rider)

  **Compatibilité des versions de .NET :** Ce guide de démarrage rapide fonctionne avec **.NET 8.0** et les versions ultérieures.
</Note>

<div id="get-started">
  ## Premiers pas
</div>

Ce guide de démarrage rapide montre comment ajouter l’authentification JWT d’Auth0 à une API Web ASP.NET Core. Vous créerez une API sécurisée avec des points de terminaison protégés à l’aide du SDK API ASP.NET Core d’Auth0.

<Steps>
  <Step title="Créer un nouveau projet" stepNumber={1}>
    Créez un nouveau projet d’API web ASP.NET Core pour ce guide de démarrage rapide

    ```bash theme={null}
    dotnet new webapi -n Auth0Api
    ```

    Ouvrir le projet

    ```bash theme={null}
    cd Auth0Api
    ```
  </Step>

  <Step title="Installez le SDK Auth0" stepNumber={2}>
    ```bash theme={null}
    dotnet add package Auth0.AspNetCore.Authentication.Api
    ```
  </Step>

  <Step title="Configurez votre API Auth0" stepNumber={3}>
    Ensuite, vous devez créer une nouvelle API sur votre tenant Auth0 et ajouter la configuration à votre projet.

    Vous pouvez effectuer cette opération automatiquement en exécutant une commande CLI ou manuellement via le tableau de bord :

    <Tabs>
      <Tab title="interface de ligne de commande">
        Exécutez la commande shell suivante à la racine du projet pour créer une API Auth0 et mettre à jour votre fichier `appsettings.json` :

        <Tabs>
          <Tab title="Mac/Linux">
            ```bash theme={null}
            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
            ```
          </Tab>

          <Tab title="Windows (PowerShell)">
            ```powershell theme={null}
            $ApiName = "My ASP.NET Core API"
            $ApiIdentifier = "https://my-api"
            $latestRelease = Invoke-RestMethod -Uri "https://api.github.com/repos/auth0/auth0-cli/releases/latest"
            $latestVersion = $latestRelease.tag_name
            $version = $latestVersion -replace "^v"
            Invoke-WebRequest -Uri "https://github.com/auth0/auth0-cli/releases/download/${latestVersion}/auth0-cli_${version}_Windows_x86_64.zip" -OutFile ".\auth0.zip"
            Expand-Archive ".\auth0.zip" .\
            [System.Environment]::SetEnvironmentVariable('PATH', $Env:PATH + ";${pwd}")
            auth0 login --no-input
            auth0 apis create -n "$ApiName" -i "$ApiIdentifier" --offline-access --token-lifetime 86400 --signing-alg RS256 --json | Set-Content -Path auth0-api-details.json
            $Domain = (auth0 tenants list --json | ConvertFrom-Json | Where-Object { $_.active -eq $true }).name
            $Audience = (Get-Content -Raw auth0-api-details.json | ConvertFrom-Json).identifier
            $Config = Get-Content -Raw appsettings.json | ConvertFrom-Json
            if (-not $Config.Auth0) { $Config | Add-Member -MemberType NoteProperty -Name Auth0 -Value @{} }
            $Config.Auth0.Domain = $Domain
            $Config.Auth0.Audience = $Audience
            $Config | ConvertTo-Json -Depth 10 | Set-Content appsettings.json
            Remove-Item auth0-api-details.json
            Write-Output "✅ appsettings.json updated with your Auth0 API details:"
            Get-Content appsettings.json
            ```
          </Tab>
        </Tabs>
      </Tab>

      <Tab title="Tableau de bord">
        Avant de commencer, ajoutez la configuration d’Auth0 à votre fichier `appsettings.json`

        ```json appsettings.json theme={null}
        {
          "Logging": {
            "LogLevel": {
              "Default": "Information",
              "Microsoft.AspNetCore": "Warning"
            }
          },
          "AllowedHosts": "*",
          "Auth0": {
            "Domain": "YOUR_AUTH0_DOMAIN",
            "Audience": "YOUR_AUTH0_API_IDENTIFIER"
          }
        }
        ```

        1. Accédez au [Auth0 Dashboard](https://manage.auth0.com) → **Applications** → **APIs**
        2. Cliquez sur **Create API**
        3. Entrez les détails de votre API :
           * **Name** : Mon API ASP.NET Core
           * **Identifier** : `https://my-api` (cela devient votre **Audience**)
           * **Signing Algorithm** : RS256
        4. Cliquez sur **Create**
        5. Remplacez `YOUR_AUTH0_DOMAIN` dans `appsettings.json` par votre **Domain** à partir de l’onglet Test (p. ex., `your-tenant.auth0.com`)
        6. Remplacez `YOUR_AUTH0_API_IDENTIFIER` dans `appsettings.json` par votre **Identifier** (p. ex., `https://my-api`)

        <Info>
          Votre **Domain** ne doit pas inclure `https://` — utilisez seulement le nom de domaine (p. ex., `your-tenant.auth0.com`).

          L’**Audience** (identifiant de l’API) est un identifiant unique pour votre API et peut être n’importe quel URI valide. Elle n’a pas besoin d’être une URL accessible publiquement.
        </Info>
      </Tab>
    </Tabs>
  </Step>

  <Step title="Configurer l’authentification" stepNumber={4}>
    Remplacez l’intégralité du contenu de `Program.cs` par le code suivant :

    ```csharp Program.cs lines theme={null}
    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();
    ```
  </Step>

  <Step title="Créer des points de terminaison publics et protégés" stepNumber={5}>
    Ajoutez des points de terminaison pour tester l’authentification. Ajoutez le code suivant à `Program.cs` avant `app.Run()` :

    ```csharp Program.cs theme={null}
    // Point de terminaison public - aucune authentification requise
    app.MapGet("/api/public", () => 
        Results.Ok(new { Message = "This endpoint is public" }))
        .WithName("GetPublic");

    // Point de terminaison protégé - authentification requise
    app.MapGet("/api/private", () => 
        Results.Ok(new { Message = "This endpoint requires authentication" }))
        .RequireAuthorization()
        .WithName("GetPrivate");
    ```
  </Step>

  <Step title="Exécutez votre API" stepNumber={6}>
    ```bash theme={null}
    dotnet run
    ```

    Votre API fonctionne maintenant à l’adresse `https://localhost:7190` (ou à une URL semblable - vérifiez la sortie de la console pour connaître l’URL exacte).
  </Step>
</Steps>

<Check>
  **Point de contrôle**

  Vous devriez maintenant avoir une API protégée par Auth0 entièrement fonctionnelle, accessible sur votre [localhost](https://localhost:7190/)
</Check>

***

<div id="advanced-usage">
  ## Utilisation avancée
</div>

<Accordion title="Appeler des API protégées">
  Testez vos points de terminaison protégés à l’aide d’un jeton d’accès.

  **1. Obtenez un jeton d’accès** auprès d’Auth0 à l’aide du flux Client Credentials :

  ```bash theme={null}
  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"}'
  ```

  <Info>
    Pour obtenir `YOUR_CLIENT_ID` et `YOUR_CLIENT_SECRET`, créez une application Machine-to-Machine dans le [tableau de bord Auth0](https://manage.auth0.com/#/applications) et autorisez-la à accéder à votre API.
  </Info>

  **2. Testez le point de terminaison public** (devrait renvoyer 200 OK) :

  ```bash theme={null}
  curl https://localhost:7190/api/public
  ```

  **3. Testez le point de terminaison protégé sans authentification** (devrait renvoyer 401 Unauthorized) :

  ```bash theme={null}
  curl https://localhost:7190/api/private
  ```

  **4. Appelez le point de terminaison protégé avec le jeton :**

  ```bash theme={null}
  curl https://localhost:7190/api/private \
    --header 'Authorization: Bearer YOUR_ACCESS_TOKEN'
  ```
</Accordion>

<Accordion title="Utiliser des points de terminaison basés sur des contrôleurs">
  Pour les API plus volumineuses, utilisez des contrôleurs plutôt que des points de terminaison d’API minimaux.

  **1. Ajoutez la prise en charge des contrôleurs :**

  ```csharp Program.cs theme={null}
  builder.Services.AddControllers();

  var app = builder.Build();

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

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

  app.MapControllers();

  app.Run();
  ```

  **2. Créez un contrôleur :**

  Créez `Controllers/MessagesController.cs` :

  ```csharp Controllers/MessagesController.cs theme={null}
  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" } });
      }
  }
  ```
</Accordion>

<Accordion title="Protéger des routes à l’aide d’une autorisation basée sur les portées">
  Protégez les points de terminaison en fonction de portées précises dans le jeton d’accès.

  **1. Définissez des portées dans votre API Auth0 :**

  Dans le [tableau de bord Auth0](https://manage.auth0.com) → APIs → Your API → Permissions, ajoutez des portées :

  * `read:messages` - Lire les messages
  * `write:messages` - Écrire des messages

  **2. Configurez les politiques d’autorisation :**

  ```csharp Program.cs theme={null}
  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. Appliquez les politiques aux points de terminaison :**

  ```csharp theme={null}
  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");
  ```

  Lorsque vous demandez un jeton d’accès, incluez la portée requise :

  ```bash theme={null}
  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"}'
  ```
</Accordion>

<Accordion title="Utiliser DPoP pour une sécurité renforcée">
  DPoP (Demonstration of Proof-of-Possession) associe les jetons d’accès à des clés cryptographiques, ce qui empêche le vol de jetons et les attaques par rejeu.

  **Activer la prise en charge de DPoP :**

  ```csharp Program.cs theme={null}
  builder.Services.AddAuth0ApiAuthentication(options =>
  {
      options.Domain = builder.Configuration["Auth0:Domain"];
      options.JwtBearerOptions = new JwtBearerOptions
      {
          Audience = builder.Configuration["Auth0:Audience"]
      };
  }).WithDPoP();  // Activer DPoP avec les paramètres par défaut
  ```

  **Modes DPoP :**

  Accepter à la fois les jetons DPoP et Bearer (par défaut) :

  ```csharp theme={null}
  using Auth0.AspNetCore.Authentication.Api.DPoP;

  .WithDPoP(dpopOptions =>
  {
      dpopOptions.Mode = DPoPModes.Allowed;
  });
  ```

  Accepter uniquement les jetons DPoP et rejeter les jetons Bearer :

  ```csharp theme={null}
  using Auth0.AspNetCore.Authentication.Api.DPoP;

  .WithDPoP(dpopOptions =>
  {
      dpopOptions.Mode = DPoPModes.Required;
  });
  ```

  Configurer les paramètres de validation temporelle :

  ```csharp theme={null}
  .WithDPoP(dpopOptions =>
  {
      dpopOptions.Mode = DPoPModes.Allowed;
      dpopOptions.IatOffset = 300;  // Autoriser une preuve DPoP datant d’au plus 5 minutes
      dpopOptions.Leeway = 30;      // Tolérance de 30 secondes pour le décalage de l’horloge
  });
  ```

  <Info>
    Pour en savoir plus sur DPoP, consultez la [documentation Auth0 sur DPoP](https://auth0.com/docs/secure/sender-constraining/demonstrating-proof-of-possession-dpop).
  </Info>
</Accordion>

<Accordion title="Implémenter des politiques d’autorisation personnalisées">
  Créer des politiques d’autorisation réutilisables pour répondre à des exigences complexes.

  **1. Créer une exigence personnalisée :**

  ```csharp Authorization/HasScopeRequirement.cs theme={null}
  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. Créer un gestionnaire :**

  ```csharp Authorization/HasScopeHandler.cs theme={null}
  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. Enregistrer et utiliser la politique :**

  ```csharp Program.cs theme={null}
  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();
  // ... reste de la configuration
  ```
</Accordion>

<Accordion title="Accès aux renseignements de l’utilisateur">
  Extrayez les renseignements de l’utilisateur à partir du jeton authentifié.

  ```csharp theme={null}
  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();
  ```
</Accordion>

<Accordion title="Validation personnalisée du jeton">
  Personnalisez les paramètres de validation du jeton JWT en fonction de vos besoins particuliers.

  ```csharp Program.cs theme={null}
  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;
              }
          }
      };
  });
  ```
</Accordion>

***

<div id="additional-resources">
  ## Ressources supplémentaires
</div>

<CardGroup cols={3}>
  <Card title="Documentation du SDK" icon="book" href="https://github.com/auth0/aspnetcore-api">
    Documentation complète du SDK et référence de l’API
  </Card>

  <Card title="Guide de migration" icon="arrow-right-arrow-left" href="https://github.com/auth0/aspnetcore-api/blob/master/MIGRATION.md">
    Migrer à partir de l’authentification JWT Bearer
  </Card>

  <Card title="Exemples de code" icon="code" href="https://github.com/auth0/aspnetcore-api/blob/master/EXAMPLES.md">
    Exemples de code et modèles complets
  </Card>

  <Card title="Documentation sur DPoP" icon="shield" href="https://auth0.com/docs/secure/sender-constraining/demonstrating-proof-of-possession-dpop">
    En savoir plus sur la sécurité par preuve de possession
  </Card>

  <Card title="Bonnes pratiques relatives aux jetons" icon="key" href="https://auth0.com/docs/secure/tokens/token-best-practices">
    Bonnes pratiques de sécurité pour les jetons
  </Card>

  <Card title="Forum de la communauté" icon="comments" href="https://community.auth0.com/">
    Obtenez de l’aide de la communauté Auth0
  </Card>
</CardGroup>

***

<div id="common-issues">
  ## Problèmes courants
</div>

<AccordionGroup>
  <Accordion title="401 Non autorisé - Audience non valide">
    **Problème :** La validation du jeton échoue en raison d’une incompatibilité de l’audience.

    **Solution :** Assurez-vous que `Audience` dans `appsettings.json` correspond exactement à l’identifiant de votre API Auth0. La revendication d’audience du jeton doit correspondre à cette valeur.

    ```json theme={null}
    {
      "Auth0": {
        "Audience": "https://my-api"  // Doit correspondre à l’identifiant de l’API Auth0
      }
    }
    ```
  </Accordion>

  <Accordion title="401 Non autorisé - Émetteur non valide">
    **Problème :** La validation du jeton échoue en raison d’une erreur liée à l’émetteur.

    **Solution :** Vérifiez que votre domaine est correct et qu’il n’inclut pas `https://`. La bibliothèque construit automatiquement l’autorité sous la forme `https://{Domain}`.

    ```json theme={null}
    {
      "Auth0": {
        "Domain": "your-tenant.auth0.com"  // Sans https://
      }
    }
    ```
  </Accordion>

  <Accordion title="Valeurs de configuration introuvables">
    **Problème :** `ArgumentNullException: Value cannot be null. (Parameter 'Domain')` ou un message semblable.

    **Solution :** Assurez-vous que `appsettings.json` contient la section Auth0 avec les valeurs Domain et Audience. Vérifiez aussi que la configuration est bien lue :

    ```csharp theme={null}
    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")
        };
    });
    ```
  </Accordion>

  <Accordion title="Erreurs de certificat HTTPS en développement">
    **Problème :** Des erreurs de certificat SSL/TLS surviennent lors de l’exécution en local.

    **Solution :** Faites approuver le certificat de développement :

    ```bash theme={null}
    dotnet dev-certs https --trust
    ```

    Ou générez un nouveau certificat :

    ```bash theme={null}
    dotnet dev-certs https --clean
    dotnet dev-certs https --trust
    ```
  </Accordion>

  <Accordion title="Problèmes d’ordre du middleware">
    **Problème :** L’authentification ne fonctionne pas malgré une configuration correcte.

    **Solution :** Assurez-vous que le middleware est dans le bon ordre. `UseAuthentication()` doit être appelé avant `UseAuthorization()` :

    ```csharp theme={null}
    app.UseAuthentication();  // Doit être avant UseAuthorization
    app.UseAuthorization();
    app.MapControllers();
    ```
  </Accordion>

  <Accordion title="Les portées ne fonctionnent pas dans les politiques d’autorisation">
    **Problème :** Les politiques d’autorisation basées sur les portées échouent systématiquement.

    **Solution :** Assurez-vous que votre jeton d’accès comprend les portées requises. Lorsque vous demandez un jeton, précisez les portées :

    ```bash theme={null}
    curl --request POST \
      --url https://YOUR_DOMAIN/oauth/token \
      --data '{"client_id":"...","client_secret":"...","audience":"...","grant_type":"client_credentials","scope":"read:messages write:messages"}'
    ```

    Vérifiez aussi que les portées sont définies dans les paramètres de votre API Auth0 (tableau de bord Auth0 → APIs → Your API → Permissions).
  </Accordion>
</AccordionGroup>

***

<div id="sample-application">
  ## Exemple d’application
</div>

Un exemple d’application complet illustrant toutes les fonctionnalités est disponible dans le dépôt du SDK.

<Card title="Application de démonstration" icon="github" href="https://github.com/auth0/aspnetcore-api/tree/master/Auth0.AspNetCore.Authentication.Api.Playground">
  Comprend des points de terminaison publics et protégés, la prise en charge de DPoP, l’intégration de Swagger UI et une collection Postman
</Card>

Clonez et exécutez :

```bash theme={null}
git clone https://github.com/auth0/aspnetcore-api.git
cd aspnetcore-api/Auth0.AspNetCore.Authentication.Api.Playground
# Mettez à jour appsettings.json avec votre configuration Auth0
dotnet run
```
