Proteger um ASP.NET Core Blazor Web App com a ID do Microsoft Entra
Este artigo descreve como proteger um com a Blazor Web App plataforma/Microsoft identity Microsoft Identity Web packages for Microsoft Entra ID usando um aplicativo de exemplo.
A seguinte especificação é abordada:
- O Blazor Web App usa o modo de renderização automática com interatividade global (
InteractiveAuto
). - O projeto do servidor chama AddAuthenticationStateSerialization para adicionar um provedor de estado de autenticação do lado do servidor que usa PersistentComponentState para fluir o estado de autenticação para o cliente. O cliente chama AddAuthenticationStateDeserialization para desserializar e usar o estado de autenticação passado pelo servidor. O estado de autenticação é corrigido para o tempo de vida do aplicativo WebAssembly.
- O aplicativo usa o Microsoft Entra ID, com base em pacotes da Web da MicrosoftIdentity.
- A atualização automática de token não interativa é gerenciada pela estrutura.
- O aplicativo usa abstrações de serviço do lado do servidor e do lado do cliente para exibir dados meteorológicos gerados:
- Ao renderizar o
Weather
componente no servidor para exibir dados meteorológicos, o componente usa oServerWeatherForecaster
no servidor para obter dados meteorológicos diretamente (não por meio de uma chamada de API Web). - Quando o
Weather
componente é renderizado no cliente, o componente usa a implementação doClientWeatherForecaster
serviço, que usa um pré-configurado HttpClient (no arquivo do projeto doProgram
cliente) para fazer uma chamada de API Web para a API mínima do projeto do servidor (/weather-forecast
) para dados meteorológicos. O endpoint da API Minimal obtém os dados meteorológicos daServerWeatherForecaster
classe e os retorna ao cliente para renderização pelo componente.
- Ao renderizar o
Aplicativo de exemplo
Este aplicativo de exemplo é composto por dois projetos:
BlazorWebAppEntra
: projeto do lado do servidor do Blazor Web App, que contém um exemplo de ponto de extremidade de API mínima de dados meteorológicos.BlazorWebAppEntra.Client
: projeto do lado do cliente do Blazor Web App.
Acesse aplicativos de exemplo por meio da pasta da versão mais recente da raiz do repositório com o link a seguir. Os projetos estão na BlazorWebAppEntra
pasta para .NET 9 ou posterior.
Exibir ou baixar código de exemplo (como baixar)
Projeto Blazor Web App do lado do servidor (BlazorWebAppEntra
)
O projeto BlazorWebAppEntra
é o projeto do lado do servidor do Blazor Web App.
O arquivo BlazorWebAppEntra.http
pode ser usado para testar a solicitação de dados meteorológicos. Observe que o projeto BlazorWebAppEntra
deve estar em execução para testar o ponto de extremidade e o ponto de extremidade está codificado no arquivo. Para obter mais informações, consulte Usar arquivos .http no Visual Studio 2022.
Projeto Blazor Web App do lado do cliente (BlazorWebAppEntra.Client
)
O projeto BlazorWebAppEntra.Client
é o projeto do lado do cliente do Blazor Web App.
Se o usuário precisar fazer logon ou logout durante a renderização do lado do cliente, um recarregamento de página inteira será iniciado.
Configuração
Esta seção explica como configurar o aplicativo de exemplo.
AddMicrosoftIdentityWebAppda Web da Microsoft Identity (Microsoft.Identity.Web
pacote NuGet, documentação da API) é configurado pela AzureAd
seção do arquivo do projeto do appsettings.json
servidor.
No registro do aplicativo no portal do Entra ou do Azure, use uma configuração de plataforma Web com um URI de redirecionamento de https://localhost/signin-oidc
(uma porta não é necessária). Confirme se os tokens de ID e os tokens de acesso em Concessão implícita e fluxos híbridos não estão selecionados. O manipulador do OpenID Connect solicita automaticamente os tokens apropriados usando o código retornado do ponto de extremidade de autorização.
Configurar o aplicativo
No arquivo de configurações do aplicativo do projeto do servidor (appsettings.json
), forneça a configuração da seção do AzureAd
aplicativo. Obtenha a ID do aplicativo (cliente), o domínio do locatário (editor) e a ID do diretório (locatário) do registro do aplicativo no portal do Entra ou do Azure:
"AzureAd": {
"CallbackPath": "/signin-oidc",
"ClientId": "{CLIENT ID}",
"Domain": "{DOMAIN}",
"Instance": "https://login.microsoftonline.com/",
"ResponseType": "code",
"TenantId": "{TENANT ID}"
},
Espaços reservados no exemplo anterior:
{CLIENT ID}
: A ID do aplicativo (cliente).{DOMAIN}
: o domínio do locatário (editor).{TENANT ID}
: A ID do diretório (locatário).
Exemplo:
"AzureAd": {
"CallbackPath": "/signin-oidc",
"ClientId": "00001111-aaaa-2222-bbbb-3333cccc4444",
"Domain": "contoso.onmicrosoft.com",
"Instance": "https://login.microsoftonline.com/",
"ResponseType": "code",
"TenantId": "aaaabbbb-0000-cccc-1111-dddd2222eeee"
},
O caminho de retorno de chamada (CallbackPath
) deve corresponder ao URI de redirecionamento (caminho de retorno de chamada de logon) configurado ao registrar o aplicativo no portal do Entra ou do Azure. Os caminhos são configurados na folha Autenticação do registro do aplicativo. O valor padrão de CallbackPath
é /signin-oidc
para um URI de redirecionamento registrado de https://localhost/signin-oidc
(uma porta não é necessária).
Aviso
Não armazene segredos de aplicativo, cadeias de conexão, credenciais, senhas, PINs (números de identificação pessoal), código C#/.NET privado ou chaves/tokens privados no código do lado do cliente, que é sempre inseguro. Em ambientes de teste/preparo e produção, o código do lado do Blazor servidor e as APIs Web devem usar fluxos de autenticação seguros que evitam a manutenção de credenciais no código do projeto ou nos arquivos de configuração. Fora dos testes de desenvolvimento local, recomendamos evitar o uso de variáveis de ambiente para armazenar dados confidenciais, pois as variáveis de ambiente não são a abordagem mais segura. Para testes de desenvolvimento local, a ferramenta Gerenciador de segredos é recomendada para proteger dados confidenciais. Para obter mais informações, consulte Manter dados e credenciais confidenciais com segurança.
Estabelecer o segredo do cliente
Crie um segredo do cliente no registro da ID do Entra do aplicativo no portal do Entra ou do Azure (Gerenciar>certificados e segredos>: Novo segredo do cliente). Use o valor do novo segredo nas diretrizes a seguir.
Use uma ou ambas as abordagens a seguir para fornecer o segredo do cliente ao aplicativo:
- Ferramenta Gerenciador de Segredos: A ferramenta Gerenciador de Segredos armazena dados privados na máquina local e é usada apenas durante o desenvolvimento local.
- Azure Key Vault: você pode armazenar o segredo do cliente em um cofre de chaves para uso em qualquer ambiente, inclusive para o ambiente de desenvolvimento ao trabalhar localmente. Alguns desenvolvedores preferem usar cofres de chaves para implantações de preparo e produção e usar a ferramenta Gerenciador de Segredos para desenvolvimento local.
É altamente recomendável que você evite armazenar segredos do cliente no código do projeto ou nos arquivos de configuração. Use fluxos de autenticação seguros, como uma ou ambas as abordagens nesta seção.
Ferramenta Gerenciador de segredos
A ferramenta Gerenciador de segredos pode armazenar o segredo do cliente do aplicativo servidor na chave AzureAd:ClientSecret
de configuração.
O aplicativo de exemplo não foi inicializado para a ferramenta Gerenciador de Segredos. Use um shell de comando, como o shell de comando do PowerShell do Desenvolvedor no Visual Studio, para executar o comando a seguir. Antes de executar o comando, altere o diretório com o cd
comando para o diretório do projeto do servidor. O comando estabelece um identificador de segredos do usuário (<UserSecretsId>
) no arquivo de projeto do aplicativo servidor, que é usado internamente pelas ferramentas para rastrear segredos do aplicativo:
dotnet user-secrets init
Execute o comando a seguir para definir o segredo do cliente. O {SECRET}
espaço reservado é o segredo do cliente obtido do registro do Entra do aplicativo:
dotnet user-secrets set "AzureAd:ClientSecret" "{SECRET}"
Se estiver usando o Visual Studio, você poderá confirmar se o segredo está definido clicando com o botão direito do mouse no projeto do servidor no Gerenciador de Soluções e selecionando Gerenciar Segredos do Usuário.
Cofre de Chave do Azure
O Azure Key Vault fornece uma abordagem segura para fornecer o segredo do cliente do aplicativo para o aplicativo.
Para criar um cofre de chaves e definir um segredo do cliente, consulte Sobre os segredos do Azure Key Vault (documentação do Azure), que vincula recursos para começar a usar o Azure Key Vault. Para implementar o código nesta seção, registre o URI do cofre de chaves e o nome do segredo do Azure ao criar o cofre de chaves e o segredo. Quando você define a política de acesso para o segredo no painel Políticas de acesso:
- Somente a permissão Obter segredo é necessária.
- Selecione o aplicativo como a entidade de segurança para o segredo.
Importante
Um segredo do cofre de chaves é criado com uma data de expiração. Certifique-se de acompanhar quando um segredo do cofre de chaves vai expirar e criar um novo segredo para o aplicativo antes que essa data passe.
O método a seguir GetKeyVaultSecret
recupera um segredo de um cofre de chaves. Adicione esse método ao projeto do servidor. Ajuste o namespace (BlazorSample.Helpers
) para corresponder ao esquema de namespace do projeto.
Helpers/AzureHelper.cs
:
using Azure;
using Azure.Identity;
using Azure.Security.KeyVault.Secrets;
namespace BlazorSample.Helpers;
public static class AzureHelper
{
public static string GetKeyVaultSecret(string tenantId, string vaultUri, string secretName)
{
DefaultAzureCredentialOptions options = new()
{
// Specify the tenant ID to use the dev credentials when running the app locally
// in Visual Studio.
VisualStudioTenantId = tenantId,
SharedTokenCacheTenantId = tenantId
};
var client = new SecretClient(new Uri(vaultUri), new DefaultAzureCredential(options));
var secret = client.GetSecretAsync(secretName).Result;
return secret.Value.Value;
}
}
Quando os serviços são registrados no arquivo do projeto do Program
servidor, obtenha e aplique o segredo do cliente usando o seguinte código:
var tenantId = builder.Configuration.GetValue<string>("AzureAd:TenantId")!;
var vaultUri = builder.Configuration.GetValue<string>("AzureAd:VaultUri")!;
var secretName = builder.Configuration.GetValue<string>("AzureAd:SecretName")!;
builder.Services.Configure<MicrosoftIdentityOptions>(
OpenIdConnectDefaults.AuthenticationScheme,
options =>
{
options.ClientSecret =
AzureHelper.GetKeyVaultSecret(tenantId, vaultUri, secretName);
});
Se você quiser controlar o ambiente em que o código anterior opera, por exemplo, para evitar a execução do código localmente porque optou por usar a ferramenta Gerenciador de Segredos para desenvolvimento local, você pode encapsular o código anterior em uma instrução condicional que verifica o ambiente:
if (!context.HostingEnvironment.IsDevelopment())
{
...
}
AzureAd
Na seção de appsettings.json
, adicione as seguintes VaultUri
chaves e SecretName
valores de configuração:
"VaultUri": "{VAULT URI}",
"SecretName": "{SECRET NAME}"
No exemplo anterior:
- O
{VAULT URI}
espaço reservado é o URI do cofre de chaves. Inclua a barra final no URI. - O
{SECRET NAME}
espaço reservado é o nome secreto.
Exemplo:
"VaultUri": "https://contoso.vault.azure.net/",
"SecretName": "BlazorWebAppEntra"
A configuração é usada para facilitar o fornecimento de cofres de chaves dedicados e nomes secretos com base nos arquivos de configuração ambiental do aplicativo. Por exemplo, você pode fornecer valores de configuração diferentes para appsettings.Development.json
desenvolvimento, appsettings.Staging.json
preparo e appsettings.Production.json
implantação de produção. Para obter mais informações, consulte Configuração no ASP.NET Core Blazor.
Redirecione para a home página ao sair
Quando um usuário navega pelo aplicativo, o componente LogInOrOut
(Layout/LogInOrOut.razor
) define um campo oculto para a URL de retorno (ReturnUrl
) para o valor da URL atual (currentURL
). Quando o usuário sai do aplicativo, o provedor de identity o retorna para a página da qual se desconectou.
Se o usuário sair de uma página segura, ele será retornado para a mesma página segura depois de sair apenas para ser enviado de volta por meio do processo de autenticação. Esse comportamento é bom quando os usuários precisam alternar contas com frequência. No entanto, uma especificação de aplicativo alternativa pode exigir que o usuário seja retornado à página do home aplicativo ou a alguma outra página após sair. O exemplo a seguir mostra como definir a página do home aplicativo como a URL de retorno para operações de saída.
As alterações importantes no componente LogInOrOut
são demonstradas no exemplo a seguir. Não há necessidade de fornecer um campo oculto para o ReturnUrl
conjunto da home página em /
porque esse é o caminho padrão. IDisposable não é mais implementado. O NavigationManager não é mais injetado. O bloco inteiro @code
é removido.
Layout/LogInOrOut.razor
:
@using Microsoft.AspNetCore.Authorization
<div class="nav-item px-3">
<AuthorizeView>
<Authorized>
<form action="authentication/logout" method="post">
<AntiforgeryToken />
<button type="submit" class="nav-link">
<span class="bi bi-arrow-bar-left-nav-menu" aria-hidden="true">
</span> Logout @context.User.Identity?.Name
</button>
</form>
</Authorized>
<NotAuthorized>
<a class="nav-link" href="authentication/login">
<span class="bi bi-person-badge-nav-menu" aria-hidden="true"></span>
Login
</a>
</NotAuthorized>
</AuthorizeView>
</div>
Solucionar problemas
Logging
O aplicativo de servidor é um aplicativo ASP.NET Core padrão. Consulte as diretrizes de registro em log do ASP.NET Core para habilitar um nível de log mais baixo no aplicativo servidor.
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 sejamlocalhost
.
A cobertura de configuração neste artigo mostra exemplos da configuração correta. Verifique cuidadosamente a configuração em busca de alguma configuração incorreta 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:
- Google Chrome (Documentação do Google)
- Microsoft Edge
- Mozilla Firefox (Documentação do Mozilla)
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:
- No portal do Azure, acesse o manifesto do aplicativo.
- Defina o atributo
allowPublicClient
comonull
outrue
.
- Erro:
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
- Microsoft Edge:
- 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
).
- Microsoft Edge: use
- 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:
- Limpe os caches do pacote NuGet do sistema local executando
dotnet nuget locals all --clear
de um shell de comando. - Exclua as pastas
bin
eobj
do projeto. - Restaure e recompile o projeto.
- 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.
Executar o aplicativo de servidor
Ao testar e solucionar problemas de um Blazor Web App, verifique se você está executando o aplicativo no projeto do servidor.
Inspecionar o usuário
O componente UserClaims
a seguir pode ser usado diretamente em aplicativos ou servir como base para personalização adicional.
UserClaims.razor
:
@page "/user-claims"
@using System.Security.Claims
@using Microsoft.AspNetCore.Authorization
@attribute [Authorize]
<PageTitle>User Claims</PageTitle>
<h1>User Claims</h1>
@if (claims.Any())
{
<ul>
@foreach (var claim in claims)
{
<li><b>@claim.Type:</b> @claim.Value</li>
}
</ul>
}
@code {
private IEnumerable<Claim> claims = Enumerable.Empty<Claim>();
[CascadingParameter]
private Task<AuthenticationState>? AuthState { get; set; }
protected override async Task OnInitializedAsync()
{
if (AuthState == null)
{
return;
}
var authState = await AuthState;
claims = authState.User.Claims;
}
}
Recursos adicionais
- Documentação da plataforma de identity da Microsoft
- Repositório do GitHub
AzureAD/microsoft-identity-web
: orientações úteis sobre como implementar o Microsoft Identity Web para Microsoft Entra ID e o Azure Active Directory B2C para aplicativos ASP.NET Core, incluindo links para aplicativos de exemplo e documentação relacionada do Azure. No momento, os Blazor Web Apps não são explicitamente abordados pela documentação do Azure, mas a definição e a configuração de um Blazor Web App do ME-ID e a hospedagem do Azure são os mesmos para qualquer aplicativo Web do ASP.NET Core. AuthenticationStateProvider
serviço- Gerenciar o estado de autenticação em Blazor Web Apps
- Abstrações de serviço em Blazor Web Apps