Partilhar via


Autenticação e autorização

Gorjeta

Este conteúdo é um excerto do eBook, Enterprise Application Patterns Using .NET MAUI, disponível no .NET Docs ou como um PDF para download gratuito que pode ser lido offline.

Padrões de aplicativos corporativos usando a miniatura da capa do eBook .NET MAUI .

A autenticação é o processo de obter credenciais de identificação, como nome e senha, de um usuário e validar essas credenciais em relação a uma autoridade. A entidade que enviou as credenciais é considerada uma identidade autenticada se as credenciais forem válidas. Depois que uma identidade é estabelecida, um processo de autorização determina se essa identidade tem acesso a um determinado recurso.

Há muitas abordagens para integrar autenticação e autorização em um aplicativo .NET MAUI que se comunica com um aplicativo Web ASP.NET, incluindo o uso do ASP.NET Core Identity, provedores de autenticação externos, como Microsoft, Google, Facebook ou Twitter, e middleware de autenticação. O aplicativo multiplataforma eShop realiza autenticação e autorização com um microsserviço de identidade em contêiner que usa o IdentityServer. O aplicativo solicita tokens de segurança do IdentityServer para autenticar um usuário ou acessar um recurso. Para que o IdentityServer emita tokens em nome de um usuário, o usuário deve entrar no IdentityServer. No entanto, o IdentityServer não fornece uma interface de usuário ou banco de dados para autenticação. Portanto, no aplicativo de referência eShop, ASP.NET Core Identity é usada para essa finalidade.

Autenticação

A autenticação é necessária quando um aplicativo precisa saber a identidade do usuário atual. ASP.NET principal mecanismo do Core para identificar usuários é o sistema de associação ASP.NET Core Identity, que armazena informações do usuário em um armazenamento de dados configurado pelo desenvolvedor. Normalmente, esse armazenamento de dados será um repositório do EntityFramework, embora armazenamentos personalizados ou pacotes de terceiros possam ser usados para armazenar informações de identidade no armazenamento do Azure, no Banco de Dados de Documentos ou em outros locais.

Para cenários de autenticação que usam um armazenamento de dados de usuário local e persistem informações de identidade entre solicitações por meio de cookies (como é típico em aplicativos Web ASP.NET), ASP.NET Core Identity é uma solução adequada. No entanto, os cookies nem sempre são um meio natural de persistência e transmissão de dados. Por exemplo, um aplicativo Web ASP.NET Core que expõe pontos de extremidade RESTful acessados de um aplicativo normalmente precisará usar a autenticação de token de portador, já que os cookies não podem ser usados nesse cenário. No entanto, os tokens de portador podem ser facilmente recuperados e incluídos no cabeçalho de autorização de solicitações da web feitas a partir do aplicativo.

Emitindo tokens de portador usando o IdentityServer

O IdentityServer é uma estrutura OpenID Connect e OAuth 2.0 de código aberto para ASP.NET Core, que pode ser usada para muitos cenários de autenticação e autorização, incluindo a emissão de tokens de segurança para usuários locais ASP.NET Core Identity.

Nota

OpenID Connect e OAuth 2.0 são muito semelhantes, embora tenham responsabilidades diferentes.

OpenID Connect é uma camada de autenticação sobre o protocolo OAuth 2.0. O OAuth 2 é um protocolo que permite que aplicativos solicitem tokens de acesso de um serviço de token de segurança e os usem para se comunicar com APIs. Essa delegação reduz a complexidade em aplicativos cliente e APIs, uma vez que a autenticação e a autorização podem ser centralizadas.

O OpenID Connect e o OAuth 2.0 combinam as duas preocupações fundamentais de segurança de autenticação e acesso à API, e o IdentityServer é uma implementação desses protocolos.

Em aplicativos que usam comunicação direta cliente-microsserviço, como o aplicativo de referência eShop, um microsserviço de autenticação dedicado atuando como um STS (Serviço de Token de Segurança) pode ser usado para autenticar usuários, conforme mostrado no diagrama a seguir. Para obter mais informações sobre a comunicação direta cliente-microsserviço, consulte Microsserviços.

