Partager via


Configurer l’authentification Web OpenID Connect (IU) dans ASP.NET Core

Par Damien Bowden

Afficher ou télécharger l’exemple de code

Cet article couvre les domaines suivants :

  • Qu’est-ce qu’un client interactif confidentiel OpenID Connect
  • Créer un client OpenID Connect dans ASP.NET Core
  • Exemples de client OpenID Connect avec des extraits de code
  • Utilisation de clients fournisseurs OpenID Connect tiers
  • Architecture de sécurité backend for frontend (BFF)
  • Fonctionnalités avancées, normes, extension du client OpenID Connect

Pour une expérience alternative utilisant la bibliothèque d'authentification Microsoft pour .NET, Microsoft IdentityWeb et Microsoft Entra ID, voir Démarrage rapide : Identifiez les utilisateurs et appelez l'API Microsoft Graph à partir d'une application Web ASP.NET Core (documentation Azure).

Pour un exemple utilisant le serveur Microsoft ID externe OIDC, voir Connexion des utilisateurs pour un exemple d'application Web ASP.NET Core dans un locataire externe et Une application Web ASP.NET Core authentifiant les utilisateurs contre Microsoft Entra ID externe à l'aide de Microsoft Identity Web.

Qu’est-ce qu’un client interactif confidentiel OpenID Connect

OpenID Connect peut être utilisé pour implémenter l’authentification dans les applications ASP.NET Core. La méthode recommandée consiste à utiliser un client confidentiel OpenID Connect à l’aide du flux de code. L’utilisation de la clé de preuve pour l’échange de code par les clients publics OAuth (PKCE) est recommandée pour cette implémentation. Le client d’application et l’utilisateur de l’application sont authentifiés dans le flux confidentiel. Le client d’application utilise une clé secrète client ou une assertion de client pour s’authentifier.

Les clients OpenID Connect/OAuth publics ne sont plus recommandés pour les applications web.

Le flux par défaut fonctionne comme indiqué dans le diagramme suivant :

Client confidentiel de flux de code OIDC à l’aide de PKCE

OpenID Connect est fourni dans de nombreuses variantes et toutes les implémentations de serveur ont des paramètres et des exigences légèrement différents. Certains serveurs ne prennent pas en charge le point de terminaison d’informations utilisateur, certains ne prennent toujours pas en charge PKCE et d’autres nécessitent des paramètres spéciaux dans la demande de jeton. Les assertions clientes peuvent être utilisées au lieu des secrets clients. De nouvelles normes existent également qui ajoutent une sécurité supplémentaire au-dessus de OpenID Connect Core, par exemple FAPI, CIBA ou DPoP pour les API en aval.

Remarque

À partir de .NET 9, OAuth 2.0 Pushed Authorization Requests (PAR) RFC 9126 est utilisé par défaut, si le serveur OpenID Connect prend en charge cela. Il s’agit d’un flux en trois étapes et non d’un flux à deux étapes, comme indiqué ci-dessus. (La demande d’informations utilisateur est une étape facultative.)

Créer un client de flux de code Open ID Connect à l’aide de Razor Pages

La section suivante montre comment implémenter un client OpenID Connect dans un projet de page Razor ASP.NET Core vide. La même logique peut être appliquée à n’importe quel projet web ASP.NET Core avec uniquement l’intégration de l’interface utilisateur différente.

Ajouter la prise en charge d’OpenID Connect

Ajoutez les packages Microsoft.AspNetCore.Authentication.OpenIdConnect Nuget au projet ASP.NET Core.

Configurer le client OpenID Connect

Ajoutez l'authentification à l'application Web en utilisant le builder.Services dans le fichier Program.cs. La configuration dépend du serveur OpenID Connect. Chaque serveur OpenID Connect nécessite de petites différences dans l’installation.

Le handler OpenID Connect est utilisé pour les défis et la déconnexion. Le cookie est utilisé pour gérer la session dans l’application web. Les schémas par défaut pour l’authentification peuvent être spécifiés en fonction des besoins.

Pour plus d’informations, consultez les instructions ASP.NET Core authentication-handler.

