Condividi tramite


Autenticazione e autorizzazione

Suggerimento

Questo contenuto è un estratto dell'eBook, Enterprise Application Patterns Using .NETMAUI, disponibile in .NET Docs o come PDF scaricabile gratuitamente che può essere letto offline.

Criteri di applicazione aziendale con .NET MAUI Anteprima copertina e-book.

L'autenticazione è il processo di recupero delle credenziali di identificazione, ad esempio nome e password da un utente e convalida di tali credenziali in base a un'autorità. L'entità che ha inviato le credenziali è considerata un'identità autenticata se le credenziali sono valide. Una volta stabilita un'identità, un processo di autorizzazione determina se tale identità ha accesso a una determinata risorsa.

Esistono molti approcci per l'integrazione dell'autenticazione e dell'autorizzazione in un'app .NET MAUI che comunica con un'applicazione Web ASP.NET, tra cui l'uso di ASP.NET Core Identity, provider di autenticazione esterni come Microsoft, Google, Facebook o Twitter e il middleware di autenticazione. L'app multipiattaforma eShop esegue l'autenticazione e l'autorizzazione con un microservizio di gestione delle identità in contenitori che usa IdentityServer. L'app richiede token di sicurezza da IdentityServer per autenticare un utente o accedere a una risorsa. Per consentire a IdentityServer di emettere token per conto di un utente, l'utente deve accedere a IdentityServer. IdentityServer, tuttavia, non fornisce un'interfaccia utente o un database per l'autenticazione. Pertanto, ASP.NET Core Identity viene usato a questo scopo nell'applicazione di riferimento eShop.

Autenticazione

L'autenticazione è necessaria quando un'applicazione deve conoscere l'identità dell'utente corrente. ASP.NET il meccanismo principale di Core per identificare gli utenti è il sistema di appartenenza ASP.NET Core Identity, che archivia le informazioni utente in un archivio dati configurato dallo sviluppatore. In genere, questo archivio dati sarà un archivio EntityFramework, anche se gli archivi personalizzati o i pacchetti di terze parti possono essere usati per archiviare le informazioni sull'identità in Archiviazione di Azure, DocumentDB o in altre posizioni.

Per gli scenari di autenticazione che usano un archivio dati utente locale e rendono persistenti le informazioni sull'identità tra le richieste tramite cookie (come in genere avviene per le applicazioni Web di ASP.NET), ASP.NET Core Identity è una soluzione adatta. Tuttavia, i cookie non sono sempre un mezzo naturale per rendere persistenti e trasmettere i dati. Ad esempio, un'applicazione Web ASP.NET Core che espone gli endpoint RESTful a cui si accede da un'app in genere dovrà usare l'autenticazione del token di connessione perché i cookie non possono essere usati in questo scenario. Tuttavia, i token di connessione possono essere facilmente recuperati e inclusi nell'intestazione di autorizzazione delle richieste Web effettuate dall'app.

Emissione di token di connessione con IdentityServer

IdentityServer è un framework OpenID Connect open source e OAuth 2.0 per ASP.NET Core, che può essere usato per molti scenari di autenticazione e autorizzazione, inclusi l'emissione di token di sicurezza per gli utenti locali ASP.NET Core Identity.

Nota

OpenID Connect e OAuth 2.0 sono molto simili, pur avendo responsabilità diverse.

OpenID Connect è un livello di autenticazione sopra il protocollo OAuth 2.0. OAuth 2 è un protocollo che consente alle applicazioni di richiedere token di accesso da un servizio token di sicurezza e usarli per comunicare con le API. Questa delega riduce la complessità sia nelle applicazioni client che nelle API, perché l'autenticazione e l'autorizzazione possono essere centralizzate.

OpenID Connect e OAuth 2.0 combinano i due principali problemi di sicurezza relativi all'autenticazione e all'accesso alle API, e IdentityServer è un'implementazione di questi protocolli.

