Compartilhar via


Proteger um aplicativo Blazor WebAssembly ASP.NET Core hospedado como Microsoft Entra ID

Este artigo explica como criar uma solução Blazor WebAssembly hospedada que usa o Microsoft Entra ID (ME-ID) para autenticação. Este artigo se concentra em um único aplicativo de locatário com um registro de aplicativo do Azure de locatário único.

Este artigo não aborda um registro ME-ID multilocatário. Para obter mais informações, confira Como tornar seu aplicativo multilocatário.

Este artigo se concentra no uso de um locatário do Microsoft Entra, conforme descrito no Início Rápido: Configurar um locatário. Se o aplicativo estiver registrado em um locatário do Azure Active Directory B2C, conforme descrito no Tutorial: Criar um locatário do Azure Active Directory B2C, mas seguir as diretrizes neste artigo, o URI da ID do Aplicativo será gerenciado de forma diferente pelo ME-ID. Para obter mais informações, confira a seção Uso de um locatário do Azure Active Directory B2C deste artigo.

Para obter cobertura adicional do cenário de segurança depois de ler este artigo, confira Cenários de segurança adicional do Blazor WebAssembly ASP.NET Core.

Passo a passo

As subseções do passo a passo explicam como:

  • Criar um locatário no Azure
  • Registrar um aplicativo de API do servidor no Azure
  • Registrar um aplicativo cliente no Azure
  • Criar o aplicativo Blazor
  • Modifique a configuração Server appsettings.json
  • Modificar o esquema padrão de escopo de token de acesso
  • Executar o aplicativo

Criar um locatário no Azure

Siga as diretrizes no Início rápido: Configurar um locatário para criar um locatário no ME-ID.

Registrar um aplicativo de API do servidor no Azure

Registre um aplicativo ME-ID para o Aplicativo de API do servidor:

  1. Navegue até o Microsoft Entra ID no portal do Azure. Selecione Aplicativos>Registros de aplicativo na barra lateral. Selecione o botão Novo registro.
  2. Dê um Nome ao aplicativo (por exemplo, Blazor Server ME-ID).
  3. Escolha um Tipo de conta com suporte. Você pode selecionar Contas somente neste diretório organizacional (locatário único) para essa experiência.
  4. O Aplicativo de API do servidor não requer um URI de redirecionamento nesse cenário, portanto, deixe a lista suspensa Selecionar uma plataforma desmarcada e não insira um URI de redirecionamento.
  5. Este artigo pressupõe que o aplicativo esteja registrado em um locatário do Microsoft Entra. Se o aplicativo estiver registrado em um locatário do Azure Active Directory B2C, a caixa de seleção Permissões>Conceder consentimento do administrador para as permissões openid e offline_access estará presente e selecionada. Desmarque a caixa de seleção para desabilitar a configuração. Ao usar um locatário do Active Azure Directory, a caixa de seleção não estará presente.
  6. Selecione Registrar.

Registre as seguintes informações:

  • Aplicativo de API do Servidor ID do aplicativo (cliente) (por exemplo, 00001111-aaaa-2222-bbbb-3333cccc4444)
  • ID do diretório (locatário) (por exemplo, aaaabbbb-0000-cccc-1111-dddd2222eeee)
  • Domínio primário/de editor/de locatário do ME-ID (por exemplo, contoso.onmicrosoft.com): o domínio está disponível como o Domínio do editor na folha Identidade visual do portal do Azure para o aplicativo registrado.

Em Permissões de API, remova a permissãoUser.Read> do Microsoft Graph, pois o aplicativo de API do servidor não requer acesso adicional à API para simplesmente entrar em usuários e chamar pontos de extremidade da API do servidor.

Em Expor uma API:

  1. Confirme ou adicione o URI da ID do Aplicativo no formato api://{SERVER API APP CLIENT ID}.
  2. Selecione Adicionar um escopo.
  3. Selecione Salvar e continuar.
  4. Forneça um Nome de escopo (por exemplo, API.Access).
  5. Forneça um Nome de exibição de consentimento do administrador (por exemplo, Access API).
  6. Forneça uma Descrição de consentimento do administrador (por exemplo, Allows the app to access server app API endpoints.).
  7. Confirme se o Estado está definido como Habilitado.
  8. Selecione Adicionar escopo.