Autenticação por um microsserviço de autenticação dedicado.

O aplicativo multiplataforma eShop se comunica com o microsserviço de identidade, que usa o IdentityServer para executar autenticação e controle de acesso para APIs. Portanto, o aplicativo multiplataforma solicita tokens do IdentityServer, seja para autenticar um usuário ou para acessar um recurso:

  • A autenticação de usuários com o IdentityServer é obtida pelo aplicativo multiplataforma que solicita um token de identidade , representando o resultado de um processo de autenticação. No mínimo, ele contém um identificador para o usuário e informações sobre como e quando o usuário é autenticado. Também pode incluir dados de identidade adicionais.
  • O acesso a um recurso com o IdentityServer é obtido pelo aplicativo multiplataforma que solicita um token de acesso , que permite o acesso a um recurso de API. Os clientes solicitam tokens de acesso e os encaminham para a API. Os tokens de acesso contêm informações sobre o cliente e o usuário, se presentes. Em seguida, as APIs usam essas informações para autorizar o acesso aos seus dados.

Nota

Um cliente deve ser registrado com IdentityServer antes de poder solicitar tokens com êxito. Para obter mais informações sobre como adicionar clientes, consulte Definindo clientes.

Adicionando o IdentityServer a um aplicativo Web

Para que um aplicativo Web ASP.NET Core use o IdentityServer, ele deve ser adicionado à solução Visual Studio do aplicativo Web. Para obter mais informações, consulte Setup and Overview na documentação do IdentityServer. Depois que o IdentityServer é incluído na solução Visual Studio do aplicativo Web, ele deve ser adicionado ao seu pipeline de processamento de solicitações HTTP para atender solicitações aos pontos de extremidade OpenID Connect e OAuth 2.0. Isso é configurado no Identity.API Program.cs do projeto, como demonstrado no exemplo de código a seguir:


...

app.UseIdentityServer();

A ordem é importante no pipeline de processamento de solicitações HTTP do aplicativo Web. Portanto, o IdentityServer deve ser adicionado ao pipeline antes da estrutura da interface do usuário que implementa a tela de login.

Configurando o IdentityServer

IdentityServer é configurado no Identity.API Program.cs do projeto chamando o AddIdentityServer método, conforme demonstrado no exemplo de código a seguir do aplicativo de referência 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();

Depois de chamar o services.AddIdentityServer método, APIs fluentes adicionais são chamadas para configurar o seguinte:

  • Credenciais usadas para assinatura.
  • API e recursos de identidade aos quais os usuários podem solicitar acesso.
  • Clientes que estarão se conectando para solicitar tokens.
  • ASP.NET Identidade Central.

Gorjeta

Carregue dinamicamente a configuração do IdentityServer. As APIs do IdentityServer permitem configurar o IdentityServer a partir de uma lista na memória de objetos de configuração. No aplicativo de referência eShop, essas coleções na memória são codificadas no aplicativo. No entanto, em cenários de produção, eles podem ser carregados dinamicamente a partir de um arquivo de configuração ou de um banco de dados.

Para obter informações sobre como configurar o IdentityServer para usar ASP.NET identidade principal, consulte Usando ASP.NET identidade principal na documentação do IdentityServer.

Configurando recursos da API

Ao configurar recursos de API, o AddInMemoryApiResources método espera uma IEnumerable<ApiResource> coleção. O exemplo de código a seguir mostra o GetApis método que fornece essa coleção no aplicativo de referência 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"),
    };
}

Esse método especifica que o IdentityServer deve proteger as ordens e as APIs da cesta. Portanto, os tokens de acesso gerenciados pelo IdentityServer serão necessários ao fazer chamadas para essas APIs. Para obter mais informações sobre o ApiResource tipo, consulte Recurso de API na documentação do IdentityServer.

Configurando recursos de identidade