builder.Services.AddAuthentication(options =>
{
    options.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
    options.DefaultChallengeScheme = OpenIdConnectDefaults.AuthenticationScheme;
})
.AddCookie()
.AddOpenIdConnect(options =>
{
    var oidcConfig = builder.Configuration.GetSection("OpenIDConnectSettings");

    options.Authority = oidcConfig["Authority"];
    options.ClientId = oidcConfig["ClientId"];
    options.ClientSecret = oidcConfig["ClientSecret"];

    options.SignInScheme = CookieAuthenticationDefaults.AuthenticationScheme;
    options.ResponseType = OpenIdConnectResponseType.Code;

    options.SaveTokens = true;
    options.GetClaimsFromUserInfoEndpoint = true;

    options.MapInboundClaims = false;
    options.TokenValidationParameters.NameClaimType = JwtRegisteredClaimNames.Name;
    options.TokenValidationParameters.RoleClaimType = "roles";
});

Pour plus de détails sur les différentes options OpenID Connect, voir Sécuriser un ASP.NET Core Blazor Web App avec OpenID Connect (OIDC).

Pour connaître les différentes possibilités de mappage des réclamations, consultez Le mappage, la personnalisation et la transformation des réclamations en ASP.NET Core.

Remarque

Les espaces de noms suivants sont requis :

using Microsoft.AspNetCore.Authentication.Cookies;
using Microsoft.AspNetCore.Authentication.OpenIdConnect;
using Microsoft.IdentityModel.Protocols.OpenIdConnect;
using Microsoft.IdentityModel.Tokens;

Configurer les propriétés de configuration

Ajoutez les paramètres du client OpenID Connect aux propriétés de configuration de l’application. Les paramètres doivent correspondre à la configuration du client sur le serveur OpenID Connect. Aucun secret ne doit être conservé dans les paramètres de l'application où il pourrait être accidentellement enregistré. Les secrets doivent être stockés dans un emplacement sécurisé comme Azure Key Vault dans des environnements de production ou dans des secrets utilisateur dans un environnement de développement. Pour plus d’informations, consultez Stockage sécurisé des secrets d’application dans le développement en ASP.NET Core.

"OpenIDConnectSettings": {
  // OpenID Connect URL. (The base URL for the /.well-known/openid-configuration)
  "Authority": "<Authority>",
  // client ID from the OpenID Connect server
  "ClientId": "<Client ID>",
  //"ClientSecret": "--stored-in-user-secrets-or-key-vault--"
},

Configuration du chemin de rappel signé

La SignedOutCallbackPath (clé de configuration : « SignedOutCallbackPath ») est le chemin de requête dans le chemin de base de l'application intercepté par le gestionnaire OpenID Connect où l'agent utilisateur est renvoyé pour la première fois après s'être déconnecté du fournisseur d'identité. L'exemple d'application ne définit pas de valeur pour le chemin d'accès car la valeur par défaut de « /signout-callback-oidc » est utilisée. Après avoir intercepté la requête, le gestionnaire OpenID Connect redirige vers le SignedOutRedirectUri ou le RedirectUri, si spécifié.

Configurez le chemin de rappel signé dans l'enregistrement du fournisseur OIDC de l'application. Dans l'exemple suivant, l'espace réservé {PORT} correspond au port de l'application :

https://localhost:{PORT}/signout-callback-oidc

Remarque

Lorsque vous utilisez Microsoft Entra ID, définissez le chemin d'accès dans les entrées Redirect URI de la configuration de la plateforme Web dans le portail Entra ou Azure. Un port n'est pas nécessaire pour les adresses localhost lorsque vous utilisez Entra. La plupart des autres fournisseurs de l'OIDC exigent le port correct. Si vous n'ajoutez pas l'URI du chemin de rappel signé à l'enregistrement de l'application dans Entra, Entra refuse de rediriger l'utilisateur vers l'application et lui demande simplement de fermer la fenêtre de son navigateur.

Mettez à jour la méthode de pipeline ASP.NET Core dans la classe de programme.

La méthode UseRouting doit être mise en œuvre avant la méthode UseAuthorization.

app.UseHttpsRedirection();
app.UseStaticFiles();

app.UseRouting();
app.UseAuthentication();
// Authorization is applied for middleware after the UseAuthorization method
app.UseAuthorization();
app.MapRazorPages();

Forcer l’autorisation

Ajoutez [Authorize]l'attribut aux pagesRazor protégées :

[Authorize]

Une meilleure approche consiste à forcer l'autorisation pour l'ensemble de l'application et à refuser les pages non sécurisées :

var requireAuthPolicy = new AuthorizationPolicyBuilder()
    .RequireAuthenticatedUser()
    .Build();

builder.Services.AddAuthorizationBuilder()
    .SetFallbackPolicy(requireAuthPolicy);

