MSAL.js(v2) で取得したトークンを使用して JavaScript 用 Azure Blob Storage v12を使う
Azure Functions や Web Apps を使わず静的なサイトでBlobを扱いたかったので、前回試していたMSAL.js(v2)のトークンを使って試しにBlobのコンテナ一覧を取得してみます。
REST APIを直接呼ぶ場合は、acquireTokenSilent で取得した accessToken を Bearer に設定。x-ms-version や x-ms-client-request-id などを Headers に追加する程度ですね。
今回は、JavaScript 用 Azure Blob Storage v12を使ってみます。サンプルは前回と同じく TypeScript + Vue.jsです。 TokenCredential と getToken の戻りとなる AccessToken を作成して、BlobServiceClient に作成した TokenCredential を渡せばコードは完了です。 あとはSASでのアクセスと同じくCORSやIAMの設定も必要です。
サンプル
import { TokenCredential } from "@azure/identity"; import * as Msal from "@azure/msal-browser"; import { AccessToken } from "@azure/core-auth"; class MsalAccessToken implements AccessToken { token = ""; expiresOnTimestamp = 0; } class MsalTokenCredential implements TokenCredential { private _context: Msal.PublicClientApplication; constructor(PublicClientApplication: Msal.PublicClientApplication) { this._context = PublicClientApplication; } getToken( scopes: string | string[], options?: import("@azure/core-auth").GetTokenOptions | undefined ): Promise<AccessToken | null> { const silentRequest = { scopes: ["https://storage.azure.com/user_impersonation"] }; const response = this._context.acquireTokenSilent(silentRequest); return response.then(res => { const ma = new MsalAccessToken(); ma.token = res.accessToken; ma.expiresOnTimestamp = Date.now() + 60 * 60 * 1000; return ma; }); } } import { BlobServiceClient } from "@azure/storage-blob"; import { ref, defineComponent, onMounted } from "@vue/composition-api"; export default defineComponent({ props: { storageAccount: { type: String, default: "" } }, setup(props, context) { const containers = ref<string[]>([]); onMounted(async () => { try { const tokenCredential = new MsalTokenCredential(context.root.$msal) const blobServiceClient = new BlobServiceClient( `https://${props.storageAccount}.blob.core.windows.net`, tokenCredential ); const iter = blobServiceClient.listContainers(); for await (const container of iter) { containers.value.push(container.name); } } catch (error) { console.log("failed: ", error); } }); return { containers }; } });