Nelle applicazioni che usano la comunicazione diretta da client a microservizi, ad esempio l'applicazione di riferimento eShop, un microservizio di autenticazione dedicato che funge da servizio token di sicurezza (STS) può essere usato per autenticare gli utenti, come illustrato nel diagramma seguente. Per altre informazioni sulla comunicazione diretta da client a microservizi, vedere Microservizi.

Autenticazione tramite un microservizio di autenticazione dedicato.

L'app multipiattaforma eShop comunica con il microservizio di gestione delle identità, che usa IdentityServer per eseguire l'autenticazione e il controllo di accesso per le API. Di conseguenza, l'app multipiattaforma richiede token da IdentityServer, per l'autenticazione di un utente o per l'accesso a una risorsa:

  • L'autenticazione degli utenti con IdentityServer viene ottenuta dall'app multipiattaforma che richiede un token di identità, che rappresenta il risultato di un processo di autenticazione. Contiene almeno un identificatore per l'utente e informazioni su come e quando l'utente viene autenticato. Può anche includere dati di identità aggiuntivi.
  • L'accesso a una risorsa con IdentityServer viene ottenuto dall'app multipiattaforma che richiede un token di accesso, che consente l'accesso a una risorsa API. I client richiedono token di accesso e li inoltrano all'API. I token di accesso contengono informazioni sul client e sull'utente, se presenti. Le API usano quindi tali informazioni per autorizzare l'accesso ai dati.

Nota

Un client deve essere registrato con IdentityServer prima di poter richiedere correttamente i token. Per altre informazioni sull'aggiunta di client, vedere Definizione dei client.

Aggiunta di IdentityServer a un'applicazione Web

Affinché un'applicazione Web ASP.NET Core usi IdentityServer, è necessario aggiungerla alla soluzione Visual Studio dell'applicazione Web. Per altre informazioni, vedere Installazione e panoramica nella documentazione di IdentityServer. Dopo aver incluso IdentityServer nella soluzione Visual Studio dell'applicazione Web, è necessario aggiungerlo alla pipeline di elaborazione delle richieste HTTP per gestire le richieste agli endpoint OpenID Connect e OAuth 2.0. Questa operazione viene configurata nel Identity.APIProgram.cs del progetto, come illustrato nell'esempio di codice seguente:


...

app.UseIdentityServer();

L'ordine è importante nella pipeline di elaborazione delle richieste HTTP dell'applicazione Web. Pertanto, IdentityServer deve essere aggiunto alla pipeline prima del framework dell'interfaccia utente che implementa la schermata di accesso.

Configurazione di IdentityServer

IdentityServer è configurato nel Identity.APIProgram.cs del progetto chiamando il metodo AddIdentityServer, come illustrato nell'esempio di codice seguente dall'applicazione di riferimento eShop:

builder.Services.AddIdentityServer(options =>
    {
        options.Authentication.CookieLifetime = TimeSpan.FromHours(2);
    
        options.Events.RaiseErrorEvents = true;
        options.Events.RaiseInformationEvents = true;
        options.Events.RaiseFailureEvents = true;
        options.Events.RaiseSuccessEvents = true;
    
        // TODO: Remove this line in production.
        options.KeyManagement.Enabled = false;
    })
    .AddInMemoryIdentityResources(Config.GetResources())
    .AddInMemoryApiScopes(Config.GetApiScopes())
    .AddInMemoryApiResources(Config.GetApis())
    .AddInMemoryClients(Config.GetClients(builder.Configuration))
    .AddAspNetIdentity<ApplicationUser>()
    // TODO: Not recommended for production - you need to store your key material somewhere secure
    .AddDeveloperSigningCredential();

Dopo aver chiamato il metodo services.AddIdentityServer, vengono chiamate API Fluent aggiuntive per configurare quanto segue:

  • Credenziali usate per la firma.
  • Risorse API e identità a cui gli utenti potrebbero richiedere l'accesso.
  • Client che si connetteranno ai token di richiesta.
  • Identità di ASP.NET Core.

