Configurare l'autenticazione Web (UI) openID Connect in ASP.NET Core
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:
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.cshtml
Razor 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 Logout
razor 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 Login
Razor per chiamare il ChallengeAsync
direttamente con il AuthProperties
necessario. 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).