Authentification Azure Directory B2C dans une application Xamarin.Forms
Tags: xamarinforms, azure, authentification, french
Published: 2021-03-19 18:22:32

---
title: Authentification Azure Directory B2C dans une application Xamarin.Forms
published: true
date: 2021-03-19 17:21:07 UTC
tags: XamarinForms,Azure,Authentification,french
canonical_url: https://www.sylvainmoingeon.fr/authentification-azure-directory-b2c-dans-une-application-xamarinforms/
---
On m’a récemment demandé d’étudier la faisabilité d’une authentification depuis Azure Directory B2C dans une application Xamarin.Forms.

La documentation officielle a un peu tendance à tourner en rond avec des liens en références circulaires, le portail Azure est vaste et pas super user-friendly (on peut passer beaucoup de temps à chercher une option qu’on est pourtant certain d’avoir aperçue cinq minutes plus tôt…).

J’ai donc rédigé un guide rapide à l’attention des développeurs de l’équipe, je vous le livre tel quel, ce n’est donc pas nécessairement très bien rédigé, mais vous aurez toutes les informations pour débuter, depuis la création du _Directory B2C_ sur Azure jusqu’à l’authentification et la récupération des données de l’utilisateur dans l’application Xamarin.Forms.

* * *

# Résumé

1. Créer un tenant _Active Directory B2C_ dans Azure.
2. Enregistrer l’application mobile dans le tenant _Active Directory B2C_.
3. Créer des _User Flows_ avec des polices de _Signin_, réinitialisation de mot de passe…
4. Utiliser la _Microsoft Authentication Library (MSAL)_ pour gérer le flux d’authentification dans l’application.

## Sources

- [Authenticate Users with Azure Active Directory B2C](https://docs.microsoft.com/en-us/xamarin/xamarin-forms/data-cloud/authentication/azure-ad-b2c)
- [Tutorial: Create an Azure Active Directory B2C tenant](https://docs.microsoft.com/en-us/azure/active-directory-b2c/tutorial-create-tenant)
- [Tutorial: Register a web application in Azure Active Directory B2C](https://docs.microsoft.com/en-us/azure/active-directory-b2c/tutorial-register-applications?tabs=app-reg-ga)

# Côté serveur

## Création du compte Azure

[https://aka.ms/azfree-docs-mobileapps](https://aka.ms/azfree-docs-mobileapps)

Pré-requis :

- Un compte microsoft
- Une carte bancaire

Je ne détaille pas, il suffit de suivre les étapes. Sachez simplement que vous disposez d’un crédit de 170€ pour débuter, de quoi faire des tests et de l’autoformation.

## Configuration du portail en ANGLAIS

Très important, peut-être un bug temporaire, mais si vous conservez le portail en français, la création de AD B2C échouera avec un message abscons vous indiquant que la valeur de _l’emplacement du groupe de ressource_ est invalide alors qu’on la sélectionne dans une liste (et peu importe la valeur sélectionnée) !

C’est simplement que la liste est traduite et que visiblement quelque part dans le code, Azure attend une valeur en dur tirée de la liste en anglais. Franchement, j’ai honte pour Microsoft !

Donc évitons-nous bien des soucis et passons immédiatement le portail en anglais.

![Configuration du portail en anglais](https://www.sylvainmoingeon.fr/media/posts/42/6ce4a4c4b1004751bddf92e7f88a9f98.png)

## Enregistrement du namespace _Mirosoft.AzureActiveDirectory_

Aucun tuto ne vous le dira, et c’est peut-être un bug temporaire, mais si vous ne le faites pas maintenant, vous obtiendrez cette erreur à la toute fin du processus et vous devrez tout recommencer. :-)

![Message d'erreur concernant Microsoft.AzureActiveDirectory](https://www.sylvainmoingeon.fr/media/posts/42/eae4e6e303ba45cfaf377ae3ab2f522e.png)

**Cliquez sur _Subscriptions_**

![Navigation vers les subscriptions](https://www.sylvainmoingeon.fr/media/posts/42/d821b9e2f1a84d46b574a439df9c1fc9.png)

**Dans la liste, sélectionnez votre subscription courante.**

Si vous venez de créer un compte gratuit, il n’y en aura qu’une :

![Sélection de la subscription](https://www.sylvainmoingeon.fr/media/posts/42/13427f5008fb459db2ea5276dd729262.png)

**Dans le panneau de gauche, cliquez sur _Resource providers_**

![Navigation vers les resource providers](https://www.sylvainmoingeon.fr/media/posts/42/979a2d1abb4a48b59a7bf9ad8486880f.png)

**Cherchez Azure, sélectionnez _Microsoft.AzureActiveDirectory_ et cliquez sur Register**

![Recherche de Microsoft.AzureActiveDirectory](https://www.sylvainmoingeon.fr/media/posts/42/8fa48e6076574a9eb090837d9231fd87.png)

Patientez… patientez… patientez… patientez… Cliquez de temps en temps sur _Refresh_ au cas où. Si ça ne fonctionne pas, recommencez (sélection, register), au bout d’un moment ça finit par passer. :-)

![Microsoft.AzureActiveDirectory est enregistré](https://www.sylvainmoingeon.fr/media/posts/42/941ed15f975649aca20eeb624c4192fd.png)

C’est bon, on y est, on peut commencer !

## Création de l’Active Directory B2C

**Cliquez sur _Create a resource_**

![Créer une ressources](https://www.sylvainmoingeon.fr/media/posts/42/26cd2d69e0cf4e2c9533a45c7ef1e726.png)

**Cherchez et sélectionnez _Active Directory B2C_**

![Sélectionner Active Directory B2C](https://www.sylvainmoingeon.fr/media/posts/42/3734c6c0c609497b8523c2ac5ee56045.png)

**Cliquez sur _Create_**

![Cliquer sur Create](https://www.sylvainmoingeon.fr/media/posts/42/8fb8757ce94343aea6ddb6b375e139ac.png)

**Create a New Azure AD B2C tenant**

![Create a New Azure AD B2C tenant](https://www.sylvainmoingeon.fr/media/posts/42/0f44978924974827b83e5498624e1827.png)

**Renseignez les informations du tenant**

Créer un _Groupe de ressources_ avec le lien _Create New_ s’il n’en existe pas déjà un.

![Renseigner les informations du tenant](https://www.sylvainmoingeon.fr/media/posts/42/bfa01cbf52b14c7b9969c162f08e83ba.png)

**Cliquez sur _Review + Create_ pour valider les informations**

![Valider les informations](https://www.sylvainmoingeon.fr/media/posts/42/eeac2be3682d457dae69874ee0e04525.png)

**Cliquez sur _Create_ pour en finir !**

Patientez. Tant que ça gigote là-dedans c’est que ça bosse :

![Indicateur d'activité dans la toolbar](https://www.sylvainmoingeon.fr/media/posts/42/2fdbea7151f948278ae450c27839495d.png)

Cliquez sur le lien, bienvenue à Black Mesa !

![Lien menant vers votre tenant Active Directory B2C](https://www.sylvainmoingeon.fr/media/posts/42/000cf65ea90e48b0b774d8405119b298.png)

## Configuration d’une _application_ côté serveur

### Selection du tenant B2C

Dans la toolbar en haut à droite, trouvez le bouton qui ressemble à un carnet avec un entonnoir :

![Buton de sélection des directories](https://www.sylvainmoingeon.fr/media/posts/42/0dc10f53aef94e8cb578f3eb0351b5bc.png)

Mais en principe vous devriez déjà être dessus si vous avez cliqué sur le lien à la fin de l’étape précédente.

Si vous vous retrouvez sur une page d’accueil comme ça et que vous ne retrouvez pas votre _tenant AD B2C_…

![Page d'accueil du Directory](https://www.sylvainmoingeon.fr/media/posts/42/619e486c4a054f2cb3ee928a143a1963.png)

Saisissez simplement _B2C_ dans la barre de recherche en haut et dans la rubrique _Services_, sélectionnez _Azure AD B2C_.

![Recherche du tenant B2C](https://www.sylvainmoingeon.fr/media/posts/42/636efe75e666412e9c7584f700c45f51.png)

### Enregistrement de l’application

**Sélectionnez _App registrations_…**

![Navigation vers l'enregistrement d'applications](https://www.sylvainmoingeon.fr/media/posts/42/1c9cbee5394f46a397a8efbdcf1dc132.png)

**Puis _New registration_**

![Nouvel enregistrement](https://www.sylvainmoingeon.fr/media/posts/42/5f5448c2423e48b4bdbc92b536d2453d.png)

**Renseignez les informations**

- 

_Nom_ et _type de compte_ supporté :

![Nom et type de compte](https://www.sylvainmoingeon.fr/media/posts/42/ebba5c97abd241ac81af607acb811a19.png)

- 

_Redirect URI_ : Cela dépend du type d’application (application mobile, web app…). Dans notre cas, il s’agira d’une application mobile Xamarin.Forms. **Attention, l’uri répond à un schéma bien particulier :** `msal[ce_que_vous_voulez]://auth`

![Redirect URi](https://www.sylvainmoingeon.fr/media/posts/42/f551892b4b9f48a8973694ff7473b391.png)

Cet URi sera à renseigner dans les manifestes Android et iOS.

- _Permissions :_

![Permisssions](https://www.sylvainmoingeon.fr/media/posts/42/f6990694e50e4f59bbf304ab240ed75f.png)

Validez le tout en cliquant sur le bouton _Register_. Bravo ! Votre application est enregistrée :

![Application enregistrée](https://www.sylvainmoingeon.fr/media/posts/42/21fa88ac0c1e4b8d97cba7c22496698f.png)

### Mais ce n’est pas fini : la case à cocher secrète

Si vous vous en tenez là et suivez le tuto Microsoft et l’application _Sample_ fournie, cela ne fonctionnera pas : les URI utilisés comme point d’accès dans l’application ne sont pas autorisés par défaut !

Rendez-vous dans la rubrique _Authentication_ et cochez les cases :

![Cocher les Uri d'authentification](https://www.sylvainmoingeon.fr/media/posts/42/cde6cd6048fa407e81ed0c4ba8559687.png)

Pensez bien à sauvegarder. Le bouton en haut, je vous laisse le trouver tout seul.

### Création des _User Flows_

Créer un _user flow_ revient à autoriser les utilisateurs à interagir avec leur compte AD : se connecter, réinitialiser son mot de passe, modifier son profile…

NB : les flows sont partageables entre les applications.

#### Sign In

Au minima, les utilisateurs auront besoin de se connecter. Dans la page de votre _tenant AD B2C_, allez sur _User flows_ dans la rubrique _Policies_ et cliquez sur _New user flow_.

![New User Flow](https://www.sylvainmoingeon.fr/media/posts/42/ff407a8e293349ff8cc82e83e5a3e4c7.png)

Puis sélectionnez _Sign In_ et créez le flow dans sa version recommandée.

![Signin User Flow](https://www.sylvainmoingeon.fr/media/posts/42/436019a0fe0643ebbcb99156b00edbbe.png)

Renseignez les informations en fonction du mode de connexion et de l’authentification multiple souhaités.

Notez bien le nom, vous en aurez besoin côté client :

![Nom de la police](https://www.sylvainmoingeon.fr/media/posts/42/67382c4d40224b36a0f04c9054364cae.png)

La dernière rubrique permet de sélectionner les données qui seront récupérées côté client lors de la connexion utilisateur. Cliquez sur _Show more…_ pour obtenir la liste complète.

![Claims](https://www.sylvainmoingeon.fr/media/posts/42/f65a66c9662f40dc9aaf15676ed7bd5a.png)

Finalisez en cliquant sur le bouton _Create_.

#### Autres flows

La procédure est similaire pour les autres types de _flows_. Créez ceux dont vous avez besoin.

### Création des utilisateurs

Sur la page de votre _tenant Azure AD B2C_, cliquez sur _Users_ dans la rubrique _Manage_.

![Création des utilisateurs](https://www.sylvainmoingeon.fr/media/posts/42/ce85fccb56374fcab27e51b008093cde.png)

Ensuite, cela dépend du mode de connexion envisagé. Il sera peut-être nécessaire de d’abord configurer un ou plusieurs fournisseurs d’identité (compte Microsoft, compte local, Github, Facebook…), dans la même rubrique que précédemment, lien _Identity providers_.

A priori, tout est en place côté serveur, reste à implémenter la couche MSAL côté client.

# Côté client

## Package nuget _Microsoft Authentication Library (MSAL)_

Direction le nuget package manager. Installez _Microsoft.Identity.Client_ sur le projet commun et les projets des plateformes :

![Package nuget Microsoft.Identity.Client](https://www.sylvainmoingeon.fr/media/posts/42/bf2ed89bfb2644a79b5f1cd0c9857761.png)

## Préparation du projet commun

### Définition de quelques constantes

Pour commencer, il est nécessaire de définir quelques constantes.

- `tenantName` : le nom de domaine que vous avez défini pour votre tenant Directory B2C
- `tenantId` : le même suffixé par `.onmicrosoft.com`
- `clientId` : _Application (client) Id_, vous trouverez cette information dans l’_overview_ de votre application sur le portail Azure : 

![ClientId dans l'overview de l'application](https://www.sylvainmoingeon.fr/media/posts/42/99664b9fc9504d75b03489fffe708bfe.png)

- `policySignin` et `policyPassword` : le nom des polices telles que vous les avez définies précédemment
- `iosKeychainSecurityGroup` : identifiant du Bundle iOS que vous trouvez dans `Info.plist`.

```csharp
public static class Constants
{
    const string tenantName = "[your_tenant_name]";
    const string tenantId = "[your_tenant_name].onmicrosoft.com";
    const string clientId = "[your_application_client_id]";
    const string policySignin = "B2C_1_signin";
    const string policyPassword = "B2C_1_resetpassword";
    const string iosKeychainSecurityGroup = "[application iOS Bundle identifier]";

    static readonly string[] scopes = { "" };
    static readonly string authorityBase = $"https://{tenantName}.b2clogin.com/tfp/{tenantId}/";

    public static string RedirectUrl => $"msal{clientId}://auth";
    public static string AuthorityBase => authorityBase;
    public static string[] Scopes => scopes;
    public static string PolicySignin => policySignin;
    public static string PolicyPassword => policyPassword;
    public static string IosKeychainSecurityGroups => iosKeychainSecurityGroup;
    public static string ClientId => clientId;
    public static string AuthoritySignin => $"{authorityBase}{policySignin}";
    public static string AuthorityPasswordReset => $"{authorityBase}{policyPassword}";
}
```

### Le service d’authentification : `AuthenticationClient`

Dans le fichier `App.xaml.cs`, définir les propriétés `AppUi` (nécessaire pour l’implémentation dans Android) et `AuthenticationClient` :

```csharp
using Microsoft.Identity.Client;
[...]

public partial class App : Application
{
    public static IPublicClientApplication AuthenticationClient { get; private set; }
    public static object UIParent { get; set; } = null;

    [...]
}
```

Le service d’authentification implémente `IPublicClientApplication`, pour l’instancier, on utilise le builder `PublicClientApplicationBuilder` :

```csharp
public App()
{
    InitializeComponent();

    AuthenticationClient = PublicClientApplicationBuilder.Create(Constants.ClientId)
            .WithIosKeychainSecurityGroup(Constants.IosKeychainSecurityGroups)
            .WithB2CAuthority(Constants.AuthoritySignin)
            .WithRedirectUri($"msal{Constants.ClientId}://auth")
            .Build();
    [...]
}
```

## Configuration de l’application iOS

### Info.plist

Souvenez-vous côté serveur, vous avez configuré un _Redirect Uri_ sous la forme `msal[nom_libre]://auth`

Il s’agit ici de renseigner cette valeur dans le fichier Info.plist du projet iOS. Cela se passe dans l’onglet _Advanced_, rubrique _URL Types_ :

![Redirect Uri dans Info.plist](https://www.sylvainmoingeon.fr/media/posts/42/e69e5ca4a86d40aaba291deee5c60caf.png)

### Keychain dans Entitlements.plist

Il est ensuite nécessaire d’enregistrer un Keychain dans _Entitlements.plist_ :

![Keychain dans Entitlements.plist](https://www.sylvainmoingeon.fr/media/posts/42/ed660e0f6cf54409b5237432c27a3909.png)

Si cela ne s’est pas fait automatiquement, vérifiez bien que le fichier _Entitlements.plist_ est sélectionné comme _Custom Entitlements_ dans l’onglet _iOS Bundle Signing_ du projet iOS.

![Custom Entitlements](https://www.sylvainmoingeon.fr/media/posts/42/bd0f850cd2e8445688885dbc6c689b59.png)

Faîtes-le bien pour chacune de vos configurations de Build, sinon vous aurez une exception à l’exécution concernant le Keychain !

### Surcharge de la méthode OpenUrl dans AppDelegate

```csharp
using Microsoft.Identity.Client;
[...]

[Register("AppDelegate")]
public partial class AppDelegate : global::Xamarin.Forms.Platform.iOS.FormsApplicationDelegate
{
    [...]

    public override bool OpenUrl(UIApplication app, NSUrl url, NSDictionary options)
    {
        AuthenticationContinuationHelper.SetAuthenticationContinuationEventArgs(url);
        return base.OpenUrl(app, url, options);
    }
}
```

## Configuration l’application Android

### Manifeste

Comme pour iOS, le _Redirect Uri_ doit être déclaré dans le manifeste Android. Mais attention, il semblerait que seul _le Client Id_ (celui qui ressemble à `ead24568-9ecc-43f7-a5b4-ac62acd0a832`) fonctionne.

```xml
<?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.adb2capp">
    <uses-sdk android:minSdkVersion="21" android:targetSdkVersion="30" />
    <application android:label="ADB2CApp.Android" android:theme="@style/MainTheme">

        <!-- MSAL REGISTRATION START -->
        <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="msal[your_app_Client_ID]" android:host="auth" />
            </intent-filter>
        </activity>
        <!-- MSAL REGISTRATION END -->
    </application>
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
</manifest>
```

### Modifications dans _MainActivity_

L’authentification MSAL nécessite :

- De passer l’activity à _App.UIParent_
- De surcharger _OnActivityResult_

```csharp
using Microsoft.Identity.Client;
[...]

public class MainActivity : FormsAppCompatActivity
{
    protected override void OnCreate(Bundle bundle)
    {
        TabLayoutResource = Resource.Layout.Tabbar;
        ToolbarResource = Resource.Layout.Toolbar;

        base.OnCreate(bundle);

        Xamarin.Essentials.Platform.Init(this, savedInstanceState);
        global::Xamarin.Forms.Forms.Init(this, savedInstanceState);
        LoadApplication(new App());
        // ADDED
        App.UIParent = this;
    }

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

    [...]
}
```

## Implémentation dans le projet Xamarin.Forms

### Création d’une page de Login

On va faire super simple, créez une page `LoginPage.xaml`, ajoutez-y un bouton `Login` et abonnez-le à l’événement `Clicked`.

```xml
<ContentPage.Content>
    <Button x:Name="LoginButton"
        Text="LOGIN"
        Clicked="LoginButton_Clicked"
        VerticalOptions="Center"
        HorizontalOptions="Center"
        />
</ContentPage.Content>
```

Visuellement, difficile de faire plus basique :

![Login Page](https://www.sylvainmoingeon.fr/media/posts/42/c2336499611b40d4a380610ef52dabe7.png)

A l’apparition de la page, appelez `AcquireTokenSilentAsync` pour rafraîchir le token d’authentification, au cas où un utilisateur soit déjà authentifié.

```csharp
public partial class LoginPage : ContentPage
{
    [...]

    protected override async void OnAppearing()
    {
        try
        {
            // Look for existing account
            IEnumerable<IAccount> accounts = await App.AuthenticationClient.GetAccountsAsync();

            AuthenticationResult result = await App.AuthenticationClient
                .AcquireTokenSilent(Constants.Scopes, accounts.FirstOrDefault())
                .ExecuteAsync();

            await Navigation.PushAsync(new LogoutPage(result));
        }
        catch
        {
            // Do nothing - the user isn't logged in
        }
        base.OnAppearing();
    }

    [...]
}
```

Au clic sur le bouton, `AcquireTokenInteractive` est utilisé pour ouvrir le navigateur de l’appareil et afficher la page de Signin.

- Si la connexion réussit le résultat de l’authentification est passé à la page `LogoutPage`.
- Si l’utilisateur clique sur l’option “j’ai oublié mon mot de passe”, une exception particulière est interceptée pour lancer la procédure de récupération de mot de passe.

```csharp
private async void LoginButton_Clicked(object sender, EventArgs e)
{
    AuthenticationResult result;
    try
    {
        result = await App.AuthenticationClient
            .AcquireTokenInteractive(Constants.Scopes)
            .WithPrompt(Prompt.SelectAccount)
            .WithParentActivityOrWindow(App.UIParent)
            .ExecuteAsync();

        await Navigation.PushAsync(new LogoutPage(result));
    }
    catch (MsalException ex)
    {
        if (ex.Message != null && ex.Message.Contains("AADB2C90118"))
        {
            result = await OnForgotPassword();
            await Navigation.PushAsync(new LogoutPage(result));
        }
        else if (ex.ErrorCode != "authentication_canceled")
        {
            await DisplayAlert("An error has occurred", "Exception message: " + ex.Message, "Dismiss");
        }
    }
}
```

Et voici le code pour la réinitialisation du mot de passe :

```csharp
private async Task<AuthenticationResult> OnForgotPassword()
{
    try
    {
        return await App.AuthenticationClient
            .AcquireTokenInteractive(Constants.Scopes)
            .WithPrompt(Prompt.SelectAccount)
            .WithParentActivityOrWindow(App.UIParent)
            .WithB2CAuthority(Constants.AuthorityPasswordReset)
            .ExecuteAsync();
    }
    catch (MsalException)
    {
        // Do nothing - ErrorCode will be displayed in OnLoginButtonClicked
        return null;
    }
}
```

Une fois la page créée, remplacez `MainPage` dans `App` par une `NavigationPage` : `MainPage = new NavigationPage(new LoginPage());` de façon à naviguer directement sur la `LoginPage` à l’ouverture de l’application.

### Création d’une page de logout

La page `LogoutPage` est très similaire à la page de login à ceci près :

- Son constructeur reçoit en paramètre le résultat de l’authentification
- Un `Label` affiche les informations de base de l’utilisateur
- Le bouton `Login` est remplacé par un bouton `Logout`

```xml
<ContentPage.Content>
    <StackLayout VerticalOptions="Center" HorizontalOptions="Center">
        <Label x:Name="UserInfoLabel"
                   FontSize="Large"
                   HorizontalTextAlignment="Center"
                   />
        <Button x:Name="LogoutButton"
                    Text="LOGOUT"
                    Clicked="LogoutButton_Clicked"
                    HorizontalOptions="Center"
                    VerticalOptions="Center"
                    />
    </StackLayout>
</ContentPage.Content>
```

Commençons par récupérer l’`AuthenticationResult` dans le constructeur de la page :

```csharp
AuthenticationResult authenticationResult;
public LogoutPage(AuthenticationResult result)
{
    InitializeComponent();    
    authenticationResult = result;
}
```

#### Les informations utilisateur (Claims)

Les informations concernant l’utilisateur, celles que vous avez sélectionnées parmi les `Claims` lors de la création de votre `User Flow Signin` sont codées dans la propriété `authenticationResult.IdToken` sous la forme d’un **[token jwt](https://fr.wikipedia.org/wiki/JSON_Web_Token).**Pour le décoder, vous aurez besoin d’installer le package nuget `System.IdentityModel.Tokens.Jwt`.

![Package nuget JWT](https://www.sylvainmoingeon.fr/media/posts/42/bab1879b2fd647caabcab68ccfaa7a27.png)

Et voici le snippet pour le décoder :

```csharp
var stream = authenticationResult.IdToken;
var handler = new JwtSecurityTokenHandler();
JwtSecurityToken decodedToken = (JwtSecurityToken)handler.ReadToken(stream);
```

Vous retrouverez toutes les informations dans une collection d’objet `Claim`, notamment au travers les propriétés `Type` et `Value` :

![Structure des données de Claim](https://www.sylvainmoingeon.fr/media/posts/42/85c24b29abca478a83d2c41aa5f504b3.png)

Exemple, pour afficher le nom et la ville de l’utilisateur :

```csharp
string name = decodedToken.Claims.FirstOrDefault(c => c.Type == "name")?.Value ?? "Noname";
string city = decodedToken.Claims.FirstOrDefault(c => c.Type == "city")?.Value ?? "Unknown city";

UserInfoLabel.Text = $"Welcome {name}, from {city}";
```

Le code sera appelé de préférence dans le `OnAppearing` de la page plutôt que dans son constructeur.

Et voilà le résultat :

![Page de Logout](https://www.sylvainmoingeon.fr/media/posts/42/1050e4916bdf4788b637930fa9fad470.png)

### Déconnexion

La déconnexion consiste principalement à retirer un compte de `AuthenticationClient` :

```csharp
private async void LogoutButton_Clicked(object sender, EventArgs e)
{
    IEnumerable<IAccount> accounts = await App.AuthenticationClient.GetAccountsAsync();
    while (accounts.Any())
    {
        await App.AuthenticationClient.RemoveAsync(accounts.First());
        accounts = await App.AuthenticationClient.GetAccountsAsync();
    }

    await Navigation.PopAsync();
}
```

### La page de Signin

![Page de Signin](https://www.sylvainmoingeon.fr/media/posts/42/cd085170ebd9443da4c69f613d06d631.png)

### Page de réinitialisation de mot de passe

![Page de réinitialisation de mot de passe](https://www.sylvainmoingeon.fr/media/posts/42/ff9ca60e682d4f16acd619ee2d0aa7c6.png)