Ao configurar recursos de identidade, o AddInMemoryIdentityResources método espera uma IEnumerable<IdentityResource> coleção. Recursos de identidade são dados como ID de usuário, nome ou endereço de e-mail. Cada recurso de identidade tem um nome exclusivo e tipos de declaração arbitrários podem ser atribuídos a ele, que serão incluídos no token de identidade do usuário. O exemplo de código a seguir mostra o GetResources método que fornece essa coleção no aplicativo de referência eShop:

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

A especificação OpenID Connect especifica alguns recursos de identidade padrão. O requisito mínimo é que o suporte seja fornecido para a emissão de um ID exclusivo para os usuários. Isto é conseguido através da exposição do IdentityResources.OpenId recurso de identidade.

Nota

A classe IdentityResources suporta todos os escopos definidos na especificação OpenID Connect (openid, email, perfil, telefone e endereço).

O IdentityServer também oferece suporte à definição de recursos de identidade personalizados. Para obter mais informações, consulte Definindo recursos de identidade personalizada na documentação do IdentityServer. Para obter mais informações sobre o tipo IdentityResource, consulte Identity Resource na documentação do IdentityServer.

Configurando clientes

Os clientes são aplicativos que podem solicitar tokens do IdentityServer. Normalmente, as seguintes configurações devem ser definidas para cada cliente como um mínimo:

  • Um ID de cliente exclusivo.
  • As interações permitidas com o serviço de token (conhecido como o tipo de concessão).
  • O local para onde os tokens de identidade e acesso são enviados (conhecido como URI de redirecionamento).
  • Uma lista de recursos aos quais o cliente tem permissão de acesso (conhecidos como escopos).

Ao configurar clientes, o AddInMemoryClients método espera uma IEnumerable<Client> coleção. O exemplo de código a seguir mostra a configuração do aplicativo multiplataforma eShop no GetClients método que fornece essa coleção no aplicativo de referência 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
        }
    };
}

Esta configuração especifica dados para as seguintes propriedades:

Property Description
ClientId Um ID exclusivo para o cliente.
ClientName O nome de exibição do cliente, que é usado para registro em log e a tela de consentimento.
AllowedGrantTypes Especifica como um cliente deseja interagir com o IdentityServer. Para obter mais informações, consulte Configurando o fluxo de autenticação.
ClientSecrets Especifica as credenciais secretas do cliente que são usadas ao solicitar tokens do ponto de extremidade do token.
RedirectUris Especifica os URIs permitidos para os quais retornar tokens ou códigos de autorização.
RequireConsent Especifica se uma tela de consentimento é necessária.
RequirePkce Especifica se os clientes que usam um código de autorização devem enviar uma chave de prova.
PostLogoutRedirectUris Especifica os URIs permitidos para serem redirecionados após o logout.
AllowedCorsOrigins Especifica a origem do cliente para que o IdentityServer possa permitir chamadas de origem cruzada da origem.
AllowedScopes Especifica os recursos aos quais o cliente tem acesso. Por padrão, um cliente não tem acesso a nenhum recurso.
AllowOfflineAccess Especifica se o cliente pode solicitar tokens de atualização.
AllowAccessTokensViaBrowser Especifica se o cliente pode receber tokens de acesso de uma janela do navegador.
AlwaysIncludeUserClaimsInIdToken Especifica que as declarações de usuário sempre serão adicionadas ao token de id. Por padrão, eles teriam que ser recuperados usando o ponto de userinfo extremidade.
AccessTokenLifetime Especifica o tempo de vida do token de acesso em segundos.
IdentityTokenLifetime Especifica o tempo de vida do token de identidade em segundos.

Configurando o fluxo de autenticação

O fluxo de autenticação entre um cliente e o IdentityServer pode ser configurado especificando os tipos de concessão na Client.AllowedGrantTypes propriedade. As especificações OpenID Connect e OAuth 2.0 definem vários fluxos de autenticação, incluindo:

