Bagikan melalui


Praktik terbaik autentikasi dengan pustaka Identitas Azure untuk JavaScript

Artikel ini menawarkan panduan untuk membantu Anda memaksimalkan performa dan keandalan aplikasi JavaScript dan TypeScript Anda saat mengautentikasi ke layanan Azure. Untuk memanfaatkan pustaka Identitas Azure untuk JavaScript, penting untuk memahami potensi masalah dan teknik mitigasi.

Menggunakan kredensial deterministik di lingkungan produksi

DefaultAzureCredential adalah cara paling mudah diakses untuk memulai pustaka Azure Identity, tetapi kemudahan itu juga memperkenalkan kompromi tertentu. Terutama, kredensial tertentu dalam rantai yang akan berhasil dan digunakan untuk autentikasi permintaan tidak dapat dijamin sebelumnya. Dalam lingkungan produksi, ketidakpastian ini dapat menimbulkan masalah yang signifikan dan terkadang halus.

Misalnya, pertimbangkan urutan peristiwa hipotetis berikut:

  1. Tim keamanan organisasi mengamanatkan semua aplikasi menggunakan identitas terkelola untuk mengautentikasi ke sumber daya Azure.
  2. Selama berbulan-bulan, aplikasi JavaScript yang dihosting di Azure Virtual Machine (VM) berhasil digunakan DefaultAzureCredential untuk mengautentikasi melalui identitas terkelola.
  3. Tanpa memberi tahu tim dukungan, pengembang menginstal Azure CLI pada VM tersebut dan menjalankan perintah az login untuk mengautentikasi ke Azure.
  4. Karena perubahan konfigurasi terpisah baru ini di lingkungan Azure, autentikasi melalui identitas terkelola asli secara tak terduga mulai gagal secara diam-diam.
  5. DefaultAzureCredential melewati ManagedIdentityCredential yang gagal dan mencari kredensial berikutnya yang tersedia, yaitu AzureCliCredential.
  6. Aplikasi mulai menggunakan kredensial Azure CLI daripada identitas terkelola, yang mungkin gagal atau mengakibatkan elevasi atau pengurangan hak istimewa yang tidak terduga.

Untuk mencegah jenis masalah halus ini atau kegagalan senyap dalam aplikasi produksi, ganti DefaultAzureCredential dengan implementasi tertentu TokenCredential , seperti ManagedIdentityCredential. Lihat dokumentasi pustaka klien Azure Identity untuk kredensial yang tersedia.

Misalnya, pertimbangkan konfigurasi berikut DefaultAzureCredential dalam proyek 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
);

Ubah kode sebelumnya untuk memilih kredensial berdasarkan lingkungan tempat aplikasi berjalan:

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
);

Dalam contoh ini, hanya ManagedIdentityCredential digunakan dalam produksi. Kebutuhan autentikasi lingkungan pengembangan lokal kemudian dilayankan oleh urutan kredensial yang ditentukan dalam else klausul.

Menggunakan ulang instance kredensial

Gunakan kembali instans kredensial jika memungkinkan untuk meningkatkan ketahanan aplikasi dan mengurangi jumlah permintaan token akses yang dikeluarkan untuk ID Microsoft Entra. Ketika kredensial dipakai ulang, upaya dilakukan untuk mengambil token dari cache token aplikasi yang dikelola oleh dependensi MSAL dasar. Untuk informasi selengkapnya, lihat Penyiapan cache Token di perpustakaan klien Azure Identity.

Perilaku penyimpanan sementara token berbeda antara browser dan lingkungan Node.js. Dalam aplikasi Node.js, token di-cache dalam memori secara default, yang berarti cache hilang saat aplikasi dimulai ulang. Dalam aplikasi browser, token dapat dipertahankan di penyimpanan browser (localStorage atau sessionStorage) tergantung pada alur dan konfigurasi autentikasi. Memahami perbedaan ini penting saat menerapkan strategi penggunaan kembali kredensial untuk berbagai jenis aplikasi.

Penting

Aplikasi bertrafik tinggi yang tidak menggunakan ulang kredensial mungkin mengalami respons pembatasan HTTP 429 dari ID Microsoft Entra, yang dapat menyebabkan gangguan pada aplikasi.

Strategi penggunaan kembali kredensial yang direkomendasikan berbeda menurut kerangka kerja aplikasi.

Untuk menerapkan penggunaan kembali kredensial dalam aplikasi JavaScript, buat satu instans kredensial dan gunakan kembali di semua objek klien:

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
);

Dalam aplikasi Express.js, Anda dapat menyimpan kredensial di pengaturan aplikasi dan mengaksesnya di penangan rute Anda:

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'));

Memahami kapan masa berlaku token dan logika penyimpanan diperlukan

Jika Anda menggunakan kredensial pustaka Azure Identity di luar konteks pustaka klien Azure SDK, maka menjadi tanggung jawab Anda untuk mengelola masa pakai token dan perilaku caching di aplikasi Anda.

Properti refreshAfterTimestamp di AccessToken, yang memberikan petunjuk kepada konsumen tentang kapan refresh token dapat dicoba, akan secara otomatis digunakan oleh pustaka klien Azure SDK yang bergantung pada pustaka Azure Core untuk menyegarkan token. Untuk penggunaan langsung kredensial pustaka Azure Identity yang mendukung penembolokan token, cache MSAL yang mendasar secara otomatis disegarkan secara proaktif ketika waktu refreshAfterTimestamp terjadi. Desain ini memungkinkan kode klien untuk memanggil TokenCredential.getToken() setiap kali token diperlukan dan mendelegasikan refresh ke pustaka.

Untuk hanya memanggil TokenCredential.getToken() jika diperlukan, perhatikan tanggal refreshAfterTimestamp dan lakukan langkah proaktif untuk menyegarkan token setelah waktu tersebut. Implementasi khusus terserah pelanggan.

Memahami strategi coba lagi identitas terkelola

Pustaka Azure Identity untuk JavaScript memungkinkan Anda mengautentikasi melalui identitas terkelola dengan ManagedIdentityCredential. Cara Anda menggunakan ManagedIdentityCredential berdampak pada strategi coba lagi yang diterapkan:

  • Ketika digunakan melalui DefaultAzureCredential, tidak ada percobaan ulang yang dilakukan jika upaya akuisisi token awal gagal atau melewati batas waktu setelah durasi singkat. Ini adalah opsi yang paling tidak tangguh karena dioptimalkan untuk "gagal cepat" guna mencapai efisiensi dalam proses pengembangan.
  • Pendekatan lain, seperti ChainedTokenCredential atau ManagedIdentityCredential secara langsung:
    • Interval waktu antara percobaan ulang dimulai pada 0,8 detik, dan maksimum lima percobaan ulang dicoba, secara default. Opsi ini dioptimalkan untuk ketahanan, tetapi dapat menyebabkan penundaan yang berpotensi tidak diinginkan dalam siklus pengembangan internal.
    • Untuk mengubah salah satu pengaturan coba lagi default, gunakan properti retryOptions pada parameter opsi. Misalnya, coba lagi maksimal tiga kali, dengan interval awal 0,5 detik:
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)
    }
  }
);

Untuk informasi selengkapnya tentang menyesuaikan kebijakan coba lagi untuk identitas terkelola, lihat salah satu opsi berikut yang diperluas dari TokenCredentialOptions: