Aller au contenu principal

31-4 Page de connexion et Local Storage

On peut maintenant basculer du côté de Blazor pour créer une page/composante de connexion!

Préparation

Afin de supporter l'authentification par API, il nous faudra deux librairies à installer (quelqu'un tient le compte des librairies installées depuis le début?):

  • Microsoft.AspNetCore.Components.Authorization pour les éléments de base
  • Blazored.LocalStorage permettant d'accéder facilement au localstorage du navigateur sans faire usage de JavaScript directement (et donc de devoir passer par l'interop).

Installer Microsoft.AspNetCore.Components.Authorization.

  1. Sous le projet Web.Admin -> Manage NuGet Packages
  2. Faire une recherche pour Microsoft.AspNetCore.Components.Authorization
  3. Installer la librairie dans le projet client.

Installer Blazored.LocalStorage

  1. Sous le projet Web.Admin -> Manage NuGet Packages
  2. Faire une recherche pour Blazored.LocalStorage
  3. Installer la librairie dans le projet Afmin.

Ajout de Blazored.LocalStorage à l'injection de dépendances

Dans Program.cs du projet ClientAdmin:

Snowfall.Web.ClientAdmin/Program.cs
// LocalStorage
builder.Services.AddBlazoredLocalStorage();

Créer la page de connexion

  1. Sous le dossier Web.Admin/Pages -> Add -> Directory
  2. Nommez le dossier Auth
  3. Sous Pages/Auth -> Add -> Blazor Component
  4. Choisir Page comme type
  5. Nommez le composant Connexion
  6. Associez la route /connexion et mettre un titre pertinent
    Snowfall.Web.Admin/Pages/Auth/Connexion.razor
    @page "/Connexion"

    <h1>Connexion</h1>

    @code {

    }

Créer le client AuthHttpClient

Pour communiquer avec l'API en lien avec l'authentification, on créera un client nommé AuthHttpClient qui encapsulera la logique de communication.

  1. Sous le dossier Admin/HttpClients -> Add -> Class/Interface
  2. Nommez la classe AuthHttpClient
  3. Assignez une URL de base et injectez via le constructure le HttpClient
    Snowfall.Web.Admin/HttpClients/AuthHttpClient.cs
    public class AuthHttpClient
    {
    private const string BaseApiUrl = "api/auth";

    private readonly HttpClient _client;

    public AuthHttpClient(HttpClient client)
    {
    _client = client;
    }
    }
  4. Ajoutez une coquille de fonction Connexion
    Snowfall.Web.Admin/HttpClients/AuthHttpClient.cs
    //...

    public async Task<ResultatConnexionDto?> Connexion(ConnexionDto connexionDto)
    {
    return null;
    }
  5. Assurez-vous d'ajouter le client pour qu'il soit disponible à l'injection de dépendance.
    Snowfall.Web.Admin/Configurations/InjectionDependancesConfig.cs
    //...
    services.AddScoped<AuthHttpClient>();
    //...

Créer le formulaire de connexion

Pour se connecter, on utilisera un formulaire relativement simple lié à un modèle de type ConnexionDto.

Le formulaire n'a rien de bien particulier par rapport à ce que nous avons fait précédemment pour le CRUD des événements. Vous pouvez donc réutiliser la coquille suivante.

Snowfall.Web.Admin/Pages/Auth/Connexion.razor
@page "/connexion"
@using Microsoft.Extensions.Localization
@using Snowfall.Application.Dtos.Auth

<div class="row">
<div class="col-md-8 col-lg-4 offset-md-2 offset-lg-4">
<h1>Connexion</h1>

@if(!String.IsNullOrEmpty(_alertMessage))
{
<div class="alert alert-danger">@_alertMessage</div>
}

<EditForm Model="@_connexionDto" OnValidSubmit="@GererSubmit">
<DataAnnotationsValidator />

<div class="form-floating mb-3">
<InputText id="email" class="form-control" type="email" placeholder="Courriel" @bind-Value="_connexionDto.Email" />
<label asp-for="email">Courriel</label>
<ValidationMessage class="invalid-feedback" For="@(() => _connexionDto.Email)" />
</div>