Suggerimento

Caricare dinamicamente la configurazione di IdentityServer. Le API di IdentityServer consentono di configurare IdentityServer da un elenco in memoria di oggetti di configurazione. Nell'applicazione di riferimento eShop queste raccolte in memoria sono hardcoded nell'applicazione. Tuttavia, negli scenari di produzione possono essere caricati dinamicamente da un file di configurazione o da un database.

Per informazioni sulla configurazione di IdentityServer per l'uso di Identità di ASP.NET Core, vedere Uso di Identità di ASP.NET Core nella documentazione di IdentityServer.

Configurazione delle risorse API

Quando si configurano le risorse API, il metodo AddInMemoryApiResources prevede una raccolta IEnumerable<ApiResource>. L'esempio di codice seguente illustra il metodo GetApis che fornisce questa raccolta nell'applicazione di riferimento eShop:

public static IEnumerable<ApiResource> GetApis()
{
    return new List<ApiResource>
    {
        new ApiScope("orders", "Orders Service"),
        new ApiScope("basket", "Basket Service"),
        new ApiScope("webhooks", "Webhooks registration Service"),
    };
}

Questo metodo specifica che IdentityServer deve proteggere gli ordini e le API carrello. Pertanto, i token di accesso gestiti da IdentityServer saranno necessari quando si effettuano chiamate a queste API. Per altre informazioni sul tipo ApiResource, vedere API Resources nella documentazione di IdentityServer.

Configurazione delle risorse di identità

Quando si configurano le risorse di identità, il metodo AddInMemoryIdentityResources prevede una raccolta IEnumerable<IdentityResource>. Le risorse di identità sono dati come ID utente, nome o indirizzo di posta elettronica. A ogni risorsa di identità è associato un nome univoco e possono essere assegnati tipi di attestazione arbitrari, che verranno inclusi nel token di identità per l'utente. L'esempio di codice seguente illustra il metodo GetResources che fornisce questa raccolta nell'applicazione di riferimento eShop:

public static IEnumerable<IdentityResource> GetResources()
{
    return new List<IdentityResource>
    {
        new IdentityResources.OpenId(),
        new IdentityResources.Profile()
    };
}

La specifica OpenID Connect specifica alcune risorse di identità standard. Il requisito minimo è che il supporto venga fornito per l'emissione di un ID univoco per gli utenti. Questa operazione viene ottenuta esponendo la risorsa di identità IdentityResources.OpenId.

Nota

La classe IdentityResources supporta tutti gli ambiti definiti nella specifica OpenID Connect (openid, email, profilo, telefono e indirizzo).

IdentityServer supporta anche la definizione di risorse di identità personalizzate. Per altre informazioni, vedere Definizione delle risorse di identità personalizzate nella documentazione di IdentityServer. Per altre informazioni sul tipo IdentityResource, vedere Identity Resources nella documentazione di IdentityServer.

Configurazione dei client

I client sono applicazioni che possono richiedere token da IdentityServer. In genere, le impostazioni seguenti devono essere definite per ogni client come minimo:

  • ID client univoco.
  • Interazioni consentite con il servizio token (noto come tipo di concessione).
  • Posizione in cui vengono inviati i token di identità e di accesso (noto come URI di reindirizzamento).
  • Elenco di risorse a cui è consentito l'accesso al client (noto come ambiti).

Quando si configurano i client, il metodo AddInMemoryClients prevede una raccolta IEnumerable<Client>. L'esempio di codice seguente illustra la configurazione per l'app multipiattaforma eShop nel metodo GetClients che fornisce questa raccolta nell'applicazione di riferimento eShop:

