Uso de Microsoft Authenticator o el Portal de empresa de Intune en aplicaciones de Xamarin

En iOS y Android, agentes como Microsoft Authenticator y el Portal de empresa de Microsoft Intune específico para Android permiten lo siguiente:

  • Inicio de sesión único (SSO) : los usuarios no tienen que iniciar sesión en cada aplicación.
  • Identificación de dispositivos: el agente tiene acceso al certificado del dispositivo. Este certificado se crea en el dispositivo cuando se une al área de trabajo.
  • Comprobación de identificación de la aplicación: cuando una aplicación llama al agente, pasa su URL de redireccionamiento. El agente comprueba la URL.

Para habilitar una de estas características, use el parámetro WithBroker() al llamar al método PublicClientApplicationBuilder.CreateApplication. El parámetro .WithBroker() se establece en true de forma predeterminada.

La configuración de la autenticación asincrónica en la biblioteca de autenticación de Microsoft para .NET (MSAL.NET) varía según la plataforma:

Autenticación asincrónica para iOS

Realice los pasos siguientes para permitir que la aplicación de Xamarin.iOS se comunique con la aplicación Microsoft Authenticator. Si tiene como destino iOS 13, considere la posibilidad de leer sobre el cambio importante en la API de Apple.

Paso 1: Habilitar la compatibilidad con el agente

Debe habilitar la compatibilidad del agente para las instancias individuales de PublicClientApplication. La compatibilidad está deshabilitada de manera predeterminada. Al crear PublicClientApplication a través de PublicClientApplicationBuilder, utilice el parámetro WithBroker() como se muestra en el ejemplo siguiente. El parámetro WithBroker() se establece en true de forma predeterminada.

var app = PublicClientApplicationBuilder
                .Create(ClientId)
                .WithBroker()
                .WithReplyUri(redirectUriOnIos) // $"msauth.{Bundle.Id}://auth" (see step 6 below)
                .Build();

Paso 2: Habilitación de acceso a la cadena de claves

Para habilitar el acceso a la cadena de claves, debe tener un grupo de acceso a la cadena de claves para su aplicación. Puede usar la API de WithIosKeychainSecurityGroup() para establecer el grupo de acceso a cadenas de claves al crear la aplicación:

var builder = PublicClientApplicationBuilder
     .Create(ClientId)
     .WithIosKeychainSecurityGroup("com.microsoft.adalcache")
     .Build();

Para más información, consulte Habilitación de acceso a la cadena de claves.

Paso 3: Actualizar AppDelegate para controlar la devolución de llamada

Cuando MSAL.NET llama al agente, este, a su vez, llama de vuelta a la aplicación con el método OpenUrl de la clase AppDelegate. Dado que MSAL espera la respuesta del agente, la aplicación debe cooperar para volver a llamar a MSAL.NET. Para permitir esta cooperación, actualice el archivo AppDelegate.cs para invalidar el método siguiente.

public override bool OpenUrl(UIApplication app, NSUrl url,
                             string sourceApplication,
                             NSObject annotation)
{
    if (AuthenticationContinuationHelper.IsBrokerResponse(sourceApplication))
    {
      AuthenticationContinuationHelper.SetBrokerContinuationEventArgs(url);
      return true;
    }

    else if (!AuthenticationContinuationHelper.SetAuthenticationContinuationEventArgs(url))
    {
         return false;
    }

    return true;
}

Este método se invoca cada vez que se inicia la aplicación. Se usa como una oportunidad para procesar la respuesta del agente y finalizar el proceso de autenticación iniciado por MSAL.NET.

Paso 4: Establecer UIViewController()

En el archivo AppDelegate.cs, establezca una ventana de objeto. Normalmente, no es necesario que establezca la ventana de objeto para Xamarin iOS, pero necesitará una para enviar y recibir respuestas del agente.

Para configurar la ventana de objeto:

  1. En el archivo AppDelegate.cs, establezca App.RootViewController en un nuevo UIViewController(). Esta asignación garantiza que la llamada al agente incluye UIViewController. Si esta configuración se asigna de forma incorrecta, puede obtener este error:

    "uiviewcontroller_required_for_ios_broker":"UIViewController is null, so MSAL.NET cannot invoke the iOS broker. See https://aka.ms/msal-net-ios-broker"

  2. En la llamada a AcquireTokenInteractive, use .WithParentActivityOrWindow(App.RootViewController) y, a continuación, pase la referencia a la ventana de objeto que usará.

    En App.cs:

       public static object RootViewController { get; set; }
    

    En AppDelegate.cs:

       LoadApplication(new App());
       App.RootViewController = new UIViewController();
    

    En la llamada AcquireToken:

    result = await app.AcquireTokenInteractive(scopes)
                 .WithParentActivityOrWindow(App.RootViewController)
                 .ExecuteAsync();
    