Désactivez l’autorisation sur les points de terminaison publics en appliquant l’attribut[AllowAnonymous] aux points de terminaison publics. Pour obtenir des exemples, consultez les sections Ajouter une nouvelle Logout.cshtml et SignedOut.cshtmlRazor pages au projet et Implémenter Login page.

Ajouter de nouvelles pages Logout.cshtml et SignedOut.cshtmlRazor au projet

Une déconnexion est nécessaire pour déconnecter cookieà la fois la session et la session OpenID Connect. Toute l'application doit être redirigée vers le serveur OpenID Connect pour se déconnecter. Après une déconnexion réussie, l'application ouvre la route RedirectUri

Implémentez une page de déconnexion par défaut et modifiez le code de la page Razor Logout comme suit :

[Authorize]
public class LogoutModel : PageModel
{
    public IActionResult OnGetAsync()
    {
        return SignOut(new AuthenticationProperties
        {
            RedirectUri = "/SignedOut"
        },
        // Clear auth cookie
        CookieAuthenticationDefaults.AuthenticationScheme,
        // Redirect to OIDC provider signout endpoint
        OpenIdConnectDefaults.AuthenticationScheme);
    }
}

Le SignedOut.cshtml nécessite l'attribut [AllowAnonymous] :

[AllowAnonymous]
public class SignedOutModel : PageModel
{
    public void OnGet()
    {
    }
}

Mettre en œuvre la page Login

Une page LoginRazor peut également être mise en œuvre pour appeler directement le ChallengeAsync avec le AuthProperties requis. Cela n'est pas nécessaire si l'application Web requiert une authentification et que le défi par défaut est utilisé.

La page Login.cshtml requiert [AllowAnonymous]l'attribut :

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

namespace RazorPageOidc.Pages;

[AllowAnonymous]
public class LoginModel : PageModel
{
    [BindProperty(SupportsGet = true)]
    public string? ReturnUrl { get; set; }

    public async Task OnGetAsync()
    {
        var properties = GetAuthProperties(ReturnUrl);
        await HttpContext.ChallengeAsync(properties);
    }

    private static AuthenticationProperties GetAuthProperties(string? returnUrl)
    {
        const string pathBase = "/";

        // Prevent open redirects.
        if (string.IsNullOrEmpty(returnUrl))
        {
            returnUrl = pathBase;
        }
        else if (!Uri.IsWellFormedUriString(returnUrl, UriKind.Relative))
        {
            returnUrl = new Uri(returnUrl, UriKind.Absolute).PathAndQuery;
        }
        else if (returnUrl[0] != '/')
        {
            returnUrl = $"{pathBase}{returnUrl}";
        }

        return new AuthenticationProperties { RedirectUri = returnUrl };
    }
}

Ajoutez un bouton de connexion et de déconnexion pour l'utilisateur

@if (Context.User.Identity!.IsAuthenticated)
{
	<li class="nav-item">
		<a class="nav-link text-dark" asp-area="" asp-page="/Logout">Logout</a>
	</li>

	<span class="nav-link text-dark">Hi @Context.User.Identity.Name</span>
}
else
{
	<li class="nav-item">
		<a class="nav-link text-dark" asp-area="" asp-page="/Index">Login</a>
	</li>
}

Exemples avec des extraits de code

Exemple d’utilisation d’un point de terminaison d’informations utilisateur

Les options OpenID Connect peuvent être utilisées pour mapper les revendications, implémenter des gestionnaires ou même enregistrer les jetons dans la session pour une utilisation ultérieure.

L'option Scope peut être utilisée pour demander différentes requêtes ou un jeton d'actualisation qui est envoyé comme information au serveur OpenID Connect. La requête du offline_access revient à demander au serveur de renvoyer un jeton d'actualisation qui peut être utilisé pour rafraîchir la session sans authentifier à nouveau l'utilisateur de l'application.