public static IEnumerable<Client> GetClients(Dictionary<string,string> clientsUrl)
{
    return new List<Client>
    {
        // Omitted for brevity
        new Client
        {
            ClientId = "maui",
            ClientName = "eShop MAUI OpenId Client",
            AllowedGrantTypes = GrantTypes.Code,                    
            //Used to retrieve the access token on the back channel.
            ClientSecrets =
            {
                new Secret("secret".Sha256())
            },
            RedirectUris = { configuration["MauiCallback"] },
            RequireConsent = false,
            RequirePkce = true,
            PostLogoutRedirectUris = { $"{configuration["MauiCallback"]}/Account/Redirecting" },
            AllowedScopes = new List<string>
            {
                IdentityServerConstants.StandardScopes.OpenId,
                IdentityServerConstants.StandardScopes.Profile,
                IdentityServerConstants.StandardScopes.OfflineAccess,
                "orders",
                "basket",
                "mobileshoppingagg",
                "webhooks"
            },
            //Allow requesting refresh tokens for long lived API access
            AllowOfflineAccess = true,
            AllowAccessTokensViaBrowser = true,
            AlwaysIncludeUserClaimsInIdToken = true,
            AccessTokenLifetime = 60 * 60 * 2, // 2 hours
            IdentityTokenLifetime = 60 * 60 * 2 // 2 hours
        }
    };
}

Questa configurazione specifica i dati per le proprietà seguenti:

Proprietà Descrizione
ClientId ID univoco per il client.
ClientName Nome visualizzato del client, usato per la registrazione e la schermata di consenso.
AllowedGrantTypes Specifica il modo in cui un client vuole interagire con IdentityServer. Per altre informazioni, vedere Configurazione del flusso di autenticazione.
ClientSecrets Specifica le credenziali del segreto client usate quando si richiedono token dall'endpoint del token.
RedirectUris Specifica gli URI consentiti a cui restituire token o codici di autorizzazione.
RequireConsent Specifica se è necessaria una schermata di consenso.
RequirePkce Specifica se i client che usano un codice di autorizzazione devono inviare una chiave di prova.
PostLogoutRedirectUris Specifica gli URI consentiti da reindirizzare a dopo la disconnessione.
AllowedCorsOrigins Specifica l'origine del client in modo che IdentityServer possa consentire chiamate tra le origini dall'origine.
AllowedScopes Specifica le risorse a cui il client ha accesso. Per impostazione predefinita, un client non ha accesso ad alcuna risorsa.
AllowOfflineAccess Specifica se il client può richiedere token di aggiornamento.
AllowAccessTokensViaBrowser Specifica se il client può ricevere token di accesso da una finestra del browser.
AlwaysIncludeUserClaimsInIdToken Specifica che le attestazioni utente verranno sempre aggiunte al token ID. Per impostazione predefinita, queste devono essere recuperate usando l'endpoint userinfo.
AccessTokenLifetime Specifica la durata del token di accesso in secondi.
IdentityTokenLifetime Specifica la durata del token di identità in secondi.

Configurazione del flusso di autenticazione

Il flusso di autenticazione tra un client e IdentityServer può essere configurato specificando i tipi di concessione nella proprietà Client.AllowedGrantTypes. Le specifiche OpenID Connect e OAuth 2.0 definiscono diversi flussi di autenticazione, tra cui:

Flusso di autenticazione Descrizione
Implicito Questo flusso è ottimizzato per le applicazioni basate su browser e deve essere usato solo per l'autenticazione dell’utente, o per le richieste di autenticazione e token di accesso. Tutti i token vengono trasmessi tramite il browser e pertanto non sono consentite funzionalità avanzate come i token di aggiornamento.
Codice di autorizzazione Questo flusso offre la possibilità di recuperare i token in un canale back, anziché il canale anteriore del browser, supportando anche l'autenticazione client.
Ibrido Questo flusso è una combinazione dei tipi di concessione del codice implicito e di autorizzazione. Il token di identità viene trasmesso tramite il canale del browser e contiene la risposta del protocollo firmata e altri artefatti, ad esempio il codice di autorizzazione. Dopo aver convalidato correttamente la risposta, il canale back deve essere usato per recuperare l'accesso e il token di aggiornamento.