Fluxo de Autenticação Description
Implícito Esse fluxo é otimizado para aplicativos baseados em navegador e deve ser usado apenas para autenticação do usuário ou solicitações de token de autenticação e acesso. Todos os tokens são transmitidos através do navegador e, portanto, recursos avançados, como tokens de atualização, não são permitidos.
Código de autorização Esse fluxo fornece a capacidade de recuperar tokens em um canal traseiro, em oposição ao canal frontal do navegador, ao mesmo tempo em que oferece suporte à autenticação do cliente.
Híbrido Esse fluxo é uma combinação dos tipos de concessão de código implícito e de autorização. O token de identidade é transmitido através do canal do navegador e contém a resposta do protocolo assinado e outros artefatos, como o código de autorização. Depois de validar com êxito a resposta, o canal traseiro deve ser usado para recuperar o token de acesso e atualização.

Gorjeta

Considere usar o fluxo de autenticação híbrida. O fluxo de autenticação híbrida atenua uma série de ataques que se aplicam ao canal do navegador e é o fluxo recomendado para aplicativos nativos que desejam recuperar tokens de acesso (e possivelmente atualizar tokens).

Para obter mais informações sobre fluxos de autenticação, consulte Tipos de concessão na documentação do IdentityServer.

Executando a autenticação

Para que o IdentityServer emita tokens em nome de um usuário, o usuário deve entrar no IdentityServer. No entanto, o IdentityServer não fornece uma interface de usuário ou banco de dados para autenticação. Portanto, no aplicativo de referência eShop, ASP.NET Core Identity é usada para essa finalidade.

O aplicativo multiplataforma eShop é autenticado com o IdentityServer com o fluxo de autenticação híbrida, que é ilustrado no diagrama abaixo.

Visão geral de alto nível do processo de login.

Uma solicitação de login é feita para <base endpoint>:5105/connect/authorize. Após a autenticação bem-sucedida, o IdentityServer retorna uma resposta de autenticação contendo um código de autorização e um token de identidade. O código de autorização é enviado para o <base endpoint>:5105/connect/token, que responde com tokens de acesso, identidade e atualização.

O aplicativo multiplataforma eShop sai do IdentityServer enviando uma solicitação para <base endpoint>:5105/connect/endsession com parâmetros adicionais. Após a saída, o IdentityServer responde enviando um redirecionamento pós-logout do URI de volta para o aplicativo multiplataforma. O diagrama abaixo ilustra este processo.

Visão geral de alto nível do processo de saída.

No aplicativo multiplataforma eShop, a comunicação com o IdentityService IdentityServer é realizada pela classe, que implementa a IIdentityService interface. Essa interface especifica que a classe de implementação deve fornecer SignInAsync, GetUserInfoAsync SignOutAsynce GetAuthTokenAsync métodos.

Iniciar sessão

Quando o usuário toca no LOGIN botão no LoginView, o SignInCommand na classe in é LoginViewModel executado, que por sua vez executa o SignInAsync método. O exemplo de código a seguir mostra esse método:

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

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

Esse método invoca o SignInAsync IdentityService método na classe, como mostrado no exemplo de código a seguir:

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

O IdentityService faz uso do OidcClient fornecido com o IdentityModel.OidcClient pacote NuGet. Esse cliente exibe a exibição da Web de autenticação para o usuário no aplicativo e captura o resultado da autenticação. O cliente se conecta ao URI do ponto de extremidade de autorização do IdentityServer com os parâmetros necessários. O ponto de extremidade de autorização está na /connect/authorize porta 5105 do ponto de extremidade base exposto como uma configuração de usuário. Para obter mais informações sobre as configurações do usuário, consulte Gerenciamento de configuração.

Nota

A superfície de ataque do aplicativo multiplataforma eShop é reduzida com a implementação da extensão PKCE (Proof Key for Code Exchange) para OAuth. PKCE protege o código de autorização de ser usado se for intercetado. Isso é conseguido pelo cliente gerando um verificador secreto, cujo hash é passado na solicitação de autorização e que é apresentado sem hash ao resgatar o código de autorização. Para obter mais informações sobre PKCE, consulte Proof Key for Code Exchange by OAuth Public Clients no site da Internet Engineering Task Force.

