Sdílet prostřednictvím


Osvědčené postupy ověřování s využitím knihovny Identit Azure pro JavaScript

Tento článek nabízí pokyny, které vám pomůžou maximalizovat výkon a spolehlivost aplikací JavaScriptu a TypeScriptu při ověřování ve službách Azure. Aby byla knihovna Identit Azure pro JavaScript co nejvíce využita, je důležité porozumět potenciálním problémům a zmírňovacím technikám.

Použití deterministických přihlašovacích údajů v produkčních prostředích

DefaultAzureCredential je nejpohodnější způsob, jak začít s knihovnou identit Azure, ale tato pohodlí přináší i určité kompromisy. Zejména konkrétní přihlašovací údaje v řetězci, které budou úspěšné a budou použity pro ověřování žádostí, není možné předem zaručit. V produkčním prostředí může tato nepředvídatelnost představovat významné a někdy drobné problémy.

Představte si například následující hypotetickou posloupnost událostí:

  1. Bezpečnostní tým organizace vyžaduje, aby všechny aplikace používaly spravovanou identitu k ověřování prostředků Azure.
  2. Již několik měsíců JavaScriptová aplikace hostovaná na virtuálním počítači Azure úspěšně používá DefaultAzureCredential k ověření prostřednictvím spravované identity.
  3. Vývojář na tento virtuální počítač nainstaluje Azure CLI a spustí příkaz az login pro ověření v Azure, aniž by řekl týmu podpory.
  4. Kvůli této nové oddělené změně konfigurace v prostředí Azure začne ověřování prostřednictvím původní spravované identity neočekávaně selhávat bez upozornění.
  5. DefaultAzureCredential přeskočí neúspěšné ManagedIdentityCredential a vyhledá další dostupné přihlašovací údaje, což je AzureCliCredential.
  6. Aplikace začne místo spravované identity využívat přihlašovací údaje Azure CLI, což může selhat nebo vést k neočekávanému zvýšení oprávnění nebo snížení oprávnění.

Chcete-li těmto typům drobných problémů nebo tichých selhání v produkčních aplikacích zabránit, nahraďte DefaultAzureCredential konkrétní TokenCredential implementací, například ManagedIdentityCredential. Dostupné přihlašovací údaje najdete v dokumentaci ke klientské knihovně azure Identity .

Představte si například následující DefaultAzureCredential konfiguraci v projektu Express.js:

import { DefaultAzureCredential } from "@azure/identity";
import { SecretClient } from "@azure/keyvault-secrets";
import { BlobServiceClient } from "@azure/storage-blob";

const credential = new DefaultAzureCredential();

const secretClient = new SecretClient("https://keyVaultName.vault.azure.net", credential);
const blobServiceClient = new BlobServiceClient(
  "https://storageAccountName.blob.core.windows.net",
  credential
);

Upravte předchozí kód tak, aby na základě prostředí, ve kterém je aplikace spuštěná, vybrali přihlašovací údaje:

import { AzureDeveloperCliCredential, ManagedIdentityCredential, ChainedTokenCredential, 
         AzureCliCredential } from "@azure/identity";
import { SecretClient } from "@azure/keyvault-secrets";
import { BlobServiceClient } from "@azure/storage-blob";

let credential;

// In production, use only ManagedIdentityCredential
if (process.env.NODE_ENV === 'production') {
  // For user-assigned managed identity, provide the client ID
  credential = new ManagedIdentityCredential(process.env.AZURE_CLIENT_ID);
}
// In development, use a chain of credentials appropriate for local work
else {
  credential = new ChainedTokenCredential(
    new AzureCliCredential(),
    new AzureDeveloperCliCredential()
  );
}

// Initialize Key Vault client
const secretClient = new SecretClient("https://keyVaultName.vault.azure.net", credential);

// Initialize Blob Storage client
const blobServiceClient = new BlobServiceClient(
  "https://storageAccountName.blob.core.windows.net",
  credential
);

V tomto příkladu se používá pouze ManagedIdentityCredential v produkčním prostředí. Požadavky na ověřování místního vývojového prostředí se pak obsluhují sekvencí přihlašovacích údajů definovaných v else klauzuli.

Opakované použití instancí autentizačních údajů

Pokud je to možné, použijte instance přihlašovacích údajů, pokud je to možné, abyste zlepšili odolnost aplikací a snížili počet žádostí o přístupový token vydaných pro Microsoft Entra ID. Při opětovném použití přihlašovacích údajů se provede pokus o načtení tokenu z mezipaměti tokenů aplikace spravované základní závislostí MSAL. Další informace najdete v tématu Ukládání tokenů do mezipaměti v klientské knihovně azure Identity.

Chování ukládání tokenů do mezipaměti se liší mezi prohlížečem a prostředími Node.js. V Node.js aplikacích se tokeny ve výchozím nastavení ukládají do mezipaměti, což znamená, že při restartování aplikace dojde ke ztrátě mezipaměti. V aplikacích prohlížeče je možné tokeny uchovávat v úložišti prohlížeče (localStorage nebo sessionStorage) v závislosti na toku ověřování a konfiguraci. Pochopení těchto rozdílů je důležité při implementaci strategií opětovného použití přihlašovacích údajů pro různé typy aplikací.

Důležité

Aplikace s vysokým počtem uživatelů, která neznovu používá přihlašovací údaje, může narazit na omezení HTTP 429 od služby Microsoft Entra ID, což může způsobit výpadky aplikace.

Doporučená strategie opětovného použití přihlašovacích údajů se liší podle architektury aplikace.

Pokud chcete implementovat opakované použití přihlašovacích údajů v javascriptových aplikacích, vytvořte jednu instanci přihlašovacích údajů a znovu ji použijte ve všech klientských objektech:

