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 proporciona información general sobre los distintos tipos de errores y recomendaciones para controlar los errores de inicio de sesión comunes.
Aspectos básicos del control de errores de MSAL
Las excepciones de Biblioteca de autenticación de Microsoft (MSAL) están diseñadas para que los desarrolladores de aplicaciones solucionen problemas, no para mostrarlos a los usuarios finales. Los mensajes de excepción no se localizan.
Al procesar excepciones y errores, puede usar el propio tipo de excepción y el código de error para distinguir entre excepciones. Para obtener una lista de códigos de error, consulte Microsoft Entra códigos de error de autenticación y autorización.
Durante la experiencia de inicio de sesión, puede encontrar errores sobre los consentimientos, el acceso condicional (MFA, Administración de dispositivos, restricciones basadas en ubicación), la emisión y el canje de tokens y las propiedades del usuario.
En la sección siguiente se proporcionan más detalles sobre el control de errores de la aplicación.
Control de errores en MSAL.NET
Tipos de excepción
MsalClientException se produce cuando la propia biblioteca detecta un estado de error, como una configuración incorrecta.
MsalServiceException se produce cuando el proveedor de identidades (Microsoft Entra ID) devuelve un error. Se trata de una traducción del error del servidor.
MsalUIRequiredException es el tipo de MsalServiceException e indica que se requiere la interacción del usuario. Por ejemplo, cuando se requiere autenticación multifactor (MFA) o cuando el usuario cambia su contraseña y no se puede adquirir un token de forma silenciosa.
Procesamiento de excepciones
Al procesar excepciones de .NET, puede usar el propio tipo de excepción y el miembro ErrorCode para distinguir entre excepciones.
ErrorCode los valores son constantes de tipo MsalError.
También puede echar un vistazo a los campos de MsalClientException, MsalServiceException y MsalUIRequiredException.
Si se produce MsalServiceException , pruebe los códigos de error de autenticación y autorización para ver si el código aparece ahí.
Si se produce MsalUIRequiredException , se trata de una indicación de que es necesario que se produzca un flujo interactivo para que el usuario resuelva el problema. En las aplicaciones cliente públicas, como la aplicación de escritorio y móvil, se resuelve mediante una llamada a AcquireTokenInteractive, que muestra un explorador. En las aplicaciones cliente confidenciales, las aplicaciones web deben redirigir al usuario a la página de autorización y las API web deben devolver un código de estado HTTP y un encabezado indicativo del error de autenticación (401 No autorizado y un encabezado de WWW-Authenticate).
Excepciones comunes de .NET
Estas son las excepciones comunes que se pueden producir y algunas posibles mitigaciones:
| Exception | Código de error | Mitigation |
|---|---|---|
| MsalUiRequiredException | AADSTS65001: el usuario o administrador no ha dado su consentimiento para usar la aplicación con el identificador '{appId}' denominado '{appName}'. Envíe una solicitud de autorización interactiva para este usuario y recurso. | Obtenga primero el consentimiento del usuario. Si no usa .NET Core (que no tiene ninguna interfaz de usuario web), llame a (solo una vez) AcquireTokenInteractive. Si usa .NET núcleo o no quiere hacer un AcquireTokenInteractive, el usuario puede ir a una dirección URL para dar su consentimiento: https://login.microsoftonline.com/common/oauth2/v2.0/authorize?client_id={clientId}&response_type=code&scope=user.read. para llamar a AcquireTokenInteractive: app.AcquireTokenInteractive(scopes).WithAccount(account).WithClaims(ex.Claims).ExecuteAsync(); |
| MsalUiRequiredException | AADSTS50079: el usuario debe usar la autenticación multifactor (MFA). | No hay mitigación. Si la autenticación de dos factores (MFA) está configurada para su inquilino y Microsoft Entra ID decide aplicarla, recurra a un flujo interactivo como AcquireTokenInteractive. |
| MsalServiceException | AADSTS90010: The grant type isn't supported over the /common or /consumers endpoints. Use the /organizations or tenant-specific endpoint. Ha usado /common. | Tal y como se explica en el mensaje de Microsoft Entra ID, la autoridad debe tener un inquilino o, en su defecto, /organizaciones. |
| MsalServiceException | AADSTS70002: el cuerpo de la solicitud debe contener el parámetro siguiente: client_secret or client_assertion. |
Esta excepción se puede producir si la aplicación no se registró como una aplicación cliente pública en Microsoft Entra ID. En el centro de administración de Microsoft Entra, edite el manifiesto de su aplicación y establezca allowPublicClient en true. |
| MsalClientException |
unknown_user Message: no se pudo identificar el usuario que ha iniciado sesión. |
La biblioteca no pudo consultar qué usuario de Windows ha iniciado sesión actualmente, o bien este usuario no está unido a Active Directory ni a Microsoft Entra (no se admiten usuarios unidos al lugar de trabajo). Solución: Implementa tu propia lógica para obtener el nombre de usuario (por ejemplo, john@contoso.com) y utiliza el formulario AcquireTokenByIntegratedWindowsAuth que admite el nombre de usuario. |
| MsalClientException | la autenticación integrada de Windows no es compatible con el usuario administrado | Este método se basa en un protocolo expuesto por Active Directory (AD). Si se creó un usuario en Microsoft Entra ID sin respaldo de AD (usuario "administrado"), se produce un error en este método. Los usuarios creados en AD y respaldados por Microsoft Entra ID (usuarios "federados") pueden beneficiarse de este método de autenticación no interactivo. Mitigación: use la autenticación interactiva. |
MsalUiRequiredException
Uno de los códigos de estado comunes devueltos de MSAL.NET al llamar a AcquireTokenSilent() es MsalError.InvalidGrantError. Este código de estado significa que la aplicación debe llamar de nuevo a la biblioteca de autenticación, pero en modo interactivo (AcquireTokenInteractive o AcquireTokenByDeviceCodeFlow para aplicaciones cliente públicas, tiene un desafío en las aplicaciones web). Esto se debe a que se requiere interacción adicional del usuario antes de que se pueda emitir el token de autenticación.
La mayoría de las veces que AcquireTokenSilent se produce un error, se debe a que la caché de tokens no tiene tokens que coincidan con la solicitud. Los tokens de acceso expiran en 1 hora e AcquireTokenSilent intenta capturar uno nuevo basado en un token de actualización (en términos de OAuth2, este es el flujo de "Token de actualización"). Este flujo también puede producir un error por varios motivos, por ejemplo, si un administrador de inquilinos configura directivas de inicio de sesión más estrictas.
La interacción tiene como objetivo hacer que el usuario realice una acción. Algunas de esas condiciones son fáciles de resolver (por ejemplo, aceptar términos de uso con un solo clic) y algunas no se pueden resolver con la configuración actual (por ejemplo, la máquina en cuestión debe conectarse a una red corporativa específica). Algunos ayudan al usuario a configurar la autenticación multifactor o a instalar Microsoft Authenticator en su dispositivo.
MsalUiRequiredException enumeración de clases
MSAL expone un campo de Classification, que puede leer para proporcionar una mejor experiencia de usuario. Por ejemplo, para indicar al usuario que su contraseña expiró o que necesita proporcionar consentimiento para usar algunos recursos. Los valores admitidos forman parte de la UiRequiredExceptionClassification enumeración:
| Classification | Meaning | Manejo recomendado |
|---|---|---|
| BasicAction | La interacción del usuario puede resolver la condición durante el flujo de autenticación interactiva. | Llame a AcquireTokenInteractively(). |
| Acción adicional | La condición se puede resolver mediante una interacción correctiva adicional con el sistema, fuera del flujo de autenticación interactiva. | Llame a AcquireTokenInteractively() para mostrar un mensaje que explica la acción correctiva. La aplicación que realiza la llamada puede optar por ocultar los flujos que requieran additional_action si es poco probable que el usuario complete la acción correctiva. |
| MessageOnly | La condición no se puede resolver en este momento. El inicio del flujo de autenticación interactiva mostrará un mensaje que explica la condición. | Llame a AcquireTokenInteractively() para mostrar un mensaje que explique la condición. AcquireTokenInteractively() devolverá el error UserCanceled después de que el usuario lea el mensaje y cierre la ventana. La aplicación de llamada puede optar por ocultar los flujos que dan lugar a message_only si es poco probable que el usuario se beneficie del mensaje. |
| Consentimiento requerido | Falta el consentimiento del usuario o se ha revocado. | Llame a AcquireTokenInteractively() para que el usuario dé su consentimiento. |
| La contraseña del usuario ha caducado | La contraseña del usuario ha expirado. | Llame a AcquireTokenInteractively() para que el usuario pueda restablecer su contraseña. |
| PromptNeverFailed | Se llamó a la autenticación interactiva con el parámetro prompt=never; esto obliga a MSAL a basarse en las cookies del explorador y no mostrar el explorador. Esto ha fallado. | Llame a AcquireTokenInteractively() sin usar Prompt.None |
| AcquireTokenSilentFailed | EL SDK de MSAL no tiene suficiente información para capturar un token de la memoria caché. Esto puede deberse a que no se encontró ningún token en la memoria caché o no se encontró ninguna cuenta. El mensaje de error tiene más detalles. | Llame a AcquireTokenInteractively(). |
| Ninguno | No se proporcionan más detalles. La interacción del usuario puede resolver la condición durante el flujo de autenticación interactiva. | Llame a AcquireTokenInteractively(). |
ejemplo de código de .NET
AuthenticationResult res;
try
{
res = await application.AcquireTokenSilent(scopes, account)
.ExecuteAsync();
}
catch (MsalUiRequiredException ex) when (ex.ErrorCode == MsalError.InvalidGrantError)
{
switch (ex.Classification)
{
case UiRequiredExceptionClassification.None:
break;
case UiRequiredExceptionClassification.MessageOnly:
// You might want to call AcquireTokenInteractive(). Azure AD will show a message
// that explains the condition. AcquireTokenInteractively() will return UserCanceled error
// after the user reads the message and closes the window. The calling application may choose
// to hide features or data that result in message_only if the user is unlikely to benefit
// from the message
try
{
res = await application.AcquireTokenInteractive(scopes).ExecuteAsync();
}
catch (MsalClientException ex2) when (ex2.ErrorCode == MsalError.AuthenticationCanceledError)
{
// Do nothing. The user has seen the message
}
break;
case UiRequiredExceptionClassification.BasicAction:
// Call AcquireTokenInteractive() so that the user can, for instance accept terms
// and conditions
case UiRequiredExceptionClassification.AdditionalAction:
// You might want to call AcquireTokenInteractive() to show a message that explains the remedial action.
// The calling application may choose to hide flows that require additional_action if the user
// is unlikely to complete the remedial action (even if this means a degraded experience)
case UiRequiredExceptionClassification.ConsentRequired:
// Call AcquireTokenInteractive() for user to give consent.
case UiRequiredExceptionClassification.UserPasswordExpired:
// Call AcquireTokenInteractive() so that user can reset their password
case UiRequiredExceptionClassification.PromptNeverFailed:
// You used WithPrompt(Prompt.Never) and this failed
case UiRequiredExceptionClassification.AcquireTokenSilentFailed:
default:
// May be resolved by user interaction during the interactive authentication flow.
res = await application.AcquireTokenInteractive(scopes)
.ExecuteAsync(); break;
}
}
Desafíos del acceso condicional y las reclamaciones
Al obtener los tokens de forma automática, la aplicación puede recibir errores si una API a la que intenta acceder requiere un desafío de notificaciones de acceso condicional como, por ejemplo, una directiva de autenticación multifactor.
El patrón para controlar este error es adquirir de forma interactiva un token mediante MSAL. De esta forma, se avisa al usuario y le da la oportunidad de cumplir con la directiva de acceso condicional requerida.
En algunos casos, al llamar a una API que requiere acceso condicional, puede recibir un desafío de notificaciones en el error de la API. Por ejemplo, si la directiva de acceso condicional es tener un dispositivo administrado (Intune), el error será similar a AADSTS53000: el dispositivo debe administrarse para acceder a este recurso o algo similar. En este caso, puede pasar las notificaciones de la llamada de adquisición del token de manera que se le pida al usuario que cumpla con la directiva adecuada.
Al llamar a una API que requiera acceso condicional desde MSAL.NET, tu aplicación debe administrar las excepciones de desafío de reclamaciones. Esto se presenta como una MsalServiceException en la que la propiedad Claims no estará vacía.
Para administrar el desafío de reclamaciones, utiliza WithClaims(String).
Reintentar después de errores y excepciones
Se espera que implemente sus propias directivas de reintentos al llamar a MSAL. MSAL realiza llamadas HTTP al servicio Microsoft Entra y, en ocasiones, se pueden producir errores. Por ejemplo, la red puede bajar o el servidor está sobrecargado.
HTTP 429
Cuando el servidor de token de servicio (STS) está sobrecargado con demasiadas solicitudes, devuelve el error HTTP 429 con una sugerencia sobre cuánto tiempo hasta que pueda intentarlo de nuevo en el Retry-After campo de respuesta.
Códigos de error HTTP 500-600
MSAL.NET implementa un mecanismo simple de reintento para errores con códigos de error HTTP 500-600.
MsalServiceException muestra System.Net.Http.Headers.HttpResponseHeaders como una propiedad namedHeaders. Puede usar información adicional del código de error para mejorar la confiabilidad de las aplicaciones. En el caso descrito, puede usar la RetryAfter propiedad (de tipo RetryConditionHeaderValue) y calcular cuándo volver a intentarlo.
Este es un ejemplo de una aplicación en segundo plano que utiliza el flujo de credenciales de cliente. Puede adaptarlo a cualquiera de los métodos para adquirir un token.
bool retry = false;
do
{
TimeSpan? delay;
try
{
result = await publicClientApplication.AcquireTokenForClient(scopes, account).ExecuteAsync();
}
catch (MsalServiceException serviceException)
{
if (serviceException.ErrorCode == "temporarily_unavailable")
{
RetryConditionHeaderValue retryAfter = serviceException.Headers.RetryAfter;
if (retryAfter.Delta.HasValue)
{
delay = retryAfter.Delta;
}
else if (retryAfter.Date.HasValue)
{
delay = (retryAfter.Date.Value – DateTimeOffset.Now).TotalMilliseconds;
}
}
}
// . . .
if (delay.HasValue)
{
Thread.Sleep((int)delay.Value.TotalMilliseconds); // sleep or other
retry = true;
}
} while (retry);
Pasos siguientes
Considere la posibilidad de habilitar el registro en MSAL.NET para ayudarle a diagnosticar y depurar problemas.