Condividi tramite


Proteggere un ASP.NET Core Blazor Web App con OpenID Connect (OIDC)

Nota

Questa non è la versione più recente di questo articolo. Per la versione corrente, vedere la versione .NET 9 di questo articolo.

Importante

Queste informazioni si riferiscono a un prodotto non definitive che può essere modificato in modo sostanziale prima che venga rilasciato commercialmente. Microsoft non riconosce alcuna garanzia, espressa o implicita, in merito alle informazioni qui fornite.

Per la versione corrente, vedere la versione .NET 9 di questo articolo.

Questo articolo descrive come proteggere un oggetto con OpenID Connect (OIDC) usando un'app di esempio nel dotnet/blazor-samples repository GitHub (.NET 8 o versione successiva) (come scaricare).Blazor Web App

Questa versione dell'articolo illustra l'implementazione di OIDC senza adottare il modello Back-end per front-end (BFF). Il modello BFF è utile per effettuare richieste autenticate a servizi esterni. Modificare il selettore di versione dell'articolo in OIDC con modello BFF se la specifica dell'app richiede l'adozione del modello BFF.

La specifica seguente è descritta:

  • Blazor Web App usa la modalità di rendering automatico con interattività globale.
  • I servizi provider di stato di autenticazione personalizzati vengono usati dal server e dalle app client per acquisire lo stato di autenticazione dell'utente e fluirlo tra il server e il client.
  • Questa app è un punto di partenza per qualsiasi flusso di autenticazione OIDC. OIDC viene configurato manualmente nell'app e non si basa su Microsoft Entra ID o pacchetti Web MicrosoftIdentity, né l'app di esempio richiede l'hosting di Microsoft Azure. Tuttavia, l'app di esempio può essere usata con Entra, Microsoft Identity Web e ospitata in Azure.
  • Aggiornamento automatico del token non interattivo.
  • Chiama in modo sicuro un'API (Web) nel progetto server per i dati.

Esempio di app

L'app di esempio è costituita da due progetti:

  • BlazorWebAppOidc: progetto lato server di Blazor Web App, contenente un esempio endpoint API minimo per i dati meteo.
  • BlazorWebAppOidc.Client: progetto lato client dell'oggetto Blazor Web App.

Accedere alle app di esempio tramite la cartella della versione più recente dalla radice del repository con il collegamento seguente. I progetti si trovano nella BlazorWebAppOidc cartella per .NET 8 o versione successiva.

Visualizzare o scaricare il codice di esempio (procedura per il download)

Progetto lato Blazor Web App server (BlazorWebAppOidc)

Il BlazorWebAppOidc progetto è il progetto lato server dell'oggetto Blazor Web App.

Il BlazorWebAppOidc.http file può essere usato per testare la richiesta di dati meteo. Si noti che il BlazorWebAppOidc progetto deve essere in esecuzione per testare l'endpoint e l'endpoint è hardcoded nel file. Per altre informazioni, vedere Usare file .http in Visual Studio 2022.

Nota

Il progetto server usa IHttpContextAccessor/HttpContext, ma non per i componenti di cui è stato eseguito il rendering interattivo. Per altre informazioni, vedere Linee guida per la mitigazione delle minacce per ASP.NET rendering lato server interattivo CoreBlazor.

Impostazione

Questa sezione illustra come configurare l'app di esempio.

Nota

Per Microsoft Entra ID o Azure AD B2C, è possibile usare microsoft AddMicrosoftIdentityWebApp Identity Web (Microsoft.Identity.Web pacchetto NuGet, documentazione dell'API), che aggiunge sia i gestori OIDC Cookie che i gestori di autenticazione con le impostazioni predefinite appropriate. L'app di esempio e le indicazioni contenute in questa sezione non usano Microsoft Identity Web. Le linee guida illustrano come configurare manualmente il gestore OIDC per qualsiasi provider OIDC. Per altre informazioni sull'implementazione di Microsoft Identity Web, vedere le risorse collegate.

Stabilire il segreto client

Avviso

Non archiviare segreti dell'app, stringa di connessione, credenziali, password, numeri di identificazione personale (PIN), codice C#/.NET privato o chiavi/token privati nel codice lato client, che è sempre non sicuro. Negli ambienti di test/gestione temporanea e produzione, il codice lato Blazor server e le API Web devono usare flussi di autenticazione sicuri che evitano di mantenere le credenziali all'interno del codice del progetto o dei file di configurazione. Al di fuori dei test di sviluppo locali, è consigliabile evitare l'uso di variabili di ambiente per archiviare i dati sensibili, perché le variabili di ambiente non sono l'approccio più sicuro. Per i test di sviluppo locali, lo strumento Secret Manager è consigliato per proteggere i dati sensibili. Per altre informazioni, vedere Gestire in modo sicuro dati e credenziali sensibili.

Per i test di sviluppo locali, usare lo strumento Secret Manager per archiviare il segreto client dell'app server nella chiave Authentication:Schemes:MicrosoftOidc:ClientSecretdi configurazione .

Nota

Se l'app usa l'ID Microsoft Entra o Azure AD B2C, creare un segreto client nella registrazione dell'app in Entra o portale di Azure (Gestisci>certificati e segreti>Nuovo segreto client). Usare il valore del nuovo segreto nelle indicazioni seguenti.

L'app di esempio non è stata inizializzata per lo strumento Secret Manager. Usare una shell dei comandi, ad esempio la shell dei comandi di Developer PowerShell in Visual Studio, per eseguire il comando seguente. Prima di eseguire il comando, modificare la directory con il cd comando nella directory del progetto server. Il comando stabilisce un identificatore di segreti utente (<UserSecretsId> nel file di progetto dell'app server):

dotnet user-secrets init

Eseguire il comando seguente per impostare il segreto client. Il {SECRET} segnaposto è il segreto client ottenuto dalla registrazione dell'app:

dotnet user-secrets set "Authentication:Schemes:MicrosoftOidc:ClientSecret" "{SECRET}"

Se si usa Visual Studio, è possibile verificare che il segreto sia impostato facendo clic con il pulsante destro del mouse sul progetto server in Esplora soluzioni e scegliendo Gestisci segreti utente.

Configurare l'app