Paso 5: Registrar un esquema de dirección URL

MSAL.NET usa direcciones URL para invocar al agente y devolver la respuesta del agente a la aplicación. Para completar el recorrido de ida y vuelta, registre un esquema de dirección URL para la aplicación en el archivo Info.plist.

El nombre CFBundleURLSchemes debe incluir el prefijo msauth.. El prefijo debe ir seguido de CFBundleURLName.

En el esquema de dirección URL, BundleId identifica de forma única la aplicación: $"msauth.(BundleId)". Por tanto, si BundleId es com.yourcompany.xforms, el esquema de dirección URL es msauth.com.yourcompany.xforms.

Nota:

Este esquema de dirección URL se convierte en parte del URI de redirección que identifica de forma única la aplicación cuando recibe la respuesta del agente.

 <key>CFBundleURLTypes</key>
    <array>
      <dict>
        <key>CFBundleTypeRole</key>
        <string>Editor</string>
        <key>CFBundleURLName</key>
        <string>com.yourcompany.xforms</string>
        <key>CFBundleURLSchemes</key>
        <array>
          <string>msauth.com.yourcompany.xforms</string>
        </array>
      </dict>
    </array>

Paso 6: Agregar el identificador de agente a la sección LSApplicationQueriesSchemes

MSAL usa –canOpenURL: para comprobar si el agente está instalado en el dispositivo. En iOS 9, Apple ha bloqueado los esquemas que puede consultar una aplicación.

Agregue msauthv2 a la sección LSApplicationQueriesSchemes del archivo Info.plist, como en el ejemplo siguiente:

<key>LSApplicationQueriesSchemes</key>
    <array>
      <string>msauthv2</string>
      <string>msauthv3</string>
    </array>

Paso 7: Adición de un identificador URI de redirección al registro de la aplicación

Sugerencia

Los pasos de este artículo pueden variar ligeramente en función del portal desde donde comienza.

SI usa el agente, se agrega un requisito adicional al URI de redirección. El URI de redirección debe tener el siguiente formato:

$"msauth.{BundleId}://auth"

Este es un ejemplo:

public static string redirectUriOnIos = "msauth.com.yourcompany.XForms://auth";

Observe que el URI de redirección coincide con el nombre CFBundleURLSchemes que incluyó en el archivo Info.plist.

Agregue el identificador URI de redireccionamiento al registro de la aplicación. Para generar un identificador URI de redireccionamiento con el formato correcto, use Registros de aplicaciones para generar el identificador URI asincrónico a partir del identificador del paquete.

Para generar el URI de redirección:

  1. Inicie sesión en el Centro de administración de Microsoft Entra como Administrador de aplicaciones en la nube.

  2. Vaya aIdentidad>Aplicaciones>Registros de aplicaciones.

  3. Busque y seleccione la aplicación.

  4. Seleccione Autenticación>Agregar una plataforma>iOS/macOS.

  5. Escriba el id. del paquete y, a continuación, seleccione Configurar.

    Copie el URI de redirección generado que aparece en el cuadro de texto URI de redirección para incluirlo en el código:

    iOS platform settings with generated redirect URI

  6. Seleccione Listo para completar la generación del identificador URI de redirección.

Autenticación asincrónica para Android

Paso 1: Habilitar la compatibilidad con el agente

La compatibilidad con el agente se habilita de forma PublicClientApplication. De forma predeterminada, está deshabilitada. Utilice el parámetro WithBroker() (establecido en true de forma predeterminada) para crear IPublicClientApplication con PublicClientApplicationBuilder.

var app = PublicClientApplicationBuilder
                .Create(ClientId)
                .WithBroker()
                .WithRedirectUri(redirectUriOnAndroid) // See step #4
                .Build();

Paso 2: Actualizar la actividad principal para controlar la devolución de llamada

Cuando MSAL.NET llame al agente, este, a su vez, volverá a llamar a la aplicación con el método OnActivityResult(). Como MSAL espera la respuesta del agente, la aplicación debe cooperar para enrutar el resultado a MSAL.NET.

Enrute el resultado al método SetAuthenticationContinuationEventArgs(int requestCode, Result resultCode, Intent data); para ello, reemplace el método OnActivityResult() como se muestra aquí:

protected override void OnActivityResult(int requestCode, Result resultCode, Intent data)
{
   base.OnActivityResult(requestCode, resultCode, data);
   AuthenticationContinuationHelper.SetAuthenticationContinuationEventArgs(requestCode, resultCode, data);
}

