Share via


Activer la génération de code QR pour les applications d’authentification TOTP dans une application web ASP.NET Core Blazor

Cet article explique comment configurer une application web ASP.NET Core Blazor avec génération de code QR pour les applications d’authentificateur TOTP.

Pour une introduction aux applications d’authentification à deux facteurs (2FA), utilisant un algorithme de mot de passe à usage unique basé sur le temps (TOTP), consultez Activer la génération de code QR pour les applications d’authentificateur TOTP dans ASP.NET Core.

Structurer le composant Activer Microsoft Authenticator dans l’application

Suivez les instructions dans ÉchafaudageIdentity dans les projets ASP.NET Core pour générer un échafaudage Pages\Manage\EnableAuthenticator dans l’application.

Remarque

Bien que seul le composant EnableAuthenticator soit sélectionné pour la génération de modèles automatique dans cet exemple, la génération de modèles automatique ajoute actuellement tous les composants Identity à l’application. En outre, les exceptions peuvent être levées pendant le processus de génération automatique de modèles dans l’application. Si des exceptions se produisent lors des migrations de bases de données, arrêtez l'application et redémarrez-la à chaque exception. Pour plus d’informations, consultez Exceptions de génération de modèles automatique pour Web App Blazor (dotnet/Scaffolding #2694).

Soyez patient pendant l’exécution des migrations. En fonction de la vitesse du système, la migration de la base de données peut prendre jusqu'à une minute ou deux.

Pour plus d’informations, consultez Génération de modèles automatiqueIdentity dans les projets ASP.NET Core. Pour obtenir des conseils sur l’utilisation de l’interface CLI .NET au lieu de Visual Studio, consultez commande dotnet aspnet-codegenerator.

Ajouter de codes QR à la page de configuration 2FA

Ces instructions utilisent le qrcode.js de Shim Sangmin : générateur QRCode inter-navigateur pour JavaScript (davidshimjs/qrcodejs référentiel GitHub).

Téléchargez la bibliothèque qrcode.min.js dans le dossier wwwroot du projet serveur de la solution. La bibliothèque n’a pas de dépendances.

Dans le composant App (Components/App.razor), placez une référence de script de bibliothèque après la balise de Blazor<script> :

<script src="qrcode.min.js"></script>

Le composant EnableAuthenticator, qui fait partie du système de code QR dans l’application et affiche le code QR aux utilisateurs, adopte le rendu statique côté serveur (SSR statique) avec une navigation améliorée. Par conséquent, les scripts normaux ne peuvent pas être exécutés lorsque le composant est chargé ou mis à jour dans le cadre d'une navigation améliorée. Des étapes supplémentaires sont nécessaires pour déclencher le chargement du code QR dans l'interface utilisateur lorsque la page est chargée. Pour effectuer le chargement du code QR, l’approche expliquée dans ASP.NET Core Blazor JavaScript avec rendu statique côté serveur (SSR statique) est adoptée.

Ajoutez l’initialiseur JavaScript suivant au dossier du projet de serveur wwwroot. L’espace réservé {NAME} doit être le nom de l’assembly de l’application pour permettre à Blazor de localiser et charger automatiquement le fichier. Si le nom de l’assembly de l’application serveur est BlazorSample, le fichier est nommé BlazorSample.lib.module.js.

wwwroot/{NAME}.lib.module.js:

const pageScriptInfoBySrc = new Map();

function registerPageScriptElement(src) {
  if (!src) {
    throw new Error('Must provide a non-empty value for the "src" attribute.');
  }

  let pageScriptInfo = pageScriptInfoBySrc.get(src);

  if (pageScriptInfo) {
    pageScriptInfo.referenceCount++;
  } else {
    pageScriptInfo = { referenceCount: 1, module: null };
    pageScriptInfoBySrc.set(src, pageScriptInfo);
    initializePageScriptModule(src, pageScriptInfo);
  }
}

function unregisterPageScriptElement(src) {
  if (!src) {
    return;
  }

  const pageScriptInfo = pageScriptInfoBySrc.get(src);
  
  if (!pageScriptInfo) {
    return;
  }

  pageScriptInfo.referenceCount--;
}

async function initializePageScriptModule(src, pageScriptInfo) {
  if (src.startsWith("./")) {
    src = new URL(src.substr(2), document.baseURI).toString();
  }

  const module = await import(src);

  if (pageScriptInfo.referenceCount <= 0) {
    return;
  }

  pageScriptInfo.module = module;
  module.onLoad?.();
  module.onUpdate?.();
}

function onEnhancedLoad() {
  for (const [src, { module, referenceCount }] of pageScriptInfoBySrc) {
    if (referenceCount <= 0) {
      module?.onDispose?.();
      pageScriptInfoBySrc.delete(src);
    }
  }

  for (const { module } of pageScriptInfoBySrc.values()) {
    module?.onUpdate?.();
  }
}