Suggerimento

Prendere in considerazione l'uso del flusso di autenticazione ibrida. Il flusso di autenticazione ibrida riduce una serie di attacchi che si applicano al canale del browser ed è il flusso consigliato per le applicazioni native che vogliono recuperare i token di accesso (ed eventualmente aggiornare i token).

Per altre informazioni sui flussi di autenticazione, vedere Grant Types nella documentazione di IdentityServer.

Esecuzione dell'autenticazione

Per consentire a IdentityServer di emettere token per conto di un utente, l'utente deve accedere a IdentityServer. IdentityServer, tuttavia, non fornisce un'interfaccia utente o un database per l'autenticazione. Pertanto, ASP.NET Core Identity viene usato a questo scopo nell'applicazione di riferimento eShop.

L'app multipiattaforma eShop esegue l'autenticazione con IdentityServer con il flusso di autenticazione ibrida, illustrato nel diagramma seguente.

Panoramica generale del processo di accesso.

Viene effettuata una richiesta di accesso a <base endpoint>:5105/connect/authorize. Dopo l'autenticazione riuscita, IdentityServer restituisce una risposta di autenticazione contenente un codice di autorizzazione e un token di identità. Il codice di autorizzazione viene inviato a <base endpoint>:5105/connect/token, che risponde con token di accesso, identità e aggiornamento.

L'app multipiattaforma eShop si disconnette da IdentityServer inviando una richiesta a <base endpoint>:5105/connect/endsession con parametri aggiuntivi. Dopo la disconnessione, IdentityServer risponde inviando un URI di reindirizzamento post-disconnessione all'app multipiattaforma. Il diagramma seguente illustra questo processo.

Panoramica generale del processo di disconnessione.

Nell'app multipiattaforma eShop la comunicazione con IdentityServer viene eseguita dalla classe IdentityService, che implementa l'interfaccia IIdentityService. Questa interfaccia specifica che la classe di implementazione deve fornire metodi SignInAsync, SignOutAsync, GetUserInfoAsync e GetAuthTokenAsync.

Accesso

Quando l'utente tocca il pulsante LOGIN su LoginView, viene eseguita l’oggetto SignInCommand nella classe LoginViewModel, che a sua volta esegue il metodo SignInAsync. L'esempio di codice seguente illustra il metodo:

[RelayCommand]
private async Task SignInAsync()
{
    await IsBusyFor(
        async () =>
        {
            var loginSuccess = await _appEnvironmentService.IdentityService.SignInAsync();

            if (loginSuccess)
            {
                await NavigationService.NavigateToAsync("//Main/Catalog");
            }
        });
}

Questo metodo richiama il metodo SignInAsync nella classe IdentityService, come illustrato nell'esempio di codice seguente:

public async Task<bool> SignInAsync()
{
    var response = await GetClient().LoginAsync(new LoginRequest()).ConfigureAwait(false);

    if (response.IsError)
    {
        return false;
    }

    await _settingsService
        .SetUserTokenAsync(
            new UserToken
            {
                AccessToken = response.AccessToken,
                IdToken = response.IdentityToken,
                RefreshToken = response.RefreshToken,
                ExpiresAt = response.AccessTokenExpiration
            })
        .ConfigureAwait(false);

    return !response.IsError;
}

La classe IdentityService usa il client OidcClient fornito con il pacchetto NuGet IdentityModel.OidcClient. Questo client mostra la webview di autenticazione per l'utente nell'applicazione e acquisisce il risultato. Il client si connette all'URI per l'endpoint di autorizzazione di IdentityServer con i parametri necessari. L'endpoint di autorizzazione si trova a /connect/authorize sulla porta 5105 dell'endpoint di base esposto come impostazione utente. Per altre informazioni sulle impostazioni utente, vedere Gestione della configurazione.

