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-apipour 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-vueouauth0-angularpour l'authentification côté client - Applications Next.js - Utilisez
auth0-nextjsqui gère à la fois le client et le serveur - Applications web Python - Utilisez
auth0-flaskpour 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 Bearerauth0-express- Pour les applications web serveur Express avec sessions connexion/déconnexionauth0-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 exempletenant.us.auth0.com)Auth0:ClientId- ID client de l'applicationAuth0: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