Página de login exibida pelo WebView.

Se o ponto de extremidade do token receber informações de autenticação válidas, código de autorização e verificador secreto PKCE, ele responderá com um token de acesso, token de identidade e token de atualização. O token de acesso (que permite o acesso aos recursos da API) e o token de identidade são armazenados como configurações do aplicativo e a navegação na página é executada. Portanto, o efeito geral no aplicativo multiplataforma eShop é o seguinte: desde que os usuários sejam capazes de se autenticar com êxito com o IdentityServer, eles são navegados até a //Main/Catalog rota, que é uma TabbedPage guia que exibe a CatalogView guia como selecionada.

Para obter informações sobre navegação de página, consulte Navegação. Para obter informações sobre como a navegação WebView faz com que um método de modelo de exibição seja executado, consulte Invocando a navegação usando comportamentos. Para obter informações sobre as configurações do aplicativo, consulte Gerenciamento de configuração.

Nota

A eShop também permite um login simulado quando o aplicativo está configurado para usar serviços simulados no SettingsView. Nesse modo, o aplicativo não se comunica com o IdentityServer, permitindo que o usuário entre usando quaisquer credenciais.

Saída

Quando o usuário toca LOG OUT no botão no ProfileView, o LogoutCommand na classe in é ProfileViewModel executado, o que executa o LogoutAsync método. Esse método executa a navegação de página para a LoginView página, passando um Logout parâmetro de consulta definido como true.

Esse parâmetro é avaliado no ApplyQueryAttributes método. Se o Logout parâmetro estiver presente com um true valor, o PerformLogoutAsync método da classe será executado, o que é mostrado no exemplo de LoginViewModel código a seguir:

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

    _settingsService.UseFakeLocation = false;

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

Esse método invoca o SignOutAsync IdentityService método na classe, que invoca o OidcClient para encerrar a sessão do usuário e limpa todos os tokens de usuário salvos. Para obter mais informações sobre as configurações do aplicativo, consulte Gerenciamento de configuração. O exemplo de código a seguir mostra o SignOutAsync método:

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

Esse método usa o OidcClient para chamar o URI para o ponto de extremidade da sessão final do IdentityServer com os parâmetros necessários. O ponto de extremidade da sessão final está na /connect/endsession porta 5105 do ponto de extremidade base exposto como uma configuração de usuário. Depois que o usuário tiver saído com êxito, LoginView for apresentado ao usuário e todas as informações salvas do usuário serão limpas.

Para obter informações sobre navegação de página, consulte Navegação. Para obter informações sobre como WebView a navegação faz com que um método de modelo de exibição seja executado, consulte Invocando a navegação usando comportamentos. Para obter informações sobre as configurações do aplicativo, consulte Gerenciamento de configuração.

Nota

A eShop também permite uma saída simulada quando o aplicativo está configurado para usar serviços simulados no SettingsView. Nesse modo, o aplicativo não se comunica com o IdentityServer e, em vez disso, limpa todos os tokens armazenados das configurações do aplicativo.

Autorização

Após a autenticação, as APIs Web ASP.NET Core geralmente precisam autorizar o acesso, o que permite que um serviço disponibilize APIs para alguns usuários autenticados, mas não para todos.

A restrição de acesso a uma rota ASP.NET Core pode ser obtida aplicando um atributo Authorize a um controlador ou ação, que limita o acesso ao controlador ou ação a usuários autenticados, conforme mostrado no exemplo de código a seguir:

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

Se um usuário não autorizado tentar acessar um controlador ou ação marcada com o atributo Authorization, a estrutura da API retornará um 401 (unauthorized) código de status HTTP.

Nota

Os parâmetros podem ser especificados no atributo Authorize para restringir uma API a usuários específicos. Para obter mais informações, consulte ASP.NET Core Docs: Authorization.

