Condividi tramite


Configurare l'autenticazione Web (UI) openID Connect in ASP.NET Core

Di Damien Bowden

Visualizzare o scaricare codice di esempio

Questo articolo illustra le aree seguenti:

  • Che cos'è un client interattivo riservato openID Connect
  • Creare un client OpenID Connect in ASP.NET Core
  • Esempi di client OpenID Connect con frammenti di codice
  • Uso di client del provider OpenID Connect di terze parti
  • Architettura di sicurezza back-end per front-end (BFF)
  • Funzionalità avanzate, standard, estensione di un client OpenID Connect

Per un'esperienza alternativa con Microsoft Authentication Library per .NET, Microsoft Identity Webe Microsoft Entra ID, vedere Avvio rapido: Consentire l'accesso agli utenti e utilizzare l'API Microsoft Graph da un'app Web ASP.NET Core (documentazione di Azure).

Per un esempio di utilizzo del server OIDC con ID esterno Microsoft Entra, vedere Accesso degli utenti per un'app web di esempio ASP.NET Core in un tenant esterno e un'app web ASP.NET Core che autentica gli utenti con l'ID esterno Microsoft Entra usando Microsoft Identity Web.

Che cos'è un client interattivo riservato openID Connect

OpenID Connect può essere usato per implementare l'autenticazione nelle applicazioni ASP.NET Core. Il modo consigliato consiste nell'usare un client riservato OpenID Connect usando il flusso di codice. Per questa implementazione è consigliabile usare la chiave di prova per lo scambio di codice da parte dei client pubblici OAuth (PKCE ). Sia il client dell'applicazione che l'utente dell'applicazione vengono autenticati nel flusso riservato. Il client dell'applicazione usa un segreto client o un'asserzione client per l'autenticazione.

I client OpenID Connect/OAuth pubblici non sono più consigliati per le applicazioni Web.

Il flusso predefinito funziona come illustrato nel diagramma seguente:

Client riservato del flusso di codice OIDC con PKCE

OpenID Connect include molte varianti e tutte le implementazioni del server hanno parametri e requisiti leggermente diversi. Alcuni server non supportano l'endpoint informazioni utente, alcuni ancora non supportano PKCE e altri richiedono parametri speciali nella richiesta di token. Le asserzioni client possono essere usate invece dei segreti client. Esistono anche nuovi standard che aggiungono sicurezza aggiuntiva su OpenID Connect Core, ad esempio FAPI, CIBA o DPoP per le API downstream.

Nota

Da .NET 9 viene usato OAuth 2.0 Pushed Authorization Requests (PAR) RFC 9126 per impostazione predefinita, se il server OpenID Connect supporta questa impostazione. Si tratta di un flusso in tre passaggi e non di un flusso in due passaggi, come illustrato in precedenza. La richiesta di informazioni utente è un passaggio facoltativo.

Creare un client del flusso di codice Open ID Connect usando Razor Pages

La sezione seguente illustra come implementare un client OpenID Connect in un progetto di pagina ASP.NET Core Razor vuoto. La stessa logica può essere applicata a qualsiasi progetto Web ASP.NET Core con solo l'integrazione dell'interfaccia utente diversa.

Aggiungere il supporto di OpenID Connect

Aggiungere i pacchetti Nuget Microsoft.AspNetCore.Authentication.OpenIdConnect al progetto ASP.NET Core.

Configurare il client OpenID Connect

Aggiungi l'autenticazione all'applicazione web utilizzando builder.Services nel file Program.cs. La configurazione dipende dal server OpenID Connect. Ogni server OpenID Connect richiede piccole differenze nell'installazione.

Il gestore OpenID Connect viene usato per le sfide e l'accesso. Viene cookie utilizzato per gestire la sessione nell'applicazione Web. Gli schemi predefiniti per l'autenticazione possono essere specificati in base alle esigenze.

Per altre informazioni, vedere le linee guida 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";
});