import { DefaultAzureCredential, ManagedIdentityCredential } from "@azure/identity";
import { SecretClient } from "@azure/keyvault-secrets";
import { BlobServiceClient } from "@azure/storage-blob";

// Create a single credential instance
const credential = process.env.NODE_ENV === 'production'
  ? new ManagedIdentityCredential(process.env.AZURE_CLIENT_ID)
  : new DefaultAzureCredential();

// Reuse the credential across different client objects
const secretClient = new SecretClient("https://keyVaultName.vault.azure.net", credential);
const blobServiceClient = new BlobServiceClient(
  "https://storageAccountName.blob.core.windows.net",
  credential
);

V Express.js aplikacích můžete přihlašovací údaje ukládat v nastavení aplikace a přistupovat k němu v obslužných rutinách tras:

import express from "express";
import { DefaultAzureCredential, ManagedIdentityCredential } from "@azure/identity";
import { SecretClient } from "@azure/keyvault-secrets";
import { BlobServiceClient } from "@azure/storage-blob";

const app = express();

// Create a single credential instance at app startup
app.locals.credential = process.env.NODE_ENV === 'production'
  ? new ManagedIdentityCredential(process.env.AZURE_CLIENT_ID)
  : new DefaultAzureCredential();

// Reuse the credential in route handlers
app.get('/api/secrets/:secretName', async (req, res) => {
  const secretClient = new SecretClient(
    "https://keyVaultName.vault.azure.net", 
    req.app.locals.credential
  );
  
  try {
    const secret = await secretClient.getSecret(req.params.secretName);
    res.json({ name: secret.name, value: secret.value });
  } catch (error) {
    res.status(500).json({ error: error.message });
  }
});

// Add this route to the existing Express app
app.get('/api/blobs/:containerName', async (req, res) => {
  const blobServiceClient = new BlobServiceClient(
    "https://storageAccountName.blob.core.windows.net", 
    req.app.locals.credential
  );
  
  try {
    // Get reference to a container
    const containerClient = blobServiceClient.getContainerClient(req.params.containerName);
    
    // List all blobs in the container
    const blobs = [];
    for await (const blob of containerClient.listBlobsFlat()) {
      blobs.push({
        name: blob.name,
        contentType: blob.properties.contentType,
        size: blob.properties.contentLength,
        lastModified: blob.properties.lastModified
      });
    }
    
    res.json({ containerName: req.params.containerName, blobs });
  } catch (error) {
    res.status(500).json({ error: error.message });
  }
});

app.listen(3000, () => console.log('Server running on port 3000'));

Vysvětlení, kdy je potřeba použít životnost tokenu a logiku ukládání do mezipaměti

Pokud používáte přihlašovací údaje knihovny Identit Azure mimo kontext klientské knihovny Azure SDK, stane se vaší zodpovědností spravovat životnost tokenů a chování ukládání do mezipaměti ve vaší aplikaci.

refreshAfterTimestamp Vlastnost AccessToken, která uživatelům poskytuje nápovědu k tomu, kdy je možné provést pokus o aktualizaci tokenu, se automaticky použije klientskými knihovnami Sady Azure SDK, které jsou závislé na knihovně Azure Core k aktualizaci tokenu. Pro přímé použití přihlašovacích údajů knihovny Azure Identity, které podporují ukládání tokenů do mezipaměti, se základní mezipaměť MSAL automaticky a proaktivně aktualizuje, když nastane určený čas refreshAfterTimestamp. Tento návrh umožňuje klientskému kódu volat TokenCredential.getToken() pokaždé, když je potřeba token, a delegovat aktualizaci do knihovny.

Aby bylo možné volat TokenCredential.getToken() pouze v případě potřeby, sledujte datum refreshAfterTimestamp a proaktivně se po tomto datu pokuste token aktualizovat. Konkrétní implementace je na zákazníkovi.

Pochopte strategii opakování spravované identity

Knihovna Identit Azure pro JavaScript umožňuje ověřování prostřednictvím spravované identity pomocí ManagedIdentityCredential. Způsob použití ManagedIdentityCredential ovlivňuje použitou strategii opakování:

  • Při použití prostřednictvím DefaultAzureCredential, nejsou prováděny žádné opakované pokusy, pokud počáteční pokus o získání tokenu selže nebo vyprší časový limit po krátké době. Jedná se o nejméně odolnou možnost, protože je optimalizovaná pro efektivní proces vnitřního vývoje tak, aby rychle selhala.
  • Jakýkoli jiný přístup, například ChainedTokenCredential nebo ManagedIdentityCredential přímo:
    • Časový interval mezi opakovanými pokusy začíná na 0,8 sekundách a ve výchozím nastavení se pokusí o maximálně pět opakování. Tato možnost je optimalizovaná pro odolnost, ale přináší potenciálně nežádoucí zpoždění ve vnitřní smyčce vývoje.
    • Pokud chcete změnit některé z výchozích nastavení opakování, použijte vlastnost retryOptions u parametru options. Zkuste například opakovat maximálně třikrát s počátečním intervalem 0,5 sekund:
import { ManagedIdentityCredential } from "@azure/identity";

const credential = new ManagedIdentityCredential(
  process.env.AZURE_CLIENT_ID, // For user-assigned managed identity
  {
    retryOptions: {
      maxRetries: 3,           // Maximum number of retry attempts
      retryDelayInMs: 500,     // Initial delay between retries (in milliseconds)
      maxRetryDelayInMs: 5000  // Maximum delay between retries (in milliseconds)
    }
  }
);

Další informace o přizpůsobení zásad opakování pro spravovanou identitu najdete v jedné z následujících možností, které rozšiřují možnosti TokenCredentialOptions: