Aggiungere l'autenticazione all'app Xamarin.Forms
Nota
Questo prodotto viene ritirato. Per una sostituzione dei progetti che usano .NET 8 o versione successiva, vedere la libreria datasync di Community Toolkit.
In questa esercitazione si aggiunge l'autenticazione Microsoft all'app usando Microsoft Entra ID. Prima di completare questa esercitazione, assicurarsi di aver creato il progetto e distribuito il back-end.
Nota
Poiché l'app iOS richiede l'accesso keychain, è necessario configurare un profilo di provisioning iOS. Un profilo di provisioning richiede un dispositivo iOS reale o un account Apple Developer a pagamento (se si usa il simulatore). È possibile ignorare questa esercitazione e passare all'aggiunta di accesso offline all'app se non è possibile usare l'autenticazione a causa di questa restrizione.
Mancia
Anche se si usa Microsoft Entra ID per l'autenticazione, è possibile usare qualsiasi libreria di autenticazione desiderata con App per dispositivi mobili di Azure.
Aggiungere l'autenticazione al servizio back-end
Il servizio back-end è un servizio standard ASP.NET 6. Qualsiasi esercitazione che illustra come abilitare l'autenticazione per un servizio ASP.NET 6 funziona con App per dispositivi mobili di Azure.
Per abilitare l'autenticazione di Microsoft Entra per il servizio back-end, è necessario:
- Registrare un'applicazione con Microsoft Entra ID.
- Aggiungere il controllo dell'autenticazione al progetto back-end ASP.NET 6.
Registrare l'applicazione
Prima di tutto, registrare l'API Web nel tenant di Microsoft Entra e aggiungere un ambito seguendo questa procedura:
Se si ha accesso a più tenant, usare il filtro Directory e sottoscrizioni nel menu in alto per passare al tenant in cui si vuole registrare l'applicazione.
Cercare e selezionare ID Microsoft Entra.
In Gestisciselezionare Registrazioni app>Nuova registrazione.
- Nome: immettere un nome per l'applicazione; ad esempio, Guida introduttiva a TodoApp. Gli utenti dell'app vedranno questo nome. È possibile modificarlo in un secondo momento.
- Tipi di account supportati: account in qualsiasi directory organizzativa (qualsiasi directory Microsoft Entra - Multi-tenant) e account Microsoft personali (ad esempio Skype, Xbox)
Selezionare Registra.
In Gestisciselezionare Esporre un'API>Aggiungere un ambito.
Per URI ID applicazione, accettare l'impostazione predefinita selezionando Salva e continua.
Immettere i dettagli seguenti:
-
nome ambito:
access_as_user
- Chi può fornire il consenso?: amministratori e utenti
-
nome visualizzato del consenso amministratore:
Access TodoApp
- Descrizione del consenso amministratore :
Allows the app to access TodoApp as the signed-in user.
-
Nome visualizzato del consenso utente:
Access TodoApp
-
Descrizione del consenso utente:
Allow the app to access TodoApp on your behalf.
- State: Enabled
-
nome ambito:
Selezionare Aggiungi ambito per completare l'aggiunta dell'ambito.
Si noti il valore dell'ambito, simile a
api://<client-id>/access_as_user
(detto ambito API Web ). È necessario l'ambito durante la configurazione del client.Selezionare Panoramica.
Si noti l'ID applicazione (client)
nella sezione Essentials (id applicazione API Web ). Questo valore è necessario per configurare il servizio back-end.
Aprire Visual Studio e selezionare il progetto TodoAppService.NET6
.
Fare clic con il pulsante destro del mouse sul progetto
TodoAppService.NET6
, quindi selezionare Gestisci pacchetti NuGet....Nella nuova scheda selezionare Sfoglia, quindi immettere Microsoft.Identity.Web nella casella di ricerca.
Selezionare il pacchetto di
Microsoft.Identity.Web
, quindi premere Installa.Seguire le istruzioni per completare l'installazione del pacchetto.
Aprire
Program.cs
. Aggiungere quanto segue all'elenco di istruzioniusing
:
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.Identity.Web;
- Aggiungere il codice seguente direttamente sopra la chiamata a
builder.Services.AddDbContext()
:
builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddMicrosoftIdentityWebApi(builder.Configuration);
builder.Services.AddAuthorization();
- Aggiungere il codice seguente direttamente sopra la chiamata a
app.MapControllers()
:
app.UseAuthentication();
app.UseAuthorization();
Il Program.cs
dovrebbe essere simile al seguente:
using Microsoft.AspNetCore.Datasync;
using Microsoft.EntityFrameworkCore;
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.Identity.Web;
using TodoAppService.NET6.Db;
var builder = WebApplication.CreateBuilder(args);
var connectionString = builder.Configuration.GetConnectionString("DefaultConnection");
if (connectionString == null)
{
throw new ApplicationException("DefaultConnection is not set");
}
builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddMicrosoftIdentityWebApi(builder.Configuration);
builder.Services.AddAuthorization();
builder.Services.AddDbContext<AppDbContext>(options => options.UseSqlServer(connectionString));
builder.Services.AddDatasyncControllers();
var app = builder.Build();
// Initialize the database
using (var scope = app.Services.CreateScope())
{
var context = scope.ServiceProvider.GetRequiredService<AppDbContext>();
await context.InitializeDatabaseAsync().ConfigureAwait(false);
}
// Configure and run the web service.
app.UseAuthentication();
app.UseAuthorization();
app.MapControllers();
app.Run();
- Modificare il
Controllers\TodoItemController.cs
. Aggiungere un attributo[Authorize]
alla classe . La classe dovrebbe essere simile alla seguente:
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Datasync;
using Microsoft.AspNetCore.Datasync.EFCore;
using Microsoft.AspNetCore.Mvc;
using TodoAppService.NET6.Db;
namespace TodoAppService.NET6.Controllers
{
[Authorize]
[Route("tables/todoitem")]
public class TodoItemController : TableController<TodoItem>
{
public TodoItemController(AppDbContext context)
: base(new EntityTableRepository<TodoItem>(context))
{
}
}
}
- Modificare il
appsettings.json
. Aggiungere il blocco seguente:
"AzureAd": {
"Instance": "https://login.microsoftonline.com",
"ClientId": "<client-id>",
"TenantId": "common"
},
Sostituire il <client-id>
con l'ID applicazione API Web registrato in precedenza. Al termine, dovrebbe essere simile al seguente:
{
"AzureAd": {
"Instance": "https://login.microsoftonline.com",
"ClientId": "<client-id>",
"TenantId": "common"
},
"ConnectionStrings": {
"DefaultConnection": "Server=(localdb)\\mssqllocaldb;Database=TodoApp;Trusted_Connection=True"
},
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
},
"AllowedHosts": "*"
}
Pubblicare di nuovo il servizio in Azure:
- Fare clic con il pulsante destro del mouse sul progetto di
TodoAppService.NET6
, quindi selezionare Pubblica.... - Selezionare il pulsante Pubblica
nell'angolo superiore destro della scheda.
Aprire un browser per https://yoursite.azurewebsites.net/tables/todoitem?ZUMO-API-VERSION=3.0.0
. Si noti che il servizio restituisce ora una risposta 401
, che indica che è necessaria l'autenticazione.
Registrare l'app con il servizio di gestione delle identità
Microsoft Data Sync Framework include il supporto predefinito per qualsiasi provider di autenticazione che usa un token Json Web (JWT) all'interno di un'intestazione della transazione HTTP. Questa applicazione usa il
Configurare un'applicazione client nativa
È possibile registrare client nativi per consentire l'autenticazione alle API Web ospitate nell'app usando una libreria client, ad esempio Microsoft Identity Library (MSAL).
Nel portale di Azure selezionare ID Microsoft Entra>Registrazioni app>Nuova registrazione.
Nella pagina Registrare un'applicazione:
- immettere un Nome per la registrazione dell'app. È possibile usare il nome
native-quickstart
per distinguerne uno da quello usato dal servizio back-end. - Selezionare Account in qualsiasi directory organizzativa (qualsiasi directory Microsoft Entra - Multi-tenant) e account Microsoft personali (ad esempio Skype, Xbox).
- In URI di reindirizzamento:
- Selezionare client pubblico (desktop & per dispositivi mobili)
- Immettere l'URL
quickstart://auth
- immettere un Nome per la registrazione dell'app. È possibile usare il nome
Selezionare Registra.
Selezionare autorizzazioni API >Aggiungere un'autorizzazione>API personali.
Selezionare la registrazione dell'app creata in precedenza per il servizio back-end. Se la registrazione dell'app non viene visualizzata, assicurarsi di aver aggiunto l'ambito access_as_user.
In Selezionare le autorizzazioniselezionare access_as_usere quindi selezionare Aggiungi autorizzazioni.
Selezionare Autenticazione>applicazioni per dispositivi mobili e desktop.
Selezionare la casella accanto a
https://login.microsoftonline.com/common/oauth2/nativeclient
.Selezionare la casella accanto a
msal{client-id}://auth
(sostituendo{client-id}
con l'ID applicazione).Selezionare Aggiungi URI, quindi aggiungere
http://localhost
nel campo per URI aggiuntivi.Selezionare Salva nella parte inferiore della pagina.
Selezionare Panoramica. Prendere nota del ID applicazione (client)
(detto ID applicazione client native client ) perché è necessario configurare l'app per dispositivi mobili.
Sono stati definiti tre URL di reindirizzamento:
-
http://localhost
viene usato dalle applicazioni WPF. -
https://login.microsoftonline.com/common/oauth2/nativeclient
viene usato dalle applicazioni UWP. -
msal{client-id}://auth
viene usato dalle applicazioni per dispositivi mobili (Android e iOS).
Aggiungere Microsoft Identity Client all'app
Aprire la soluzione TodoApp.sln
in Visual Studio e impostare il progetto TodoApp.Forms
come progetto di avvio.
Aggiungere il
Fare clic con il pulsante destro del mouse sul progetto, quindi selezionare Gestisci pacchetti NuGet....
Selezionare la scheda sfoglia
. Immettere
Microsoft.Identity.Client
nella casella di ricerca, quindi premere INVIO.Selezionare il risultato
Microsoft.Identity.Client
, quindi fare clic su Installa.Accettare il contratto di licenza per continuare l'installazione.
Aggiungere l'ID client nativo e l'ambito back-end alla configurazione.
Aprire il progetto TodoApp.Data
e modificare il file di Constants.cs
. Aggiungere costanti per ApplicationId
e Scopes
:
public static class Constants
{
/// <summary>
/// The base URI for the Datasync service.
/// </summary>
public static string ServiceUri = "https://demo-datasync-quickstart.azurewebsites.net";
/// <summary>
/// The application (client) ID for the native app within Microsoft Entra ID
/// </summary>
public static string ApplicationId = "<client-id>";
/// <summary>
/// The list of scopes to request
/// </summary>
public static string[] Scopes = new[]
{
"<scope>"
};
}
Sostituire il <client-id>
con l'ID applicazione native ricevuta durante la registrazione dell'applicazione client in Microsoft Entra ID e l'<scope>
con l'ambito api Web copiato quando è stato usato Esporre un API durante la registrazione dell'applicazione di servizio.
Aprire il progetto TodoApp.Forms
. Aggiungere un nuovo file denominato IPlatform.cs
con il contenuto seguente:
using Microsoft.Identity.Client;
namespace TodoApp.Forms
{
public interface IPlatform
{
IPublicClientApplication GetIdentityClient(string applicationId);
}
}
Questa interfaccia viene usata più avanti per consentire al progetto condiviso di chiedere al progetto della piattaforma un client di identità adatto per la piattaforma.
Aprire App.xaml.cs
. Aggiungere le istruzioni using
seguenti:
using Microsoft.Datasync.Client;
using Microsoft.Identity.Client;
using System.Diagnostics;
using System.Linq;
using System.Threading.Tasks;
Nella classe App
aggiungere due nuove proprietà:
public IPublicClientApplication IdentityClient { get; set; }
public IPlatform PlatformService { get; }
Modificare il costruttore per leggere:
public App(IPlatform platformService)
{
InitializeComponent();
PlatformService = platformService;
TodoService = new RemoteTodoService(GetAuthenticationToken);
MainPage = new NavigationPage(new MainPage(this, TodoService));
}
Aggiungere il metodo GetAuthenticationToken
alla classe :
public async Task<AuthenticationToken> GetAuthenticationToken()
{
if (IdentityClient == null)
{
IdentityClient = PlatformService.GetIdentityClient(Constants.ApplicationId);
}
var accounts = await IdentityClient.GetAccountsAsync();
AuthenticationResult result = null;
bool tryInteractiveLogin = false;
try
{
result = await IdentityClient
.AcquireTokenSilent(Constants.Scopes, accounts.FirstOrDefault())
.ExecuteAsync();
}
catch (MsalUiRequiredException)
{
tryInteractiveLogin = true;
}
catch (Exception ex)
{
Debug.WriteLine($"MSAL Silent Error: {ex.Message}");
}
if (tryInteractiveLogin)
{
try
{
result = await IdentityClient
.AcquireTokenInteractive(Constants.Scopes)
.ExecuteAsync()
.ConfigureAwait(false);
}
catch (Exception ex)
{
Debug.WriteLine($"MSAL Interactive Error: {ex.Message}");
}
}
return new AuthenticationToken
{
DisplayName = result?.Account?.Username ?? "",
ExpiresOn = result?.ExpiresOn ?? DateTimeOffset.MinValue,
Token = result?.AccessToken ?? "",
UserId = result?.Account?.Username ?? ""
};
}
Il metodo GetAuthenticationToken()
funziona con Microsoft Identity Library (MSAL) per ottenere un token di accesso adatto per autorizzare l'utente connesso al servizio back-end. Questa funzione viene quindi passata al RemoteTodoService
per la creazione del client. Se l'autenticazione ha esito positivo, il AuthenticationToken
viene generato con i dati necessari per autorizzare ogni richiesta. In caso contrario, viene generato un token non valido scaduto.
Configurare l'app Android per l'autenticazione
Aprire il progetto TodoApp.Forms.Android
. Creare una nuova classe MsalActivity
con il codice seguente:
using Android.App;
using Android.Content;
using Microsoft.Identity.Client;
namespace TodoApp.Forms.Droid
{
[Activity(Exported = true)]
[IntentFilter(new[] { Intent.ActionView },
Categories = new[] { Intent.CategoryBrowsable, Intent.CategoryDefault },
DataHost = "auth",
DataScheme = "msal{client-id}")]
public class MsalActivity : BrowserTabActivity
{
}
}
Sostituire {client-id}
con l'ID applicazione del client nativo (uguale a Constants.ApplicationId
).
Se il progetto è destinato a Android versione 11 (API versione 30) o successiva, è necessario aggiornare il AndroidManifest.xml
per soddisfare i requisiti di visibilità dei pacchetti Android . Aprire TodoApp.Forms.Android/Properties/AndroidManifest.xml
e aggiungere i nodi di queries/intent
seguenti al nodo manifest
:
<manifest>
...
<queries>
<intent>
<action android:name="android.support.customtabs.action.CustomTabsService" />
</intent>
</queries>
</manifest>
Aprire MainActivity.cs
. Aggiungere IPlatform
alla definizione della classe MainActivity
:
public class MainActivity : global::Xamarin.Forms.Platform.Android.FormsAppCompatActivity, IPlatform
Modificare la chiamata LoadApplication()
nel metodo OnCreate()
:
protected override void OnCreate(Bundle savedInstanceState)
{
base.OnCreate(savedInstanceState);
Xamarin.Essentials.Platform.Init(this, savedInstanceState);
global::Xamarin.Forms.Forms.Init(this, savedInstanceState);
LoadApplication(new App(this));
}
Aggiungere il codice seguente alla fine della classe :
protected override void OnActivityResult(int requestCode, [GeneratedEnum] Result resultCode, Intent data)
{
base.OnActivityResult(requestCode, resultCode, data);
// Return control to MSAL
AuthenticationContinuationHelper.SetAuthenticationContinuationEventArgs(requestCode, resultCode, data);
}
public IPublicClientApplication GetIdentityClient(string applicationId)
{
var identityClient = PublicClientApplicationBuilder.Create(applicationId)
.WithAuthority(AzureCloudInstance.AzurePublic, "common")
.WithRedirectUri($"msal{applicationId}://auth")
.WithParentActivityOrWindow(() => this)
.Build();
return identityClient;
}
Quando il progetto condiviso richiede l'autenticazione, ottiene un client di identità da GetIdentityClient()
, quindi passa a un'attività interna che apre il browser di sistema. Al termine dell'autenticazione, il browser di sistema reindirizza all'URL di reindirizzamento definito (msal{client-id}://auth
). Il MsalActivity
intercettare l'URL di reindirizzamento, che quindi torna all'attività principale chiamando OnActivityResult()
. Viene quindi chiamato l'helper di autenticazione MSAL, che completa la transazione.
Configurare l'app iOS per l'autenticazione
Aprire il file AppDelegate.cs
nel progetto TodoApp.Forms.iOS
. Aggiungere IPlatform
alla definizione della classe AppDelegate
:
public partial class AppDelegate : global::Xamarin.Forms.Platform.iOS.FormsApplicationDelegate, IPlatform
Modificare il metodo FinishedLaunching()
per leggere:
public override bool FinishedLaunching(UIApplication app, NSDictionary options)
{
global::Xamarin.Forms.Forms.Init();
LoadApplication(new App(this));
return base.FinishedLaunching(app, options);
}
Aggiungere il codice seguente alla fine della classe :
public override bool OpenUrl(UIApplication app, NSUrl url, NSDictionary options)
{
bool result = AuthenticationContinuationHelper.SetAuthenticationContinuationEventArgs(url);
return result || base.OpenUrl(app, url, options);
}
public IPublicClientApplication GetIdentityClient(string applicationId)
{
var identityClient = PublicClientApplicationBuilder.Create(applicationId)
.WithIosKeychainSecurityGroup("com.microsoft.adalcache")
.WithRedirectUri($"msal{applicationId}://auth")
.Build();
return identityClient;
}
Aggiungere l'accesso keychain al Entitlements.plist
:
Aprire il file
Entitlements.plist
.Selezionare Keychain.
Selezionare Aggiungi nuovo nei gruppi keychain.
Immettere
com.microsoft.adalcache
come valore:
Aggiungere i diritti personalizzati al progetto:
Fare clic con il pulsante destro del mouse sul progetto di
TodoApp.Forms.iOS
, quindi selezionare Proprietà.Selezionare firma del bundle iOS.
Selezionare il pulsante
... accanto al campo diritti personalizzati. Selezionare
Entitlements
, quindi selezionare Apri.Premere CTRL+S per salvare il progetto.
Testare l'app Android
Impostare TodoApp.Forms.Android
come progetto di avvio, quindi premere F5 per compilare ed eseguire l'app. All'avvio dell'app viene richiesto di accedere all'app. Alla prima esecuzione viene chiesto di fornire il consenso all'app. Al termine dell'autenticazione, l'app viene eseguita normalmente.
Testare l'app iOS
Nota
Poiché l'app iOS richiede l'accesso keychain, è necessario configurare un profilo di provisioning. Un profilo di provisioning richiede un dispositivo reale o un account Apple Developer a pagamento (se si usa il simulatore). Per altre informazioni, vedere Provisioning dei dispositivi per iOS.
Impostare TodoApp.Forms.iOS
come progetto di avvio, quindi premere F5 per compilare ed eseguire l'app. All'avvio dell'app viene richiesto di accedere all'app. Alla prima esecuzione viene chiesto di fornire il consenso all'app. Al termine dell'autenticazione, l'app viene eseguita normalmente.
Passaggi successivi
Configurare quindi l'applicazione in modo che funzioni offline l'implementazione di un archivio offline.
Altre informazioni
- Guida introduttiva: Proteggere un'API Web con Microsoft Identity Platform
- Requisiti di configurazione e suggerimenti per la risoluzione dei problemi per Xamarin Android con MSAL.NET
- Considerazioni sull'uso di Xamarin iOS con MSAL.NET
- scenario : applicazione per dispositivi mobili che chiama le API Web