Per informazioni dettagliate sulle diverse opzioni di OpenID Connect, vedere Proteggere un ASP.NET Core Blazor Web App con OpenID Connect (OIDC).

Per le diverse possibilità di mapping delle attestazioni, vedere Mapping , personalizzazione e trasformazione delle attestazioni in ASP.NET Core.

Nota

Sono necessari gli spazi dei nomi seguenti:

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

Configurare le proprietà di configurazione

Aggiungere le impostazioni client OpenID Connect alle proprietà di configurazione dell'applicazione. Le impostazioni devono corrispondere alla configurazione client nel server OpenID Connect. Nessun segreto deve essere salvato in modo permanente nelle impostazioni dell'applicazione in cui potrebbero essere archiviate accidentalmente. I segreti devono essere archiviati in una posizione sicura, ad esempio Azure Key Vault in ambienti di produzione o in segreti utente in un ambiente di sviluppo. Per altre informazioni, vedere Archiviazione sicura dei segreti dell'app in fase di sviluppo in 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--"
},

Configurazione del percorso di callback disconnesso

Il SignedOutCallbackPath (chiave di configurazione: "SignedOutCallbackPath") è il percorso della richiesta all'interno del percorso di base dell'app, intercettato dal gestore OpenID Connect, dove l'agente utente viene restituito per la prima volta dopo essersi disconnesso dal provider identity. L'app di esempio non imposta un valore per il percorso perché viene usato il valore predefinito "/signout-callback-oidc". Dopo aver intercettato la richiesta, il gestore OpenID Connect reindirizza al SignedOutRedirectUri o RedirectUri, se specificato.

Configurare il percorso di callback di disconnessione nella registrazione del provider OIDC dell'app. Nell'esempio seguente il segnaposto {PORT} è la porta dell'app:

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

Nota

Quando si usa Microsoft Entra ID, impostare il percorso nella configurazione della piattaformaURI di reindirizzamento voci nel portale di Entra o Azure. Una porta non è necessaria per gli indirizzi localhost quando si usa Entra. La maggior parte degli altri provider OIDC richiede la porta corretta. Se non si aggiunge l'URI del percorso di callback per la disconnessione alla registrazione dell'app in Entra, Entra rifiuta di reindirizzare l'utente all'app e chiede loro semplicemente di chiudere la finestra del browser.

Aggiornare il metodo della pipeline ASP.NET Core nella classe program.

Il metodo UseRouting deve essere implementato prima del metodo UseAuthorization.

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

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

Forzare l'autorizzazione

Aggiungere l'attributo [Authorize] alle pagine Razor protette:

[Authorize]

Un approccio migliore consiste nel forzare l'autorizzazione per l'intera app e rifiutare esplicitamente le pagine non sicure:

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

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

Aggiungere nuove pagine Logout.cshtml e SignedOut.cshtmlRazor al progetto

È necessaria una disconnessione per disconnettere sia la sessione cookie che la sessione OpenID Connect. L'intera app deve reindirizzare al server OpenID Connect per disconnettersi. Dopo il successo della disconnessione, l'app apre la route RedirectUri.

Implementare una pagina di disconnessione predefinita e modificare il codice della pagina Logoutrazor come segue:

[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);
    }
}

Il SignedOut.cshtml richiede l'attributo [AllowAnonymous]:

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

Implementare la pagina Login

È anche possibile implementare una pagina LoginRazor per chiamare il ChallengeAsync direttamente con il AuthPropertiesnecessario. Questa operazione non è necessaria se l'app Web richiede l'autenticazione e viene usata la richiesta di verifica predefinita.

La pagina Login.cshtml richiede l'attributo [AllowAnonymous]:

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 };
    }
}

Aggiungere un pulsante di accesso e disconnessione per l'utente

@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>
}

Esempi con frammenti di codice

Esempio di utilizzo dell'endpoint informazioni utente

Le opzioni OpenID Connect possono essere usate per eseguire il mapping delle attestazioni, implementare gestori o anche salvare i token nella sessione per un utilizzo successivo.