<div class="form-floating mb-3">
<InputText id="password" class="form-control" type="password" placeholder="Mot de passe" @bind-Value="_connexionDto.Password" />
<label asp-for="password">Mot de passe</label>
<ValidationMessage class="invalid-feedback" For="@(() => _connexionDto.Password)" />
</div>

<button class="btn btn-primary" type="submit">Se connecter</button>
</EditForm>
</div>
</div>

@code {
private ConnexionDto _connexionDto = new();
private string? _alertMessage;

async Task GererSubmit()
{

}
}

Compléter le client

  1. Premièrement, on initialise à null le résultat de connexion. Il s'agira de la valeur par défaut retournée.
    Snowfall.Web.Admin/HttpClients/AuthHttpClient.cs
    public async Task<ResultatConnexionDto?> Connexion(ConnexionDto connexionDto)
    {
    ResultatConnexionDto? resultatConnexionDto = null;

    return resultatConnexionDto;
    }
  2. On débute l'authentification en appelant l'API, via une requête POST contenant le DTO de connexion.
    public async Task<ResultatConnexionDto?> Connexion(ConnexionDto connexionDto)
    {
    ResultatConnexionDto? resultatConnexionDto = null;

    var response = await _client.PostAsJsonAsync(BaseApiUrl, connexionDto);

    return resultatConnexionDto;
    }
  3. Si le code de retour est un code de succès, on peut lire le retour de l'API à partir de ReadFromJasonAsync et convertir le retour en objet ResultatConnexionDto.
    public async Task<ResultatConnexionDto?> Connexion(ConnexionDto connexionDto)
    {
    ResultatConnexionDto? resultatConnexionDto = null;

    var response = await _client.PostAsJsonAsync(BaseApiUrl, connexionDto);

    if (response.IsSuccessStatusCode)
    {
    resultatConnexionDto = await response.Content.ReadFromJsonAsync<ResultatConnexionDto>();
    }

    return resultatConnexionDto;
    }

Appeler AuthHttpClient lors de la connexion

  1. Injectez le client dans le composant
    Snowfall.Web.Admin/Pages/Auth/Connexion.razor
    @page "/connexion"
    @using Microsoft.Extensions.Localization
    @using Snowfall.Application.Dtos.Auth
    @using Snowfall.Web.Admin.HttpClients

    @inject AuthHttpClient AuthHttpClient
  2. Appeler le client dans le composant et traiter le retour
    Snowfall.Web.Admin/Pages/Auth/Connexion.razor
    async Task GererSubmit()
    {
    var resultatConnexionDto = await AuthHttpClient.Connexion(_connexionDto);

    if (resultatConnexionDto is not null)
    {
    // À faire: stocker le jeton dans le localstorage
    }
    }
  3. Pour stocker le jeton dans le localstorage, on peut utiliser la librairie Blazored.LocalStorage installée précédemment. On doit pour ce faire injecter la dépendance associée à cette librairie.
    Snowfall.Web.Admin/Pages/Auth/Connexion.razor
    @inject ILocalStorageService LocalStorage
  4. Stocker le jeton dans le local storage. Pour ce faire, on peut utiliser la librairie Blazored.LocalStorage installée précédemment.
    Snowfall.Web.ClientAdmin/Pages/Auth/Connexion.razor
    async Task GererSubmit()
    {
    var resultatConnexionDto = await AuthHttpClient.Connexion(_connexionDto);

    if (resultatConnexionDto is not null)
    {
    await LocalStorage.SetItemAsStringAsync("authToken", resultatConnexionDto.Token);
    }
    }
  5. Dans le cas d'une erreur, fort probablement pour une mauvaise combinaison de courriel/mot de passe, on affichera le message d'erreur.
    Snowfall.Web.Admin/Pages/Auth/Connexion.razor
    async Task GererSubmit()
    {
    var resultatConnexionDto = await AuthHttpClient.Connexion(_connexionDto);

    if (resultatConnexionDto is not null)
    {
    await LocalStorage.SetItemAsStringAsync("authToken", resultatConnexionDto.Token);
    }
    else
    {
    _alertMessage = "Mauvaise combinaison de courriel et mot de passe";
    }
    }

Test

Si tout se passe bien jusqu'à maintenant, vous devriez pouvoir vous compléter le formulaire, cliquer sur le bouton Connexion et le jeton devrait apparaitre dans le Local Storage.

Imgur

Et dans le cas d'une erreur...

Imgur