Este método se invoca cada vez que se inicia la aplicación del agente y se usa como una oportunidad para procesar la respuesta del agente y completar el proceso de autenticación iniciado por MSAL.NET.

Paso 3: Establecer una actividad

Para habilitar la autenticación asincrónica, establezca una actividad de forma que MSAL pueda enviar y recibir las respuestas del agente. Para ello, proporcione la actividad (normalmente, MainActivity) para el objeto primario WithParentActivityOrWindow(object parent).

Por ejemplo, en la llamada a AcquireTokenInteractive():

result = await app.AcquireTokenInteractive(scopes)
             .WithParentActivityOrWindow((Activity)context))
             .ExecuteAsync();

Paso 4: Adición de un identificador URI de redirección al registro de la aplicación

MSAL usa las direcciones URL para invocar al agente y regresar a la aplicación. Para completar este recorrido de ida y vuelta, registre un URI de redireccionamiento para la aplicación.

El formato del URI de redirección para la aplicación depende del certificado que se use para firmar el archivo APK. Por ejemplo:

msauth://com.microsoft.xforms.testApp/hgbUYHVBYUTvuvT&Y6tr554365466=

La última parte del URI, hgbUYHVBYUTvuvT&Y6tr554365466=, es la versión codificada en Base64 de la firma con la que se ha firmado el APK. Durante el desarrollo de la aplicación en Visual Studio, si está depurando el código sin firmar el APK con un certificado específico, Visual Studio lo firmará automáticamente con fines de depuración. Cuando Visual Studio firma el APK de esta manera, le asigna una firma única para la máquina en la que se compiló. Por tanto, cada vez que compile la aplicación en otra máquina, tendrá que actualizar el URI de redireccionamiento en el código de la aplicación y el registro de la aplicación para poder autenticarse con MSAL.

Durante la depuración, es posible que se produzca una excepción de MSAL (o un mensaje de registro) que indique que el URI de redireccionamiento proporcionado no es correcto. Esta excepción o mensaje de registros también le indica el URI de redirección que debe usar con la máquina actual en la que está realizando la depuración. Puede usar el identificador URI de redireccionamiento proporcionado para seguir desarrollando la aplicación siempre que actualice el URI de redireccionamiento en el código y agregue el identificador URI de redireccionamiento especificado al registro de la aplicación.

Una vez que esté preparado para finalizar el código, actualice el identificador URI de redireccionamiento en el código y en el registro de la aplicación para usar la firma del certificado con el que se firma el APK.

En la práctica, esto significa que debería considerar la posibilidad de agregar un URI de redireccionamiento para cada miembro del equipo de desarrollo y otro para la versión del APK firmada para producción.

Puede procesar esta firma usted mismo, del mismo modo que lo hace MSAL:

   private string GetRedirectUriForBroker()
   {
      string packageName = Application.Context.PackageName;
      string signatureDigest = this.GetCurrentSignatureForPackage(packageName);
      if (!string.IsNullOrEmpty(signatureDigest))
      {
            return string.Format(CultureInfo.InvariantCulture, "{0}://{1}/{2}", RedirectUriScheme,
               packageName.ToLowerInvariant(), signatureDigest);
      }

      return string.Empty;
   }

   private string GetCurrentSignatureForPackage(string packageName)
   {
      Android.Content.PM.Signature signature = null;
      if (Build.VERSION.SdkInt >= BuildVersionCodes.Tiramisu)
      {
          var packageInfo = Application.Context.PackageManager.GetPackageInfo(packageName, PackageManager.PackageInfoFlags.Of((long)PackageInfoFlags.SigningCertificates));
          if (packageInfo.SigningInfo != null)
          {
              var signatures = packageInfo.SigningInfo.GetApkContentsSigners();
              if (signatures != null && signatures.Length > 0)
                  signature = signatures[0];
          }
      }
      else
      {
#pragma warning disable CS0618 // Type or member is obsolete
          var packageInfo = Application.Context.PackageManager.GetPackageInfo(packageName, PackageInfoFlags.Signatures);
          if (packageInfo != null && packageInfo.Signatures != null && packageInfo.Signatures.Count > 0)
              signature = packageInfo.Signatures[0];
#pragma warning restore CS0618 // Type or member is obsolete
      }
    
      if (signature != null)
      {
          // First available signature. Applications can be signed with multiple signatures.
          // The order of Signatures is not guaranteed.
          var md = MessageDigest.GetInstance("SHA");
          md.Update(signature.ToByteArray());
          return Convert.ToBase64String(md.Digest(), Base64FormattingOptions.None);
          // Server side needs to register all other tags. ADAL will
          // send one of them.
      }
   }