export function afterWebStarted(blazor) {
  customElements.define('page-script', class extends HTMLElement {
    static observedAttributes = ['src'];

    attributeChangedCallback(name, oldValue, newValue) {
      if (name !== 'src') {
        return;
      }

      this.src = newValue;
      unregisterPageScriptElement(oldValue);
      registerPageScriptElement(newValue);
    }

    disconnectedCallback() {
      unregisterPageScriptElement(this.src);
    }
  });

  blazor.addEventListener('enhancedload', onEnhancedLoad);
}

Ajoutez le composant partagé PageScript suivant à l’application de serveur.

Components/PageScript.razor:

<page-script src="@Src"></page-script>

@code {
    [Parameter]
    [EditorRequired]
    public string Src { get; set; } = default!;
}

Ajoutez le fichier colocalisé JS suivant pour le composant EnableAuthenticator, qui se trouve à Components/Account/Pages/Manage/EnableAuthenticator.razor. La fonction onLoad crée le code QR avec la bibliothèque qrcode.js de Sangmin à l’aide de l’URI de code QR généré par la méthode GenerateQrCodeUri dans le bloc @code du composant.

Components/Account/Pages/Manage/EnableAuthenticator.razor.js:

export function onLoad() {
  const uri = document.getElementById('qrCodeData').getAttribute('data-url');
  new QRCode(document.getElementById('qrCode'), uri);
}

Sous le composant <PageTitle> du composant EnableAuthenticator, ajoutez le composant PageScript avec le chemin d’accès au fichier JS colocalisé :

<PageScript Src="./Components/Account/Pages/Manage/EnableAuthenticator.razor.js" />

Remarque

Une alternative à l’utilisation de l’approche avec le composant PageScript consiste à utiliser un écouteur d’événements (blazor.addEventListener("enhancedload", {CALLBACK})) inscrit dans un initialiseur afterWebStartedJS pour écouter les mises à jour de page provoquées par une navigation améliorée. Le rappel (espace réservé {CALLBACK}) effectue la logique d’initialisation du code QR.

À l’aide de l’approche de rappel avec enhancedload, le code s’exécute pour chaque navigation améliorée, même lorsque le code QR <div> n’est pas rendu. Par conséquent, un code supplémentaire doit être ajouté pour vérifier la présence de <div> avant d’exécuter le code qui ajoute un code QR.

Supprimez l’élément <div> qui contient les instructions de code QR :

- <div class="alert alert-info">
-     Learn how to <a href="https://go.microsoft.com/fwlink/?Linkid=852423">enable 
-     QR code generation</a>.
- </div>

Recherchez les deux éléments <div> où le code QR doit apparaître et où les données de code QR sont stockées dans la page.

Apportez les modifications suivantes :

  • Pour le vide <div>, donnez à l’élément un id de qrCode.
  • Pour le <div> avec l’attribut data-url, donnez à l’élément un id de qrCodeData.
- <div></div>
- <div data-url="@authenticatorUri"></div>
+ <div id="qrCode"></div>
+ <div id="qrCodeData" data-url="@authenticatorUri"></div>

Modifiez le nom du site dans la méthode GenerateQrCodeUri du composant EnableAuthenticator. La valeur par défaut est Microsoft.AspNetCore.Identity.UI. Remplacez la valeur par un nom de site significatif que les utilisateurs peuvent facilement identifier dans leur application d'authentification avec d'autres codes QR pour d'autres applications. Laissez la valeur encodée dans l’URL. Les développeurs définissent généralement un nom de site correspondant au nom de l'entreprise. Exemples : Yahoo, Amazon, Etsy, Microsoft, Zoho.

Dans l’exemple suivant, l’espace réservé {SITE NAME} est l’emplacement où le nom du site (société) est le suivant :

private string GenerateQrCodeUri(string email, string unformattedKey)
{
    return string.Format(
        CultureInfo.InvariantCulture,
        AuthenticatorUriFormat,
-       UrlEncoder.Encode("Microsoft.AspNetCore.Identity.UI"),
+       UrlEncoder.Encode("{SITE NAME}"),
        UrlEncoder.Encode(email),
        unformattedKey);
}

Lancez l'application et assurez-vous que le code QR peut être scanné et que le code est validé.

Composant EnableAuthenticator dans la source de référence

Le composant EnableAuthenticator peut être inspecté dans la source de référence :

Composant EnableAuthenticator dans la source de référence

Remarque

Les liens de documentation vers la source de référence .NET chargent généralement la branche par défaut du référentiel, qui représente le développement actuel pour la prochaine version de .NET. Pour sélectionner une balise pour une version spécifique, utilisez la liste déroulante Échanger les branches ou les balises. Pour plus d’informations, consultez Comment sélectionner une balise de version du code source ASP.NET Core (dotnet/AspNetCore.Docs #26205).

Ressources supplémentaires