Protección de un ASP.NET Core Blazor Web App con el identificador de Entra de Microsoft
En este artículo se describe cómo proteger un con los paquetes web de la plataforma/Microsoft identity Identity para el id. de Microsoft Entra mediante una aplicación de ejemplo. Blazor Web App
Se trata la especificación siguiente:
- usa el modo de representación automática con interactividad global (
InteractiveAuto
).Blazor Web App - El proyecto de servidor llama AddAuthenticationStateSerialization a para agregar un proveedor de estado de autenticación del lado servidor que usa PersistentComponentState para fluir el estado de autenticación al cliente. El cliente llama AddAuthenticationStateDeserialization a para deserializar y usar el estado de autenticación pasado por el servidor. El estado de autenticación es fijo durante la vigencia de la aplicación WebAssembly.
- La aplicación usa el identificador de Entra de Microsoft, en función de los paquetes web de MicrosoftIdentity.
- La actualización automática de tokens no interactivas se administra mediante el marco de trabajo.
- La aplicación usa abstracciones de servicio del lado servidor y del lado cliente para mostrar los datos meteorológicos generados:
- Al representar el
Weather
componente en el servidor para mostrar datos meteorológicos, el componente usa enServerWeatherForecaster
el servidor para obtener directamente datos meteorológicos (no a través de una llamada api web). - Cuando el
Weather
componente se representa en el cliente, el componente usa laClientWeatherForecaster
implementación del servicio, que usa un preconfigurado HttpClient (en el archivo del proyecto clienteProgram
) para realizar una llamada API web a la API mínima del proyecto de servidor (/weather-forecast
) para los datos meteorológicos. El punto de conexión de LA API mínima obtiene los datos meteorológicos de laServerWeatherForecaster
clase y los devuelve al cliente para su representación por parte del componente.
- Al representar el
Aplicación de ejemplo
El ejemplo consta de dos proyectos:
BlazorWebAppEntra
: proyecto del lado servidor de la Blazor Web App, que contiene un punto de conexión de API mínima de ejemplo para datos meteorológicos.BlazorWebAppEntra.Client
: proyecto del lado cliente de la Blazor Web App.
Acceda a las aplicaciones de ejemplo a través de la carpeta de versión más reciente desde la raíz del repositorio con el vínculo siguiente. Los proyectos se encuentran en la BlazorWebAppEntra
carpeta de .NET 9 o posterior.
Vea o descargue el código de ejemplo (cómo descargarlo)
Proyecto de Blazor Web App del lado servidor (BlazorWebAppEntra
)
El proyecto BlazorWebAppEntra
es el proyecto del lado servidor de la Blazor Web App.
El archivo BlazorWebAppEntra.http
se puede usar para probar la solicitud de datos meteorológicos. Ten en cuenta que el proyecto BlazorWebAppEntra
debe ejecutarse para probar el punto de conexión y el punto de conexión está codificado de forma dura en el archivo. Para obtener más información, consulta Usar archivos .http en Visual Studio 2022.
Proyecto de Blazor Web App del lado cliente (BlazorWebAppEntra.Client
)
El proyecto BlazorWebAppEntra.Client
es el proyecto del lado cliente de Blazor Web App.
Si el usuario necesita iniciar sesión o cerrar sesión durante la representación del lado cliente, se inicia una recarga de página completa.
Configuración
En esta sección se explica cómo configurar la aplicación de ejemplo.
AddMicrosoftIdentityWebApp desde Microsoft Identity Web (Microsoft.Identity.Web
paquete NuGet, documentación de API) se configura mediante la AzureAd
sección del archivo del proyecto de appsettings.json
servidor.
En el registro de la aplicación en Entra o Azure Portal, use una configuración de plataforma web con un URI de redirección de https://localhost/signin-oidc
(no se requiere un puerto). Confirme que los tokens de identificador y los tokens de acceso en Concesión implícita y flujos híbridos no están seleccionados. El controlador de OpenID Connect solicita automáticamente los tokens adecuados mediante el código devuelto desde el punto de conexión de autorización.
Configuración de la aplicación
En el archivo de configuración de la aplicación del proyecto de servidor (appsettings.json
), proporcione la configuración de la sección de AzureAd
la aplicación. Obtenga el identificador de aplicación (cliente), el dominio del inquilino (publicador) y el identificador de directorio (inquilino) de la aplicación en el registro de la aplicación en Entra o Azure Portal:
"AzureAd": {
"CallbackPath": "/signin-oidc",
"ClientId": "{CLIENT ID}",
"Domain": "{DOMAIN}",
"Instance": "https://login.microsoftonline.com/",
"ResponseType": "code",
"TenantId": "{TENANT ID}"
},
Marcadores de posición en el ejemplo anterior:
{CLIENT ID}
: el identificador de la aplicación (cliente).{DOMAIN}
: el dominio del inquilino (publicador).{TENANT ID}
: identificador de directorio (inquilino).
Ejemplo:
"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"
},
La ruta de acceso de devolución de llamada (CallbackPath
) debe coincidir con el URI de redirección (ruta de acceso de devolución de llamada de inicio de sesión) configurado al registrar la aplicación en Entra o Azure Portal. Las rutas de acceso se configuran en la hoja Autenticación del registro de la aplicación. El valor predeterminado de CallbackPath
es /signin-oidc
para un URI de redireccionamiento registrado de https://localhost/signin-oidc
(no se requiere un puerto).
Advertencia
No almacene secretos de aplicación, cadena de conexión s, credenciales, contraseñas, números de identificación personal (PIN), código C#/.NET privado o claves o tokens privados en el código del lado cliente, lo que siempre es inseguro. En entornos de prueba/ensayo y producción, el código del lado Blazor servidor y las API web deben usar flujos de autenticación seguros que eviten mantener las credenciales dentro del código del proyecto o los archivos de configuración. Fuera de las pruebas de desarrollo local, se recomienda evitar el uso de variables de entorno para almacenar datos confidenciales, ya que las variables de entorno no son el enfoque más seguro. Para las pruebas de desarrollo local, se recomienda la herramienta Secret Manager para proteger los datos confidenciales. Para obtener más información, consulte Mantener de forma segura los datos confidenciales y las credenciales.
Establecimiento del secreto de cliente
Cree un secreto de cliente en el registro de id. entra de la aplicación en Entra o Azure Portal (administrar>certificados y secretos>Nuevo secreto de cliente). Use el valor del nuevo secreto en las instrucciones siguientes.
Use cualquiera de los métodos siguientes o ambos para proporcionar el secreto de cliente a la aplicación:
- Herramienta Administrador de secretos: la herramienta Secret Manager almacena datos privados en el equipo local y solo se usa durante el desarrollo local.
- Azure Key Vault: puede almacenar el secreto de cliente en un almacén de claves para su uso en cualquier entorno, incluido para el entorno de desarrollo al trabajar localmente. Algunos desarrolladores prefieren usar almacenes de claves para implementaciones de ensayo y producción y usar la herramienta Secret Manager para el desarrollo local.
Se recomienda encarecidamente evitar almacenar secretos de cliente en archivos de configuración o código de proyecto. Use flujos de autenticación seguros, como o ambos enfoques de esta sección.
Herramienta Administrador de secretos
La herramienta Administrador de secretos puede almacenar el secreto de cliente de la aplicación de servidor en la clave AzureAd:ClientSecret
de configuración .
La aplicación de ejemplo no se ha inicializado para la herramienta Administrador de secretos. Use un shell de comandos, como el shell de comandos de PowerShell para desarrolladores en Visual Studio, para ejecutar el comando siguiente. Antes de ejecutar el comando, cambie el directorio con el cd
comando al directorio del proyecto de servidor. El comando establece un identificador de secretos de usuario (<UserSecretsId>
) en el archivo de proyecto de la aplicación de servidor, que se usa internamente mediante las herramientas para realizar un seguimiento de los secretos de la aplicación:
dotnet user-secrets init
Ejecute el siguiente comando para establecer el secreto de cliente. El {SECRET}
marcador de posición es el secreto de cliente obtenido del registro entra de la aplicación:
dotnet user-secrets set "AzureAd:ClientSecret" "{SECRET}"
Si usa Visual Studio, puede confirmar que el secreto está establecido haciendo clic con el botón derecho en el proyecto de servidor en Explorador de soluciones y seleccionando Administrar secretos de usuario.
Azure Key Vault
Azure Key Vault proporciona un enfoque seguro para proporcionar el secreto de cliente de la aplicación a la aplicación.
Para crear un almacén de claves y establecer un secreto de cliente, consulte Acerca de los secretos de Azure Key Vault (documentación de Azure), que incluyen recursos entre vínculos para empezar a trabajar con Azure Key Vault. Para implementar el código de esta sección, registre el URI del almacén de claves y el nombre del secreto de Azure al crear el almacén de claves y el secreto. Al establecer la directiva de acceso para el secreto en el panel Directivas de acceso:
- Solo se requiere el permiso Obtener secreto.
- Seleccione la aplicación como entidad de seguridad para el secreto.
Importante
Se crea un secreto del almacén de claves con una fecha de expiración. Asegúrese de realizar un seguimiento de cuándo va a expirar un secreto del almacén de claves y crear un nuevo secreto para la aplicación antes de pasar esa fecha.
El método siguiente GetKeyVaultSecret
recupera un secreto de un almacén de claves. Agregue este método al proyecto de servidor. Ajuste el espacio de nombres (BlazorSample.Helpers
) para que coincida con el esquema del espacio de nombres del proyecto.
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;
}
}
Donde los servicios se registran en el archivo del proyecto de Program
servidor, obtenga y aplique el secreto de cliente mediante el código siguiente:
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);
});
Si desea controlar el entorno en el que funciona el código anterior, por ejemplo, para evitar ejecutar el código localmente porque ha optado por usar la herramienta Administrador de secretos para el desarrollo local, puede encapsular el código anterior en una instrucción condicional que compruebe el entorno:
if (!context.HostingEnvironment.IsDevelopment())
{
...
}
En la AzureAd
sección de appsettings.json
, agregue las claves y SecretName
valores de configuración siguientesVaultUri
:
"VaultUri": "{VAULT URI}",
"SecretName": "{SECRET NAME}"
En el ejemplo anterior:
- El
{VAULT URI}
marcador de posición es el URI del almacén de claves. Incluya la barra diagonal final en el URI. - El
{SECRET NAME}
marcador de posición es el nombre del secreto.
Ejemplo:
"VaultUri": "https://contoso.vault.azure.net/",
"SecretName": "BlazorWebAppEntra"
La configuración se usa para facilitar el suministro de almacenes de claves dedicados y nombres secretos basados en los archivos de configuración del entorno de la aplicación. Por ejemplo, puede proporcionar valores de configuración diferentes para appsettings.Development.json
en desarrollo, appsettings.Staging.json
cuando el almacenamiento provisional y appsettings.Production.json
para la implementación de producción. Para obtener más información, consulta Configuración de Blazor en ASP.NET Core.
Redireccionamiento a la página al cerrar sesión home
Cuando un usuario navega por la aplicación, el componente LogInOrOut
(Layout/LogInOrOut.razor
) establece un campo oculto para la dirección URL de retorno (ReturnUrl
) en el valor de la dirección URL actual (currentURL
). Cuando el usuario cierra la sesión de la aplicación, el proveedor de identity lo devuelve a la página desde la que cerró la sesión.
Si el usuario cierra sesión desde una página segura, se le devuelve a la misma página segura después de cerrar la sesión, solo para el envío de vuelta a través del proceso de autenticación. Este comportamiento es adecuado cuando los usuarios necesitan cambiar de cuenta con frecuencia. Sin embargo, una especificación de aplicación alternativa puede llamar a que el usuario se devuelva a la página de la home aplicación o a otra página después de cerrar la sesión. En el ejemplo siguiente se muestra cómo establecer la página de home la aplicación como la dirección URL de retorno para las operaciones de cierre de sesión.
Los cambios importantes en el componente LogInOrOut
se muestran en el ejemplo siguiente. No es necesario proporcionar un campo oculto para el ReturnUrl
conjunto en la home página en /
porque es la ruta de acceso predeterminada. IDisposable ya no se implementa. NavigationManager ya no se inserta. Se elimina todo el bloque @code
.
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>
Solución de problemas
Registro
La aplicación de servidor es una aplicación estándar ASP.NET Core. Consulta la guía de registro de ASP.NET Core para habilitar un nivel de registro inferior en la aplicación de servidor.
Para habilitar el registro de depuración o rastreo para la autenticación de Blazor WebAssembly, consulta la sección Registro de autenticación del lado del cliente del Registro de Blazor de ASP.NET Core con el selector de versión del artículo establecido en ASP.NET Core 7.0 o posterior.
Errores comunes
Error de configuración de la aplicación o del proveedor de Identity (IP)
Los errores más comunes se deben a una configuración incorrecta. Estos son algunos ejemplos:
- En función de los requisitos del escenario, la disponibilidad o no de una autoridad, una instancia, un identificador o dominio de inquilino, un identificador de cliente o un URI de redireccionamiento, o bien que estos no elementos no sean correctos, impide a una aplicación autenticar clientes.
- Los ámbitos de solicitud incorrectos impiden a los clientes acceder a los puntos de conexión de la API web del servidor.
- Faltan permisos de la API de servidor o estos son incorrectos, lo cual impide a los clientes acceder a los puntos de conexión de API web.
- Ejecutar la aplicación en un puerto diferente al configurado en el URI de redirección del registro de aplicación de la IP. Ten en cuenta que no se requiere ningún puerto para Microsoft Entra ID y una aplicación que se ejecute en una dirección de pruebas de desarrollo
localhost
, pero la configuración del puerto de la aplicación y el puerto en el que se ejecuta la aplicación deben coincidir para las direcciones que no seanlocalhost
.
La cobertura de configuración de este artículo muestra ejemplos de la configuración correcta. Comprueba cuidadosamente la configuración que busca la aplicación y la configuración incorrecta de IP.
Si la configuración parece correcta:
Analiza los registros de la aplicación.
Examina el tráfico de red entre la aplicación cliente y la de servidor, o la dirección IP con las herramientas de desarrollo del explorador. A menudo, la aplicación de servidor o la dirección IP devuelve al cliente un mensaje de error exacto o un mensaje con una pista sobre la causa del problema. En los siguientes artículos encontrarás instrucciones sobre las herramientas de desarrollo:
- Google Chrome (documentación de Google)
- Microsoft Edge
- Mozilla Firefox (documentación de Mozilla)
El equipo de documentación responde a los comentarios y los errores en los artículos (abre una incidencia en la sección de comentarios de esta página), pero no puede proporcionar soporte técnico para el producto. Existen varios foros de soporte técnico públicos que ayudan a solucionar los problemas de una aplicación. Se recomienda lo siguiente:
Microsoft no posee ni controla ninguno de los foros anteriores.
Respecto a los informes de errores del marco que no son de seguridad ni confidenciales, o que no se pueden reproducir, abre una incidencia con la unidad de producto ASP.NET Core. No abras una incidencia con la unidad de producto hasta que hayas investigado exhaustivamente su causa y no puedas resolverlo por tu cuenta o con la ayuda de la comunidad en un foro de soporte técnico público. La unidad de producto no puede solucionar problemas de aplicaciones individuales cuyo funcionamiento se haya interrumpido debido a errores de configuración o casos de uso sencillos que involucren servicios de terceros. Si un informe es confidencial o delicado por naturaleza o describe un posible error de seguridad en el producto que los ciberdelincuentes puedan aprovechar, consulta Informes de problemas de seguridad y errores (repositorio de GitHub
dotnet/aspnetcore
).Cliente no autorizado para ME-ID
Información: Error de autorización de Microsoft.AspNetCore.Authorization.DefaultAuthorizationService[2]. No se cumplen estos requisitos: DenyAnonymousAuthorizationRequirement: se requiere un usuario autenticado.
Error de devolución de llamada de inicio de sesión de ME-ID:
- Error:
unauthorized_client
- Descripción:
AADB2C90058: The provided application is not configured to allow public clients.
Para resolver el error:
- En Azure Portal, accede al manifiesto de la aplicación.
- Establece el atributo
allowPublicClient
ennull
otrue
.
- Error:
Cookies y datos de sitios
Las cookies y los datos de sitios pueden persistir durante las actualizaciones de la aplicación e interferir con las pruebas y la solución de problemas. Borra los elementos siguientes al realizar cambios en el código de la aplicación, cambios en la cuenta de usuario con el proveedor o cuando el proveedor modifique la configuración de la aplicación:
- Cookies de inicio de sesión de usuario
- Cookies de aplicación
- Datos de sitios almacenados y en caché
El enfoque siguiente sirve para evitar que las cookies persistentes y los datos de sitios interfieran con las pruebas y la solución de problemas:
- Configuración de un explorador
- Usa un explorador para las pruebas, y configúralo para que elimine todas las cookies y los datos del sitio cada vez que se cierre.
- Asegúrate de que el explorador se cierra manualmente o mediante el IDE siempre que se produzca cualquier cambio en la aplicación, el usuario de prueba o la configuración del proveedor.
- Usa un comando personalizado para abrir un explorador en el modo incógnito o privado en Visual Studio:
- Abre el cuadro de diálogo Examinar con mediante el botón Ejecutar de Visual Studio.
- Selecciona el botón Agregar.
- Proporciona la ruta de acceso al explorador en el campo Programa. Las siguientes rutas de acceso del archivo ejecutable son ubicaciones de instalación típicas para Windows 10. Si el explorador está instalado en una ubicación diferente o no usa Windows 10, proporciona la ruta de acceso al archivo ejecutable del explorador.
- 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:
- En el campo Argumentos, proporciona la opción de línea de comandos que utiliza el explorador para abrirse en el modo incógnito o privado. Algunos exploradores requieren la dirección URL de la aplicación.
- Microsoft Edge: Usa
-inprivate
. - Google Chrome: usa
--incognito --new-window {URL}
, donde el marcador de posición{URL}
es la dirección URL que se va a abrir (por ejemplo,https://localhost:5001
). - Mozilla Firefox: usa
-private -url {URL}
, donde el marcador de posición{URL}
es la dirección URL que se va a abrir (por ejemplo,https://localhost:5001
).
- Microsoft Edge: Usa
- Proporciona un nombre en el campo Nombre descriptivo. Por ejemplo:
Firefox Auth Testing
. - Selecciona el botón Aceptar.
- Para evitar tener que seleccionar el perfil de explorador para cada iteración de pruebas con una aplicación, establece el perfil como predeterminado con el botón Establecer como predeterminado.
- Asegúrate de que el explorador se cierra mediante el IDE siempre que se produzca cualquier cambio en la aplicación, el usuario de prueba o la configuración del proveedor.
Actualizaciones de aplicaciones
Una aplicación en funcionamiento deja de ejecutarse inmediatamente después de actualizar el SDK de .NET Core en la máquina de desarrollo o de cambiar las versiones del paquete en la aplicación. En algunos casos, los paquetes incoherentes pueden interrumpir una aplicación al realizar actualizaciones importantes. La mayoría de estos problemas puede corregirse siguiendo estas instrucciones:
- Borra las memorias caché del paquete NuGet del sistema local ejecutando
dotnet nuget locals all --clear
desde un shell de comandos. - Elimina las carpetas
bin
yobj
del proyecto. - Restaura el proyecto y vuelve a compilarlo.
- Elimina todos los archivos de la carpeta de implementación del servidor antes de volver a implementar la aplicación.
Nota
No se pueden usar versiones de paquetes que no sean compatibles con la plataforma de destino de la aplicación. Para obtener información sobre un paquete, usa la galería de NuGet o el explorador de paquetes FuGet.
Ejecución de la aplicación Server
Al probar y solucionar problemas de una Blazor Web App, asegúrate de que ejecutas la aplicación desde el proyecto del servidor.
Inspección del usuario
El siguiente componente UserClaims
se puede usar directamente en las aplicaciones, o bien servir como base para una mayor personalización.
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 adicionales
- Documentación de Microsoft identity Platform
- Repositorio GitHub de
AzureAD/microsoft-identity-web
: guía útil sobre la implementación de Microsoft Identity Web para Microsoft Entra ID y Azure Active Directory B2C para aplicaciones ASP.NET Core, incluidos vínculos a aplicaciones de ejemplo y documentación relacionada de Azure. Actualmente, la documentación de Azure no aborda explícitamente los objetos Blazor Web App, pero la configuración de un objeto Blazor Web App para ME-ID y el hospedaje de Azure es igual que para cualquier aplicación web de ASP.NET Core. AuthenticationStateProvider
del ssDE- Administrar el estado de autenticación en Blazor Web App
- Abstracciones de servicio en Blazor Web Apps