O IdentityServer pode ser integrado ao fluxo de trabalho de autorização para que os tokens de acesso forneçam autorização de controle. Esta abordagem é mostrada no diagrama abaixo.

Autorização por token de acesso.

O aplicativo multiplataforma eShop se comunica com o microsserviço de identidade e solicita um token de acesso como parte do processo de autenticação. O token de acesso é então encaminhado para as APIs expostas pelos microsserviços de pedido e cesta como parte das solicitações de acesso. Os tokens de acesso contêm informações sobre o cliente e o usuário. Em seguida, as APIs usam essas informações para autorizar o acesso aos seus dados. Para obter informações sobre como configurar o IdentityServer para proteger APIs, consulte Configurando recursos de API.

Configurando o IdentityServer para executar a autorização

Para executar a autorização com o IdentityServer, seu middleware de autorização deve ser adicionado ao pipeline de solicitação HTTP do aplicativo Web. O middleware é adicionado no AddDefaultAuthentication método extension, que é invocado a AddApplicationServices partir do método na Program classe e é demonstrado no exemplo de código a seguir do aplicativo de referência 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;
}

Esse método garante que a API só possa ser acessada com um token de acesso válido. O middleware valida o token de entrada para garantir que ele seja enviado de um emissor confiável e valida se o token é válido para ser usado com a API que o recebe. Portanto, navegar até o controlador de pedido ou cesta retornará um 401 (unauthorized) código de status HTTP, indicando que um token de acesso é necessário.

Fazendo solicitações de acesso a APIs

Ao fazer solicitações para os microsserviços de pedido e cesto, o token de acesso obtido do IdentityServer durante o processo de autenticação deve ser incluído na solicitação, conforme mostrado no exemplo de código a seguir:

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

O token de acesso é armazenado com a implementação e pode ser recuperado IIdentityService usando o GetAuthTokenAsync método.

Da mesma forma, o token de acesso deve ser incluído ao enviar dados para uma API protegida pelo IdentityServer, conforme mostrado no exemplo de código a seguir:

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

O token de acesso é recuperado do IIdentityService e incluído na chamada para o ClearBasketAsync método na BasketService classe.

A RequestProvider classe no aplicativo multiplataforma eShop usa a HttpClient classe para fazer solicitações às APIs RESTful expostas pelo aplicativo de referência eShop. Ao fazer solicitações para as APIs de pedido e cesta, que exigem autorização, um token de acesso válido deve ser incluído com a solicitação. Isso é conseguido adicionando o token de acesso aos cabeçalhos da instância HttpClient, conforme demonstrado no exemplo de código a seguir:

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

A DefaultRequestHeaders propriedade da classe expõe os cabeçalhos que são enviados com cada solicitação, e o token de acesso é adicionado ao Authorization cabeçalho prefixado com a cadeia de HttpClient caracteres Bearer. Quando a solicitação é enviada para uma API RESTful, o valor do cabeçalho é extraído Authorization e validado para garantir que seja enviado de um emissor confiável e usado para determinar se o usuário tem permissão para invocar a API que o recebe.

Para obter mais informações sobre como o aplicativo multiplataforma eShop faz solicitações da Web, consulte Acessando dados remotos.

Resumo

Há muitas abordagens para integrar autenticação e autorização em um aplicativo .NET MAUI que se comunica com um aplicativo Web ASP.NET. O aplicativo multiplataforma eShop realiza autenticação e autorização com um microsserviço de identidade em contêiner que usa o IdentityServer. O IdentityServer é uma estrutura OpenID Connect e OAuth 2.0 de código aberto para ASP.NET Core que se integra com ASP.NET Core Identity para executar a autenticação de token de portador.

O aplicativo multiplataforma solicita tokens de segurança do IdentityServer para autenticar um usuário ou acessar um recurso. Ao acessar um recurso, um token de acesso deve ser incluído na solicitação para APIs que exigem autorização. O middleware do IdentityServer valida tokens de acesso de entrada para garantir que eles sejam enviados de um emissor confiável e que sejam válidos para serem usados com a API que os recebe.