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 inserta enServerWeatherForecaster
, que se usa para llamar a CallApiForUserAsync y obtener datos meteorológicos de una API web externa (elMinimalApiJwt
proyecto). - 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)
Registros de aplicaciones de identificación de Microsoft Entra
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 identificador de inquilino, el dominio del inquilino y el identificador de cliente de la aplicación, junto con la dirección base de la API web, el URI del identificador de la aplicación y el nombre del ámbito de clima, se usan para configurar la aplicación en su archivo appsettings.json
. Conceda permiso de API para acceder a la API web en registros de aplicaciones>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 aplicaciones de flujos híbridos y concesión implícita de Entra o Azure Portal, no active ninguna casilla para que el punto de conexión de autorización devuelva tokens de acceso o tokens de identificador. 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). Mantenga presionado el valor del secreto de cliente para usar la sección siguiente.
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 AddJwtBearer llamada en el MinimalApiJwt
archivo del Program
proyecto.
Para el registro de la aplicación de API web, el alcance se configura en el portal de Entra o Azure en Weather.Get
.
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 la audiencia 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 inquilino de ME-ID:
jwtOptions.Audience = "api://11112222-bbbb-3333-cccc-4444dddd5555";
Ejemplo de inquilino de AAD B2C:
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 URI del identificador de aplicación se obtiene para el Weather.Get
ámbito del registro de la API web. No incluya el nombre del ámbito al tomar el URI del identificador de aplicación desde el portal.
En el BlazorWebAppEntra
archivo de proyecto Program
, proporcione los valores de 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 del App ID para ámbitos de API web. Se usan cualquiera de los siguientes formatos, donde el{CLIENT ID (WEB API)}
marcador de posición es el identificador de cliente del registro Entra de la API web y el{DIRECTORY NAME}
marcador de posición es el nombre de directorio del dominio del inquilino (publicadores) (ejemplo:contoso
).- ME-ID formato de inquilino:
api://{CLIENT ID (WEB API)}
- Formato de inquilino B2C:
https://{DIRECTORY NAME}.onmicrosoft.com/{CLIENT ID (WEB API)}
- ME-ID formato de inquilino:
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 inserta enServerWeatherForecaster
, que se usa para llamar a CallApiForUserAsync y obtener datos meteorológicos de una API web externa (elMinimalApiJwt
proyecto). - 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 (MinimalApiJwt
proyecto) para obtener y devolver datos meteorológicos al cliente para su representación por parte del 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)
Registros de aplicaciones de identificación de Microsoft Entra
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 identificador de inquilino, el dominio del inquilino y el identificador de cliente de la aplicación, junto con la dirección base de la API web, el URI del identificador de la aplicación y el nombre del ámbito de clima, se usan para configurar la aplicación en su archivo appsettings.json
. Conceda permiso de API para acceder a la API web en registros de aplicaciones>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 aplicaciones de flujos híbridos y concesión implícita de Entra o Azure Portal, no active ninguna casilla para que el punto de conexión de autorización devuelva tokens de acceso o tokens de identificador. 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). Mantenga presionado el valor del secreto de cliente para usar la sección siguiente.
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 MinimalApiJwt
proyecto en el JwtBearerOptions de la AddJwtBearer llamada en el archivo del Program
proyecto.
Para el registro de la aplicación de API web, el alcance se configura en el portal de Entra o Azure en Weather.Get
.
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 la audiencia 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 inquilino de ME-ID:
jwtOptions.Audience = "api://11112222-bbbb-3333-cccc-4444dddd5555";
Ejemplo de inquilino de AAD B2C:
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 URI del identificador de aplicación se obtiene para el Weather.Get
ámbito del registro de la API web. No incluya el nombre del ámbito al tomar el URI del identificador de aplicación desde el portal.
En el BlazorWebAppEntra
archivo de proyecto Program
, proporcione los valores de 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 del App ID para ámbitos de API web. Se usan cualquiera de los siguientes formatos, donde el{CLIENT ID (WEB API)}
marcador de posición es el identificador de cliente del registro Entra de la API web y el{DIRECTORY NAME}
marcador de posición es el nombre de directorio del dominio del inquilino (publicadores) (ejemplo:contoso
).- ME-ID formato de inquilino:
api://{CLIENT ID (WEB API)}
- Formato de inquilino B2C:
https://{DIRECTORY NAME}.onmicrosoft.com/{CLIENT ID (WEB API)}
- ME-ID formato de inquilino:
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).
SignedOutCallbackPath es la ruta de solicitud dentro de la ruta base de la aplicación que es interceptada por el manejador OpenID Connect, donde el agente de usuario es redirigido inicialmente después de cerrar sesión de 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 Blazor aplicación de servidor 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. Al establecer la política de acceso para el secreto en el panel de Directivas de acceso:
- Solo se requiere el permiso Obtener secreto.
- Seleccione la aplicación como Principal para 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;
using Azure.Identity;
using Azure.Security.KeyVault.Secrets;
namespace BlazorWebAppEntra.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 sección AzureAd
de appsettings.json
, agregue las siguientes claves VaultUri
y valores SecretName
de configuración:
"VaultUri": "{VAULT URI}",
"SecretName": "{SECRET NAME}"
En el ejemplo anterior:
- El marcador de posición
{VAULT URI}
es el URI de el almacén de claves. Incluya la barra diagonal final en el URI. - El marcador de posición
{SECRET NAME}
es el nombre del secreto.
Ejemplo:
"VaultUri": "https://contoso.vault.azure.net/",
"SecretName": "BlazorWebAppEntra"
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.
Serializar solo las reclamaciones de nombre y 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
.
Proporcione la configuración con el proveedor de configuración JSON (configuración de la aplicación)
Los proyectos de solución de ejemplo configuran la autenticación de portador Web y JWT de Microsoft en sus Identity archivos para hacer que las opciones de configuración sean identificables a través del 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 del App ID para ámbitos de API web. Se usan cualquiera de los siguientes formatos, donde el{CLIENT ID (WEB API)}
marcador de posición es el identificador de cliente del registro Entra de la API web y el{DIRECTORY NAME}
marcador de posición es el nombre de directorio del dominio del inquilino (publicadores) (ejemplo:contoso
).- ME-ID formato de inquilino:
api://{CLIENT ID (WEB API)}
- Formato de inquilino B2C:
https://{DIRECTORY NAME}.onmicrosoft.com/{CLIENT ID (WEB API)}
- ME-ID formato de 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"
},
"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 inquilino 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 inquilino 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 deshabilitar la memoria caché L1 configurando DisableL1Cache a
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. - Durante el desarrollo para fines de depuración, puede deshabilitar el cifrado de tokens en reposo estableciendo Encrypt a
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, incluidas las instrucciones sobre la devolución de llamada para errores de caché L2 (OnL2CacheFailure) y escrituras asincrónicas de caché L2 (EnableAsyncL2Write), consulte MsalDistributedTokenCacheAdapterOptions y Serialización de cachés de tokens: cachés de tokens distribuidos.
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.
Use un anillo compartido de claves de protección de datos en producción para que las instancias de la aplicación a través de servidores de una granja web puedan descifrar tokens cuando MsalDistributedTokenCacheAdapterOptions.Encrypt se establece 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 sus conjuntos de documentación dedicados, que se enumeran 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 y cifrarlas en reposo con Azure Key Vault:
Cree una cuenta de almacenamiento de Azure. El nombre de la cuenta en el ejemplo siguiente es
contoso
.Cree un contenedor para contener las claves de protección de datos. El nombre del contenedor en el ejemplo siguiente es
data-protection
.Cree el archivo de clave en el equipo local. En el ejemplo siguiente, el archivo de clave se denomina
keys.xml
. Puede usar un editor de texto para crear el archivo.keys.xml
:<?xml version="1.0" encoding="utf-8"?> <repository> </repository>
Cargue el archivo de clave (
keys.xml
) en el contenedor de la cuenta de almacenamiento. Use el comando View/edit del menú contextual al final de la fila de claves del portal para confirmar que el blob contiene el contenido anterior.Use el comando Generar SAS del menú contextual para obtener el URI del blob con una firma de acceso compartido (SAS). Al crear la SAS, use los siguientes permisos:
Read
,Add
,Create
,Write
, .Delete
El URI se usa más adelante donde aparece el{BLOB URI WITH SAS}
marcador de posición.
Al establecer el almacén de claves en el portal de Entra o Azure:
Configurar el almacén de claves para usar una directiva de acceso al almacén. Confirme que el acceso público en el paso Redes está habilitado (activado).
En el panel Directivas de acceso, cree una nueva directiva de acceso con permisos de
Get
,Unwrap Key
, yWrap Key
Clave. Seleccione la aplicación registrada como entidad de servicio.Cuando el cifrado de claves está activo, las claves del archivo de claves incluyen el comentario "This key is encrypted with Azure Key Vault." Después de iniciar la aplicación, seleccione el comando Ver o editar en el menú contextual al final de la fila de claves para confirmar que una clave está presente con la seguridad del almacén de claves aplicada.
El AzureEventSourceLogForwarder servicio del ejemplo siguiente reenvía los mensajes de registro del SDK de Azure para el registro y requiere el Microsoft.Extensions.Azure
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.
Al inicio del archivo Program
, proporcione acceso a la API en el espacio de nombres Microsoft.Extensions.Azure.
using Microsoft.Extensions.Azure;
Use el código siguiente en el Program
archivo donde se registran los servicios:
builder.Services.TryAddSingleton<AzureEventSourceLogForwarder>();
builder.Services.AddDataProtection()
.PersistKeysToAzureBlobStorage(new Uri("{BLOB URI WITH SAS}"))
.ProtectKeysWithAzureKeyVault(new Uri("{KEY IDENTIFIER}"), new DefaultAzureCredential());
{BLOB URI WITH SAS}
: el URI completo donde se debe almacenar el archivo de clave con el token de SAS como parámetro de cadena de consulta. Azure Storage genera el URI cuando solicita una SAS para el archivo de clave cargado. El nombre del contenedor en el ejemplo siguiente es data-protection
y el nombre de la cuenta de almacenamiento es contoso
. El archivo de clave se denomina keys.xml
.
Ejemplo:
https://contoso.blob.core.windows.net/data-protection/keys.xml?sp={PERMISSIONS}&st={START DATETIME}&se={EXPIRATION DATETIME}&spr=https&sv={STORAGE VERSION DATE}&sr=c&sig={TOKEN}
{KEY IDENTIFIER}
: identificador de clave de Azure Key Vault que se usa para el cifrado de claves. El nombre del almacén de claves es contoso
en el ejemplo siguiente, y una directiva de acceso permite a la aplicación acceder al almacén de claves con permisos de Get
, Unwrap Key
, y Wrap Key
. El nombre de clave de ejemplo es data-protection
. La versión de la clave ({KEY VERSION}
marcador de posición) se obtiene de la clave en Entra o Azure Portal después de crearla.
Ejemplo:
https://contoso.vault.azure.net/keys/data-protection/{KEY VERSION}
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": {
"BlobUriWithSasToken": "{BLOB URI WITH SAS}",
"KeyIdentifier": "{KEY IDENTIFIER}"
}
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()
- .PersistKeysToAzureBlobStorage(new Uri("{BLOB URI WITH SAS}"))
- .ProtectKeysWithAzureKeyVault(new Uri("{KEY IDENTIFIER}"), new DefaultAzureCredential());
Agregue el código siguiente donde los servicios están configurados en el Program
archivo:
var config = builder.Configuration.GetSection("DataProtection");
builder.Services.AddDataProtection()
.PersistKeysToAzureBlobStorage(
new Uri(config.GetValue<string>("BlobUriWithSasToken") ??
throw new Exception("Missing Blob URI")))
.ProtectKeysWithAzureKeyVault(
new Uri(config.GetValue<string>("KeyIdentifier") ??
throw new Exception("Missing Key Identifier")),
new DefaultAzureCredential());
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:
- 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
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 de trazas para la Blazor WebAssembly autenticación, consulte la sección Registro de autenticación del lado cliente de ASP.NET Blazor logging con el selector de versiones del artículo configurado 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