Registre as seguintes informações:

  • GUID de URI da ID do Aplicativo (por exemplo, registro 00001111-aaaa-2222-bbbb-3333cccc4444 do URI da ID do Aplicativo de api://00001111-aaaa-2222-bbbb-3333cccc4444)
  • Nome do escopo (por exemplo, API.Access)

Importante

Se um valor personalizado for usado para o URI da ID do Aplicativo, as alterações de configuração serão necessárias para os aplicativos Server e Client após a criação dos aplicativos a partir do modelo de projeto Blazor WebAssembly. Para obter mais informações, confira a seção Uso de um URI da ID de Aplicativo personalizado.

Registrar um aplicativo cliente no Azure

Registre um aplicativo ME-ID para o Aplicativo cliente:

  1. Navegue até o Microsoft Entra ID no portal do Azure. Selecione Registros de aplicativo na barra lateral. Selecione o botão Novo registro.
  2. Dê um Nome ao aplicativo (por exemplo, Blazor Cliente ME-ID).
  3. Escolha um Tipo de conta com suporte. Você pode selecionar Contas somente neste diretório organizacional (locatário único) para essa experiência.
  4. Defina a lista suspensa de URI de Redirecionamento como SPA (aplicativo de página única) e forneça o seguinte URI de redirecionamento: https://localhost/authentication/login-callback. Se você souber o URI de redirecionamento da produção do host padrão do Azure (por exemplo, azurewebsites.net) ou o host de domínio personalizado (por exemplo, contoso.com), também poderá adicionar o URI de redirecionamento de produção ao mesmo tempo em que fornece o URI de redirecionamento localhost. Certifique-se de incluir o número da porta para portas não :443 em URIs de redirecionamento da produção que você vá adicionar.
  5. Este artigo pressupõe que o aplicativo esteja registrado em um locatário do Microsoft Entra. Se o aplicativo estiver registrado em um locatário do Azure Active Directory B2C, a caixa de seleção Permissões>Conceder consentimento do administrador para as permissões openid e offline_access estará presente e selecionada. Desmarque a caixa de seleção para desabilitar a configuração. Ao usar um locatário do Active Azure Directory, a caixa de seleção não estará presente.
  6. Selecione Registrar.

Observação

Não é necessário fornecer o número da porta para um URI de redirecionamento do ME-ID localhost. Para obter mais informações, consulte restrições e limitações do URI de redirecionamento (URL de resposta): exceções de localhost (documentação do Entra).

Registre o ID do aplicativo Client(cliente) (por exemplo, 11112222-bbbb-3333-cccc-4444dddd5555).

Em Autenticação>Configurações da plataforma>Aplicativo de página única:

  1. Confirme se o URI de redirecionamento de https://localhost/authentication/login-callback está presente.
  2. Na seção Concessão implícita, verifique se as caixas de seleção Tokens de acesso e Tokens de ID não estão marcadas. A concessão implícita não é recomendada para aplicativos Blazor que usam MSAL v2.0 ou posterior. Para obter mais informações, confira Proteger o ASP.NET Core Blazor WebAssembly.
  3. Os padrões restantes para o aplicativo são aceitáveis para essa experiência.
  4. Selecione o botão Salvar se você fez alterações.

Em Permissões de API:

  1. Confirme se o aplicativo tem a permissão User.Read> do Microsoft Graph.
  2. Selecione Adicionar uma permissão seguida por Minhas APIs.
  3. Selecione o Aplicativo de API do servidor na coluna Nome (por exemplo, Blazor Server ME-ID). Você deve ser um proprietário do registro do aplicativo (e do registro do aplicativo da API, se esta for um aplicativo separado) para ver a API na área Minhas APIs do portal do Azure. Para obter mais informações, confira Atribuir um proprietário do aplicativo (documentação do Microsoft Entra).
  4. Abra a lista de API .
  5. Habilitar o acesso à API (por exemplo, API.Access).
  6. Selecione Adicionar permissões.
  7. Selecione o botão Conceder consentimento do administrador para {NOME DO LOCATÁRIO}. Clique em Sim para confirmar.

Importante

Se você não tiver autoridade para conceder consentimento de administrador ao locatário na última etapa da configuração de Permissões de API porque o consentimento para usar o aplicativo é delegado aos usuários, você deve seguir as seguintes etapas adicionais:

  • O aplicativo deve usar um domínio de editor confiável.
  • Server Na configuração do aplicativo no portal do Azure, selecione Expor uma API. Em Aplicativos de cliente autorizados, selecione Adicionar um aplicativo cliente. Registre o ID do aplicativo (cliente) Client(por exemplo, 11112222-bbbb-3333-cccc-4444dddd5555).

Criar o aplicativo Blazor

Em uma pasta vazia, substitua os espaços reservados no comando a seguir pelas informações registradas anteriormente e execute o seguinte comando em um shell de comando:

dotnet new blazorwasm -au SingleOrg --api-client-id "{SERVER API APP CLIENT ID}" --app-id-uri "{SERVER API APP ID URI GUID}" --client-id "{CLIENT APP CLIENT ID}" --default-scope "{DEFAULT SCOPE}" --domain "{TENANT DOMAIN}" -ho -o {PROJECT NAME} --tenant-id "{TENANT ID}"

Aviso

Evite usar traços (-) no nome do aplicativo {PROJECT NAME} que interrompem a formação do identificador de aplicativo OIDC. A lógica no modelo de projeto Blazor WebAssembly usa o nome do projeto para um identificador de aplicativo OIDC na configuração da solução. Caso Pascal (BlazorSample) ou sublinhados (Blazor_Sample) são alternativas aceitáveis. Para obter mais informações, consulte Traços em um nome de projeto Blazor WebAssembly hospedado interrompem a segurança do OIDC (dotnet/aspnetcore #35337).

Espaço reservado Nome do portal do Azure Exemplo
{PROJECT NAME} BlazorSample
{CLIENT APP CLIENT ID} ID do aplicativo (cliente) para o aplicativo Client 11112222-bbbb-3333-cccc-4444dddd5555
{DEFAULT SCOPE} Nome do escopo API.Access
{SERVER API APP CLIENT ID} ID do aplicativo (cliente) para o Aplicativo de API do Servidor 00001111-aaaa-2222-bbbb-3333cccc4444
{SERVER API APP ID URI GUID} GUID de URI da ID do Aplicativo 00001111-aaaa-2222-bbbb-3333cccc4444 (GUID ONLY, corresponde ao {SERVER API APP CLIENT ID})
{TENANT DOMAIN} Domínio primário/de editor/de locatário contoso.onmicrosoft.com
{TENANT ID} ID do diretório (locatário) aaaabbbb-0000-cccc-1111-dddd2222eeee

A localização de saída especificada com a opção -o|--output criará uma pasta de projeto, se ela não existir, e se tornará parte do nome do projeto. Evite usar traços (-) no nome do aplicativo que interrompem a formação do identificador de aplicativo OIDC (consulte o AVISO anterior).

Importante

Se um valor personalizado for usado para o URI da ID do Aplicativo, as alterações de configuração serão necessárias para os aplicativos Server e Client após a criação dos aplicativos a partir do modelo de projeto Blazor WebAssembly. Para obter mais informações, confira a seção Uso de um URI da ID de Aplicativo personalizado.

Executar o aplicativo

Execute o aplicativo no projeto Server. Ao usar também o Visual Studio:

  • Selecione a seta suspensa ao lado do botão Executar . Abra Configurar Projetos de Inicialização na lista suspensa. Selecione a opção Projeto de inicialização única. Confirme ou altere o projeto do projeto de inicialização para o projeto Server.

  • Confirme se o Server projeto está realçado em Gerenciador de Soluções antes de iniciar o aplicativo com qualquer uma das seguintes abordagens:

    • Selecione o botão Executar.
    • Use Depurar>Iniciar Depuração no menu.
    • Pressione F5.
  • Em um shell de comando, navegue até a Server pasta do projeto da solução. Execute o comando dotnet watch (ou dotnet run).

configurar User.Identity.Name

As diretrizes nesta seção abrangem, opcionalmente, o preenchimento User.Identity.Name com o valor da name declaração.

A API do aplicativo Server preenche User.Identity.Name com o valor do tipo de declaração http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name (por exemplo, bbbb0000-cccc-1111-dddd-2222eeee3333@contoso.onmicrosoft.com).

Para configurar o aplicativo para receber o valor do tipo de declaração name :

Partes da solução

Esta seção descreve as partes de uma solução gerada a partir do modelo de projeto Blazor WebAssembly e descreve como os projetos Client e Server da solução são configurados para referência. Não há diretrizes específicas a serem seguidas nesta seção para um aplicativo de trabalho básico se você criou o aplicativo usando as diretrizes na seção Passo a passo. As diretrizes nesta seção são úteis para atualizar um aplicativo para autenticar e autorizar usuários. No entanto, uma abordagem alternativa para atualizar um aplicativo é criar um novo aplicativo a partir das diretrizes na seção Passo a passo e mover os componentes, classes e recursos do aplicativo para o novo aplicativo.

Configuração de appsettings.json

Esta seção pertence ao aplicativo Server da solução.

O arquivo appsettings.json contém as opções para configurar o manipulador de portador JWT usado para validar tokens de acesso. Adicione a seguinte seção de configuração AzureAd:

{
  "AzureAd": {
    "Instance": "https://login.microsoftonline.com/",
    "Domain": "{TENANT DOMAIN}",
    "TenantId": "{TENANT ID}",
    "ClientId": "{SERVER API APP CLIENT ID}",
    "CallbackPath": "/signin-oidc",
    "Scopes": "{SCOPES}"
  }
}

Exemplo:

{
  "AzureAd": {
    "Instance": "https://login.microsoftonline.com/",
    "Domain": "contoso.onmicrosoft.com",
    "TenantId": "aaaabbbb-0000-cccc-1111-dddd2222eeee",
    "ClientId": "00001111-aaaa-2222-bbbb-3333cccc4444",
    "CallbackPath": "/signin-oidc",
    "Scopes": "API.Access"
  }
}

Importante

Se o aplicativo Server estiver registrado para usar um URI da ID do Aplicativo personalizado no ME-ID (não no formato api://{SERVER API APP CLIENT ID}padrão), confira a seção Uso de um URI da ID do Aplicativo personalizado. As alterações são necessárias nos aplicativos Server e Client.

Pacote de autenticação

Esta seção pertence ao aplicativo Server da solução.

O suporte para autenticar e autorizar chamadas para ASP.NET APIs Web principais com a plataforma Microsoft identity é fornecido pelo Microsoft.Identity.Web pacote.

Observação

Para obter diretrizes sobre como adicionar pacotes a aplicativos .NET, consulte os artigos em Instalar e gerenciar pacotes no Fluxo de trabalho de consumo de pacotes (documentação do NuGet). Confirme as versões corretas de pacote em NuGet.org.

O aplicativo Server de uma solução hospedada Blazor criada a partir do modelo Blazor WebAssembly inclui o pacote Microsoft.Identity.Web.UI. O pacote adiciona a interface do usuário para autenticação de usuário em aplicativos Web e não é usado pela estrutura Blazor. Se o aplicativo Server não for usado para autenticar os usuários diretamente, é seguro remover a referência do pacote do arquivo de projeto do aplicativo Server.

Suporte ao serviço de autenticação

Esta seção pertence ao aplicativo Server da solução.

O método AddAuthentication configura os serviços de autenticação no aplicativo e configura o manipulador de Portador JWT como o método de autenticação padrão. O AddMicrosoftIdentityWebApi método configura serviços para proteger a API Web com a plataforma Microsoft identity v2.0. Esse método espera uma seção AzureAd na configuração do aplicativo com as configurações necessárias para inicializar as opções de autenticação.

builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
    .AddMicrosoftIdentityWebApi(Configuration.GetSection("AzureAd"));

Observação

Quando um único esquema de autenticação é registrado, o esquema de autenticação é usado automaticamente como o esquema padrão do aplicativo e não é necessário declarar o esquema para AddAuthentication ou por meio de AuthenticationOptions. Para obter mais informações, consulte Visão geral da Autenticação ASP.NET Core e o comunicado de ASP.NET Core (aspnet/Announcements #490).

UseAuthentication e UseAuthorization verifique se:

  • O aplicativo tenta analisar e validar tokens em solicitações de entrada.
  • Qualquer solicitação que tente acessar um recurso protegido sem credenciais adequadas falhará.
app.UseAuthentication();
app.UseAuthorization();

Controlador WeatherForecast

Esta seção pertence ao aplicativo Server da solução.

O controlador WeatherForecast (Controllers/WeatherForecastController.cs) expõe uma API protegida com o atributo [Authorize] aplicado ao controlador. É importante entender que:

  • O atributo [Authorize] nesse controlador de API é a única coisa que protege essa API contra acesso não autorizado.
  • O atributo [Authorize] usado no aplicativo Blazor WebAssembly serve apenas como uma dica para o aplicativo de que o usuário deve ser autorizado para que o aplicativo funcione corretamente.
[Authorize]
[ApiController]
[Route("[controller]")]
[RequiredScope(RequiredScopesConfigurationKey = "AzureAd:Scopes")]
public class WeatherForecastController : ControllerBase
{
    [HttpGet]
    public IEnumerable<WeatherForecast> Get()
    {
        ...
    }
}

Configuração de wwwroot/appsettings.json

Esta seção pertence ao aplicativo Client da solução.

A configuração é fornecida pelo arquivo wwwroot/appsettings.json:

{
  "AzureAd": {
    "Authority": "https://login.microsoftonline.com/{TENANT ID}",
    "ClientId": "{CLIENT APP CLIENT ID}",
    "ValidateAuthority": true
  }
}

Exemplo:

{
  "AzureAd": {
    "Authority": "https://login.microsoftonline.com/e86c78e2-...-918e0565a45e",
    "ClientId": "11112222-bbbb-3333-cccc-4444dddd5555",
    "ValidateAuthority": true
  }
}

Pacote de autenticação

Esta seção pertence ao aplicativo Client da solução.

Quando um aplicativo é criado para usar contas corporativas ou de estudante (SingleOrg), o aplicativo recebe automaticamente uma referência de pacote para a Biblioteca de Autenticação da Microsoft (Microsoft.Authentication.WebAssembly.Msal). O pacote fornece um conjunto de primitivos que ajudam o aplicativo a autenticar usuários e obter tokens para chamar APIs protegidas.

Se for adicionar autenticação a um aplicativo, adicione manualmente o pacote Microsoft.Authentication.WebAssembly.Msal ao aplicativo.

Observação

Para obter diretrizes sobre como adicionar pacotes a aplicativos .NET, consulte os artigos em Instalar e gerenciar pacotes no Fluxo de trabalho de consumo de pacotes (documentação do NuGet). Confirme as versões corretas de pacote em NuGet.org.

O pacote Microsoft.Authentication.WebAssembly.Msal adiciona transitivamente o pacote Microsoft.AspNetCore.Components.WebAssembly.Authentication ao aplicativo.

Suporte ao serviço de autenticação

Esta seção pertence ao aplicativo Client da solução.

É adicionado suporte para instâncias HttpClient que incluem tokens de acesso ao fazer solicitações ao aplicativo Server.

No arquivo Program:

builder.Services.AddHttpClient("{PROJECT NAME}.ServerAPI", client => 
        client.BaseAddress = new Uri(builder.HostEnvironment.BaseAddress))
    .AddHttpMessageHandler<BaseAddressAuthorizationMessageHandler>();

builder.Services.AddScoped(sp => sp.GetRequiredService<IHttpClientFactory>()
    .CreateClient("{PROJECT NAME}.ServerAPI"));

O espaço reservado {PROJECT NAME} é o nome do projeto na criação da solução. Fornecer um nome de projeto BlazorSample, por exemplo, produz um HttpClient nomeado de BlazorSample.ServerAPI.

O suporte à autenticação de usuários é registrado no contêiner de serviço com o método de extensão AddMsalAuthentication fornecido pelo pacote Microsoft.Authentication.WebAssembly.Msal. Esse método configura os serviços necessários para que o aplicativo interaja com o Provedor Identity (IP).

No arquivo Program:

builder.Services.AddMsalAuthentication(options =>
{
    builder.Configuration.Bind("AzureAd", options.ProviderOptions.Authentication);
    options.ProviderOptions.DefaultAccessTokenScopes.Add("{SCOPE URI}");
});

O método AddMsalAuthentication aceita um retorno de chamada para configurar os parâmetros necessários para autenticar um aplicativo. Os valores necessários para configurar o aplicativo podem ser obtidos na configuração do ID ME do Portal do Azure ao registrar o aplicativo.

Escopos do token de acesso

Esta seção pertence ao aplicativo Client da solução.

Os escopos de token de acesso padrão representam a lista de escopos de token de acesso que são:

  • Incluído na solicitação de entrada.
  • Usado para provisionar um token de acesso imediatamente após a autenticação.

Escopos adicionais podem ser adicionados, conforme necessário, ao arquivo Program:

builder.Services.AddMsalAuthentication(options =>
{
    ...
    options.ProviderOptions.DefaultAccessTokenScopes.Add("{SCOPE URI}");
});

Especifique escopos adicionais com AdditionalScopesToConsent:

options.ProviderOptions.AdditionalScopesToConsent.Add("{ADDITIONAL SCOPE URI}");

Observação

A AdditionalScopesToConsent não consegue provisionar permissões de usuário delegadas para o Microsoft Graph por meio da interface de consentimento do Microsoft Entra ID quando um usuário usa pela primeira vez um aplicativo registrado no Microsoft Azure. Para obter mais informações, consulte Usar a API do Graph com o ASP.NET Core Blazor WebAssembly.

Exemplo de escopo de token de acesso padrão:

options.ProviderOptions.DefaultAccessTokenScopes.Add(
    "api://00001111-aaaa-2222-bbbb-3333cccc4444/API.Access");

Para obter mais informações, confira as seções a seguir do artigo Cenários adicionais:

Modo de logon

Esta seção pertence ao aplicativo Client da solução.

A estrutura usa como padrão o modo de logon pop-up e volta para o modo de logon de redirecionamento quando um pop-up não pode ser aberto. Configure a MSAL para usar o modo de logon de redirecionamento definindo a propriedade LoginMode de MsalProviderOptions como redirect:

builder.Services.AddMsalAuthentication(options =>
{
    ...
    options.ProviderOptions.LoginMode = "redirect";
});

A configuração padrão é popup, e o valor da cadeia de caracteres não diferencia maiúsculas de minúsculas.

Importa o arquivo

Esta seção pertence ao aplicativo Client da solução.

O namespace Microsoft.AspNetCore.Components.Authorization é disponibilizado em todo o aplicativo por meio do arquivo _Imports.razor:

@using System.Net.Http
@using System.Net.Http.Json
@using Microsoft.AspNetCore.Components.Authorization
@using Microsoft.AspNetCore.Components.Forms
@using Microsoft.AspNetCore.Components.Routing
@using Microsoft.AspNetCore.Components.Web
@using Microsoft.AspNetCore.Components.Web.Virtualization
@using Microsoft.AspNetCore.Components.WebAssembly.Http
@using Microsoft.JSInterop
@using {APPLICATION ASSEMBLY}
@using {APPLICATION ASSEMBLY}.Shared

Página de índice

Esta seção pertence ao aplicativo Client da solução.

A página Índice (wwwroot/index.html) inclui um script que define o AuthenticationService em JavaScript. O AuthenticationService manipula os detalhes de baixo nível do protocolo OIDC. O aplicativo chama internamente métodos definidos no script para executar as operações de autenticação.

<script src="_content/Microsoft.Authentication.WebAssembly.Msal/AuthenticationService.js"></script>

Componente do aplicativo

Esta seção pertence ao aplicativo Client da solução.

O componente App (App.razor) é semelhante ao componente App encontrado em aplicativos Blazor Server:

  • O componente CascadingAuthenticationState gerencia a exposição do AuthenticationState ao rest do aplicativo.
  • O componente AuthorizeRouteView garante que o usuário atual esteja autorizado a acessar uma determinada página ou renderize o componente RedirectToLogin.
  • O componente RedirectToLogin gerencia o redirecionamento de usuários não autorizados para a página de logon.

Devido a alterações na estrutura em versões do ASP.NET Core, a marcação do Razor para o componente App (App.razor) não é mostrada nesta seção. Para inspecionar a marcação do componente para uma determinada versão, use uma das seguintes abordagens:

  • Crie um aplicativo provisionado para autenticação do modelo de projeto padrão do Blazor WebAssembly para a versão do ASP.NET Core que você pretende usar. Inspecione o componente App (App.razor) no aplicativo gerado.

  • Inspecione o componente App (App.razor) na fonte de referência. Selecione a versão do seletor de ramificação e pesquise o componente na pasta ProjectTemplates do repositório porque o local do componente App foi alterado ao longo dos anos.

    Observação

    Os links de documentação para a fonte de referência do .NET geralmente carregam o branch padrão do repositório, que representa o desenvolvimento atual da próxima versão do .NET. Para selecionar uma marca para uma versão específica, use a lista suspensa para Alternar branches ou marcas. Para saber mais, confira Como selecionar uma marca de versão do código-fonte do ASP.NET Core (dotnet/AspNetCore.Docs #26205).

Componente RedirectToLogin

Esta seção pertence ao aplicativo Client da solução.

O componente RedirectToLogin (RedirectToLogin.razor):

  • Gerencia o redirecionamento de usuários não autorizados para a página de logon.
  • A URL atual que o usuário está tentando acessar é mantida para que ele possa ser retornado a essa página se a autenticação for bem-sucedida usando:

Inspecione o componente RedirectToLogin na fonte de referência. O local do componente mudou com o tempo, portanto, portanto, use as ferramentas de pesquisa do GitHub para localizar o componente.

Observação

Os links de documentação para a fonte de referência do .NET geralmente carregam o branch padrão do repositório, que representa o desenvolvimento atual da próxima versão do .NET. Para selecionar uma marca para uma versão específica, use a lista suspensa para Alternar branches ou marcas. Para saber mais, confira Como selecionar uma marca de versão do código-fonte do ASP.NET Core (dotnet/AspNetCore.Docs #26205).

Componente LoginDisplay

Esta seção pertence ao aplicativo Client da solução.

O componente LoginDisplay (LoginDisplay.razor) é renderizado no componente MainLayout (MainLayout.razor) e gerencia os seguintes comportamentos:

  • Para usuários autenticados:
    • Exibe o nome de usuário atual.
    • Oferece um link para a página de perfil do usuário na Identity do ASP.NET Core.
    • Oferece um botão para sair do aplicativo.
  • Para usuários anônimos:
    • Oferece a opção de se registrar.
    • Oferece a opção de fazer logon.

Devido a alterações na estrutura em versões do ASP.NET Core, a marcação do Razor para o componente LoginDisplay não é mostrada nesta seção. Para inspecionar a marcação do componente para uma determinada versão, use uma das seguintes abordagens:

  • Crie um aplicativo provisionado para autenticação do modelo de projeto padrão do Blazor WebAssembly para a versão do ASP.NET Core que você pretende usar. Inspecione o componente LoginDisplay no aplicativo gerado.

  • Inspecione o componente LoginDisplay na fonte de referência. O local do componente mudou com o tempo, portanto, portanto, use as ferramentas de pesquisa do GitHub para localizar o componente. O conteúdo com modelo para Hosted igual a true é usado.

    Observação

    Os links de documentação para a fonte de referência do .NET geralmente carregam o branch padrão do repositório, que representa o desenvolvimento atual da próxima versão do .NET. Para selecionar uma marca para uma versão específica, use a lista suspensa para Alternar branches ou marcas. Para saber mais, confira Como selecionar uma marca de versão do código-fonte do ASP.NET Core (dotnet/AspNetCore.Docs #26205).

Componente de autenticação

Esta seção pertence ao aplicativo Client da solução.

A página produzida pelo componente Authentication (Pages/Authentication.razor) define as rotas necessárias para lidar com diferentes estágios de autenticação.

O componente RemoteAuthenticatorView:

@page "/authentication/{action}"
@using Microsoft.AspNetCore.Components.WebAssembly.Authentication

<RemoteAuthenticatorView Action="@Action" />

@code {
    [Parameter]
    public string? Action { get; set; }
}

Observação

Há suporte a NRTs (tipos de referência anuláveis) e análise estática de estado nulo do compilador .NET no ASP.NET Core no .NET 6 ou posterior. Antes do lançamento do ASP.NET Core no .NET 6, o tipo string aparecia sem a designação de tipo nulo (?).

Componente FetchData

Esta seção pertence ao aplicativo Client da solução.

O componente FetchData mostra como:

  • Provisão de um token de acesso.
  • Use o token de acesso para chamar uma API de recurso protegido no aplicativo Servidor .

A diretiva @attribute [Authorize] indica ao sistema de autorização Blazor WebAssembly que o usuário deve ser autorizado para visitar esse componente. A presença do atributo no aplicativo Client não impede que a API no servidor seja chamada sem as credenciais adequadas. O aplicativo Server também deve usar [Authorize] nos pontos de extremidade apropriados para protegê-los corretamente.

IAccessTokenProvider.RequestAccessToken cuida da solicitação de um token de acesso que pode ser adicionado à solicitação para chamar a API. Se o token for armazenado em cache ou se o serviço puder provisionar um novo token de acesso sem interação do usuário, a solicitação de token será bem-sucedida. Caso contrário, a solicitação de token falhará com um AccessTokenNotAvailableException, que é capturado em uma instrução try-catch.

Para obter o token real a ser incluído na solicitação, o aplicativo deve verificar se a solicitação foi bem-sucedida chamando tokenResult.TryGetToken(out var token).

Se a solicitação tiver sido bem-sucedida, a variável de token será preenchida com o token de acesso. A propriedade AccessToken.Value do token expõe a cadeia de caracteres literal a ser incluída no cabeçalho da solicitação Authorization .

Se o token não pode ser provisionado sem a interação do usuário resultando em uma solicitação com falha:

  • ASP.NET Core em .NET 7 ou posterior: O aplicativo navega para AccessTokenResult.InteractiveRequestUrl usando o AccessTokenResult.InteractionOptions fornecido para permitir a atualização do token de acesso.
  • ASP.NET Core no .NET 6 ou anterior: o resultado do token contém uma URL de redirecionamento. Navegar até essa URL leva o usuário para a página de logon e volta para a página atual após uma autenticação bem-sucedida.
@page "/fetchdata"
@using Microsoft.AspNetCore.Authorization
@using Microsoft.AspNetCore.Components.WebAssembly.Authentication
@using {APP NAMESPACE}.Shared
@attribute [Authorize]
@inject HttpClient Http

...

@code {
    private WeatherForecast[] forecasts;

    protected override async Task OnInitializedAsync()
    {
        try
        {
            forecasts = await Http.GetFromJsonAsync<WeatherForecast[]>("WeatherForecast");
        }
        catch (AccessTokenNotAvailableException exception)
        {
            exception.Redirect();
        }
    }
}

Uso de um locatário do Azure Active Directory B2C

Se o aplicativo estiver registrado em um locatário do Azure Active Directory B2C, conforme descrito no Tutorial: Criar um locatário do Azure Active Directory B2C, mas seguir as diretrizes neste artigo, o URI da ID do Aplicativo será gerenciado de forma diferente pelo ME-ID.

Você pode verificar o tipo de locatário de um locatário existente selecionando o link Gerenciar locatários na parte superior da Visão geral da organização do ME-ID. Examine o valor da coluna Tipo de locatário da organização. Esta seção refere-se a aplicativos que seguem as diretrizes neste artigo, mas que estão registrados em um locatário do Azure Active Directory B2C.

Em vez do URI da ID do Aplicativo que corresponde ao formato api://{SERVER API APP CLIENT ID OR CUSTOM VALUE}, o URI da ID do Aplicativo tem o formato https://{TENANT}.onmicrosoft.com/{SERVER API APP CLIENT ID OR CUSTOM VALUE}. Essa diferença afeta as configurações do aplicativo Client e Server:

  • Para o aplicativo de API do servidor, defina o Audience no arquivo de configurações do aplicativo (appsettings.json) para corresponder ao público do aplicativo (URI da ID do Aplicativo) fornecido pelo portal do Azure sem barra à direita:

    "Audience": "https://{TENANT}.onmicrosoft.com/{SERVER API APP CLIENT ID OR CUSTOM VALUE}"
    

    Exemplo:

    "Audience": "https://contoso.onmicrosoft.com/00001111-aaaa-2222-bbbb-3333cccc4444"
    
  • No arquivo Program do aplicativo Client, defina o público-alvo do escopo (URI da ID do Aplicativo) para que ele corresponda ao público-alvo do aplicativo de API do servidor:

    options.ProviderOptions.DefaultAccessTokenScopes
        .Add("https://{TENANT}.onmicrosoft.com/{SERVER API APP CLIENT ID OR CUSTOM VALUE}/{DEFAULT SCOPE}");
    

    No escopo anterior, o URI/público-alvo da ID do Aplicativo é a parte do valor https://{TENANT}.onmicrosoft.com/{SERVER API APP CLIENT ID OR CUSTOM VALUE}, que não inclui uma barra à direita (/) e não inclui o nome do escopo ({DEFAULT SCOPE}).

    Exemplo:

    options.ProviderOptions.DefaultAccessTokenScopes
        .Add("https://contoso.onmicrosoft.com/00001111-aaaa-2222-bbbb-3333cccc4444/API.Access");
    

    No escopo anterior, o URI/público-alvo da ID do Aplicativo é a parte do valor https://contoso.onmicrosoft.com/00001111-aaaa-2222-bbbb-3333cccc4444, que não inclui uma barra à direita (/) e não inclui o nome do escopo (API.Access).

Uso de um URI da ID do Aplicativo personalizado

Se o URI da ID do Aplicativo for um valor personalizado, você deverá atualizar manualmente o URI do escopo do token de acesso padrão no aplicativo Client e adicionar o público-alvo à configuração do ME-ID do aplicativo Server.

Importante

A configuração a seguir não é necessária ao usar o URI da ID do aplicativo padrão do api://{SERVER API APP CLIENT ID}.

Exemplo de URI da ID do Aplicativo de urn://custom-app-id-uri e um nome de escopo do API.Access:

  • No arquivo Program do aplicativo Client:

    options.ProviderOptions.DefaultAccessTokenScopes.Add(
        "urn://custom-app-id-uri/API.Access");
    
  • No appsettings.json do aplicativo Server, adicione uma entrada Audience com apenas o URI da ID do Aplicativo e nenhuma barra à direita:

    "Audience": "urn://custom-app-id-uri"
    

Solucionar problemas

Logging

Para habilitar o registro em log de depuração ou rastreamento para autenticação Blazor WebAssembly, confira a seção Logs de autenticação do lado do cliente de Logs do Blazor no ASP.NET Core com o seletor de versão do artigo definido como ASP.NET Core 7.0 ou posterior.

Erros comuns

  • Configuração incorreta do aplicativo ou provedor Identity (IP)

    Os erros mais comuns são causados pela configuração incorreta. A seguir, estão alguns exemplos:

    • Dependendo dos requisitos do cenário, uma Autoridade, Instância, ID do Locatário, Domínio do Locatário, ID do Cliente ou URI de Redirecionamento ausente ou incorreto impede um aplicativo autenticar clientes.
    • Escopos de solicitação incorretos impedem que os clientes acessem pontos de extremidade da API Web do servidor.
    • Permissões incorretas ou ausentes da API do servidor impedem os clientes de acessar pontos de extremidade da API Web do servidor.
    • Executar o aplicativo em uma porta diferente da configurada no URI de Redirecionamento do registro de aplicativo do IP. Observe que uma porta não é necessária para o Microsoft Entra ID e um aplicativo em execução em um endereço de teste de desenvolvimento localhost, mas a configuração da porta do aplicativo e a porta em que o aplicativo está sendo executado devem corresponder a endereços que não sejam localhost.

    As seções de configuração das diretrizes deste artigo mostram exemplos da configuração correta. Verifique cuidadosamente cada seção do artigo em busca de configurações incorretas de aplicativo e IP.

    Se a configuração aparecer correta:

    • Analisar logs de aplicativos.

    • Examine o tráfego de rede entre o aplicativo cliente e o aplicativo IP ou servidor com as ferramentas de desenvolvedor do navegador. Muitas vezes, uma mensagem de erro exata ou uma mensagem com uma pista do que está causando o problema é retornada ao cliente pelo aplicativo IP ou servidor depois de fazer uma solicitação. As diretrizes das ferramentas de desenvolvedor são encontradas nos seguintes artigos:

    • Para versões de Blazor em que um JWT (Token Web JSON) é usado, decodifique o conteúdo do token usado para autenticar um cliente ou acessar uma API Web do servidor, dependendo de onde o problema estiver ocorrendo. Para obter mais informações, consulte Inspecionar o conteúdo de um JWT (Token Web JSON).

    A equipe de documentação responde a comentários de documentos e bugs em artigos (abra um problema na seção de comentários desta página), mas não consegue fornecer suporte ao produto. Vários fóruns de suporte público estão disponíveis para ajudar na solução de problemas de um aplicativo. Recomendamos o seguinte:

    Os fóruns anteriores não são de propriedade ou controlados pela Microsoft.

    Para relatórios de bugs de estrutura reproduzível não confidenciais e não confidenciais, abra um problema com a unidade do produto do ASP.NET Core. Não abra um problema com a unidade do produto até que você investigue completamente a causa de um problema e não possa resolvê-lo por conta própria e com a ajuda da comunidade em um fórum de suporte público. A unidade do produto não é capaz de solucionar problemas de aplicativos individuais que estão não estão funcionando devido a uma simples configuração incorreta ou casos de uso envolvendo serviços de terceiros. Se um relatório for confidencial ou de natureza confidencial ou descrever uma potencial falha de segurança no produto que possa ser explorada por invasores cibernéticos, confira Relatar problemas e bugs de segurança (Repositório GitHub dotnet/aspnetcore).

  • Cliente não autorizado para o ME-ID

    informação: falha na autorização do Microsoft.AspNetCore.Authorization.DefaultAuthorizationService[2]. Esses requisitos não foram atendidos: DenyAnonymousAuthorizationRequirement: requer um usuário autenticado.

    Erro de retorno de chamada de logon do ME-ID:

    • Erro: unauthorized_client
    • Descrição: AADB2C90058: The provided application is not configured to allow public clients.

    Para resolver o erro:

    1. No portal do Azure, acesse o manifesto do aplicativo.
    2. Defina o atributo allowPublicClient como null ou true.

Cookies e dados do site

Cookies e dados do site podem persistir nas atualizações do aplicativo e interferir em testes e solução de problemas. Desmarque o seguinte ao fazer alterações no código do aplicativo, alterações na conta de usuário com o provedor ou alterações na configuração do aplicativo do provedor:

  • Cookies de login do usuário
  • Cookies de aplicativos
  • Dados do site armazenados e em cache

Uma abordagem para impedir que cookies e dados do site persistentes interfiram no teste e na solução de problemas é:

  • Configurar um navegador
    • Use um navegador para testar se você consegue configurar a exclusão de todos os dados de cookies e sites sempre que o navegador é fechado.
    • Verifique se o navegador está fechado manualmente ou pelo IDE para qualquer alteração no aplicativo, usuário de teste ou configuração do provedor.
  • Use um comando personalizado para abrir um navegador no modo InPrivate ou Incógnito no Visual Studio:
    • Abra a caixa de diálogo Procurar com no botão Executar do Visual Studio.
    • Selecione o botão Adicionar.
    • Forneça o caminho para o navegador no campo Programa. Os seguintes caminhos executáveis são locais de instalação típicos para Windows 10. Se o navegador estiver instalado em um local diferente ou você não estiver usando Windows 10, forneça o caminho para o executável do navegador.
      • 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
    • No campo Argumentos, forneça a opção de linha de comando que o navegador usa para abrir no modo InPrivate ou Incógnito. Alguns navegadores exigem a URL do aplicativo.
      • Microsoft Edge: use -inprivate.
      • Google Chrome: use --incognito --new-window {URL}, onde o espaço reservado {URL} é a URL a ser aberta (por exemplo, https://localhost:5001).
      • Mozilla Firefox: Use -private -url {URL}, onde o {URL} espaço reservado é a URL para abrir (por exemplo, https://localhost:5001).
    • Forneça um nome no campo Nome amigável. Por exemplo, Firefox Auth Testing.
    • Selecione o botão OK.
    • Para evitar a necessidade de selecionar o perfil do navegador para cada iteração de teste com um aplicativo, defina o perfil como o padrão com o botão Definir como Padrão.
    • Verifique se o navegador está fechado pelo IDE para qualquer alteração no aplicativo, usuário de teste ou configuração do provedor.

Atualizações de aplicativos

Um aplicativo em funcionamento pode falhar imediatamente depois de atualizar o SDK do .NET Core no computador de desenvolvimento ou alterar as versões do pacote dentro do aplicativo. Em alguns casos, pacotes incoerentes podem interromper um aplicativo ao executar atualizações principais. A maioria desses problemas pode ser corrigida seguindo estas instruções:

  1. Limpe os caches do pacote NuGet do sistema local executando dotnet nuget locals all --clear de um shell de comando.
  2. Exclua as pastas bin e obj do projeto.
  3. Restaure e recompile o projeto.
  4. Exclua todos os arquivos na pasta de implantação no servidor antes de reimplantar o aplicativo.

Observação

Não há suporte para o uso de versões de pacote incompatíveis com a estrutura de destino do aplicativo. Para obter informações sobre um pacote, use a Galeria do NuGet ou a Gerenciador de Pacotes FuGet.

Execute o aplicativo Server

Ao testar e solucionar problemas de uma solução Blazor WebAssemblyhospedada, verifique se você está executando o aplicativo no projeto Server.

Inspecionar o usuário

O componente User a seguir pode ser usado diretamente em aplicativos ou servir como base para personalização adicional.

User.razor:

@page "/user"
@attribute [Authorize]
@using System.Text.Json
@using System.Security.Claims
@inject IAccessTokenProvider AuthorizationService

<h1>@AuthenticatedUser?.Identity?.Name</h1>

<h2>Claims</h2>

@foreach (var claim in AuthenticatedUser?.Claims ?? Array.Empty<Claim>())
{
    <p class="claim">@(claim.Type): @claim.Value</p>
}

<h2>Access token</h2>

<p id="access-token">@AccessToken?.Value</p>

<h2>Access token claims</h2>

@foreach (var claim in GetAccessTokenClaims())
{
    <p>@(claim.Key): @claim.Value.ToString()</p>
}

@if (AccessToken != null)
{
    <h2>Access token expires</h2>

    <p>Current time: <span id="current-time">@DateTimeOffset.Now</span></p>
    <p id="access-token-expires">@AccessToken.Expires</p>

    <h2>Access token granted scopes (as reported by the API)</h2>

    @foreach (var scope in AccessToken.GrantedScopes)
    {
        <p>Scope: @scope</p>
    }
}

@code {
    [CascadingParameter]
    private Task<AuthenticationState> AuthenticationState { get; set; }

    public ClaimsPrincipal AuthenticatedUser { get; set; }
    public AccessToken AccessToken { get; set; }

    protected override async Task OnInitializedAsync()
    {
        await base.OnInitializedAsync();
        var state = await AuthenticationState;
        var accessTokenResult = await AuthorizationService.RequestAccessToken();

        if (!accessTokenResult.TryGetToken(out var token))
        {
            throw new InvalidOperationException(
                "Failed to provision the access token.");
        }

        AccessToken = token;

        AuthenticatedUser = state.User;
    }

    protected IDictionary<string, object> GetAccessTokenClaims()
    {
        if (AccessToken == null)
        {
            return new Dictionary<string, object>();
        }

        // header.payload.signature
        var payload = AccessToken.Value.Split(".")[1];
        var base64Payload = payload.Replace('-', '+').Replace('_', '/')
            .PadRight(payload.Length + (4 - payload.Length % 4) % 4, '=');

        return JsonSerializer.Deserialize<IDictionary<string, object>>(
            Convert.FromBase64String(base64Payload));
    }
}

Inspecionar o conteúdo de um JWT (Token Web JSON)

Para decodificar um JWT (Token Web ON), use a ferramenta jwt.ms da Microsoft. Os valores na interface do usuário nunca saem do navegador.

Exemplo de JWT codificado (abreviado para exibição):

eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsImtpZCI6Ilg1ZVhrNHh5b2pORnVtMWtsMll0djhkbE5QNC1j ... bQdHBHGcQQRbW7Wmo6SWYG4V_bU55Ug_PW4pLPr20tTS8Ct7_uwy9DWrzCMzpD-EiwT5IjXwlGX3IXVjHIlX50IVIydBoPQtadvT7saKo1G5Jmutgq41o-dmz6-yBMKV2_nXA25Q

Exemplo de JWT decodificado pela ferramenta para um aplicativo que se autentica no Azure AAD B2C:

{
  "typ": "JWT",
  "alg": "RS256",
  "kid": "X5eXk4xyojNFum1kl2Ytv8dlNP4-c57dO6QGTVBwaNk"
}.{
  "exp": 1610059429,
  "nbf": 1610055829,
  "ver": "1.0",
  "iss": "https://mysiteb2c.b2clogin.com/11112222-bbbb-3333-cccc-4444dddd5555/v2.0/",
  "sub": "aaaaaaaa-0000-1111-2222-bbbbbbbbbbbb",
  "aud": "00001111-aaaa-2222-bbbb-3333cccc4444",
  "nonce": "bbbb0000-cccc-1111-dddd-2222eeee3333",
  "iat": 1610055829,
  "auth_time": 1610055822,
  "idp": "idp.com",
  "tfp": "B2C_1_signupsignin"
}.[Signature]

Recursos adicionais