Requisitos de configuração e dicas de solução de problemas para o Xamarin Android com MSAL.NET
Há várias alterações de configuração que você precisa fazer no seu código ao usar o Xamarin Android com a Biblioteca de Autenticação da Microsoft para .NET (MSAL.NET). As seções a seguir descrevem as modificações necessárias, seguidas por uma seção de solução de problemas para ajudar a evitar alguns dos problemas mais comuns.
Observação
As versões 4.61.0 e superiores do MSAL.NET não oferecem suporte à Plataforma Universal do Windows (UWP), Xamarin Android e Xamarin iOS. Recomendamos que você migre seus aplicativos Xamarin para estruturas modernas, como o MAUI. Leia mais sobre a substituição em Anunciando a substituição futura de MSAL.NET para Xamarin e UWP.
Definir a atividade pai
No Xamarin Android, defina a atividade pai para que o token seja retornado após a interação:
var authResult = AcquireTokenInteractive(scopes)
.WithParentActivityOrWindow(parentActivity)
.ExecuteAsync();
Na MSAL.NET 4.2 e versões posteriores, você também pode definir essa funcionalidade no nível de [PublicClientApplication][PublicClientApplication]. Para fazer isso, use um retorno de chamada:
// Requires MSAL.NET 4.2 or later
var pca = PublicClientApplicationBuilder
.Create("<your-client-id-here>")
.WithParentActivityOrWindow(() => parentActivity)
.Build();
Se você usar CurrentActivityPlugin, o código do construtor [PublicClientApplication
][PublicClientApplication] deverá ser semelhante a este snippet de código:
// Requires MSAL.NET 4.2 or later
var pca = PublicClientApplicationBuilder
.Create("<your-client-id-here>")
.WithParentActivityOrWindow(() => CrossCurrentActivity.Current)
.Build();
Verifique se o controle retorna ao MSAL
Quando a parte interativa do fluxo de autenticação terminar, retorne o controle à MSAL substituindo o método [Activity
][Activity].[OnActivityResult()
][OnActivityResult].
Em sua substituição, chame o método AuthenticationContinuationHelper
. do MSAL.NETSetAuthenticationContinuationEventArgs()
Para retornar o controle ao MSAL no final da parte interativa do fluxo de autenticação.
protected override void OnActivityResult(int requestCode,
Result resultCode,
Intent data)
{
base.OnActivityResult(requestCode, resultCode, data);
// Return control to MSAL
AuthenticationContinuationHelper.SetAuthenticationContinuationEventArgs(requestCode,
resultCode,
data);
}
Atualizar o manifesto do Android para o suporte do sistema de WebView
Para dar suporte ao sistema WebView, o arquivo AndroidManifest.xml deve conter os seguintes valores:
<activity android:name="microsoft.identity.client.BrowserTabActivity" android:configChanges="orientation|screenSize" android:exported="true">
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="msal{Client Id}" android:host="auth" />
</intent-filter>
</activity>
O valor android:scheme
é criado a partir do URI de redirecionamento configurado no portal do aplicativo. Por exemplo, se o URI de redirecionamento for msal00001111-aaaa-2222-bbbb-3333cccc4444://auth
, a entrada android:scheme
no manifesto seria semelhante a este exemplo:
<data android:scheme="msal00001111-aaaa-2222-bbbb-3333cccc4444" android:host="auth" />
Como alternativa, crie a atividade no código em vez de editar manualmente AndroidManifest.xml. Para criar a atividade no código, crie primeiro uma classe que inclua os atributo Activity
e IntentFilter
.
Veja um exemplo de uma classe que representa os valores do arquivo XML:
[Activity(Exported = true)]
[IntentFilter(new[] { Intent.ActionView },
Categories = new[] { Intent.CategoryBrowsable, Intent.CategoryDefault },
DataHost = "auth",
DataScheme = "msal{client_id}")]
public class MsalActivity : BrowserTabActivity
{
}
Usar o WebView do sistema na autenticação agenciada
Para usar o WebView do sistema como um fallback para autenticação interativa quando você configurou seu aplicativo para usar a autenticação orientada e o dispositivo não tem um agente instalado, habilite o MSAL para capturar a resposta de autenticação usando o URI de redirecionamento do agente. O MSAL tentará autenticar usando o sistema de WebView padrão no dispositivo quando detectar que o agente está indisponível. Usando esse padrão, ele falhará porque o URI de redirecionamento está configurado para usar um agente e o WebView do sistema não sabe como usá-lo para retornar ao MSAL. Para resolver isso, crie um filtro de intenção usando o URI de redirecionamento do agente configurado anteriormente. Para adicionar o filtro de intenção, mude o manifesto do aplicativo como neste exemplo:
<!--Intent filter to capture System WebView or Authenticator calling back to our app after sign-in-->
<activity
android:name="microsoft.identity.client.BrowserTabActivity">
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="msauth"
android:host="Enter_the_Package_Name"
android:path="/Enter_the_Signature_Hash" />
</intent-filter>
</activity>
Substitua o nome do pacote que você registrou no portal do Azure pelo valor android:host=
. Substitua o hash de chave que você registrou no portal do Azure pelo valor android:path=
. O hash de assinatura não deve ser codificado por URL. Verifique se uma barra à esquerda (/
) é exibida no início do hash de assinatura.
Manifesto Xamarin.Forms 4.3.x
O Xamarin. Forms 4.3.x gera código que define o atributo package
como com.companyname.{appName}
em AndroidManifest.xml. Se você usar DataScheme
como msal{client_id}
, talvez queira mudar o valor para corresponder ao valor do namespace MainActivity.cs
.
Suporte para Android 11
Para usar o navegador do sistema e a autenticação orientada no Android 11, você precisa primeiro declarar esses pacotes para que eles fiquem visíveis para o aplicativo. Os aplicativos destinados ao Android 10 (API 29) e anteriores podem consultar o sistema operacional para receber uma lista de pacotes disponíveis no dispositivo em um determinado momento. Para permitir privacidade e segurança, o Android 11 reduz a visibilidade do pacote a uma lista padrão de pacotes do sistema operacional e aos pacotes especificados no arquivo AndroidManifest.xml do aplicativo.
Para permitir que o aplicativo seja autenticado usando o navegador do sistema e o agente, adicione a seguinte seção a AndroidManifest.xml:
<!-- Required for API Level 30 to make sure the app can detect browsers and other apps where communication is needed.-->
<!--https://developer.android.com/training/basics/intents/package-visibility-use-cases-->
<queries>
<package android:name="com.azure.authenticator" />
<package android:name="{Package Name}" />
<package android:name="com.microsoft.windowsintune.companyportal" />
<!-- Required for API Level 30 to make sure the app detect browsers
(that don't support custom tabs) -->
<intent>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="https" />
</intent>
<!-- Required for API Level 30 to make sure the app can detect browsers that support custom tabs -->
<!-- https://developers.google.com/web/updates/2020/07/custom-tabs-android-11#detecting_browsers_that_support_custom_tabs -->
<intent>
<action android:name="android.support.customtabs.action.CustomTabsService" />
</intent>
</queries>
Substitua {Package Name}
pelo nome do pacote de aplicativos.
Seu manifesto atualizado, que agora inclui suporte para o navegador do sistema e a autenticação orientada, deve ser semelhante a este exemplo:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" android:versionCode="1" android:versionName="1.0" package="com.companyname.XamarinDev">
<uses-sdk android:minSdkVersion="21" android:targetSdkVersion="30" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<application android:theme="@android:style/Theme.NoTitleBar">
<activity android:name="microsoft.identity.client.BrowserTabActivity" android:configChanges="orientation|screenSize">
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="msal00001111-aaaa-2222-bbbb-3333cccc4444" android:host="auth" />
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="msauth" android:host="com.companyname.XamarinDev" android:path="/Fc4l/5I4mMvLnF+l+XopDuQ2gEM=" />
</intent-filter>
</activity>
</application>
<!-- Required for API Level 30 to make sure we can detect browsers and other apps we want to
be able to talk to.-->
<!--https://developer.android.com/training/basics/intents/package-visibility-use-cases-->
<queries>
<package android:name="com.azure.authenticator" />
<package android:name="com.companyname.xamarindev" />
<package android:name="com.microsoft.windowsintune.companyportal" />
<!-- Required for API Level 30 to make sure we can detect browsers
(that don't support custom tabs) -->
<intent>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="https" />
</intent>
<!-- Required for API Level 30 to make sure we can detect browsers that support custom tabs -->
<!-- https://developers.google.com/web/updates/2020/07/custom-tabs-android-11#detecting_browsers_that_support_custom_tabs -->
<intent>
<action android:name="android.support.customtabs.action.CustomTabsService" />
</intent>
</queries>
</manifest>
Usar a exibição da Web inserida (opcional)
Por padrão, MSAL.NET o navegador da Web do sistema. Este navegador permite obter SSO (logon único) usando aplicativos Web e outros aplicativos. Em alguns casos raros, talvez você queira que o seu sistema use uma exibição da Web inserida.
Este exemplo de código mostra como configurar uma exibição da Web inserida:
bool useEmbeddedWebView = !app.IsSystemWebViewAvailable;
var authResult = AcquireTokenInteractive(scopes)
.WithParentActivityOrWindow(parentActivity)
.WithEmbeddedWebView(useEmbeddedWebView)
.ExecuteAsync();
Para obter mais informações, confira Usar navegadores da Web para MSAL.NET e Considerações sobre o navegador do sistema Xamarin Android.
Solução de problemas
Dicas gerais
- Atualize o pacote NuGet do MSAL.NET para a versão mais recente do MSAL.NET.
- Verifique se o Xamarin.Forms está na versão mais recente.
- Verifique se Xamarin.Android.Support.v4 está na versão mais recente.
- Verifique se todos os pacotes Xamarin.Android.Support têm como destino a versão mais recente.
- Limpe ou recompile o aplicativo.
- No Visual Studio, tente definir o número máximo de compilações de projetos paralelas como 1. Para fazer isso, selecione Opções>Projetos e soluções>Compilar e executar>Número máximo de compilações de projetos paralelos.
- Se estiver criando a partir da linha de comando e o comando usar
/m
, tente remover esse elemento do comando.
Erro: o nome AuthenticationContinuationHelper não existe no contexto atual
Se um erro indicar que AuthenticationContinuationHelper
não existe no contexto atual, o Visual Studio poderá ter atualizado incorretamente o arquivo Android.csproj*. Às vezes, o caminho do arquivo no elemento <HintPath>
contém incorretamente netstandard13
em vez de monoandroid90
.
Este exemplo contém um caminho de arquivo correto:
<Reference Include="Microsoft.Identity.Client, Version=3.0.4.0, Culture=neutral, PublicKeyToken=0a613f4dd989e8ae,
processorArchitecture=MSIL">
<HintPath>..\..\packages\Microsoft.Identity.Client.3.0.4-preview\lib\monoandroid90\Microsoft.Identity.Client.dll</HintPath>
</Reference>
Próximas etapas
Para testar amostras adicionais, Aplicativos clientes públicos móveis.