Nota

La superficie di attacco dell'app multipiattaforma eShop viene ridotta implementando l'estensione Proof Key for Code Exchange (PKCE) in OAuth. PKCE protegge il codice di autorizzazione dall'uso se viene intercettato. Questo risultato viene ottenuto dal client generando un verificatore segreto, il cui hash viene passato nella richiesta di autorizzazione e che viene presentato senza hash durante il riscatto del codice di autorizzazione. Per altre informazioni su PKCE, vedere Proof Key for Code Exchange by OAuth Public Clients (Chiave di prova per Exchange di client pubblici OAuth) nel sito Web Internet Engineering Task Force.

Pagina di accesso visualizzata dalla webview.

Se l'endpoint del token riceve informazioni di autenticazione, codice di autorizzazione e classificatore segreto PKCE validi, risponde con un token di accesso, un token di identità e un token di aggiornamento. Il token di accesso (che consente l'accesso alle risorse API) e il token di identità vengono archiviati come impostazioni dell'applicazione, e viene eseguita la navigazione nella pagina. Pertanto, l'effetto complessivo nell'app multipiattaforma eShop è il seguente: a condizione che gli utenti siano in grado di eseguire correttamente l'autenticazione con IdentityServer, vengono indirizzati alla route //Main/Catalog, ovvero un oggetto TabbedPage che visualizza CatalogView come scheda selezionata.

Per informazioni sullo spostamento tra le pagine, vedere Navigazione. Per informazioni sulla modalità di esecuzione di un metodo del modello di visualizzazione, vedere Richiamo dello spostamento tramite comportamenti. Per informazioni sulle impostazioni dell'applicazione, vedere Gestione della configurazione.

Nota

eShop consente anche un accesso fittizio quando l'app è configurata per usare servizi fittizi in SettingsView. In questa modalità, l'app non comunica con IdentityServer, consentendo invece all'utente di accedere usando le credenziali.

Disconnessione

Quando l'utente tocca il pulsante LOG OUT in ProfileView, viene eseguito l’oggetto LogoutCommand nella classe ProfileViewModel, che esegue il metodo LogoutAsync. Questo metodo esegue lo spostamento della pagina alla pagina LoginView tramite un parametro di query Logout impostato su true.

Tale parametro viene valutato nel metodo ApplyQueryAttributes. Se il parametro Logout è presente con un valore true, viene eseguito il metodo PerformLogoutAsync della classe LoginViewModel, come illustrato nell'esempio di codice seguente:

private async Task PerformLogoutAsync()
{
    await _appEnvironmentService.IdentityService.SignOutAsync();

    _settingsService.UseFakeLocation = false;

    UserName.Value = string.Empty;
    Password.Value = string.Empty;
}

Questo metodo richiama il metodo SignOutAsync nella classe IdentityService, che richiama il client OidcClient per terminare la sessione dell'utente e cancella eventuali token utente salvati. Per altre informazioni sulle impostazioni dell'applicazione, vedere Gestione della configurazione. L'esempio di codice seguente illustra il metodo SignOutAsync:

public async Task<bool> SignOutAsync()
{
    var response = await GetClient().LogoutAsync(new LogoutRequest()).ConfigureAwait(false);

    if (response.IsError)
    {
        return false;
    }

    await _settingsService.SetUserTokenAsync(default);

    return !response.IsError;
}

Questo metodo usa il client OidcClient per chiamare l'URI dell'endpoint di fine sessione di IdentityServer con i parametri necessari. L'endpoint della sessione finale si trova a /connect/endsession sulla porta 5105 dell'endpoint di base esposto come impostazione utente. Dopo che l'utente è stato disconnesso, all'utente viene presentato LoginView e tutte le informazioni utente salvate verranno cancellate.