L'opzione Scope può essere usata per richiedere attestazioni diverse o un token di aggiornamento che viene inviato come informazioni al server OpenID Connect. La richiesta del offline_access richiede al server di restituire un token di riferimento che può essere usato per aggiornare la sessione senza autenticare nuovamente l'utente dell'applicazione.

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";
});

Implementazione dei provider Microsoft identity

Microsoft dispone di più identity provider e implementazioni di OpenID Connect. Microsoft dispone di server OpenID Connect diversi:

  • Microsoft Entra ID
  • Microsoft Entra per ID esterno
  • Azure AD B2C

Se si esegue l'autenticazione con un provider Microsoft identity in ASP.NET Core, è raccomandato utilizzare i pacchetti NuGet Microsoft.Identity.Web.

I pacchetti Nuget Microsoft.Identity.Web sono un client specifico di Microsoft basato sul client OpenID Connect di ASP.NET core con alcune modifiche apportate al client predefinito.

Uso di client del provider OpenID Connect di terze parti

Molte implementazioni del server OpenID Connect creano pacchetti Nuget ottimizzati per la stessa implementazione di OpenID Connect. Questi pacchetti implementano le specifiche del client OpenID Connect con gli elementi aggiuntivi richiesti dal server OpenID Connect specifico. Microsoft.Identity.Web è un esempio di questo.

Se si implementano più client OpenID Connect da server OpenID Connect diversi in una singola applicazione, in genere è preferibile ripristinare l'implementazione predefinita ASP.NET Core perché i diversi client sovrascrivono alcune opzioni che influiscono sugli altri client.

OpenIddict Web providers è un'implementazione client che supporta molte implementazioni server diverse.

IdentityModel è una libreria di supporto standard .NET per le funzioni basate su attestazioni identity, OAuth 2.0 e OpenID Connect. Questa operazione può essere usata anche per facilitare l'implementazione del client.

Architettura di sicurezza back-end per front-end (BFF)

Non è più consigliabile implementare client pubblici OpenID Connect per le app Web.

Per ulteriori informazioni, vedere la bozza di OAuth 2.0 per le applicazioni Browser-Based.

Se si implementa applicazioni web senza back-end indipendente, è consigliabile usare il modello back-end di per front-end (BFF) architettura di sicurezza. Questo modello può essere implementato in modi diversi, ma l'autenticazione viene sempre implementata nel back-end e non vengono inviati dati sensibili al client Web per ulteriori autorizzazioni o flussi di autenticazione.

Funzionalità avanzate, standard, estensione del client OIDC

Registrazione

Il debug dei client OpenID Connect può essere difficile. I dati personali non vengono registrati per impostazione predefinita. Se si esegue il debug in modalità di sviluppo, il IdentityModelEventSource.ShowPII può essere usato per registrare dati personali sensibili. Non distribuire un'app con IdentityModelEventSource.ShowPII nei server produttivi.

//using ...

using Microsoft.IdentityModel.Logging;

var builder = WebApplication.CreateBuilder(args);

//... code 

var app = builder.Build();

IdentityModelEventSource.ShowPII = true;

//... code 

app.Run();

Per altre informazioni, vedere Logging.

Nota

È possibile abbassare il livello di log configurato per visualizzare tutti i log necessari.

Personalizzazione dei parametri OIDC e OAuth

L'opzione dei gestori di autenticazione OAuth e OIDC (AdditionalAuthorizationParameters) consente la personalizzazione dei parametri del messaggio di autorizzazione solitamente inclusi come parte della stringa di query di reindirizzamento.

Eseguire il mapping delle attestazioni da OpenID Connect

Per altre informazioni, vedere Mapping , personalizzazione e trasformazione delle attestazioni in ASP.NET Core.

Blazor OpenID Connect

Per altre informazioni, vedere Proteggere un Blazor Web App Core ASP.NET con OpenID Connect (OIDC).

Standard