services.AddAuthentication(options =>
{
    options.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
    options.DefaultChallengeScheme = OpenIdConnectDefaults.AuthenticationScheme;
})
.AddCookie()
.AddOpenIdConnect(OpenIdConnectDefaults.AuthenticationScheme, options =>
{
    var oidcConfig = builder.Configuration.GetSection("OpenIDConnectSettings");
    options.Authority = oidcConfig["IdentityProviderUrl"];
    options.ClientSecret = oidcConfig["ClientSecret"];
    options.ClientId = oidcConfig["Audience"];
    options.ResponseType = OpenIdConnectResponseType.Code;

    options.Scope.Clear();
    options.Scope.Add("openid");
    options.Scope.Add("profile");
    options.Scope.Add("email");
    options.Scope.Add("offline_access");

    options.ClaimActions.Remove("amr");
    options.ClaimActions.MapUniqueJsonKey("website", "website");

    options.GetClaimsFromUserInfoEndpoint = true;
    options.SaveTokens = true;

    // .NET 9 feature
    options.PushedAuthorizationBehavior = PushedAuthorizationBehavior.Require;

    options.TokenValidationParameters.NameClaimType = "name";
    options.TokenValidationParameters.RoleClaimType = "role";
});

Implémentation de fournisseurs d’identité Microsoft

Microsoft dispose de plusieurs fournisseurs d’identité et d’implémentations OpenID Connect. Microsoft dispose de différents serveurs OpenID Connect :

  • ID d'entrée Microsoft
  • Microsoft Entra External ID
  • Azure AD B2C

Si vous vous authentifiez à l’aide de l’un des fournisseurs d’identité Microsoft dans ASP.NET Core, il est recommandé d’utiliser les packages Nuget Microsoft.Identity.Web.

Le package Nuget Microsoft.Identity.Web est un client spécifique à Microsoft construit sur le client ASP.NET Core OpenID Connect avec quelques changements par rapport au client par défaut.

Utilisation de clients fournisseurs OpenID Connect tiers

De nombreuses implémentations de serveur OpenID Connect créent des packages Nuget optimisés pour la même implémentation OpenID Connect. Ces packages implémentent les spécificités du client OpenID Connect avec les extras requis par le serveur OpenID Connect spécifique. Microsoft.Identity.Web est un exemple de cela.

Si vous mettez en œuvre plusieurs clients OpenID Connect provenant de différents serveurs OpenID Connect dans une même application, il est normalement préférable de revenir à l'implémentation ASP.NET Core par défaut, car les différents clients écrasent certaines options qui affectent les autres clients.

Les fournisseurs Web OpenIddict sont une implémentation cliente qui prend en charge de nombreuses implémentations de serveur différentes.

IdentityModel est une bibliothèque d’assistance standard .NET pour l’identité basée sur les revendications, OAuth 2.0 et OpenID Connect. Cela peut également être utilisé pour faciliter l’implémentation du client.

Architecture de sécurité backend for frontend (BFF)

Il n'est plus recommandé d'implémenter les clients publics OpenID Connect pour toute application Web.

Pour plus d'informations, consultez le projet OAuth 2.0 for Browser-Based Applications.

Si vous implémentez applications web qui n’ont pas de back-end indépendant, nous vous recommandons d’utiliser l’architecture de sécurité du modèle Backend pour Frontend (BFF). Ce modèle peut être mis en œuvre de différentes manières, mais l'authentification est toujours implémentée dans le backend, et aucune donnée sensible n'est envoyée au client Web pour d'autres flux d'autorisation ou d'authentification.

Fonctionnalités avancées, normes, extension du client OIDC

Journalisation

Le débogage des clients OpenID Connect peut être difficile. Les données d’informations d’identification personnelle (PII) ne sont pas enregistrées par défaut. En cas de débogage en mode développement, le IdentityModelEventSource.ShowPII peut être utilisé pour journaliser des données personnelles sensibles. Ne déployez pas une application avec IdentityModelEventSource.ShowPII sur des serveurs productifs.

//using ...

using Microsoft.IdentityModel.Logging;

var builder = WebApplication.CreateBuilder(args);

//... code 

var app = builder.Build();

IdentityModelEventSource.ShowPII = true;

//... code 

app.Run();

Pour plus d’informations, consultez Journalisation.

Remarque

Vous pouvez souhaiter réduire le niveau de journal configuré pour afficher tous les journaux requis.

Personnalisation des paramètres OAuth et OIDC

L'option des gestionnaires d'authentification OAuth et OIDC (AdditionalAuthorizationParameters) permet de personnaliser les paramètres du message d'autorisation qui sont généralement inclus dans la chaîne de requête de redirection.

Mapper les revendications d’OpenID Connect

Pour plus d’informations, consultez Mappage, personnalisation et transformation des assertions dans ASP.NET Core.

Blazor OpenID Connect

Pour plus d'informations, consultez Sécuriser un ASP.NET Core Blazor Web App avec OpenID Connect (OIDC).

Standards