Per informazioni sullo spostamento tra le pagine, vedere Navigazione. Per informazioni su come la navigazione WebView determina l'esecuzione di un metodo del modello di visualizzazione, vedere Richiamare la navigazione tramite comportamenti. Per informazioni sulle impostazioni dell'applicazione, vedere Gestione della configurazione.

Nota

eShop consente anche una disconnessione fittizia quando l'app è configurata per usare servizi fittizi in SettingsView. In questa modalità, l'app non comunica con IdentityServer e cancella invece i token archiviati dalle impostazioni dell'applicazione.

Autorizzazione

Dopo l'autenticazione, ASP.NET API Web core spesso devono autorizzare l'accesso, consentendo a un servizio di rendere disponibili API ad alcuni utenti autenticati, ma non a tutti.

È possibile limitare l'accesso a una route ASP.NET Core applicando un attributo Authorize a un controller o a un'azione, che limita l'accesso al controller o all'azione agli utenti autenticati, come illustrato nell'esempio di codice seguente:

[Authorize]
public sealed class BasketController : Controller
{
    // Omitted for brevity
}

Se un utente non autorizzato tenta di accedere a un controller o a un'azione contrassegnata con l'attributo Authorize, il framework API restituisce un codice di stato HTTP 401 (unauthorized).

Nota

I parametri possono essere specificati nell'attributo Authorize per limitare un'API a utenti specifici. Per altre informazioni, vedere ASP.NET Core Docs: Authorization(Documentazione principale: autorizzazione).

IdentityServer può essere integrato nel flusso di lavoro di autorizzazione in modo che i token di accesso forniscano l'autorizzazione di controllo. Questo approccio è illustrato nel diagramma seguente.

Autorizzazione tramite token di accesso.

L'app multipiattaforma eShop comunica con il microservizio di gestione delle identità e richiede un token di accesso come parte del processo di autenticazione. Il token di accesso viene quindi inoltrato alle API esposte dai microservizi di ordinamento e carrello come parte delle richieste di accesso. I token di accesso contengono informazioni sul client e sull'utente. Le API usano quindi tali informazioni per autorizzare l'accesso ai dati. Per informazioni su come configurare IdentityServer per proteggere le API, vedere Configurazione delle risorse API.

Configurazione di IdentityServer per eseguire l'autorizzazione

Per eseguire l'autorizzazione con IdentityServer, è necessario aggiungere il middleware di autorizzazione alla pipeline di richiesta HTTP dell'applicazione Web. Il middleware viene aggiunto nel metodo di estensione AddDefaultAuthentication, richiamato dal metodo AddApplicationServices nella classe Program ed è illustrato nell'esempio di codice seguente dell'applicazione di riferimento eShop:

public static IServiceCollection AddDefaultAuthentication(this IHostApplicationBuilder builder)
{
    var services = builder.Services;
    var configuration = builder.Configuration;

    var identitySection = configuration.GetSection("Identity");

    if (!identitySection.Exists())
    {
        // No identity section, so no authentication
        return services;
    }

    // prevent from mapping "sub" claim to nameidentifier.
    JsonWebTokenHandler.DefaultInboundClaimTypeMap.Remove("sub");

    services.AddAuthentication().AddJwtBearer(options =>
    {
        var identityUrl = identitySection.GetRequiredValue("Url");
        var audience = identitySection.GetRequiredValue("Audience");

        options.Authority = identityUrl;
        options.RequireHttpsMetadata = false;
        options.Audience = audience;
        options.TokenValidationParameters.ValidIssuers = [identityUrl];
        options.TokenValidationParameters.ValidateAudience = false;
    });

    services.AddAuthorization();

    return services;
}

