auth0-aspnetcore-authentication

Par auth0 · agent-skills

À utiliser pour ajouter la connexion, la déconnexion et le profil utilisateur à une application web ASP.NET Core MVC, Razor Pages ou Blazor Server avec une authentification par cookie — intègre Auth0.AspNetCore.Authentication pour les applications rendues côté serveur avec les flux login/callback/profil/déconnexion.

npx skills add https://github.com/auth0/agent-skills --skill auth0-aspnetcore-authentication

Intégration d'une application web Auth0 ASP.NET Core

Ajoutez la connexion, la déconnexion et le profil utilisateur à une application ASP.NET Core MVC, Razor Pages ou Blazor Server en utilisant Auth0.AspNetCore.Authentication.


Prérequis

  • Application ASP.NET Core (.NET 8 ou supérieur)
  • Application web régulière Auth0 configurée (pas une API - doit être une Application)
  • Si vous n'avez pas encore configuré Auth0, utilisez d'abord la skill auth0-quickstart

Quand NE PAS utiliser

  • ASP.NET Core Web APIs avec validation JWT Bearer - Utilisez auth0-aspnetcore-api pour les API REST protégées par JWT
  • Blazor WebAssembly - Nécessite l'authentification OIDC côté client ; consultez le démarrage rapide Auth0 Blazor WebAssembly
  • Applications monopage - Utilisez auth0-react, auth0-vue ou auth0-angular pour l'authentification côté client
  • Applications Next.js - Utilisez auth0-nextjs qui gère à la fois le client et le serveur
  • Applications web Python - Utilisez auth0-flask pour Flask ou consultez le démarrage rapide Django

Flux de démarrage rapide

1. Installer le SDK

dotnet add package Auth0.AspNetCore.Authentication

2. Configurer les identifiants

Ajoutez les paramètres Auth0 à appsettings.json :

{
  "Auth0": {
    "Domain": "your-tenant.us.auth0.com",
    "ClientId": "your_client_id",
    "ClientSecret": "your_client_secret"
  }
}

Pour le développement local, gardez les secrets hors du contrôle de source - utilisez dotnet user-secrets pour éviter de valider ClientSecret :

dotnet user-secrets set "Auth0:Domain" "your-tenant.us.auth0.com"
dotnet user-secrets set "Auth0:ClientId" "your_client_id"
dotnet user-secrets set "Auth0:ClientSecret" "your_client_secret"

