1923

都内と業界の隅っこで生活しているエンジニアのノート

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