Questo metodo garantisce che l'API sia accessibile solo con un token di accesso valido. Il middleware convalida il token in ingresso per assicurarsi che venga inviato da un'autorità di certificazione attendibile e convalida che il token sia valido per essere usato con l'API che la riceve. Pertanto, l'esplorazione del controller di ordinamento o carrello restituirà un codice di stato HTTP 401 (unauthorized), a indicare che è necessario un token di accesso.

Effettuare richieste di accesso alle API

Quando si effettuano richieste ai microservizi di ordinamento e carrello, il token di accesso ottenuto da IdentityServer durante il processo di autenticazione deve essere incluso nella richiesta, come illustrato nell'esempio di codice seguente:

public async Task CreateOrderAsync(Models.Orders.Order newOrder)
{
    var authToken = await _identityService.GetAuthTokenAsync().ConfigureAwait(false);

    if (string.IsNullOrEmpty(authToken))
    {
        return;
    }

    var uri = $"{UriHelper.CombineUri(_settingsService.GatewayOrdersEndpointBase, ApiUrlBase)}?api-version=1.0";

    var success = await _requestProvider.PostAsync(uri, newOrder, authToken, "x-requestid").ConfigureAwait(false);
}

Il token di accesso viene archiviato con l'implementazione di IIdentityService e può essere recuperato usando il metodo GetAuthTokenAsync.

Analogamente, il token di accesso deve essere incluso quando si inviano dati a un'API protetta IdentityServer, come illustrato nell'esempio di codice seguente:

public async Task ClearBasketAsync()
{
    var authToken = await _identityService.GetAuthTokenAsync().ConfigureAwait(false);

    if (string.IsNullOrEmpty(authToken))
    {
        return;
    }

    await GetBasketClient().DeleteBasketAsync(new DeleteBasketRequest(), CreateAuthenticationHeaders(authToken))
        .ConfigureAwait(false);
}

Il token di accesso viene recuperato da IIdentityService e incluso nella chiamata al metodo ClearBasketAsync nella classe BasketService.

La classe RequestProvider nell'app multipiattaforma eShop usa la classe HttpClient per inviare richieste alle API RESTful esposte dall'applicazione di riferimento eShop. Quando si effettuano richieste alle API di ordinamento e carrello, che richiedono l'autorizzazione, è necessario includere un token di accesso valido nella richiesta. A tale scopo, aggiungere il token di accesso alle intestazioni dell'istanza HttpClient, come illustrato nell'esempio di codice seguente:

httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token);

La proprietà DefaultRequestHeaders della classe HttpClient espone le intestazioni inviate a ogni richiesta e il token di accesso viene aggiunto all'intestazione Authorization preceduta dalla stringa Bearer. Quando la richiesta viene inviata a un'API RESTful, il valore dell'intestazione Authorization viene estratto e convalidato per assicurarsi che venga inviato da un emittente attendibile e usato per determinare se l'utente ha l'autorizzazione per richiamare l'API che lo riceve.

Per altre informazioni su come l'app multipiattaforma eShop effettua richieste Web, vedere Accesso ai dati remoti.

Riepilogo

Esistono molti approcci per l'integrazione dell'autenticazione e dell'autorizzazione in un'app .NET MAUI che comunica con un'applicazione Web ASP.NET. L'app multipiattaforma eShop esegue l'autenticazione e l'autorizzazione con un microservizio di gestione delle identità in contenitori che usa IdentityServer. IdentityServer è un framework OpenID Connect open source e OAuth 2.0 per ASP.NET Core che si integra con ASP.NET Core Identity per eseguire l'autenticazione del token di connessione.

L'app multipiattaforma richiede token di sicurezza da IdentityServer per autenticare un utente o accedere a una risorsa. Quando si accede a una risorsa, è necessario includere un token di accesso nella richiesta alle API che richiedono l'autorizzazione. Il middleware di IdentityServer convalida i token di accesso in ingresso per assicurarsi che vengano inviati da un'autorità di certificazione attendibile e che siano validi per essere usati con l'API che li riceve.