Nota
El acceso a esta página requiere autorización. Puede intentar iniciar sesión o cambiar directorios.
El acceso a esta página requiere autorización. Puede intentar cambiar los directorios.
En este artículo se describe cómo proteger un Blazor Web App con la plataforma de identidad de Microsoft utilizando paquetes web de Microsoft Identity para Microsoft Entra ID mediante una aplicación de ejemplo.
En esta versión del artículo se describe cómo implementar Entra sin adoptar el patrón Backend for Frontend (BFF). El patrón BFF es útil para realizar solicitudes autenticadas a servicios externos. Cambie el selector de versión del artículo a patrón BFF si la especificación de la aplicación llama a la adopción del patrón BFF.
La siguiente especificación está cubierta:
- El Blazor Web App usa el modo de renderizado automático con interactividad global (
InteractiveAuto
). - El proyecto de servidor llama AddAuthenticationStateSerialization para agregar un proveedor de estado de autenticación del lado del servidor que usa PersistentComponentState para transferir el estado de autenticación hacia el cliente. El cliente llama AddAuthenticationStateDeserialization 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 Microsoft Entra ID, basado en los paquetes web de Microsoft Identity.
- La actualización automática de tokens no interactiva se administra mediante el framework.
- La aplicación usa abstracciones de servicio del lado servidor y del lado cliente para mostrar los datos meteorológicos generados:
- Al renderizar el componente
Weather
en el servidor para mostrar los datos meteorológicos, el componente usa elServerWeatherForecaster
. Los paquetes web de Microsoft Identity proporcionan API para crear un servicio web descendente con nombre para realizar llamadas a la API web. IDownstreamApi se inyecta enServerWeatherForecaster
, que se utiliza para llamar a CallApiForUserAsync para obtener datos meteorológicos de una API web externa (proyectoMinimalApiJwt
). - Cuando el componente
Weather
se representa en el cliente, el componente usa la implementación del servicioClientWeatherForecaster
, que usa un preconfigurado HttpClient (en el archivoProgram
del proyecto cliente) para realizar una llamada API web a la API mínima del proyecto del servidor (/weather-forecast
) para obtener datos meteorológicos. El punto de conexión de la API Mínima obtiene los datos meteorológicos de la claseServerWeatherForecaster
y los retorna al cliente para que el componente los represente.
- Al renderizar el componente
Solución de ejemplo
La solución de ejemplo consta de los siguientes 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.MinimalApiJwt
: API web de back-end, que contiene un punto de conexión de API mínima de ejemplo para los datos meteorológicos.
Acceda al ejemplo a través de la carpeta de versión más reciente del repositorio de ejemplos de Blazor con el vínculo siguiente. El ejemplo está en la BlazorWebAppEntra
carpeta de .NET 9 o posterior.
Inicie la solución desde el Aspire/Aspire.AppHost
proyecto.
Vea o descargue el código de ejemplo (cómo descargarlo)
Microsoft Entra ID: registros de aplicaciones
Se recomienda usar registros independientes para aplicaciones y API web, incluso cuando las aplicaciones y las API web están en la misma solución. Las instrucciones siguientes son para la aplicación BlazorWebAppEntra
y MinimalApiJwt
API web de la solución de ejemplo, pero las mismas instrucciones se aplican generalmente a los registros basados en Entra para aplicaciones y API web.
Registre primero la API web (MinimalApiJwt
) para que pueda conceder acceso a la API web al registrar la aplicación. El identificador de inquilino y el identificador de cliente de la API web se usan para configurar la API web en su Program
archivo. Después de registrar la API web, exponga la API web en Registros> de aplicacionesExponga una API con un nombre de ámbito de Weather.Get
. Registre el URI del identificador de aplicación para usarlo en la configuración de la aplicación.
A continuación, registre la aplicación (BlazorWebAppEntra
) con una configuración de plataforma web y un URI de redirección de https://localhost/signin-oidc
(no se requiere un puerto). El ID de inquilino de la aplicación, el dominio de inquilino y el ID de cliente, junto con la dirección base de la API web, el URI de ID de aplicación y el nombre del ámbito meteorológico, se utilizan para configurar la aplicación en su archivo appsettings.json
. Conceda permiso de API para acceder a la API web en Registros de app>Permisos de API. Si la especificación de seguridad de la aplicación lo requiere, puede conceder el consentimiento del administrador para que la organización acceda a la API de la web. Los usuarios y grupos autorizados están asignados al registro de la aplicación en Registros de aplicaciones>Aplicaciones empresariales.
En la configuración de registro de app flujos híbridos y concesión implícita del portal Entra o Azure, no seleccione ninguna casilla de verificación para que el punto de conexión de autorización devuelva Access tokens o ID tokens. 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.
Cree un secreto de cliente en el registro de la aplicación en Entra o Azure Portal (Administrar>certificados y secretos>Nuevo secreto de cliente). Guarde el secreto de cliente Valor para utilizarlo en la siguiente sección.
Más adelante en este artículo se proporcionan instrucciones de configuración de Entra adicionales para configuraciones específicas.
Proyecto Blazor Web App del lado de servidor (BlazorWebAppEntra
)
El proyecto BlazorWebAppEntra
es el proyecto del lado servidor de la Blazor Web App.
Proyecto Blazor Web App del lado del 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.
Proyecto de API web de back-end (MinimalApiJwt
)
El proyecto MinimalApiJwt
es una API web de back-end para varios proyectos de front-end. El proyecto configura un punto de conexión de API mínima para datos meteorológicos.
El archivo MinimalApiJwt.http
se puede usar para probar la solicitud de datos meteorológicos. Ten en cuenta que el proyecto MinimalApiJwt
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.
El proyecto incluye paquetes y configuración para generar documentos openAPI y la interfaz de usuario de Swagger en el entorno de desarrollo. Para obtener más información, consulte Uso de los documentos openAPI generados.
Un punto de conexión de datos de previsión meteorológica seguro se encuentra en el archivo del Program
proyecto:
app.MapGet("/weather-forecast", () =>
{
var forecast = Enumerable.Range(1, 5).Select(index =>
new WeatherForecast
(
DateOnly.FromDateTime(DateTime.Now.AddDays(index)),
Random.Shared.Next(-20, 55),
summaries[Random.Shared.Next(summaries.Length)]
))
.ToArray();
return forecast;
}).RequireAuthorization();
El método de extensión RequireAuthorization requiere autorización para la definición de ruta. Para los controladores que agregues al proyecto, agrega el atributo [Authorize]
al controlador o la acción.
Configure el proyecto de API web backend (MinimalApiJwt
)
Configure el proyecto en el JwtBearerOptions de la llamada AddJwtBearer en el archivo MinimalApiJwt
del proyecto Program
.
Para el registro de la app web API, el ámbito Weather.Get
se configura en el portal Entra o Azure en Exponer una API.
Authority establece la autoridad para realizar llamadas OIDC.
jwtOptions.Authority = "{AUTHORITY}";
En los ejemplos siguientes se usa un identificador de inquilino de aaaabbbb-0000-cccc-1111-dddd2222eeee
.
Si la aplicación está registrada en un inquilino ME-ID, la autoridad debe coincidir con el emisor (iss
) del JWT devuelto por el proveedor de identidades:
jwtOptions.Authority = "https://sts.windows.net/aaaabbbb-0000-cccc-1111-dddd2222eeee/";
Si la aplicación está registrada en un inquilino de AAD B2C:
jwtOptions.Authority = "https://login.microsoftonline.com/aaaabbbb-0000-cccc-1111-dddd2222eeee/v2.0/";
Audience establece el Ámbito para cualquier token de acceso JWT recibido.
jwtOptions.Audience = "{AUDIENCE}";
Haga coincidir el valor únicamente con la ruta de acceso del URI de identificador de aplicación configurado al agregar el Weather.Get
ámbito de Exponer una API en Entra o Azure Portal. No incluya el nombre del ámbito, "Weather.Get
", en el valor .
En los ejemplos siguientes se usa un identificador de aplicación (cliente) de 11112222-bbbb-3333-cccc-4444dddd5555
. En el segundo ejemplo se usa un dominio de cliente de contoso.onmicrosoft.com
.
Ejemplo de arrendatario ME-ID:
jwtOptions.Audience = "api://11112222-bbbb-3333-cccc-4444dddd5555";
AAD B2C tenant ejemplo:
jwtOptions.Audience = "https://contoso.onmicrosoft.com/11112222-bbbb-3333-cccc-4444dddd5555";
Configurar el proyecto de servidor (BlazorWebAppEntra
)
AddMicrosoftIdentityWebApp desde Microsoft Identity Web (Microsoft.Identity.Web
paquete NuGet, documentación de API) se configura en el BlazorWebAppEntra
archivo del Program
proyecto.
Obtenga el identificador de aplicación (cliente), el dominio del inquilino (publicador) y el identificador de directorio (inquilino) del registro de la aplicación en Entra o Azure Portal. El App ID URI se obtiene para el ámbito Weather.Get
a partir del registro de la API web. No incluya el nombre del ámbito cuando tome el App ID URI del portal.
En el archivo BlazorWebAppEntra
del proyecto Program
, proporcione los valores para los siguientes marcadores de posición en la configuración Web de Microsoft Identity:
builder.Services.AddAuthentication(OpenIdConnectDefaults.AuthenticationScheme)
.AddMicrosoftIdentityWebApp(msIdentityOptions =>
{
msIdentityOptions.CallbackPath = "/signin-oidc";
msIdentityOptions.ClientId = "{CLIENT ID (BLAZOR APP)}";
msIdentityOptions.Domain = "{DIRECTORY NAME}.onmicrosoft.com";
msIdentityOptions.Instance = "https://login.microsoftonline.com/";
msIdentityOptions.ResponseType = "code";
msIdentityOptions.TenantId = "{TENANT ID}";
})
.EnableTokenAcquisitionToCallDownstreamApi()
.AddDownstreamApi("DownstreamApi", configOptions =>
{
configOptions.BaseUrl = "{BASE ADDRESS}";
configOptions.Scopes = [ "{APP ID URI}/Weather.Get" ];
})
.AddDistributedTokenCaches();
Marcadores de posición en la configuración anterior:
{CLIENT ID (BLAZOR APP)}
: el identificador de la aplicación (cliente).{DIRECTORY NAME}
: el nombre de directorio del dominio del inquilino (publicador).{TENANT ID}
: ID de directorio (arrendatario).{BASE ADDRESS}
: dirección base de la API web.-
{APP ID URI}
: El URI de ID de aplicación para ámbitos de API web. Se utiliza cualquiera de los siguientes formatos, donde el marcador de posición{CLIENT ID (WEB API)}
es el Client Id del registro Entra de la API web, y el marcador de posición{DIRECTORY NAME}
es el nombre del directorio del dominio del tenant (editores) (ejemplo:contoso
).- Formato de inquilino ME-ID:
api://{CLIENT ID (WEB API)}
- Formato de inquilino B2C:
https://{DIRECTORY NAME}.onmicrosoft.com/{CLIENT ID (WEB API)}
- Formato de inquilino ME-ID:
Ejemplo:
builder.Services.AddAuthentication(OpenIdConnectDefaults.AuthenticationScheme)
.AddMicrosoftIdentityWebApp(msIdentityOptions =>
{
msIdentityOptions.CallbackPath = "/signin-oidc";
msIdentityOptions.ClientId = "00001111-aaaa-2222-bbbb-3333cccc4444";
msIdentityOptions.Domain = "contoso.onmicrosoft.com";
msIdentityOptions.Instance = "https://login.microsoftonline.com/";
msIdentityOptions.ResponseType = "code";
msIdentityOptions.TenantId = "aaaabbbb-0000-cccc-1111-dddd2222eeee";
})
.EnableTokenAcquisitionToCallDownstreamApi()
.AddDownstreamApi("DownstreamApi", configOptions =>
{
configOptions.BaseUrl = "https://localhost:7277";
configOptions.Scopes = [ "api://11112222-bbbb-3333-cccc-4444dddd5555/Weather.Get" ];
})
.AddDistributedTokenCaches();
Esta versión del artículo trata de la implementación de Entra con el patrón back-end para front-end (BFF). Cambie el selector de versión del artículo al patrón No BFF si la especificación de la aplicación no llama a la adopción del patrón BFF.
La siguiente especificación está cubierta:
- El Blazor Web App usa el modo de renderizado automático con interactividad global (
InteractiveAuto
). - El proyecto de servidor llama AddAuthenticationStateSerialization para agregar un proveedor de estado de autenticación del lado del servidor que usa PersistentComponentState para transferir el estado de autenticación hacia el cliente. El cliente llama AddAuthenticationStateDeserialization 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 Microsoft Entra ID, basado en los paquetes web de Microsoft Identity.
- La actualización automática de tokens no interactiva se administra mediante el framework.
- El patrón Backend for Frontend (BFF) se utiliza utilizando .NET Aspire para la detección de servicios y YARP para proxiar solicitudes a un endpoint meteorológico en la aplicación backend.
- Una API web de backend utiliza la autenticación JWT-bearer para validar los tokens JWT que la Blazor Web App guarda durante el proceso de inicio de sesión de la cookie.
- Aspire mejora la experiencia de creación de aplicaciones nativas de nube .NET. Proporciona un conjunto coherente y fundamentado de herramientas y patrones para compilar y ejecutar aplicaciones distribuidas.
- YARP es una biblioteca que se usa para crear un servidor proxy inverso.
- La aplicación usa abstracciones de servicio del lado servidor y del lado cliente para mostrar los datos meteorológicos generados.
- Al renderizar el componente
Weather
en el servidor para mostrar los datos meteorológicos, el componente usa elServerWeatherForecaster
. Los paquetes web de Microsoft Identity proporcionan API para crear un servicio web descendente con nombre para realizar llamadas a la API web. IDownstreamApi se inyecta enServerWeatherForecaster
, que se utiliza para llamar a CallApiForUserAsync para obtener datos meteorológicos de una API web externa (proyectoMinimalApiJwt
). - Cuando el componente
Weather
se representa en el cliente, el componente usa la implementación del servicioClientWeatherForecaster
, que usa un preconfigurado HttpClient (en el archivoProgram
del proyecto cliente) para realizar una llamada API web a la API mínima del proyecto del servidor (/weather-forecast
) para obtener datos meteorológicos. El punto de conexión mínimo de la API obtiene un token de acceso para el usuario llamando a GetAccessTokenForUserAsync. Junto con los ámbitos correctos, se realiza una llamada de proxy inverso a la API web externa (proyectoMinimalApiJwt
) para obtener y devolver los datos meteorológicos al cliente para su representación por el componente.
- Al renderizar el componente
Para obtener más información sobre .NET Aspire, consulta Disponibilidad general de .NET Aspire: simplificación del desarrollo nativo de nube de .NET (mayo de 2024).
Prerrequisitos
.NET Aspire requiere Visual Studio versión 17.10 o versión posterior.
Consulte también la sección Requisitos previos de Inicio rápido: Creación de la primera aplicación .NET Aspire.
Solución de ejemplo
La solución de ejemplo consta de los siguientes proyectos:
- .NET Aspire:
Aspire.AppHost
: se usa para administrar los problemas de orquestación de alto nivel de la aplicación.Aspire.ServiceDefaults
: contiene configuraciones de aplicaciones .NET Aspire predeterminadas que se pueden ampliar y personalizar según sea necesario.
MinimalApiJwt
: API web de back-end, que contiene un punto de conexión de API mínima de ejemplo para los datos meteorológicos.BlazorWebAppEntra
: Proyecto del lado del servidor de la clase Blazor Web App.BlazorWebAppEntra.Client
: proyecto del lado cliente de la Blazor Web App.
Acceda al ejemplo a través de la carpeta de versión más reciente del repositorio de ejemplos de Blazor con el vínculo siguiente. El ejemplo está en la BlazorWebAppEntraBff
carpeta de .NET 9 o posterior.
Vea o descargue el código de ejemplo (cómo descargarlo)
Microsoft Entra ID: registros de aplicaciones
Se recomienda usar registros independientes para aplicaciones y API web, incluso cuando las aplicaciones y las API web están en la misma solución. Las instrucciones siguientes son para la aplicación BlazorWebAppEntra
y MinimalApiJwt
API web de la solución de ejemplo, pero las mismas instrucciones se aplican generalmente a los registros basados en Entra para aplicaciones y API web.
Registre primero la API web (MinimalApiJwt
) para que pueda conceder acceso a la API web al registrar la aplicación. El identificador de inquilino y el identificador de cliente de la API web se usan para configurar la API web en su Program
archivo. Después de registrar la API web, exponga la API web en Registros> de aplicacionesExponga una API con un nombre de ámbito de Weather.Get
. Registre el URI del identificador de aplicación para usarlo en la configuración de la aplicación.
A continuación, registre la aplicación (BlazorWebAppEntra
) con una configuración de plataforma web y un URI de redirección de https://localhost/signin-oidc
(no se requiere un puerto). El ID de inquilino de la aplicación, el dominio de inquilino y el ID de cliente, junto con la dirección base de la API web, el URI de ID de aplicación y el nombre del ámbito meteorológico, se utilizan para configurar la aplicación en su archivo appsettings.json
. Conceda permiso de API para acceder a la API web en Registros de app>Permisos de API. Si la especificación de seguridad de la aplicación lo requiere, puede conceder el consentimiento del administrador para que la organización acceda a la API de la web. Los usuarios y grupos autorizados están asignados al registro de la aplicación en Registros de aplicaciones>Aplicaciones empresariales.
En la configuración de registro de app flujos híbridos y concesión implícita del portal Entra o Azure, no seleccione ninguna casilla de verificación para que el punto de conexión de autorización devuelva Access tokens o ID tokens. 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.
Cree un secreto de cliente en el registro de la aplicación en Entra o Azure Portal (Administrar>certificados y secretos>Nuevo secreto de cliente). Guarde el secreto de cliente Valor para utilizarlo en la siguiente sección.
Más adelante en este artículo se proporcionan instrucciones de configuración de Entra adicionales para configuraciones específicas.
Proyectos .NET Aspire
Para obtener más información sobre el uso de .NET Aspire y detalles sobre los proyectos .AppHost
y .ServiceDefaults
de la aplicación de ejemplo, consulta la documentación de .NET Aspire.
Confirma que cumples los requisitos previos para .NET Aspire. Para obtener más información, consulta la sección Requisitos previos de Inicio rápido: Compilación de la primera aplicación .NET Aspire.
La aplicación de muestra solo configura un perfil de inicio HTTP no seguro (http
) para usarlo durante las pruebas de desarrollo. Para obtener más información, incluido un ejemplo de perfiles de configuración de inicio inseguros y seguros, consulte Permitir el transporte no seguro en .NET Aspire (.NET Aspire documentación).
Proyecto Blazor Web App del lado de servidor (BlazorWebAppEntra
)
El proyecto BlazorWebAppEntra
es el proyecto del lado servidor de la Blazor Web App.
Proyecto Blazor Web App del lado del 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.
Proyecto de API web de back-end (MinimalApiJwt
)
El proyecto MinimalApiJwt
es una API web de back-end para varios proyectos de front-end. El proyecto configura un punto de conexión de API mínima para datos meteorológicos. Las solicitudes del proyecto del lado del servidor Blazor Web App (BlazorWebAppEntra
) se redirigen mediante proxy al proyecto MinimalApiJwt
.
El archivo MinimalApiJwt.http
se puede usar para probar la solicitud de datos meteorológicos. Ten en cuenta que el proyecto MinimalApiJwt
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.
El proyecto incluye paquetes y configuración para generar documentos openAPI y la interfaz de usuario de Swagger en el entorno de desarrollo. Para obtener más información, consulte Uso de los documentos openAPI generados.
Un punto de conexión de datos de previsión meteorológica seguro se encuentra en el archivo del Program
proyecto:
app.MapGet("/weather-forecast", () =>
{
var forecast = Enumerable.Range(1, 5).Select(index =>
new WeatherForecast
(
DateOnly.FromDateTime(DateTime.Now.AddDays(index)),
Random.Shared.Next(-20, 55),
summaries[Random.Shared.Next(summaries.Length)]
))
.ToArray();
return forecast;
}).RequireAuthorization();
El método de extensión RequireAuthorization requiere autorización para la definición de ruta. Para los controladores que agregues al proyecto, agrega el atributo [Authorize]
al controlador o la acción.
Configure el proyecto de API web backend (MinimalApiJwt
)
Configure el proyecto MinimalApiJwt
en el JwtBearerOptions de la llamada AddJwtBearer en el archivo Program
del proyecto.
Para el registro de la app web API, el ámbito Weather.Get
se configura en el portal Entra o Azure en Exponer una API.
Authority establece la autoridad para realizar llamadas OIDC.
jwtOptions.Authority = "{AUTHORITY}";
En los ejemplos siguientes se usa un identificador de inquilino de aaaabbbb-0000-cccc-1111-dddd2222eeee
.
Si la aplicación está registrada en un inquilino ME-ID, la autoridad debe coincidir con el emisor (iss
) del JWT devuelto por el proveedor de identidades:
jwtOptions.Authority = "https://sts.windows.net/aaaabbbb-0000-cccc-1111-dddd2222eeee/";
Si la aplicación está registrada en un inquilino de AAD B2C:
jwtOptions.Authority = "https://login.microsoftonline.com/aaaabbbb-0000-cccc-1111-dddd2222eeee/v2.0/";
Audience establece el Ámbito para cualquier token de acceso JWT recibido.
jwtOptions.Audience = "{AUDIENCE}";
Haga coincidir el valor únicamente con la ruta de acceso del URI de identificador de aplicación configurado al agregar el Weather.Get
ámbito de Exponer una API en Entra o Azure Portal. No incluya el nombre del ámbito, "Weather.Get
", en el valor .
En los ejemplos siguientes se usa un identificador de aplicación (cliente) de 11112222-bbbb-3333-cccc-4444dddd5555
. En el segundo ejemplo se usa un dominio de cliente de contoso.onmicrosoft.com
.
Ejemplo de arrendatario ME-ID:
jwtOptions.Audience = "api://11112222-bbbb-3333-cccc-4444dddd5555";
AAD B2C tenant ejemplo:
jwtOptions.Audience = "https://contoso.onmicrosoft.com/11112222-bbbb-3333-cccc-4444dddd5555";
Configurar el proyecto de servidor (BlazorWebAppEntra
)
AddMicrosoftIdentityWebApp desde Microsoft Identity Web (Microsoft.Identity.Web
paquete NuGet, documentación de API) se configura en el BlazorWebAppEntra
archivo del Program
proyecto.
Obtenga el identificador de aplicación (cliente), el dominio del inquilino (publicador) y el identificador de directorio (inquilino) del registro de la aplicación en Entra o Azure Portal. El App ID URI se obtiene para el ámbito Weather.Get
a partir del registro de la API web. No incluya el nombre del ámbito cuando tome el App ID URI del portal.
En el archivo BlazorWebAppEntra
del proyecto Program
, proporcione los valores para los siguientes marcadores de posición en la configuración Web de Microsoft Identity:
builder.Services.AddAuthentication(OpenIdConnectDefaults.AuthenticationScheme)
.AddMicrosoftIdentityWebApp(msIdentityOptions =>
{
msIdentityOptions.CallbackPath = "/signin-oidc";
msIdentityOptions.ClientId = "{CLIENT ID (BLAZOR APP)}";
msIdentityOptions.Domain = "{DIRECTORY NAME}.onmicrosoft.com";
msIdentityOptions.Instance = "https://login.microsoftonline.com/";
msIdentityOptions.ResponseType = "code";
msIdentityOptions.TenantId = "{TENANT ID}";
})
.EnableTokenAcquisitionToCallDownstreamApi()
.AddDownstreamApi("DownstreamApi", configOptions =>
{
configOptions.BaseUrl = "{BASE ADDRESS}";
configOptions.Scopes = [ "{APP ID URI}/Weather.Get" ];
})
.AddDistributedTokenCaches();
Marcadores de posición en la configuración anterior:
{CLIENT ID (BLAZOR APP)}
: el identificador de la aplicación (cliente).{DIRECTORY NAME}
: el nombre de directorio del dominio del inquilino (publicador).{TENANT ID}
: ID de directorio (arrendatario).{BASE ADDRESS}
: dirección base de la API web.-
{APP ID URI}
: El URI de ID de aplicación para ámbitos de API web. Se utiliza cualquiera de los siguientes formatos, donde el marcador de posición{CLIENT ID (WEB API)}
es el Client Id del registro Entra de la API web, y el marcador de posición{DIRECTORY NAME}
es el nombre del directorio del dominio del tenant (editores) (ejemplo:contoso
).- Formato de inquilino ME-ID:
api://{CLIENT ID (WEB API)}
- Formato de inquilino B2C:
https://{DIRECTORY NAME}.onmicrosoft.com/{CLIENT ID (WEB API)}
- Formato de inquilino ME-ID:
Ejemplo:
builder.Services.AddAuthentication(OpenIdConnectDefaults.AuthenticationScheme)
.AddMicrosoftIdentityWebApp(msIdentityOptions =>
{
msIdentityOptions.CallbackPath = "/signin-oidc";
msIdentityOptions.ClientId = "00001111-aaaa-2222-bbbb-3333cccc4444";
msIdentityOptions.Domain = "contoso.onmicrosoft.com";
msIdentityOptions.Instance = "https://login.microsoftonline.com/";
msIdentityOptions.ResponseType = "code";
msIdentityOptions.TenantId = "aaaabbbb-0000-cccc-1111-dddd2222eeee";
})
.EnableTokenAcquisitionToCallDownstreamApi()
.AddDownstreamApi("DownstreamApi", configOptions =>
{
configOptions.BaseUrl = "https://localhost:7277";
configOptions.Scopes = [ "api://11112222-bbbb-3333-cccc-4444dddd5555/Weather.Get" ];
})
.AddDistributedTokenCaches();
Advertencia
Las aplicaciones de producción deben usar un proveedor de caché de tokens distribuidos de producción. De lo contrario, la aplicación puede tener un rendimiento deficiente en algunos escenarios. Para obtener más información, consulte la sección Uso de un proveedor de caché de tokens distribuidos de producción .
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 el portal de Entra o Azure. Las rutas de acceso se configuran en el panel de 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).
El SignedOutCallbackPath es la ruta de solicitud dentro de la ruta base de la app interceptada por el manejador OpenID Connect donde el agente de usuario es devuelto por primera vez después de firmar desde Entra. La aplicación de ejemplo no establece un valor para la ruta de acceso porque se usa el valor predeterminado de "/signout-callback-oidc
". Después de interceptar la solicitud, el controlador openID Connect redirige al SignedOutRedirectUri o RedirectUri, si se especifica.
Configure la ruta de devolución de llamada cuando se cierre la sesión en el registro de Entra de la aplicación. En el portal Entra o Azure, establezca la ruta en las entradas Redireccionamiento URI de la configuración de la plataforma Web:
https://localhost/signout-callback-oidc
Nota
No se requiere un puerto para direcciones localhost
cuando se utiliza Entra.
Si no se agrega el URI de la ruta de retorno de llamada de salida al registro de la aplicación en Entra, Entra se niega a redirigir al usuario de vuelta a la aplicación y simplemente le pide que cierre la ventana de su navegador.
Nota
Entra no redirige a un usuario administrador principal (cuenta raíz) ni a un usuario externo a la aplicación de Blazor. En su lugar, Entra cierra la sesión del usuario de la aplicación y recomienda que cierre todas sus ventanas del explorador. Para obtener más información, vea postLogoutRedirectUri no funciona cuando la dirección URL de autoridad contiene un identificador de inquilino (AzureAD/microsoft-authentication-library-for-js
#5783).
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
Esta sección solo se aplica al proyecto de servidor de Blazor Web App.
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. Utilice flujos de autenticación seguros, como cualquiera de los enfoques o ambos de esta sección.
Herramienta Administrador de secretos
La Herramienta de administración 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 servidor Blazor 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 marcador de posición {SECRET}
es el secreto del cliente obtenido del registro de 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 enlaza recursos para comenzar a usar Azure Key Vault. Para implementar el código de esta sección, registra el URI de el almacén de claves y el nombre del secreto de Azure cuando crees el almacén de claves y el secreto. En el ejemplo de esta sección, el nombre del secreto es "BlazorWebAppEntraClientSecret
".
Al establecer la bóveda de claves en el portal Entra o Azure:
Configure la bóveda de claves para utilizar el control de acceso basado en roles (RABC) de Azure. Si no está trabajando en una instancia de Azure Virtual Network, incluido el desarrollo y las pruebas locales, confirme que el acceso público en el paso Redes está habilitado (activado). Al habilitar el acceso público solo se expone el punto final del depósito de claves. Las cuentas autenticadas siguen siendo necesarias para el acceso.
Cree un Azure Managed Identity (o agregue un rol al Managed Identity existente que planea utilizar) con el rol Key Vault Secrets User. Asigne el Managed Identity al Azure App Service que hospeda la implementación: Configuración>Identity>Usuario asignado>Añadir.
Nota
Si también tiene previsto ejecutar una aplicación localmente con un usuario autorizado para el acceso a Azure Key Vault mediante la CLI de Azure o la autenticación de servicio de Azure de Visual Studio, agregue su cuenta de usuario de Azure de desarrollador en Control de acceso (IAM) con el rol de usuario de Secretos de Key Vault. Si quiere usar la CLI de Azure a través de Visual Studio, ejecute el
az login
comando desde el panel de PowerShell para desarrolladores y siga las indicaciones para autenticarse con el inquilino.
Para implementar el código de esta sección, registre el URI del almacén de claves (por ejemplo: "https://contoso.vault.azure.net/
", barra diagonal final requerida) y el nombre del secreto (ejemplo: "BlazorWebAppEntraClientSecret
") de Azure al crear el almacén de claves y el secreto.
Importante
Un secreto de almacén de claves se crea con una fecha de caducidad. Asegúrese de hacer un seguimiento de la fecha de expiración de un secreto del almacén de claves y crear un nuevo secreto para la aplicación antes de que pase la fecha de expiración.
Agregue la siguiente clase AzureHelper
al proyecto de servidor. El método GetKeyVaultSecret
recupera un secreto de una bóveda de claves. Ajuste el espacio de nombres (BlazorSample.Helpers
) para que coincida con el esquema del espacio de nombres del proyecto.
Helpers/AzureHelper.cs
:
using Azure.Core;
using Azure.Security.KeyVault.Secrets;
namespace BlazorWebAppEntra.Helpers;
public static class AzureHelper
{
public static string GetKeyVaultSecret(string vaultUri,
TokenCredential credential, string secretName)
{
var client = new SecretClient(new Uri(vaultUri), credential);
var secret = client.GetSecretAsync(secretName).Result;
return secret.Value.Value;
}
}
Nota
En el ejemplo anterior se usa DefaultAzureCredential para simplificar la autenticación al desarrollar aplicaciones que se implementan en Azure mediante la combinación de credenciales usadas en entornos de hospedaje de Azure con credenciales usadas en el desarrollo local. Al pasar a producción, una alternativa es una mejor opción, como ManagedIdentityCredential. Para más información, consulte Autenticación de aplicaciones .NET hospedadas en Azure en recursos de Azure mediante una identidad administrada asignada por el sistema.
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:
TokenCredential? credential;
if (builder.Environment.IsProduction())
{
credential = new ManagedIdentityCredential("{MANAGED IDENTITY CLIENT ID}");
}
else
{
// Local development and testing only
DefaultAzureCredentialOptions options = new()
{
// Specify the tenant ID to use the dev credentials when running the app locally
// in Visual Studio.
VisualStudioTenantId = "{TENANT ID}",
SharedTokenCacheTenantId = "{TENANT ID}"
};
credential = new DefaultAzureCredential(options);
}
Cuando MicrosoftIdentityOptions estén configurados, llame a GetKeyVaultSecret
para recibir y asignar el secreto de cliente de la aplicación:
msIdentityOptions.ClientSecret = AzureHelper.GetKeyVaultSecret("{VAULT URI}",
credential, "{SECRET NAME}");
{MANAGED IDENTITY CLIENT ID}
: identificador de cliente administrado Identity (GUID) de Azure.
{TENANT ID}
: ID de directorio (arrendatario). Ejemplo: aaaabbbb-0000-cccc-1111-dddd2222eeee
{VAULT URI}
: URI del almacén de claves. Incluya la barra diagonal final en el URI. Ejemplo: https://contoso.vault.azure.net/
{SECRET NAME}
: nombre secreto. Ejemplo: BlazorWebAppEntraClientSecret
La configuración se utiliza para facilitar el suministro de bóvedas de claves dedicadas 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
en etapa de pruebas y appsettings.Production.json
para el despliegue en producción. Para obtener más información, consulta Configuración de Blazor en ASP.NET Core.
Solo serializa el nombre y los reclamos de rol
En el archivo Program
, todas las reclamaciones se serializan estableciendo SerializeAllClaims en true
. Si solo desea que el nombre y las reclamaciones de rol se serialicen para CSR, quite la opción o establézcala en false
.
Configuración de suministro con el proveedor de configuración JSON (configuración de la app)
Los proyectos de solución de ejemplo configuran la autenticación Microsoft Identity Web y JWT bearer en sus archivos Program
con el fin de que los ajustes de configuración se puedan descubrir mediante el autocompletado de C#. Las aplicaciones profesionales suelen usar un proveedor de configuración para configurar las opciones de OIDC, como el proveedor de configuración JSON predeterminado. El proveedor de configuración JSON carga la configuración de la aplicación desde los archivos de configuración appsettings.json
/appsettings.{ENVIRONMENT}.json
, donde el {ENVIRONMENT}
marcador de posición es el entorno de ejecución de la aplicación. Siga las instrucciones de esta sección para usar los archivos de configuración de la aplicación para la configuración.
En el archivo de configuración de la aplicación (appsettings.json
) del BlazorWebAppEntra
proyecto, agregue la siguiente configuración JSON:
{
"AzureAd": {
"CallbackPath": "/signin-oidc",
"ClientId": "{CLIENT ID (BLAZOR APP)}",
"Domain": "{DIRECTORY NAME}.onmicrosoft.com",
"Instance": "https://login.microsoftonline.com/",
"ResponseType": "code",
"TenantId": "{TENANT ID}"
},
"DownstreamApi": {
"BaseUrl": "{BASE ADDRESS}",
"Scopes": [ "{APP ID URI}/Weather.Get" ]
}
}
Actualice los marcadores de posición de la configuración anterior para que coincidan con los valores que usa la aplicación en el Program
archivo:
{CLIENT ID (BLAZOR APP)}
: el identificador de la aplicación (cliente).{DIRECTORY NAME}
: el nombre de directorio del dominio del inquilino (publicador).{TENANT ID}
: ID de directorio (arrendatario).{BASE ADDRESS}
: dirección base de la API web.-
{APP ID URI}
: El URI de ID de aplicación para ámbitos de API web. Se utiliza cualquiera de los siguientes formatos, donde el marcador de posición{CLIENT ID (WEB API)}
es el Client Id del registro Entra de la API web, y el marcador de posición{DIRECTORY NAME}
es el nombre del directorio del dominio del tenant (editores) (ejemplo:contoso
).- Formato de inquilino ME-ID:
api://{CLIENT ID (WEB API)}
- Formato de inquilino B2C:
https://{DIRECTORY NAME}.onmicrosoft.com/{CLIENT ID (WEB API)}
- Formato de inquilino ME-ID:
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"
},
"DownstreamApi": {
"BaseUrl": "https://localhost:7277",
"Scopes": [ "api://11112222-bbbb-3333-cccc-4444dddd5555/Weather.Get" ]
}
Actualice los demás valores de la configuración anterior para que coincidan con los valores personalizados o no predeterminados usados en el Program
archivo.
El generador de autenticación recoge automáticamente la configuración.
Realice los siguientes cambios en el archivo Program
:
builder.Services.AddAuthentication(OpenIdConnectDefaults.AuthenticationScheme)
- .AddMicrosoftIdentityWebApp(msIdentityOptions =>
- {
- msIdentityOptions.CallbackPath = "...";
- msIdentityOptions.ClientId = "...";
- msIdentityOptions.Domain = "...";
- msIdentityOptions.Instance = "...";
- msIdentityOptions.ResponseType = "...";
- msIdentityOptions.TenantId = "...";
- })
+ .AddMicrosoftIdentityWebApp(builder.Configuration.GetSection("AzureAd"))
.EnableTokenAcquisitionToCallDownstreamApi()
- .AddDownstreamApi("DownstreamApi", configOptions =>
- {
- configOptions.BaseUrl = "...";
- configOptions.Scopes = [ "..." ];
- })
+ .AddDownstreamApi("DownstreamApi", builder.Configuration.GetSection("DownstreamApi"))
.AddDistributedTokenCaches();
Nota
Las aplicaciones de producción deben usar un proveedor de caché de tokens distribuidos de producción. De lo contrario, la aplicación puede tener un rendimiento deficiente en algunos escenarios. Para obtener más información, consulte la sección Uso de un proveedor de caché de tokens distribuidos de producción .
En el MinimalApiJwt
proyecto, agregue la siguiente configuración de la aplicación al archivo appsettings.json
:
"Authentication": {
"Schemes": {
"Bearer": {
"Authority": "https://sts.windows.net/{TENANT ID (WEB API)}/",
"ValidAudiences": [ "{APP ID URI (WEB API)}" ]
}
}
},
Actualice los marcadores de posición de la configuración anterior para que coincidan con los valores que usa la aplicación en el Program
archivo:
{TENANT ID (WEB API)}
: identificador de inquilino de la API web.{APP ID URI (WEB API)}
: el URI del identificador de aplicación de la API web.
Los formatos de autoridad adoptan los siguientes patrones:
- ME-ID tipo de inquilino:
https://sts.windows.net/{TENANT ID}/
- Tipo de arrendatario B2C:
https://login.microsoftonline.com/{TENANT ID}/v2.0/
Los formatos de audiencia adoptan los siguientes patrones ({CLIENT ID}
es el identificador de cliente de la API web; {DIRECTORY NAME}
es el nombre del directorio, por ejemplo, contoso
):
- ME-ID tipo de inquilino:
api://{CLIENT ID}
- Tipo de arrendatario B2C:
https://{DIRECTORY NAME}.onmicrosoft.com/{CLIENT ID}
El generador de autenticación de portador JWT recoge automáticamente la configuración.
Quite las siguientes líneas del Program
archivo:
- jwtOptions.Authority = "...";
- jwtOptions.Audience = "...";
Para obtener más información sobre la configuración, consulte los siguientes recursos:
Uso de un proveedor de caché de tokens distribuidos de producción
Las memorias caché de tokens distribuidos en memoria se crean al llamar a AddDistributedTokenCaches para garantizar que exista una implementación base disponible para el almacenamiento en caché de tokens distribuidos.
Las aplicaciones web de producción y las API web deben usar una caché de tokens distribuidos de producción (por ejemplo: Redis, Microsoft SQL Server, Microsoft Azure Cosmos DB).
Nota
Para el desarrollo y las pruebas locales en una sola máquina, puede usar cachés de tokens en memoria en lugar de cachés de tokens distribuidos:
builder.Services.AddInMemoryTokenCaches();
Más adelante en el período de desarrollo y pruebas, adopte un proveedor de caché de tokens distribuidos de producción.
AddDistributedMemoryCache agrega una implementación predeterminada de IDistributedCache que almacena los elementos de caché en memoria, que es utilizada por Microsoft Identity Web para el almacenamiento en caché de tokens.
La caché de tokens distribuida se configura mediante MsalDistributedTokenCacheAdapterOptions:
- En el desarrollo con fines de depuración, puede desactivar la caché L1 estableciendo DisableL1Cache en
true
. Asegúrese de restablecerlo afalse
para producción. - Establezca el tamaño máximo de la memoria caché L1 con
L1CacheOptions.SizeLimit
para evitar que la memoria caché sobrerute la memoria del servidor. El valor predeterminado es 500 MB. - En desarrollo con fines de depuración, puede desactivar el cifrado de tokens en reposo estableciendo Encrypt en
false
, que es el valor predeterminado. Asegúrese de restablecerlo atrue
para producción. - Establezca la expulsión de tokens de la memoria caché con SlidingExpiration. El valor predeterminado es 1 hora.
- Para obtener más información, incluida la orientación sobre la devolución de llamada para fallos de caché L2 (OnL2CacheFailure) y escrituras asíncronas de caché L2 (EnableAsyncL2Write), consulte MsalDistributedTokenCacheAdapterOptions y Serialización de caché de tokens: Cachés de tokens distribuidas.
builder.Services.AddDistributedMemoryCache();
builder.Services.Configure<MsalDistributedTokenCacheAdapterOptions>(
options =>
{
// The following lines that are commented out reflect
// default values. We recommend overriding the default
// value of Encrypt to encrypt tokens at rest.
//options.DisableL1Cache = false;
//options.L1CacheOptions.SizeLimit = 500 * 1024 * 1024;
options.Encrypt = true;
//options.SlidingExpiration = TimeSpan.FromHours(1);
});
AddDistributedMemoryCache requiere una referencia de paquete al Microsoft.Extensions.Caching.Memory
paquete NuGet.
Nota
Para obtener instrucciones sobre cómo agregar paquetes a aplicaciones .NET, consulta los artículos de Instalación y administración de paquetes en Flujo de trabajo de consumo de paquetes (documentación de NuGet). Confirme las versiones correctas del paquete en NuGet.org.
Para configurar un proveedor de caché distribuida de producción, consulte Almacenamiento en caché distribuido en ASP.NET Core.
Advertencia
Reemplace siempre las memorias caché de tokens distribuidos en memoria por un proveedor de caché de tokens real al implementar la aplicación en un entorno de producción. Si no adopta un proveedor de caché de tokens distribuidos de producción, la aplicación puede sufrir un rendimiento significativamente degradado.
Para obtener más información, consulte Serialización de caché de tokens: cachés distribuidas. Sin embargo, los ejemplos de código que se muestran no se aplican a aplicaciones de ASP.NET Core, que configuran cachés distribuidas a través de AddDistributedMemoryCache, no AddDistributedTokenCache.
Utilice un anillo de claves de protección de datos compartido en producción para que las instancias de la aplicación en los servidores de una granja web puedan descifrar tokens cuando MsalDistributedTokenCacheAdapterOptions.Encrypt se establezca en true
.
Nota
Para el desarrollo temprano y las pruebas locales en una sola máquina, puede establecer Encrypt a false
y configurar un anillo compartido de claves de protección de datos más adelante:
options.Encrypt = false;
Más adelante en el período de desarrollo y pruebas, habilite el cifrado de tokens y adopte un anillo de claves de protección de datos compartido.
En el ejemplo siguiente se muestra cómo usar Azure Blob Storage y Azure Key Vault (PersistKeysToAzureBlobStorage
/ProtectKeysWithAzureKeyVault
) para el anillo de claves compartido. Las configuraciones de servicio son escenarios de casos base con fines de demostración. Antes de implementar aplicaciones de producción, familiarícese con los servicios de Azure y adopte procedimientos recomendados mediante los conjuntos de documentación dedicados de los servicios de Azure, que están vinculados al final de esta sección.
Confirme la presencia de los siguientes paquetes en el proyecto de servidor de Blazor Web App:
Nota
Para obtener instrucciones sobre cómo agregar paquetes a aplicaciones .NET, consulta los artículos de Instalación y administración de paquetes en Flujo de trabajo de consumo de paquetes (documentación de NuGet). Confirme las versiones correctas del paquete en NuGet.org.
Nota
Antes de continuar con los pasos siguientes, confirme que la aplicación está registrada con Microsoft Entra.
El código siguiente se implementa normalmente al mismo tiempo que se implementa un proveedor de caché de tokens distribuidos de producción . Otras opciones, tanto dentro de Azure como fuera de Azure, están disponibles para administrar claves de protección de datos en varias instancias de aplicación, pero la aplicación de ejemplo muestra cómo usar los servicios de Azure.
Configure Azure Blob Storage para mantener las claves de protección de datos. Siga las instrucciones de Proveedores de almacenamiento de claves en ASP.NET Core.
Configure Azure Key Vault para cifrar las claves de protección de datos en reposo. Siga las instrucciones de Configuración de la protección de datos de ASP.NET Core.
Use el código siguiente en el Program
archivo donde se registran los servicios:
TokenCredential? credential;
if (builder.Environment.IsProduction())
{
credential = new ManagedIdentityCredential("{MANAGED IDENTITY CLIENT ID}");
}
else
{
// Local development and testing only
DefaultAzureCredentialOptions options = new()
{
// Specify the tenant ID to use the dev credentials when running the app locally
// in Visual Studio.
VisualStudioTenantId = "{TENANT ID}",
SharedTokenCacheTenantId = "{TENANT ID}"
};
credential = new DefaultAzureCredential(options);
}
builder.Services.AddDataProtection()
.SetApplicationName("BlazorWebAppEntra")
.PersistKeysToAzureBlobStorage(new Uri("{BLOB URI}"), credential)
.ProtectKeysWithAzureKeyVault(new Uri("{KEY IDENTIFIER}"), credential);
Puede pasar cualquier nombre de aplicación a SetApplicationName. Solo tiene que confirmar que todas las implementaciones de aplicaciones usan el mismo valor.
{MANAGED IDENTITY CLIENT ID}
: identificador de cliente administrado Identity (GUID) de Azure.
{TENANT ID}
: id. de inquilino.
{BLOB URI}
: URI completo al archivo de claves. Azure Storage genera el URI al crear el archivo de clave. No utilice un SAS.
{KEY IDENTIFIER}
: identificador de clave de Azure Key Vault que se usa para el cifrado de claves. Una directiva de acceso permite a la aplicación acceder al almacén de claves con permisos Get
, Unwrap Key
y Wrap Key
. La versión de la clave se obtiene del portal de Entra o del portal de Azure después de que la clave ha sido creada. Si habilita la autorotación de la clave de la bóveda de claves, asegúrese de utilizar un identificador de clave sin versión en la configuración de la bóveda de claves de la aplicación, donde no se coloque ningún GUID de clave al final del identificador (ejemplo: https://contoso.vault.azure.net/keys/data-protection
).
Nota
En entornos que no son de producción, el ejemplo anterior usa DefaultAzureCredential para simplificar la autenticación al desarrollar aplicaciones que se implementan en Azure mediante la combinación de credenciales usadas en entornos de hospedaje de Azure con credenciales usadas en el desarrollo local. Para más información, consulte Autenticación de aplicaciones .NET hospedadas en Azure en recursos de Azure mediante una identidad administrada asignada por el sistema.
Como alternativa, puede configurar la aplicación para proporcionar los valores de los archivos de configuración de la aplicación mediante el proveedor de configuración JSON. Agregue lo siguiente al archivo de configuración de la aplicación:
"DistributedTokenCache": {
"DisableL1Cache": false,
"L1CacheSizeLimit": 524288000,
"Encrypt": true,
"SlidingExpirationInHours": 1
},
"DataProtection": {
"BlobUri": "{BLOB URI}",
"KeyIdentifier": "{KEY IDENTIFIER}"
}
Sección de ejemplo DataProtection
:
"DataProtection": {
"BlobUri": "https://contoso.blob.core.windows.net/data-protection/keys.xml",
"KeyIdentifier": "https://contoso.vault.azure.net/keys/data-protection"
}
Nota
El identificador de clave del ejemplo anterior es sin versiones. No hay ninguna versión de clave GUID al final del identificador. Esto es especialmente importante si opta por configurar la rotación automática de claves para la clave. Para más información, consulte Configuración de la rotación automática de claves criptográficas en Azure Key Vault: Directiva de rotación de claves.
Realice los siguientes cambios en el archivo Program
:
builder.Services.Configure<MsalDistributedTokenCacheAdapterOptions>(
options =>
{
+ var config = builder.Configuration.GetSection("DistributedTokenCache");
- options.DisableL1Cache = false;
+ options.DisableL1Cache = config.GetValue<bool>("DisableL1Cache");
- options.L1CacheOptions.SizeLimit = 500 * 1024 * 1024;
+ options.L1CacheOptions.SizeLimit = config.GetValue<long>("L1CacheSizeLimit");
- options.Encrypt = true;
+ options.Encrypt = config.GetValue<bool>("Encrypt");
- options.SlidingExpiration = TimeSpan.FromHours(1);
+ options.SlidingExpiration =
+ TimeSpan.FromHours(config.GetValue<int>("SlidingExpirationInHours"));
});
- builder.Services.AddDataProtection()
- .SetApplicationName("BlazorWebAppEntra")
- .PersistKeysToAzureBlobStorage(new Uri("{BLOB URI}"), credential)
- .ProtectKeysWithAzureKeyVault(new Uri("{KEY IDENTIFIER}"), credential);
Agregue el código siguiente donde los servicios están configurados en el Program
archivo:
var config = builder.Configuration.GetSection("DataProtection");
builder.Services.AddDataProtection()
.SetApplicationName("BlazorWebAppEntra")
.PersistKeysToAzureBlobStorage(
new Uri(config.GetValue<string>("BlobUri") ??
throw new Exception("Missing Blob URI")),
credential)
.ProtectKeysWithAzureKeyVault(
new Uri(config.GetValue<string>("KeyIdentifier") ??
throw new Exception("Missing Key Identifier")),
credential);
Para obtener más información sobre el uso de un anillo de claves y proveedores de almacenamiento de claves compartidos de Protección de datos, consulte los siguientes recursos:
- Proveedores de almacenamiento de claves en ASP.NET Core
- Configuración de la protección de datos principal de ASP.NET
- Uso del SDK de Azure para .NET en aplicaciones ASP.NET Core
- Hospedar ASP.NET Core en una granja de servidores web: Protección de datos
- Configuración de la protección de datos principal de ASP.NET
- Proveedores de almacenamiento de claves en ASP.NET Core
- Documentación de Azure Key Vault
- Documentación de Azure Storage
- Acceso a las claves, los certificados y los secretos de Key Vault con un control de acceso basado en rol de Azure
Prefijo de destino del reenviador YARP
El reenviador YARP del proyecto de servidor Blazor Web App, donde el token de acceso del usuario está vinculado a la llamada a la API web MinimalApiJwt
, especifica un prefijo de destino de https://weatherapi
. Este valor coincide con el nombre del proyecto pasado a AddProject en el archivo Program
del proyecto Aspire.AppHost
.
Reenviador en el servidor Blazor Web App del proyecto (BlazorWebAppEntra
):
app.MapForwarder("/weather-forecast", "https://weatherapi", transformBuilder =>
{
...
}).RequireAuthorization();
Nombre de proyecto coincidente en el Program
archivo del proyecto Aspire App Host (Aspire.AppHost
):
var weatherApi = builder.AddProject<Projects.MinimalApiJwt>("weatherapi");
No es necesario cambiar el prefijo de destino del reenviador YARP al desplegar el Blazor Web App a producción. El paquete de la API Web Descendente de Microsoft Identity utiliza el URI de base proporcionado a través de la configuración para realizar la llamada a la API web desde ServerWeatherForecaster
, y no el prefijo de destino del reenvío YARP. En producción, el reenviador YARP simplemente transforma la solicitud, agregando el token de acceso del usuario.
Redireccionamiento a la página principal al cerrar sesión
El componente LogInOrOut
(Layout/LogInOrOut.razor
) establece un campo oculto para la dirección URL de retorno (ReturnUrl
) en la dirección URL actual (currentURL
). Cuando el usuario cierra la sesión de la aplicación, el proveedor de identidades devuelve al usuario a la página desde la que ha cerrado la sesión. Si el usuario cierra sesión desde una página segura, se devuelve a la misma página segura y se devuelve a través del proceso de autenticación. Este flujo de autenticación es razonable cuando los usuarios necesitan cambiar las cuentas con regularidad.
Como alternativa, use el siguiente componente LogInOrOut
, que no proporciona una dirección URL de retorno al cerrar sesión.
Layout/LogInOrOut.razor
:
<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
</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>
Seguridad de datos meteorológicos
Para obtener más información sobre cómo esta aplicación protege sus datos meteorológicos, consulte Protección de datos en Blazor Web App con representación automática interactiva.
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 Blazor WebAssembly, consulte la sección Registro de autenticación del lado del cliente de Registro de ASP.NET Core Blazor con el selector de versión del artículo establecido en ASP.NET Core en .NET 7 o posterior.
Errores comunes
El depurador se interrumpe en una excepción durante el cierre de sesión con Microsoft Entra ID externo
La siguiente excepción detiene el depurador de Visual Studio durante el cierre de sesión con Microsoft Entra ID externo:
Uncaught TypeError TypeError: Failed to execute 'postMessage' on 'Window': The provided value cannot be converted to a sequence.
La excepción es lanzada desde el código JavaScript de Entra, por lo que no es un problema con ASP.NET Core. La excepción no afecta a la funcionalidad de la aplicación en producción, por lo que la excepción se puede omitir durante las pruebas de desarrollo local.
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 falta o incorrección de una autoridad, instancia, identificador de inquilino, dominio de inquilino, identificador de cliente o URI de redireccionamiento impide a una aplicación autenticar a los 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. Revisa cuidadosamente la configuración para detectar errores en la configuración de la aplicación y de la 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 aplicación del servidor o la dirección IP utilizando las herramientas de desarrollo del navegador. A menudo, la dirección IP o la aplicación del servidor 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, abra 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:
- Abra 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: Use
-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: Use
- Proporciona un nombre en el campo Nombre amigable. 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. - Restaure el proyecto y vuelva 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, use la galería de NuGet.
Iniciar la solución desde el proyecto correcto
Blazor Web Apps:
- Para uno de los ejemplos de patrones Backend-for-Frontend (BFF), inicie la solución desde el
Aspire/Aspire.AppHost
proyecto. - Para uno de los ejemplos de patrones que no son BFF, inicie la solución desde el proyecto de servidor.
Blazor Server:
Inicie la solución desde el proyecto de servidor.
Inspeccionar al 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
- Llamada a una API web desde una aplicación ASP.NET Core Blazor : Plataforma de identidad de Microsoft para llamadas API web
- documentación de la plataforma de identidad de Microsoft
- Documentación de la API web | Plataforma de identidad de Microsoft
- Una API web que llama a las API web: Llamada a una API: Opción 2: Llamada a una API web de bajada con la clase auxiliar
- Repositorio de GitHub: guía útil sobre la implementación de Microsoft Web para Microsoft Entra ID y Azure Active Directory B2C en aplicaciones de 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.
- Servicio
AuthenticationStateProvider
- Administración del estado de la autenticación en Blazor Web Apps
- Abstracciones de servicio en Blazor Web Apps