Si quiere, también puede adquirir la firma del paquete mediante keytool con los siguientes comandos:

  • Windows:
    keytool.exe -list -v -keystore "%LocalAppData%\Xamarin\Mono for Android\debug.keystore" -alias androiddebugkey -storepass android -keypass android
    
  • macOS:
    keytool -exportcert -alias androiddebugkey -keystore ~/.android/debug.keystore | openssl sha1 -binary | openssl base64
    

Paso 5 (opcional): Reversión al explorador del sistema

Si MSAL está configurado para usar el agente pero este no está instalado, MSAL revertirá al uso de una vista web (un explorador). MSAL intentará realizar la autenticación con el explorador del sistema predeterminado en el dispositivo, lo que produce un error porque el URI de redirección está configurado para el agente y el explorador del sistema no sabe cómo usarlo para regresar a MSAL. Para evitar el error, puede configurar un filtro de intención con el URI de redirección del agente que usó en el paso 4.

Modifique el manifiesto de la aplicación para agregar el filtro de intención:

<!-- NOTE the SLASH (required) that prefixes the signature value in the path attribute.
     The signature value is the Base64-encoded signature discussed above. -->
<intent-filter>
      <data android:scheme="msauth"
                    android:host="Package Name"
                    android:path="/Package Signature"/>

Por ejemplo, si tiene un URI de redirección de msauth://com.microsoft.xforms.testApp/hgbUYHVBYUTvuvT&Y6tr554365466=, el manifiesto debe tener un aspecto similar al siguiente fragmento de código XML.

La barra diagonal (/) delante de la firma en el valor android:path es obligatoria.

<!-- NOTE the SLASH (required) that prefixes the signature value in the path attribute.
     The signature value is the Base64-encoded signature discussed above. -->
<intent-filter>
      <data android:scheme="msauth"
                    android:host="com.microsoft.xforms.testApp"
                    android:path="/hgbUYHVBYUTvuvT&Y6tr554365466="/>

Para obtener más información sobre la configuración de la aplicación con fines de compatibilidad con el explorador del sistema y Android 11, consulte la actualización del manifiesto de Android para la compatibilidad con el explorador del sistema.

También puede configurar MSAL para revertir al explorador incrustado, que no depende de un URI de redirección:

.WithUseEmbeddedWebUi(true)

Sugerencias para la solución de problemas de autenticación asincrónica de Android

A continuación se ofrecen algunas sugerencias sobre cómo evitar problemas al implementar la autenticación asincrónica en Android:

  • Identificador URI de redireccionamiento: agregue un identificador URI de redireccionamiento al registro de la aplicación. Un URI de redirección faltante o incorrecto es un problema común que los desarrolladores experimentan.

  • Versión de agente: instale la versión mínima necesaria de las aplicaciones de agente. Cualquiera de estas dos aplicaciones se puede usar para la autenticación asincrónica en Android.

  • Precedencia de agente: MSAL se comunica con el primer agente instalado en el dispositivo cuando se instalan varios.

    Ejemplo: Si primero instala Microsoft Authenticator y, a continuación, instala Portal de empresa de Intune, la autenticación asincrónica solo se produce en Microsoft Authenticator.

  • Registros: si encuentra un problema con la autenticación asincrónica, ver los registros del agente podría ayudarle a diagnosticar la causa.

    • Acceda a los registros de Microsoft Authenticator:

      1. Seleccione el botón de menú en la esquina superior derecha de la aplicación.
      2. Seleccione Enviar comentarios>¿Tiene problemas? .
      3. En ¿Qué intenta hacer? , seleccione una opción e incluya una descripción.
      4. Para enviar los registros, seleccione la flecha situada en la esquina superior derecha de la aplicación.

      Después de enviar los registros, un cuadro de diálogo mostrará el identificador del incidente. Registre el identificador de incidente y proporciónelo cuando solicite asistencia.

    • Acceda a los registros del Portal de empresa de Intune:

      1. Seleccione el botón de menú en la esquina superior izquierda de la aplicación.
      2. Seleccione Help>Email Support (Ayuda >Soporte por correo electrónico).
      3. Para enviar los registros, seleccione Upload Logs Only (Cargar solo registros).

      Después de enviar los registros, un cuadro de diálogo mostrará el identificador del incidente. Registre el identificador de incidente y proporciónelo cuando solicite asistencia.

Pasos siguientes

Para obtener información, consulte Consideraciones para usar la Plataforma universal de Windows con MSAL.NET.