Auth0:Domain est votre domaine de tenant (sans https://). Auth0:ClientId et Auth0:ClientSecret proviennent de vos paramètres d'application Auth0.

3. Configurer le tableau de bord Auth0

Dans vos paramètres d'application Auth0 :

  • URLs de rappel autorisées : http://localhost:5000/callback
  • URLs de déconnexion autorisées : http://localhost:5000
  • Origines web autorisées : http://localhost:5000

4. Enregistrer Auth0 dans Program.cs

using Auth0.AspNetCore.Authentication;

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddAuth0WebAppAuthentication(options =>
{
    options.Domain = builder.Configuration["Auth0:Domain"];
    options.ClientId = builder.Configuration["Auth0:ClientId"];
    options.ClientSecret = builder.Configuration["Auth0:ClientSecret"];
});

builder.Services.AddControllersWithViews();

var app = builder.Build();

// Middleware standard...
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();

app.UseAuthentication();    // Doit venir avant UseAuthorization
app.UseAuthorization();     // Critique : l'ordre compte

app.MapControllerRoute(
    name: "default",
    pattern: "{controller=Home}/{action=Index}/{id?}");

app.Run();

Critique : UseAuthentication() doit venir avant UseAuthorization(). Inverser ces deux provoque des défaillances silencieuses d'authentification où les routes protégées ne sont jamais challeng­ées.

5. Créer AccountController

using Auth0.AspNetCore.Authentication;
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Authentication.Cookies;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;

public class AccountController : Controller
{
    public async Task Login(string returnUrl = "/")
    {
        var authenticationProperties = new LoginAuthenticationPropertiesBuilder()
            .WithRedirectUri(returnUrl)
            .Build();

        await HttpContext.ChallengeAsync(Auth0Constants.AuthenticationScheme, authenticationProperties);
    }

    [Authorize]
    public async Task Logout()
    {
        var authenticationProperties = new LogoutAuthenticationPropertiesBuilder()
            .WithRedirectUri(Url.Action("Index", "Home"))
            .Build();

        await HttpContext.SignOutAsync(Auth0Constants.AuthenticationScheme, authenticationProperties);
        await HttpContext.SignOutAsync(CookieAuthenticationDefaults.AuthenticationScheme);
    }

    [Authorize]
    public IActionResult Profile()
    {
        return View();
    }
}

Login n'a pas besoin de [Authorize] - c'est le point d'entrée pour les utilisateurs non authentifiés. Logout exige [Authorize] pour assurer que la déconnexion ne se déclenche que pour les sessions authentifiées. Appelez toujours les deux méthodes SignOutAsync - se déconnecter uniquement du schéma Auth0 laisse un cookie local ; se déconnecter uniquement du schéma cookie ignore l'URL de déconnexion Auth0.

6. Créer la vue Profile

Créez Views/Account/Profile.cshtml :

@{
    ViewData["Title"] = "User Profile";
}

<div class="row">
    <div class="col-md-2">
        <img src="@User.FindFirst(c => c.Type == "picture")?.Value"
             alt="Profile picture" class="img-fluid rounded-circle" />
    </div>
    <div class="col-md-10">
        <h3>@User.Identity.Name</h3>
        <p><strong>Email:</strong>
           @User.FindFirst(c => c.Type == System.Security.Claims.ClaimTypes.Email)?.Value</p>
        <p><strong>User ID:</strong>
           @User.FindFirst(c => c.Type == System.Security.Claims.ClaimTypes.NameIdentifier)?.Value</p>
    </div>
</div>

<h4 class="mt-4">Claims</h4>
<table class="table">
    <thead><tr><th>Claim Type</th><th>Claim Value</th></tr></thead>
    <tbody>
        @foreach (var claim in User.Claims)
        {
            <tr><td>@claim.Type</td><td>@claim.Value</td></tr>
        }
    </tbody>
</table>

7. Mettre à jour la navigation (_Layout.cshtml)

Ajoutez les liens connexion/déconnexion/profil à votre barre de navigation dans _Layout.cshtml :

@if (User.Identity.IsAuthenticated)
{
    <li class="nav-item">
        <a class="nav-link text-dark" asp-controller="Account" asp-action="Profile">@User.Identity.Name</a>
    </li>
    <li class="nav-item">
        <a class="nav-link text-dark" asp-controller="Account" asp-action="Logout">Logout</a>
    </li>
}
else
{
    <li class="nav-item">
        <a class="nav-link text-dark" asp-controller="Account" asp-action="Login">Login</a>
    </li>
}

8. Tester l'application

dotnet run

Visitez http://localhost:5000 et cliquez sur Login pour démarrer le flux de connexion Auth0.


Variante Blazor Server

Pour les applications Blazor Server, utilisez Razor Pages comme endpoints d'authentification - les composants Blazor ne peuvent pas effectuer les redirections HTTP requises par les challenges OAuth.

Configuration supplémentaire de Program.cs

using Auth0.AspNetCore.Authentication;

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddAuth0WebAppAuthentication(options =>
{
    options.Domain = builder.Configuration["Auth0:Domain"];
    options.ClientId = builder.Configuration["Auth0:ClientId"];
    options.ClientSecret = builder.Configuration["Auth0:ClientSecret"];
});

builder.Services.AddRazorComponents()
    .AddInteractiveServerComponents();

builder.Services.AddCascadingAuthenticationState();  // Requis pour l'état d'auth Blazor
builder.Services.AddRazorPages();                     // Requis pour les endpoints d'auth

var app = builder.Build();

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

app.MapRazorPages();
app.MapRazorComponents<App>()
    .AddInteractiveServerRenderMode();

app.Run();

Page Razor de connexion (Pages/Login.cshtml.cs)

using Auth0.AspNetCore.Authentication;
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;

public class LoginModel : PageModel
{
    public async Task OnGet(string returnUrl = "/")
    {
        var authenticationProperties = new LoginAuthenticationPropertiesBuilder()
            .WithRedirectUri(returnUrl)
            .Build();

        await HttpContext.ChallengeAsync(Auth0Constants.AuthenticationScheme, authenticationProperties);
    }
}

Page Razor de déconnexion (Pages/Logout.cshtml.cs)

using Auth0.AspNetCore.Authentication;
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Authentication.Cookies;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;

public class LogoutModel : PageModel
{
    public async Task OnGet()
    {
        var authenticationProperties = new LogoutAuthenticationPropertiesBuilder()
            .WithRedirectUri(Url.Content("~/"))
            .Build();

        await HttpContext.SignOutAsync(Auth0Constants.AuthenticationScheme, authenticationProperties);
        await HttpContext.SignOutAsync(CookieAuthenticationDefaults.AuthenticationScheme);
    }
}

Composant Profile (Components/Pages/Profile.razor)

@page "/profile"
@attribute [Authorize]
@using System.Security.Claims

<h1>Profile</h1>

<AuthorizeView>
    <Authorized>
        <div class="row">
            <div class="col-2">
                <img src="@context.User.FindFirst("picture")?.Value"
                     alt="Profile" class="img-fluid rounded-circle" />
            </div>
            <div class="col-10">
                <h3>@context.User.Identity?.Name</h3>
                <p><strong>Email:</strong> @context.User.FindFirst(ClaimTypes.Email)?.Value</p>
            </div>
        </div>

        <h4 class="mt-4">Claims</h4>
        <table class="table">
            <thead><tr><th>Type</th><th>Value</th></tr></thead>
            <tbody>
                @foreach (var claim in context.User.Claims)
                {
                    <tr><td>@claim.Type</td><td>@claim.Value</td></tr>
                }
            </tbody>
        </table>
    </Authorized>
</AuthorizeView>

Mettre à jour la navigation MainLayout.razor

@using Microsoft.AspNetCore.Components.Authorization

<AuthorizeView>
    <Authorized>
        <a href="/profile">@context.User.Identity?.Name</a>
        <a href="/Logout">Logout</a>
    </Authorized>
    <NotAuthorized>
        <a href="/Login">Login</a>
    </NotAuthorized>
</AuthorizeView>

Routes.razor

Enveloppez le Router dans CascadingAuthenticationState pour activer l'autorisation dans tout l'arbre des composants :

<CascadingAuthenticationState>
    <Router AppAssembly="typeof(Program).Assembly">
        <Found Context="routeData">
            <AuthorizeRouteView RouteData="routeData" DefaultLayout="typeof(Layout.MainLayout)" />
            <FocusOnNavigate RouteData="routeData" Selector="h1" />
        </Found>
    </Router>
</CascadingAuthenticationState>

Variante Razor Pages

Pour les applications Razor Pages (sans Blazor), utilisez AddRazorPages() au lieu de AddControllersWithViews() dans Program.cs. Les endpoints d'authentification sont les mêmes que les modèles de page Login/Logout présentés dans la section Blazor Server. Remplacez la navigation dans _Layout.cshtml en utilisant le même contrôle User.Identity.IsAuthenticated montré dans la section MVC.


Erreurs courantes

Erreur Correction
Hardcoder Domain, ClientId ou ClientSecret dans le source Lisez depuis la configuration - utilisez builder.Configuration["Auth0:Domain"] ; ne jamais intégrer les identifiants
Valider ClientSecret au contrôle de source Utilisez dotnet user-secrets ou les variables d'environnement pour le secret client - ne jamais le valider
UseAuthorization() avant UseAuthentication() Doit appeler UseAuthentication() en premier - l'ordre incorrect empêche l'authentification de se déclencher
Se déconnecter d'un seul schéma Appelez toujours à la fois SignOutAsync(Auth0Constants.AuthenticationScheme) et SignOutAsync(CookieAuthenticationDefaults.AuthenticationScheme)
Ajouter [Authorize] à l'action Login Login doit être accessible aux utilisateurs non authentifiés - appliquez [Authorize] uniquement à Logout et Profile
Ne pas configurer les URLs de rappel dans le tableau de bord Auth0 Doit ajouter http://localhost:5000/callback aux URLs de rappel autorisées
Passer Domain avec le préfixe https:// Domain doit être le domaine nu, par exemple my-tenant.us.auth0.com, pas https://my-tenant.us.auth0.com
Ne pas ajouter AddCascadingAuthenticationState() dans Blazor Requis pour Blazor Server - sans cela, AuthorizeView et les attributs [Authorize] n'ont pas de contexte d'auth
Utiliser des composants Blazor pour les redirections login/logout Les composants Blazor ne peuvent pas effectuer les redirections HTTP - utilisez Razor Pages (/Login, /Logout) pour les endpoints d'auth
Ne pas ajouter AddRazorPages() et MapRazorPages() dans Blazor Les pages Razor Login et Logout ne seront pas routées sans ces enregistrements
Utiliser Auth0.AspNetCore.Authentication.Api pour les applications web Ce package est pour les APIs protégées par JWT - utilisez Auth0.AspNetCore.Authentication pour les applications web basées sur les sessions
Utiliser AddJwtBearer au lieu de AddAuth0WebAppAuthentication AddJwtBearer est pour l'authentification sans état des APIs - les applications web basées sur les sessions nécessitent AddAuth0WebAppAuthentication
Ne pas créer le répertoire Views/Account/ pour la vue Profile MVC nécessite que le répertoire existe avant de créer la vue

Méthodes clés du SDK

Méthode/Propriété Utilisation Objectif
AddAuth0WebAppAuthentication builder.Services.AddAuth0WebAppAuthentication(options => { ... }) Enregistre l'authentification basée sur les cookies Auth0
LoginAuthenticationPropertiesBuilder new LoginAuthenticationPropertiesBuilder().WithRedirectUri(url).Build() Crée les propriétés pour le challenge de connexion
LogoutAuthenticationPropertiesBuilder new LogoutAuthenticationPropertiesBuilder().WithRedirectUri(url).Build() Crée les propriétés pour la redirection de déconnexion
ChallengeAsync await HttpContext.ChallengeAsync(Auth0Constants.AuthenticationScheme, props) Initie la redirection Auth0 Universal Login
SignOutAsync (Auth0) await HttpContext.SignOutAsync(Auth0Constants.AuthenticationScheme, props) Se déconnecte d'Auth0 et redirige vers l'URL de déconnexion
SignOutAsync (Cookie) await HttpContext.SignOutAsync(CookieAuthenticationDefaults.AuthenticationScheme) Efface le cookie de session local
User.FindFirst User.FindFirst(c => c.Type == "picture")?.Value Accède aux claims individuels de l'utilisateur dans les contrôleurs/vues
User.Identity.IsAuthenticated @if (User.Identity.IsAuthenticated) Vérifie l'état d'authentification dans les vues/layouts
[Authorize] attribut [Authorize] sur l'action du contrôleur ou le composant Razor Protège les routes nécessitant l'authentification
AddCascadingAuthenticationState builder.Services.AddCascadingAuthenticationState() Requis pour la propagation d'état d'auth Blazor Server

Skills liées

  • auth0-aspnetcore-api - Pour les APIs Web ASP.NET Core avec validation de token JWT Bearer
  • auth0-express - Pour les applications web serveur Express avec sessions connexion/déconnexion
  • auth0-flask - Pour les applications Flask avec authentification basée sur les sessions

Référence rapide

Enregistrement du SDK :

builder.Services.AddAuth0WebAppAuthentication(options =>
{
    options.Domain = builder.Configuration["Auth0:Domain"];        // requis
    options.ClientId = builder.Configuration["Auth0:ClientId"];    // requis
    options.ClientSecret = builder.Configuration["Auth0:ClientSecret"]; // requis
});

Action de connexion :

var props = new LoginAuthenticationPropertiesBuilder().WithRedirectUri(returnUrl).Build();
await HttpContext.ChallengeAsync(Auth0Constants.AuthenticationScheme, props);

Action de déconnexion (appelez toujours les deux) :

var props = new LogoutAuthenticationPropertiesBuilder().WithRedirectUri(Url.Action("Index", "Home")).Build();
await HttpContext.SignOutAsync(Auth0Constants.AuthenticationScheme, props);
await HttpContext.SignOutAsync(CookieAuthenticationDefaults.AuthenticationScheme);

Protection des routes :

[Authorize]
public IActionResult Profile() { return View(); }

Clés de configuration appsettings.json :

  • Auth0:Domain - Domaine de tenant Auth0 (par exemple tenant.us.auth0.com)
  • Auth0:ClientId - ID client de l'application
  • Auth0:ClientSecret - Secret client de l'application (utilisez user-secrets en développement)

Documentation détaillée

  • Guide de configuration - Scripts de configuration automatisée, configuration des identifiants, utilisation d'Auth0 CLI
  • Guide d'intégration - Routes protégées, appel d'APIs, patrons Blazor, gestion des erreurs
  • Référence API - Configuration complète du SDK, options du builder, référence des claims

Références

Skills similaires