La configurazione seguente OpenIdConnectOptions è disponibile nel file del Program progetto nella chiamata a AddOpenIdConnect:

  • SignInScheme: imposta lo schema di autenticazione corrispondente al middleware responsabile della persistenza dell'utente identity dopo un'autenticazione riuscita. Il gestore OIDC deve usare uno schema di accesso in grado di rendere persistenti le credenziali utente tra le richieste. La seguente riga è presente solo a scopo dimostrativo. Se omesso, DefaultSignInScheme viene usato come valore di fallback.

    oidcOptions.SignInScheme = CookieAuthenticationDefaults.AuthenticationScheme;
    
  • Ambiti per openid e () (Scopefacoltativo): anche gli openid ambiti e profile profile sono configurati per impostazione predefinita perché sono necessari per il funzionamento del gestore OIDC, ma potrebbe essere necessario aggiungerli nuovamente se gli ambiti sono inclusi nella Authentication:Schemes:MicrosoftOidc:Scope configurazione. Per indicazioni generali sulla configurazione, vedere Configurazione in ASP.NET Core e configurazione di ASP.NET CoreBlazor.

    oidcOptions.Scope.Add(OpenIdConnectScope.OpenIdProfile);
    
  • SaveTokens: definisce se i token di accesso e aggiornamento devono essere archiviati in AuthenticationProperties dopo un'autorizzazione riuscita. Questa proprietà è impostata su false per ridurre le dimensioni dell'autenticazione cookiefinale.

    oidcOptions.SaveTokens = false;
    
  • Ambito per l'accesso offline (Scope): l'ambito offline_access è obbligatorio per il token di aggiornamento.

    oidcOptions.Scope.Add(OpenIdConnectScope.OfflineAccess);
    
  • Authority e ClientId: imposta l'autorità e l'ID client per le chiamate OIDC.

    oidcOptions.Authority = "{AUTHORITY}";
    oidcOptions.ClientId = "{CLIENT ID}";
    

    Esempio:

    • Autorità (): https://login.microsoftonline.com/aaaabbbb-0000-cccc-1111-dddd2222eeee/v2.0/ ({AUTHORITY}usa l'ID aaaabbbb-0000-cccc-1111-dddd2222eeeetenant )
    • ID client ({CLIENT ID}): 00001111-aaaa-2222-bbbb-3333cccc4444
    oidcOptions.Authority = "https://login.microsoftonline.com/aaaabbbb-0000-cccc-1111-dddd2222eeee/v2.0/";
    oidcOptions.ClientId = "00001111-aaaa-2222-bbbb-3333cccc4444";
    

    Esempio per l'autorità "common" di Microsoft Azure:

    L'autorità "comune" deve essere usata per le app multi-tenant. È anche possibile usare l'autorità "comune" per le app a tenant singolo, ma è necessario un personalizzato IssuerValidator , come illustrato più avanti in questa sezione.

    oidcOptions.Authority = "https://login.microsoftonline.com/common/v2.0/";
    
  • ResponseType: configura il gestore OIDC per eseguire solo il flusso del codice di autorizzazione. Le concessioni implicite e i flussi ibridi non sono necessari in questa modalità.

    Nella configurazione di registrazione dell'app Entra o portale di Azure implicita e dei flussi ibridi, non selezionare la casella di controllo relativa all'endpoint di autorizzazione per restituire token di accesso o token ID. Il gestore OIDC richiede automaticamente i token appropriati usando il codice restituito dall'endpoint di autorizzazione.

    oidcOptions.ResponseType = OpenIdConnectResponseType.Code;
    
  • MapInboundClaimse la configurazione di NameClaimType e : molti server OIDC usano "name" e "role" anziché le impostazioni predefinite SOAP/WS-Fed in ClaimTypesRoleClaimType. Quando MapInboundClaims è impostato su false, il gestore non esegue i mapping delle attestazioni e i nomi delle attestazioni del token JWT vengono usati direttamente dall'app. Nell'esempio seguente il tipo di attestazione del ruolo viene impostato su "roles", appropriato per Microsoft Entra ID (ME-ID). Per altre informazioni, vedere la identity documentazione del provider.

    Nota

    MapInboundClaims deve essere impostato su false per la maggior parte dei provider OIDC, che impedisce la ridenominazione delle attestazioni.

    oidcOptions.MapInboundClaims = false;
    oidcOptions.TokenValidationParameters.NameClaimType = "name";
    oidcOptions.TokenValidationParameters.RoleClaimType = "roles";
    
  • Configurazione del percorso: i percorsi devono corrispondere all'URI di reindirizzamento (percorso di callback di accesso) e ai percorsi di reindirizzamento post disconnessione (percorso di callback con disconnessione) configurati durante la registrazione dell'applicazione con il provider OIDC. Nel portale di Azure i percorsi vengono configurati nel pannello Autenticazione della registrazione dell'app. Entrambi i percorsi di accesso e disconnessione devono essere registrati come URI di reindirizzamento. I valori predefiniti sono /signin-oidc e /signout-callback-oidc.

    • CallbackPath: percorso della richiesta all'interno del percorso di base dell'app in cui viene restituito l'agente utente.

      In Entra o portale di Azure impostare il percorso nell'URI di reindirizzamento della configurazione della piattaforma Web:

      https://localhost/signin-oidc

      Nota

      Una porta non è necessaria per localhost gli indirizzi quando si usa Microsoft Entra ID. La maggior parte degli altri provider OIDC richiede una porta corretta.

    • SignedOutCallbackPath: percorso della richiesta all'interno del percorso di base dell'app in cui viene restituito l'agente utente dopo la identity disconnessione dal provider.

      In Entra o portale di Azure impostare il percorso nell'URI di reindirizzamento della configurazione della piattaforma Web:

      https://localhost/signout-callback-oidc

      Nota

      Una porta non è necessaria per localhost gli indirizzi quando si usa Microsoft Entra ID. La maggior parte degli altri provider OIDC richiede una porta corretta.

      Nota

      Se si usa Microsoft Identity Web, il provider attualmente reindirizza di nuovo a SignedOutCallbackPath se viene usata l'autorità microsoftonline.com (https://login.microsoftonline.com/{TENANT ID}/v2.0/). Questa limitazione non esiste se è possibile usare l'autorità "comune" con Microsoft Identity Web. Per altre informazioni, vedere postLogoutRedirectUri not working when authority URL contains a tenant ID (AzureAD/microsoft-authentication-library-for-js #5783).

    • RemoteSignOutPath: le richieste ricevute in questo percorso causano il richiamo della disconnessione da parte del gestore tramite lo schema di disconnessione.

      In Entra o portale di Azure impostare l'URL di disconnessione del canale anteriore:

      https://localhost/signout-oidc

      Nota

      Una porta non è necessaria per localhost gli indirizzi quando si usa Microsoft Entra ID. La maggior parte degli altri provider OIDC richiede una porta corretta.

      oidcOptions.CallbackPath = new PathString("{PATH}");
      oidcOptions.SignedOutCallbackPath = new PathString("{PATH}");
      oidcOptions.RemoteSignOutPath = new PathString("{PATH}");
      

      Esempi (valori predefiniti):

      oidcOptions.CallbackPath = new PathString("/signin-oidc");
      oidcOptions.SignedOutCallbackPath = new PathString("/signout-callback-oidc");
      oidcOptions.RemoteSignOutPath = new PathString("/signout-oidc");
      
  • (Microsoft Azure solo con l'endpoint "comune") TokenValidationParameters.IssuerValidator: molti provider OIDC funzionano con il validator predefinito dell'autorità di certificazione, ma è necessario tenere conto dell'autorità di certificazione con parametri con l'ID tenant ({TENANT ID}) restituito da https://login.microsoftonline.com/common/v2.0/.well-known/openid-configuration. Per altre informazioni, vedere SecurityTokenInvalidIssuerException con OpenID Connect e l'endpoint "common" di Azure AD (AzureAD/azure-activedirectory-identitymodel-extensions-for-dotnet #1731).

    Solo per le app che usano Microsoft Entra ID o Azure AD B2C con l'endpoint "comune":

    var microsoftIssuerValidator = AadIssuerValidator.GetAadIssuerValidator(oidcOptions.Authority);
    oidcOptions.TokenValidationParameters.IssuerValidator = microsoftIssuerValidator.Validate;
    

Codice dell'app di esempio

Esaminare l'app di esempio per le funzionalità seguenti:

  • Aggiornamento automatico del token non interattivo con l'aiuto di un aggiornamento personalizzato cookie (CookieOidcRefresher.cs).
  • Il progetto server chiama AddAuthenticationStateSerialization per aggiungere un provider di stato di autenticazione lato server che usa PersistentComponentState per trasferire lo stato di autenticazione al client. Il client chiama AddAuthenticationStateDeserialization per deserializzare e usare lo stato di autenticazione passato dal server. Lo stato di autenticazione è fisso per la durata dell'applicazione WebAssembly.
  • Un esempio di richieste a per i Blazor Web App dati meteo viene gestito da un endpoint API minimo (/weather-forecast) nel Program file (Program.cs). L'endpoint richiede l'autorizzazione chiamando RequireAuthorization. Per tutti i controller aggiunti al progetto, aggiungere l'attributo [Authorize] al controller o all'azione.
  • L'app chiama in modo sicuro un'API (Web) nel progetto server per i dati meteo:
    • Quando si esegue il rendering del Weather componente nel server, il componente usa sul ServerWeatherForecaster server per ottenere i dati meteo direttamente (non tramite una chiamata API Web).
    • Quando viene eseguito il rendering del componente nel client, il componente usa l'implementazione del ClientWeatherForecaster servizio, che usa un preconfigurato HttpClient (nel file del Program progetto client) per effettuare una chiamata API Web al progetto server. Un endpoint API minimo (/weather-forecast) definito nel file del progetto server Program ottiene i dati meteo da ServerWeatherForecaster e restituisce i dati al client.
  • Aggiornamento automatico del token non interattivo con l'aiuto di un aggiornamento personalizzato cookie (CookieOidcRefresher.cs).
  • La PersistingAuthenticationStateProvider classe (PersistingAuthenticationStateProvider.cs) è un lato AuthenticationStateProvider server che usa PersistentComponentState per trasferire lo stato di autenticazione al client, che viene quindi risolto per la durata dell'applicazione WebAssembly.
  • Un esempio di richieste a per i Blazor Web App dati meteo viene gestito da un endpoint API minimo (/weather-forecast) nel Program file (Program.cs). L'endpoint richiede l'autorizzazione chiamando RequireAuthorization. Per tutti i controller aggiunti al progetto, aggiungere l'attributo [Authorize] al controller o all'azione.
  • L'app chiama in modo sicuro un'API (Web) nel progetto server per i dati meteo:
    • Quando si esegue il rendering del Weather componente nel server, il componente usa sul ServerWeatherForecaster server per ottenere i dati meteo direttamente (non tramite una chiamata API Web).
    • Quando viene eseguito il rendering del componente nel client, il componente usa l'implementazione del ClientWeatherForecaster servizio, che usa un preconfigurato HttpClient (nel file del Program progetto client) per effettuare una chiamata API Web al progetto server. Un endpoint API minimo (/weather-forecast) definito nel file del progetto server Program ottiene i dati meteo da ServerWeatherForecaster e restituisce i dati al client.

Per altre informazioni sulle chiamate API (Web) tramite astrazioni di un servizio in Blazor Web Apps, vedere Chiamare un'API Web da un'app ASP.NET CoreBlazor.

Progetto lato client Blazor Web App (BlazorWebAppOidc.Client)

Il BlazorWebAppOidc.Client progetto è il progetto lato client di Blazor Web App.

Il client chiama AddAuthenticationStateDeserialization per deserializzare e usare lo stato di autenticazione passato dal server. Lo stato di autenticazione è fisso per la durata dell'applicazione WebAssembly.

La PersistentAuthenticationStateProvider classe (PersistentAuthenticationStateProvider.cs) è un lato AuthenticationStateProvider client che determina lo stato di autenticazione dell'utente cercando i dati persistenti nella pagina quando è stato eseguito il rendering nel server. Lo stato di autenticazione è fisso per la durata dell'applicazione WebAssembly.

Se l'utente deve accedere o disconnettersi, è necessario ricaricare una pagina completa.

L'app di esempio fornisce solo un nome utente e un messaggio di posta elettronica a scopo di visualizzazione. Non include token che eseguono l'autenticazione al server durante l'esecuzione di richieste successive, che funziona separatamente usando un cookie oggetto incluso nelle HttpClient richieste al server.

Questa versione dell'articolo illustra l'implementazione di OIDC con il modello Back-end per il front-end (BFF). Modificare il selettore della versione dell'articolo in OIDC senza modello BFF se la specifica dell'app non richiede l'adozione del modello BFF.

La specifica seguente è descritta:

  • Blazor Web App usa la modalità di rendering automatico con interattività globale.
  • I servizi provider di stato di autenticazione personalizzati vengono usati dal server e dalle app client per acquisire lo stato di autenticazione dell'utente e fluirlo tra il server e il client.
  • Questa app è un punto di partenza per qualsiasi flusso di autenticazione OIDC. OIDC viene configurato manualmente nell'app e non si basa su Microsoft Entra ID o pacchetti Web MicrosoftIdentity, né l'app di esempio richiede l'hosting di Microsoft Azure. Tuttavia, l'app di esempio può essere usata con Entra, Microsoft Identity Web e ospitata in Azure.
  • Aggiornamento automatico del token non interattivo.
  • Il modello Back-end per front-end (BFF) viene adottato usando .NET Aspire per l'individuazione del servizio e YARP per il proxy delle richieste a un endpoint di previsione meteo nell'app back-end.
    • Un'API Web back-end cookieusa l'autenticazione con connessione JWT per convalidare i token JWT salvati da nell'accesso Blazor Web App .
    • L'aspirare migliora l'esperienza di creazione di app native del cloud .NET. Fornisce un set di strumenti e modelli coerente e con opinioni per la creazione e l'esecuzione di app distribuite.
    • YARP (Yet Another Reverse Proxy) è una libreria usata per creare un server proxy inverso.

Per altre informazioni su .NET Aspire, vedere Disponibilità generale di : Semplificazione dello .NET Aspiresviluppo nativo del cloud .NET (maggio 2024).

Prerequisito

.NET Aspire richiede Visual Studio versione 17.10 o successiva.

Esempio di app

L'app di esempio è costituita da cinque progetti:

  • .NET Aspire:
    • Aspire.AppHost: usato per gestire i problemi di orchestrazione di alto livello dell'app.
    • Aspire.ServiceDefaults: contiene configurazioni di app predefinite .NET Aspire che possono essere estese e personalizzate in base alle esigenze.
  • MinimalApiJwt: API Web back-end contenente un esempio di endpoint API minimo per i dati meteo.
  • BlazorWebAppOidc: progetto lato server dell'oggetto Blazor Web App.
  • BlazorWebAppOidc.Client: progetto lato client dell'oggetto Blazor Web App.

Accedere alle app di esempio tramite la cartella della versione più recente dalla radice del repository con il collegamento seguente. I progetti si trovano nella BlazorWebAppOidcBff cartella per .NET 8 o versione successiva.

Visualizzare o scaricare il codice di esempio (procedura per il download)

.NET Aspire progetti

Per altre informazioni sull'uso .NET Aspire e sui .AppHost progetti e .ServiceDefaults dell'app di esempio, vedere la .NET Aspire documentazione.

Verificare di aver soddisfatto i prerequisiti per .NET Aspire. Per altre informazioni, vedere la sezione Prerequisiti di Avvio rapido: Creare la prima .NET Aspire app.

L'app di esempio configura solo un profilo di avvio HTTP non sicuro (http) da usare durante i test di sviluppo. Per altre informazioni, incluso un esempio di profili di impostazioni di avvio non sicure e sicure, vedere Consentire il trasporto non sicuro in .NET Aspire (.NET Aspire documentazione).

Progetto lato Blazor Web App server (BlazorWebAppOidc)

Il BlazorWebAppOidc progetto è il progetto lato server dell'oggetto Blazor Web App. Il progetto usa YARP per eseguire il proxy delle richieste a un endpoint delle previsioni meteo nel progetto API Web back-end (MinimalApiJwt) con l'oggetto access_token archiviato nell'autenticazione cookie.

Il BlazorWebAppOidc.http file può essere usato per testare la richiesta di dati meteo. Si noti che il BlazorWebAppOidc progetto deve essere in esecuzione per testare l'endpoint e l'endpoint è hardcoded nel file. Per altre informazioni, vedere Usare file .http in Visual Studio 2022.

Nota

Il progetto server usa IHttpContextAccessor/HttpContext, ma non per i componenti di cui è stato eseguito il rendering interattivo. Per altre informazioni, vedere Linee guida per la mitigazione delle minacce per ASP.NET rendering lato server interattivo CoreBlazor.

Impostazione

Questa sezione illustra come configurare l'app di esempio.

Nota

Per Microsoft Entra ID o Azure AD B2C, è possibile usare microsoft AddMicrosoftIdentityWebApp Identity Web (Microsoft.Identity.Web pacchetto NuGet, documentazione dell'API), che aggiunge sia i gestori OIDC Cookie che i gestori di autenticazione con le impostazioni predefinite appropriate. L'app di esempio e le indicazioni contenute in questa sezione non usano Microsoft Identity Web. Le linee guida illustrano come configurare manualmente il gestore OIDC per qualsiasi provider OIDC. Per altre informazioni sull'implementazione di Microsoft Identity Web, vedere le risorse collegate.

Stabilire il segreto client

Avviso

Non archiviare segreti dell'app, stringa di connessione, credenziali, password, numeri di identificazione personale (PIN), codice C#/.NET privato o chiavi/token privati nel codice lato client, che è sempre non sicuro. Negli ambienti di test/gestione temporanea e produzione, il codice lato Blazor server e le API Web devono usare flussi di autenticazione sicuri che evitano di mantenere le credenziali all'interno del codice del progetto o dei file di configurazione. Al di fuori dei test di sviluppo locali, è consigliabile evitare l'uso di variabili di ambiente per archiviare i dati sensibili, perché le variabili di ambiente non sono l'approccio più sicuro. Per i test di sviluppo locali, lo strumento Secret Manager è consigliato per proteggere i dati sensibili. Per altre informazioni, vedere Gestire in modo sicuro dati e credenziali sensibili.

Per i test di sviluppo locali, usare lo strumento Secret Manager per archiviare il segreto client dell'app server nella chiave Authentication:Schemes:MicrosoftOidc:ClientSecretdi configurazione .

Nota

Se l'app usa l'ID Microsoft Entra o Azure AD B2C, creare un segreto client nella registrazione dell'app in Entra o portale di Azure (Gestisci>certificati e segreti>Nuovo segreto client). Usare il valore del nuovo segreto nelle indicazioni seguenti.

L'app di esempio non è stata inizializzata per lo strumento Secret Manager. Usare una shell dei comandi, ad esempio la shell dei comandi di Developer PowerShell in Visual Studio, per eseguire il comando seguente. Prima di eseguire il comando, modificare la directory con il cd comando nella directory del progetto server. Il comando stabilisce un identificatore di segreti utente (<UserSecretsId> nel file di progetto dell'app server):

dotnet user-secrets init

Eseguire il comando seguente per impostare il segreto client. Il {SECRET} segnaposto è il segreto client ottenuto dalla registrazione dell'app:

dotnet user-secrets set "Authentication:Schemes:MicrosoftOidc:ClientSecret" "{SECRET}"

Se si usa Visual Studio, è possibile verificare che il segreto sia impostato facendo clic con il pulsante destro del mouse sul progetto server in Esplora soluzioni e scegliendo Gestisci segreti utente.

Configurare l'app

La configurazione seguente OpenIdConnectOptions è disponibile nel file del Program progetto nella chiamata a AddOpenIdConnect:

  • SignInScheme: imposta lo schema di autenticazione corrispondente al middleware responsabile della persistenza dell'utente identity dopo un'autenticazione riuscita. Il gestore OIDC deve usare uno schema di accesso in grado di rendere persistenti le credenziali utente tra le richieste. La seguente riga è presente solo a scopo dimostrativo. Se omesso, DefaultSignInScheme viene usato come valore di fallback.

    oidcOptions.SignInScheme = CookieAuthenticationDefaults.AuthenticationScheme;
    
  • Ambiti per openid e () (Scopefacoltativo): anche gli openid ambiti e profile profile sono configurati per impostazione predefinita perché sono necessari per il funzionamento del gestore OIDC, ma potrebbe essere necessario aggiungerli nuovamente se gli ambiti sono inclusi nella Authentication:Schemes:MicrosoftOidc:Scope configurazione. Per indicazioni generali sulla configurazione, vedere Configurazione in ASP.NET Core e configurazione di ASP.NET CoreBlazor.

    oidcOptions.Scope.Add(OpenIdConnectScope.OpenIdProfile);
    
  • SaveTokens: definisce se i token di accesso e aggiornamento devono essere archiviati in AuthenticationProperties dopo un'autorizzazione riuscita. Il valore è impostato su true per autenticare le richieste di dati meteo dal progetto API Web back-end (MinimalApiJwt).

    oidcOptions.SaveTokens = true;
    
  • Ambito per l'accesso offline (Scope): l'ambito offline_access è obbligatorio per il token di aggiornamento.

    oidcOptions.Scope.Add(OpenIdConnectScope.OfflineAccess);
    
  • Ambiti per ottenere i dati meteo dall'API Web (Scope): l'ambito Weather.Get è configurato nel portale di Azure o Entra in Esporre un'API. Questa operazione è necessaria per il progetto API Web back-end (MinimalApiJwt) per convalidare il token di accesso con bearer JWT.

    oidcOptions.Scope.Add("{APP ID URI}/{API NAME}");
    

    Esempio:

    • URI ID app ({APP ID URI}): https://{DIRECTORY NAME}.onmicrosoft.com/{CLIENT ID}
      • Nome directory ({DIRECTORY NAME}): contoso
      • ID applicazione (client) ({CLIENT ID}): 00001111-aaaa-2222-bbbb-3333cccc4444
    • Ambito configurato per i dati meteo da MinimalApiJwt ({API NAME}): Weather.Get
    oidcOptions.Scope.Add("https://contoso.onmicrosoft.com/00001111-aaaa-2222-bbbb-3333cccc4444/Weather.Get");
    

    L'esempio precedente riguarda un'app registrata in un tenant con un tipo di tenant AAD B2C. Se l'app viene registrata in un tenant ME-ID, l'URI ID app è diverso, quindi l'ambito è diverso.

    Esempio:

    • URI ID app ({APP ID URI}): api://{CLIENT ID} con ID applicazione (client) ({CLIENT ID}): 00001111-aaaa-2222-bbbb-3333cccc4444
    • Ambito configurato per i dati meteo da MinimalApiJwt ({API NAME}): Weather.Get
    oidcOptions.Scope.Add("api://00001111-aaaa-2222-bbbb-3333cccc4444/Weather.Get");
    
  • Authority e ClientId: imposta l'autorità e l'ID client per le chiamate OIDC.

    oidcOptions.Authority = "{AUTHORITY}";
    oidcOptions.ClientId = "{CLIENT ID}";
    

    Esempio:

    • Autorità (): https://login.microsoftonline.com/aaaabbbb-0000-cccc-1111-dddd2222eeee/v2.0/ ({AUTHORITY}usa l'ID aaaabbbb-0000-cccc-1111-dddd2222eeeetenant )
    • ID client ({CLIENT ID}): 00001111-aaaa-2222-bbbb-3333cccc4444
    oidcOptions.Authority = "https://login.microsoftonline.com/aaaabbbb-0000-cccc-1111-dddd2222eeee/v2.0/";
    oidcOptions.ClientId = "00001111-aaaa-2222-bbbb-3333cccc4444";
    

    Esempio per l'autorità "common" di Microsoft Azure:

    L'autorità "comune" deve essere usata per le app multi-tenant. È anche possibile usare l'autorità "comune" per le app a tenant singolo, ma è necessario un personalizzato IssuerValidator , come illustrato più avanti in questa sezione.

    oidcOptions.Authority = "https://login.microsoftonline.com/common/v2.0/";
    
  • ResponseType: configura il gestore OIDC per eseguire solo il flusso del codice di autorizzazione. Le concessioni implicite e i flussi ibridi non sono necessari in questa modalità.

    Nella configurazione di registrazione dell'app Entra o portale di Azure implicita e dei flussi ibridi, non selezionare la casella di controllo relativa all'endpoint di autorizzazione per restituire token di accesso o token ID. Il gestore OIDC richiede automaticamente i token appropriati usando il codice restituito dall'endpoint di autorizzazione.

    oidcOptions.ResponseType = OpenIdConnectResponseType.Code;
    
  • MapInboundClaimse la configurazione di NameClaimType e : molti server OIDC usano "name" e "role" anziché le impostazioni predefinite SOAP/WS-Fed in ClaimTypesRoleClaimType. Quando MapInboundClaims è impostato su false, il gestore non esegue mapping delle attestazioni e i nomi delle attestazioni del token JWT vengono usati direttamente dall'app. Nell'esempio seguente il tipo di attestazione del ruolo viene impostato su "roles", appropriato per Microsoft Entra ID (ME-ID). Per altre informazioni, vedere la identity documentazione del provider.

    Nota

    MapInboundClaims deve essere impostato su false per la maggior parte dei provider OIDC, che impedisce la ridenominazione delle attestazioni.

    oidcOptions.MapInboundClaims = false;
    oidcOptions.TokenValidationParameters.NameClaimType = "name";
    oidcOptions.TokenValidationParameters.RoleClaimType = "roles";
    
  • Configurazione del percorso: i percorsi devono corrispondere all'URI di reindirizzamento (percorso di callback di accesso) e ai percorsi di reindirizzamento post disconnessione (percorso di callback con disconnessione) configurati durante la registrazione dell'applicazione con il provider OIDC. Nel portale di Azure i percorsi vengono configurati nel pannello Autenticazione della registrazione dell'app. Entrambi i percorsi di accesso e disconnessione devono essere registrati come URI di reindirizzamento. I valori predefiniti sono /signin-oidc e /signout-callback-oidc.

    • CallbackPath: percorso della richiesta all'interno del percorso di base dell'app in cui viene restituito l'agente utente.

      In Entra o portale di Azure impostare il percorso nell'URI di reindirizzamento della configurazione della piattaforma Web:

      https://localhost/signin-oidc

      Nota

      Una porta non è necessaria per localhost gli indirizzi.

    • SignedOutCallbackPath: percorso della richiesta all'interno del percorso di base dell'app in cui viene restituito l'agente utente dopo la identity disconnessione dal provider.

      In Entra o portale di Azure impostare il percorso nell'URI di reindirizzamento della configurazione della piattaforma Web:

      https://localhost/signout-callback-oidc

      Nota

      Una porta non è necessaria per localhost gli indirizzi.

      Nota

      Se si usa Microsoft Identity Web, il provider attualmente reindirizza di nuovo a SignedOutCallbackPath se viene usata l'autorità microsoftonline.com (https://login.microsoftonline.com/{TENANT ID}/v2.0/). Questa limitazione non esiste se è possibile usare l'autorità "comune" con Microsoft Identity Web. Per altre informazioni, vedere postLogoutRedirectUri not working when authority URL contains a tenant ID (AzureAD/microsoft-authentication-library-for-js #5783).

    • RemoteSignOutPath: le richieste ricevute in questo percorso causano il richiamo della disconnessione da parte del gestore tramite lo schema di disconnessione.

      In Entra o portale di Azure impostare l'URL di disconnessione del canale anteriore:

      https://localhost/signout-oidc

      Nota

      Una porta non è necessaria per localhost gli indirizzi.

      oidcOptions.CallbackPath = new PathString("{PATH}");
      oidcOptions.SignedOutCallbackPath = new PathString("{PATH}");
      oidcOptions.RemoteSignOutPath = new PathString("{PATH}");
      

      Esempi (valori predefiniti):

      oidcOptions.CallbackPath = new PathString("/signin-oidc");
      oidcOptions.SignedOutCallbackPath = new PathString("/signout-callback-oidc");
      oidcOptions.RemoteSignOutPath = new PathString("/signout-oidc");
      
  • (Microsoft Azure solo con l'endpoint "comune") TokenValidationParameters.IssuerValidator: molti provider OIDC funzionano con il validator predefinito dell'autorità di certificazione, ma è necessario tenere conto dell'autorità di certificazione con parametri con l'ID tenant ({TENANT ID}) restituito da https://login.microsoftonline.com/common/v2.0/.well-known/openid-configuration. Per altre informazioni, vedere SecurityTokenInvalidIssuerException con OpenID Connect e l'endpoint "common" di Azure AD (AzureAD/azure-activedirectory-identitymodel-extensions-for-dotnet #1731).

    Solo per le app che usano Microsoft Entra ID o Azure AD B2C con l'endpoint "comune":

    var microsoftIssuerValidator = AadIssuerValidator.GetAadIssuerValidator(oidcOptions.Authority);
    oidcOptions.TokenValidationParameters.IssuerValidator = microsoftIssuerValidator.Validate;
    

Codice dell'app di esempio

Esaminare l'app di esempio per le funzionalità seguenti:

  • Aggiornamento automatico del token non interattivo con l'aiuto di un aggiornamento personalizzato cookie (CookieOidcRefresher.cs).
  • Il progetto server chiama AddAuthenticationStateSerialization per aggiungere un provider di stato di autenticazione lato server che usa PersistentComponentState per trasferire lo stato di autenticazione al client. Il client chiama AddAuthenticationStateDeserialization per deserializzare e usare lo stato di autenticazione passato dal server. Lo stato di autenticazione è fisso per la durata dell'applicazione WebAssembly.
  • Le richieste a Blazor Web App vengono inoltrate tramite proxy al progetto API Web back-end (MinimalApiJwt). MapForwarder nel file aggiunge l'inoltro Program diretto di richieste HTTP che corrispondono al modello specificato a una destinazione specifica usando la configurazione predefinita per la richiesta in uscita, le trasformazioni personalizzate e il client HTTP predefinito:
    • Quando si esegue il rendering del Weather componente nel server, il componente usa ServerWeatherForecaster per proxyare la richiesta di dati meteo con il token di accesso dell'utente.
    • Quando viene eseguito il rendering del componente nel client, il componente usa l'implementazione del ClientWeatherForecaster servizio, che usa un preconfigurato HttpClient (nel file del Program progetto client) per effettuare una chiamata API Web al progetto server. Un endpoint API minimo (/weather-forecast) definito nel file del Program progetto server trasforma la richiesta con il token di accesso dell'utente per ottenere i dati meteo.
  • Aggiornamento automatico del token non interattivo con l'aiuto di un aggiornamento personalizzato cookie (CookieOidcRefresher.cs).
  • La PersistingAuthenticationStateProvider classe (PersistingAuthenticationStateProvider.cs) è un lato AuthenticationStateProvider server che usa PersistentComponentState per trasferire lo stato di autenticazione al client, che viene quindi risolto per la durata dell'applicazione WebAssembly.
  • Le richieste a Blazor Web App vengono inoltrate tramite proxy al progetto API Web back-end (MinimalApiJwt). MapForwarder nel file aggiunge l'inoltro Program diretto di richieste HTTP che corrispondono al modello specificato a una destinazione specifica usando la configurazione predefinita per la richiesta in uscita, le trasformazioni personalizzate e il client HTTP predefinito:
    • Quando si esegue il rendering del Weather componente nel server, il componente usa ServerWeatherForecaster per proxyare la richiesta di dati meteo con il token di accesso dell'utente.
    • Quando viene eseguito il rendering del componente nel client, il componente usa l'implementazione del ClientWeatherForecaster servizio, che usa un preconfigurato HttpClient (nel file del Program progetto client) per effettuare una chiamata API Web al progetto server. Un endpoint API minimo (/weather-forecast) definito nel file del Program progetto server trasforma la richiesta con il token di accesso dell'utente per ottenere i dati meteo.

Per altre informazioni sulle chiamate API (Web) tramite astrazioni di un servizio in Blazor Web Apps, vedere Chiamare un'API Web da un'app ASP.NET CoreBlazor.

Progetto lato client Blazor Web App (BlazorWebAppOidc.Client)

Il BlazorWebAppOidc.Client progetto è il progetto lato client di Blazor Web App.

Il client chiama AddAuthenticationStateDeserialization per deserializzare e usare lo stato di autenticazione passato dal server. Lo stato di autenticazione è fisso per la durata dell'applicazione WebAssembly.

La PersistentAuthenticationStateProvider classe (PersistentAuthenticationStateProvider.cs) è un lato AuthenticationStateProvider client che determina lo stato di autenticazione dell'utente cercando i dati persistenti nella pagina quando è stato eseguito il rendering nel server. Lo stato di autenticazione è fisso per la durata dell'applicazione WebAssembly.

Se l'utente deve accedere o disconnettersi, è necessario ricaricare una pagina completa.

L'app di esempio fornisce solo un nome utente e un messaggio di posta elettronica a scopo di visualizzazione. Non include token che eseguono l'autenticazione al server durante l'esecuzione di richieste successive, che funziona separatamente usando un cookie oggetto incluso nelle HttpClient richieste al server.

Progetto API Web back-end (MinimalApiJwt)

Il MinimalApiJwt progetto è un'API Web back-end per più progetti front-end. Il progetto configura un endpoint API minimo per i dati meteo. Le richieste dal Blazor Web App progetto lato server (BlazorWebAppOidc) vengono inviate tramite proxy al MinimalApiJwt progetto.

Impostazione

Configurare il progetto nella JwtBearerOptions classe della AddJwtBearer chiamata nel file del Program progetto:

  • Audience: imposta il gruppo di destinatari per qualsiasi token OpenID Connect ricevuto.

    Nel portale di Azure o Entra: associare il valore solo al percorso dell'URI ID applicazione configurato quando si aggiunge l'ambito Weather.Get in Esporre un'API:

    jwtOptions.Audience = "{APP ID URI}";
    

    Esempio:

    URI ID app ({APP ID URI}): https://{DIRECTORY NAME}.onmicrosoft.com/{CLIENT ID}:

    • Nome directory ({DIRECTORY NAME}): contoso
    • ID applicazione (client) ({CLIENT ID}): 00001111-aaaa-2222-bbbb-3333cccc4444
    jwtOptions.Audience = "https://contoso.onmicrosoft.com/00001111-aaaa-2222-bbbb-3333cccc4444";
    

    L'esempio precedente riguarda un'app registrata in un tenant con un tipo di tenant AAD B2C. Se l'app viene registrata in un tenant ME-ID, l'URI ID app è diverso, quindi il gruppo di destinatari è diverso.

    Esempio:

    URI ID app ({APP ID URI}): api://{CLIENT ID} con ID applicazione (client) ({CLIENT ID}): 00001111-aaaa-2222-bbbb-3333cccc4444

    jwtOptions.Audience = "api://00001111-aaaa-2222-bbbb-3333cccc4444";
    
  • Authority: imposta l'autorità per l'esecuzione di chiamate OpenID Connect. Trovare la corrispondenza del valore con l'autorità configurata per il gestore OIDC in BlazorWebAppOidc/Program.cs:

    jwtOptions.Authority = "{AUTHORITY}";
    

    Esempio:

    Autorità (): https://login.microsoftonline.com/aaaabbbb-0000-cccc-1111-dddd2222eeee/v2.0/ ({AUTHORITY}usa l'ID aaaabbbb-0000-cccc-1111-dddd2222eeeetenant )

    jwtOptions.Authority = "https://login.microsoftonline.com/aaaabbbb-0000-cccc-1111-dddd2222eeee/v2.0/";
    

    L'esempio precedente riguarda un'app registrata in un tenant con un tipo di tenant AAD B2C. Se l'app è registrata in un tenant ME-ID, l'autorità deve corrispondere all'issurer (iss) del token JWT restituito dal identity provider:

    jwtOptions.Authority = "https://sts.windows.net/aaaabbbb-0000-cccc-1111-dddd2222eeee/";
    

API minima per i dati meteo

Proteggere l'endpoint dei dati delle previsioni meteo nel file del Program progetto:

app.MapGet("/weather-forecast", () =>
{
    var forecast = Enumerable.Range(1, 5).Select(index =>
        new WeatherForecast
        (
            DateOnly.FromDateTime(DateTime.Now.AddDays(index)),
            Random.Shared.Next(-20, 55),
            summaries[Random.Shared.Next(summaries.Length)]
        ))
        .ToArray();
    return forecast;
}).RequireAuthorization();

Il RequireAuthorization metodo di estensione richiede l'autorizzazione per la definizione di route. Per tutti i controller aggiunti al progetto, aggiungere l'attributo [Authorize] al controller o all'azione.

Reindirizzamento alla pagina di home disconnetti

Quando un utente si sposta all'interno dell'app, il LogInOrOut componente (Layout/LogInOrOut.razor) imposta un campo nascosto per l'URL restituito (ReturnUrl) sul valore dell'URL corrente (currentURL). Quando l'utente si disconnette dall'app, il identity provider li restituisce alla pagina da cui si è disconnesso.

Se l'utente si disconnette da una pagina sicura, viene restituito alla stessa pagina protetta dopo la disconnessione solo per essere restituito tramite il processo di autenticazione. Questo comportamento è corretto quando gli utenti devono cambiare account di frequente. Tuttavia, una specifica dell'app alternativa può richiedere che l'utente venga restituito alla pagina dell'app home o a un'altra pagina dopo la disconnettersi. L'esempio seguente illustra come impostare la pagina dell'app home come URL restituito per le operazioni di disconnessione.

Le modifiche importanti apportate al LogInOrOut componente sono illustrate nell'esempio seguente. Non è necessario fornire un campo nascosto per il ReturnUrl set alla home pagina in / perché si tratta del percorso predefinito. IDisposable non è più implementato. l'oggetto NavigationManager non viene più inserito. L'intero @code blocco viene rimosso.

Layout/LogInOrOut.razor:

@using Microsoft.AspNetCore.Authorization

<div class="nav-item px-3">
    <AuthorizeView>
        <Authorized>
            <form action="authentication/logout" method="post">
                <AntiforgeryToken />
                <button type="submit" class="nav-link">
                    <span class="bi bi-arrow-bar-left-nav-menu" aria-hidden="true">
                    </span> Logout @context.User.Identity?.Name
                </button>
            </form>
        </Authorized>
        <NotAuthorized>
            <a class="nav-link" href="authentication/login">
                <span class="bi bi-person-badge-nav-menu" aria-hidden="true"></span> 
                Login
            </a>
        </NotAuthorized>
    </AuthorizeView>
</div>

Nonce crittografico

Un nonce è un valore stringa che associa la sessione di un client a un token ID per attenuare gli attacchi di riproduzione.

Se si riceve un errore nonce durante lo sviluppo e il test dell'autenticazione, usare una nuova sessione del browser InPrivate/incognito per ogni esecuzione di test, indipendentemente dalla piccola modifica apportata all'app o dall'utente di test perché i dati non aggiornati cookie possono causare un errore nonce. Per altre informazioni, vedere la sezione Cookie e dati del sito.

Un nonce non è obbligatorio o viene usato quando un token di aggiornamento viene scambiato per un nuovo token di accesso. Nell'app di esempio , (CookieOidcRefresherCookieOidcRefresher.cs) imposta OpenIdConnectProtocolValidator.RequireNonce deliberatamente su false.

Ruoli applicazione per le app non registrate con Microsoft Entra (ME-ID)

Questa sezione riguarda le app che non usano Microsoft Entra ID (ME-ID) come identity provider. Per le app registrate con ME-ID, vedere la sezione Ruoli applicazione per le app registrate con Microsoft Entra (ME-ID).

Configurare il tipo di attestazione del ruolo (TokenValidationParameters.RoleClaimType) in OpenIdConnectOptions di Program.cs:

oidcOptions.TokenValidationParameters.RoleClaimType = "{ROLE CLAIM TYPE}";

Per molti provider OIDC identity , il tipo di attestazione del ruolo è role. Controllare la identity documentazione del provider per ottenere il valore corretto.

Sostituire la UserInfo classe nel BlazorWebAppOidc.Client progetto con la classe seguente.

UserInfo.cs:

using Microsoft.AspNetCore.Components.WebAssembly.Authentication;
using System.Security.Claims;

namespace BlazorWebAppOidc.Client;

// Add properties to this class and update the server and client 
// AuthenticationStateProviders to expose more information about 
// the authenticated user to the client.
public sealed class UserInfo
{
    public required string UserId { get; init; }
    public required string Name { get; init; }
    public required string[] Roles { get; init; }

    public const string UserIdClaimType = "sub";
    public const string NameClaimType = "name";
    private const string RoleClaimType = "role";

    public static UserInfo FromClaimsPrincipal(ClaimsPrincipal principal) =>
        new()
        {
            UserId = GetRequiredClaim(principal, UserIdClaimType),
            Name = GetRequiredClaim(principal, NameClaimType),
            Roles = principal.FindAll(RoleClaimType).Select(c => c.Value)
                .ToArray(),
        };

    public ClaimsPrincipal ToClaimsPrincipal() =>
        new(new ClaimsIdentity(
            Roles.Select(role => new Claim(RoleClaimType, role))
                .Concat([
                    new Claim(UserIdClaimType, UserId),
                    new Claim(NameClaimType, Name),
                ]),
            authenticationType: nameof(UserInfo),
            nameType: NameClaimType,
            roleType: RoleClaimType));

    private static string GetRequiredClaim(ClaimsPrincipal principal,
        string claimType) =>
            principal.FindFirst(claimType)?.Value ??
            throw new InvalidOperationException(
                $"Could not find required '{claimType}' claim.");
}

A questo punto, Razor i componenti possono adottare l'autorizzazione basata sui ruoli e basata su criteri. I ruoli applicazione vengono visualizzati nelle role attestazioni, un'attestazione per ogni ruolo.

Ruoli applicazione per le app registrate con Microsoft Entra (ME-ID)

Usare le indicazioni riportate in questa sezione per implementare i ruoli applicazione, i gruppi di sicurezza ME-ID e i ruoli di amministratore predefiniti ME-ID per le app usando Microsoft Entra ID (ME-ID).

L'approccio descritto in questa sezione configura ME-ID per inviare gruppi e ruoli nell'intestazione di autenticazione cookie . Quando gli utenti sono solo membri di alcuni gruppi di sicurezza e ruoli, l'approccio seguente dovrebbe funzionare per la maggior parte delle piattaforme di hosting senza riscontrare un problema per cui le intestazioni sono troppo lunghe, ad esempio con l'hosting IIS con un limite di lunghezza dell'intestazione predefinito di 16 KB (MaxRequestBytes). Se la lunghezza dell'intestazione è un problema dovuto all'appartenenza a gruppi o ruoli elevati, è consigliabile non seguire le indicazioni riportate in questa sezione a favore dell'implementazione di Microsoft Graph per ottenere i gruppi e i ruoli di un utente da ME-ID separatamente, un approccio che non gonfia le dimensioni dell'autenticazione cookie. Per altre informazioni, vedere Richiesta non valida - Richiesta troppo lunga - Server IIS (dotnet/aspnetcore #57545)..

Configurare il tipo di attestazione del ruolo (TokenValidationParameters.RoleClaimType) in OpenIdConnectOptions di Program.cs. Impostare il valore su roles:

oidcOptions.TokenValidationParameters.RoleClaimType = "roles";

Anche se non è possibile assegnare ruoli ai gruppi senza un account PREMIUM ME-ID, è possibile assegnare ruoli agli utenti e ricevere attestazioni di ruolo per gli utenti con un account Azure standard. Le indicazioni contenute in questa sezione non richiedono un account ME-ID Premium.

Quando si usa la directory predefinita, seguire le indicazioni riportate in Aggiungere ruoli dell'app all'applicazione e riceverli nel token (documentazione di ME-ID) per configurare e assegnare ruoli. Se non si usa la directory predefinita, modificare il manifesto dell'app nel portale di Azure per stabilire manualmente i ruoli dell'app nella appRoles voce del file manifesto. Per altre informazioni, vedere Configurare l'attestazione del ruolo (documentazione di ME-ID).

I gruppi di sicurezza di Azure di un utente arrivano nelle groups attestazioni e le assegnazioni di ruolo di amministratore ME-ID predefinite di un utente arrivano in attestazioni di IDwids () note. I valori per entrambi i tipi di attestazione sono GUID. Quando vengono ricevute dall'app, queste attestazioni possono essere usate per stabilire l'autorizzazione di ruoli e criteri nei Razor componenti.

Nel manifesto dell'app nel portale di Azure impostare l'attributo groupMembershipClaims su .All Un valore di All restituisce ME-ID inviando tutti i gruppi di sicurezza/distribuzione (groups attestazioni) e ruoli (wids attestazioni) dell'utente connesso. Per impostare l'attributo groupMembershipClaims :

  1. Aprire la registrazione dell'app nel portale di Azure.
  2. Selezionare Gestisci>manifesto nella barra laterale.
  3. Trovare l'attributo groupMembershipClaims .
  4. Impostare il valore su All ("groupMembershipClaims": "All").
  5. Selezionare il pulsante Salva.

Sostituire la UserInfo classe nel BlazorWebAppOidc.Client progetto con la classe seguente.

UserInfo.cs:

using Microsoft.AspNetCore.Components.WebAssembly.Authentication;
using System.Security.Claims;

namespace BlazorWebAppOidc.Client;

// Add properties to this class and update the server and client 
// AuthenticationStateProviders to expose more information about 
// the authenticated user to the client.
public sealed class UserInfo
{
    public required string UserId { get; init; }
    public required string Name { get; init; }
    public required string[] Roles { get; init; }
    public required string[] Groups { get; init; }
    public required string[] Wids { get; init; }

    public const string UserIdClaimType = "sub";
    public const string NameClaimType = "name";
    private const string RoleClaimType = "roles";
    private const string GroupsClaimType = "groups";
    private const string WidsClaimType = "wids";

    public static UserInfo FromClaimsPrincipal(ClaimsPrincipal principal) =>
        new()
        {
            UserId = GetRequiredClaim(principal, UserIdClaimType),
            Name = GetRequiredClaim(principal, NameClaimType),
            Roles = principal.FindAll(RoleClaimType).Select(c => c.Value)
                .ToArray(),
            Groups = principal.FindAll(GroupsClaimType).Select(c => c.Value)
                .ToArray(),
            Wids = principal.FindAll(WidsClaimType).Select(c => c.Value)
                .ToArray(),
        };

    public ClaimsPrincipal ToClaimsPrincipal() =>
        new(new ClaimsIdentity(
            Roles.Select(role => new Claim(RoleClaimType, role))
                .Concat(Groups.Select(role => new Claim(GroupsClaimType, role)))
                .Concat(Wids.Select(role => new Claim(WidsClaimType, role)))
                .Concat([
                    new Claim(UserIdClaimType, UserId),
                    new Claim(NameClaimType, Name),
                ]),
            authenticationType: nameof(UserInfo),
            nameType: NameClaimType,
            roleType: RoleClaimType));

    private static string GetRequiredClaim(ClaimsPrincipal principal,
        string claimType) =>
            principal.FindFirst(claimType)?.Value ??
            throw new InvalidOperationException(
                $"Could not find required '{claimType}' claim.");
}

A questo punto, Razor i componenti possono adottare l'autorizzazione basata sui ruoli e basata su criteri:

  • I ruoli applicazione vengono visualizzati nelle roles attestazioni, un'attestazione per ogni ruolo.
  • I gruppi di sicurezza vengono visualizzati nelle groups attestazioni, un'attestazione per gruppo. I GUID del gruppo di sicurezza vengono visualizzati nella portale di Azure quando si crea un gruppo di sicurezza e vengono elencati quando si seleziona Identity>Panoramica>Gruppi>di visualizzazione.
  • I ruoli di amministratore ME-ID predefiniti vengono visualizzati nelle wids attestazioni, un'attestazione per ogni ruolo. L'attestazione wids con un valore di b79fbf4d-3ef9-4689-8143-76b194e85509 viene sempre inviata da ME-ID per gli account non guest del tenant e non fa riferimento a un ruolo di amministratore. I GUID ruolo amministratore (ID modello di ruolo) vengono visualizzati nel portale di Azure quando si seleziona Ruoli e amministratori, seguiti dai puntini di sospensione (...) >Descrizione per il ruolo elencato. Gli ID modello di ruolo sono elencati anche in Ruoli predefiniti di Microsoft Entra (documentazione entra).

Risoluzione dei problemi

Registrazione

L'app server è un'app standard ASP.NET Core. Vedere le linee guida per la registrazione di ASP.NET Core per abilitare un livello di registrazione inferiore nell'app server.

Per abilitare la registrazione di debug o traccia per Blazor WebAssembly l'autenticazione, vedere la sezione Registrazione dell'autenticazione lato client di ASP.NET Core Blazor con il selettore della versione dell'articolo impostato su ASP.NET Core 7.0 o versione successiva.

Errori comuni

  • Configurazione errata dell'app o Identity del provider (IP)

    Gli errori più comuni sono causati da una configurazione errata. Di seguito sono riportati alcuni esempi:

    • A seconda dei requisiti dello scenario, un'autorità mancante o non corretta, istanza, ID tenant, dominio tenant, ID client o URI di reindirizzamento impedisce a un'app di autenticare i client.
    • Gli ambiti di richiesta non corretti impediscono ai client di accedere agli endpoint DELL'API Web del server.
    • Autorizzazioni DELL'API server non corrette o mancanti impediscono ai client di accedere agli endpoint DELL'API Web del server.
    • L'esecuzione dell'app in una porta diversa da quella configurata nell'URI di reindirizzamento della registrazione dell'app ip. Si noti che non è necessaria una porta per Microsoft Entra ID e un'app in esecuzione in un localhost indirizzo di test di sviluppo, ma la configurazione della porta dell'app e la porta in cui è in esecuzione l'app devono corrispondere per gli indirizzi nonlocalhost .

    La copertura della configurazione in questo articolo illustra esempi della configurazione corretta. Controllare attentamente la configurazione alla ricerca di errori di configurazione di app e IP.

    Se la configurazione è corretta:

    • Analizzare i log delle applicazioni.

    • Esaminare il traffico di rete tra l'app client e l'app IP o server con gli strumenti di sviluppo del browser. Spesso, un messaggio di errore esatto o un messaggio con un indizio sulla causa del problema viene restituito al client dall'app IP o server dopo aver effettuato una richiesta. Strumenti di sviluppo materiale sussidiario sono disponibili negli articoli seguenti:

    Il team della documentazione risponde al feedback e ai bug dei documenti negli articoli (aprire un problema dalla sezione Commenti e suggerimenti della pagina ), ma non è in grado di fornire supporto tecnico. Sono disponibili diversi forum di supporto pubblico per facilitare la risoluzione dei problemi di un'app. Consigliamo quanto segue:

    I forum precedenti non sono di proprietà o controllati da Microsoft.

    Per i report sui bug del framework non riservati, non sensibili e non riservati, aprire un problema con l'unità del prodotto ASP.NET Core. Non aprire un problema con l'unità di prodotto fino a quando non hai approfondito la causa di un problema e non puoi risolverlo autonomamente e con l'aiuto della community in un forum di supporto pubblico. L'unità prodotto non è in grado di risolvere i problemi relativi alle singole app interrotte a causa di semplici errori di configurazione o casi d'uso che coinvolgono servizi di terze parti. Se un report è sensibile o riservato in natura o descrive un potenziale difetto di sicurezza nel prodotto che potrebbero sfruttare i cyberattacker, vedere Segnalazione di problemi e bug di sicurezza (dotnet/aspnetcorerepository GitHub).

  • Client non autorizzato per ME-ID

    info: Microsoft.AspNetCore.Authorization.DefaultAuthorizationService[2] Autorizzazione non riuscita. Questi requisiti non sono stati soddisfatti: DenyAnonymousAuthorizationRequirement: richiede un utente autenticato.

    Errore di callback di accesso da ME-ID:

    • Errore: unauthorized_client
    • Description (Descrizione): AADB2C90058: The provided application is not configured to allow public clients.

    Per risolvere l'errore:

    1. Nella portale di Azure accedere al manifesto dell'app.
    2. Impostare l'attributo allowPublicClient su null o .true

Cookie e dati del sito

I cookie e i dati del sito possono persistere tra gli aggiornamenti delle app e interferire con i test e la risoluzione dei problemi. Cancellare quanto segue quando si apportano modifiche al codice dell'app, modifiche all'account utente con il provider o modifiche alla configurazione dell'app del provider:

  • Cookie di accesso utente
  • Cookie dell'app
  • Dati del sito memorizzati nella cache e archiviati

Un approccio per evitare che i cookie e i dati del sito persistenti interferiscano con i test e la risoluzione dei problemi consiste nel:

  • Configurare un browser
    • Usare un browser per i test che è possibile configurare per eliminare tutti i cookie dati del sito e ogni volta che il browser viene chiuso.
    • Assicurarsi che il browser venga chiuso manualmente o dall'IDE per qualsiasi modifica apportata alla configurazione dell'app, dell'utente di test o del provider.
  • Usare un comando personalizzato per aprire un browser in modalità InPrivate o In incognito in Visual Studio:
    • Aprire la finestra di dialogo Sfoglia con dal pulsante Esegui di Visual Studio.
    • Seleziona il pulsante Aggiungi.
    • Specificare il percorso del browser nel campo Programma . I percorsi eseguibili seguenti sono percorsi di installazione tipici per Windows 10. Se il browser è installato in un percorso diverso o non si usa Windows 10, specificare il percorso dell'eseguibile del browser.
      • Microsoft Edge: C:\Program Files (x86)\Microsoft\Edge\Application\msedge.exe
      • Google Chrome: C:\Program Files (x86)\Google\Chrome\Application\chrome.exe
      • Mozilla Firefox: C:\Program Files\Mozilla Firefox\firefox.exe
    • Nel campo Argomenti specificare l'opzione della riga di comando usata dal browser per aprire in modalità InPrivate o Incognito. Alcuni browser richiedono l'URL dell'app.
      • Microsoft Edge: usare -inprivate.
      • Google Chrome: usare --incognito --new-window {URL}, dove il {URL} segnaposto è l'URL da aprire (ad esempio, https://localhost:5001).
      • Mozilla Firefox: usare -private -url {URL}, dove il {URL} segnaposto è l'URL da aprire (ad esempio, https://localhost:5001).
    • Specificare un nome nel campo Nome descrittivo. Ad esempio: Firefox Auth Testing.
    • Selezionare il pulsante OK.
    • Per evitare di dover selezionare il profilo del browser per ogni iterazione di test con un'app, impostare il profilo come predefinito con il pulsante Imposta come predefinito .
    • Assicurarsi che il browser sia chiuso dall'IDE per qualsiasi modifica apportata all'app, all'utente di test o alla configurazione del provider.

Aggiornamenti di app

Un'app funzionante potrebbe non riuscire immediatamente dopo l'aggiornamento di .NET Core SDK nel computer di sviluppo o la modifica delle versioni dei pacchetti all'interno dell'app. In alcuni casi i pacchetti incoerenti possono interrompere un'app quando si eseguono aggiornamenti principali. La maggior parte di questi problemi può essere risolta attenendosi alle istruzioni seguenti:

  1. Cancellare le cache dei pacchetti NuGet del sistema locale eseguendo dotnet nuget locals all --clear da una shell dei comandi.
  2. Eliminare le cartelle e obj del bin progetto.
  3. Ripristinare e ricompilare il progetto.
  4. Eliminare tutti i file nella cartella di distribuzione nel server prima di ridistribuire l'app.

Nota

L'uso di versioni del pacchetto incompatibili con il framework di destinazione dell'app non è supportato. Per informazioni su un pacchetto, usare La raccolta NuGet o Esplora pacchetti FuGet.

Eseguire l'app server

Durante i test e la risoluzione dei problemi Blazor Web App, assicurarsi di eseguire l'app dal progetto server.

Esaminare l'utente

Il componente seguente UserClaims può essere usato direttamente nelle app o funge da base per un'ulteriore personalizzazione.

UserClaims.razor:

@page "/user-claims"
@using System.Security.Claims
@using Microsoft.AspNetCore.Authorization
@attribute [Authorize]

<PageTitle>User Claims</PageTitle>

<h1>User Claims</h1>

@if (claims.Any())
{
    <ul>
        @foreach (var claim in claims)
        {
            <li><b>@claim.Type:</b> @claim.Value</li>
        }
    </ul>
}

@code {
    private IEnumerable<Claim> claims = Enumerable.Empty<Claim>();

    [CascadingParameter]
    private Task<AuthenticationState>? AuthState { get; set; }

    protected override async Task OnInitializedAsync()
    {
        if (AuthState == null)
        {
            return;
        }

        var authState = await AuthState;
        claims = authState.User.Claims;
    }
}

Risorse aggiuntive