@azure/storage-blob中TokenCredential的Token解析及SPA场景获取问题问询
Hey Rasmus, great question—this is a super common scenario when building SPAs that interact with Azure Storage without server-side middlemen, so let's walk through what's going on and fix it for you.
First: What is the Token in TokenCredential?
The token referenced in TokenCredential is an Azure AD access token—a short-lived, OAuth 2.0-compliant token that represents a user (or application) and their permissions to access Azure Storage. It contains claims like who the token is for (aud), what permissions it grants (scp), and when it expires. For Storage, this token tells the Blob service that the authenticated user has permission to perform actions like list blobs, upload files, etc., via the user_impersonation permission you set up.
Why Your MSAL Token Isn't Working (And How to Fix It)
The most likely culprit here is that the access token you're fetching with MSAL isn't targeted at Azure Storage. When requesting tokens with MSAL, you need to specify the correct scope tied to the Storage service—otherwise, the token will be valid for a different resource (like Microsoft Graph) and get rejected by Storage.
Step 1: Request the Correct Scope
When calling acquireTokenSilent (or any MSAL token method), you must use the scope https://storage.azure.com/user_impersonation. This tells Azure AD to issue a token specifically for accessing Azure Storage with the user impersonation permission you granted.
Here's how to adjust your MSAL code:
// Initialize your MSAL instance as you already have const msalInstance = new PublicClientApplication(yourMsalConfig); // Fetch the token with the Storage-specific scope const getStorageAccessToken = async () => { const activeAccount = msalInstance.getActiveAccount(); if (!activeAccount) { // No user logged in—redirect or popup for login first const loginResponse = await msalInstance.loginPopup({ scopes: ["https://storage.azure.com/user_impersonation"] }); return loginResponse.accessToken; } try { // Silent token acquisition (refreshes if needed) const tokenResponse = await msalInstance.acquireTokenSilent({ account: activeAccount, scopes: ["https://storage.azure.com/user_impersonation"] }); return tokenResponse.accessToken; } catch (error) { // Silent fetch failed—fallback to popup if (error instanceof InteractionRequiredAuthError) { const tokenResponse = await msalInstance.acquireTokenPopup({ scopes: ["https://storage.azure.com/user_impersonation"] }); return tokenResponse.accessToken; } throw error; } };
Step 2: Verify the Token is Valid
To confirm you have the right token, copy it and paste it into jwt.ms (a safe, client-side tool to parse tokens). Check these two claims:
aud: Should behttps://storage.azure.com/(this is the audience, meaning the token is meant for Storage)scp: Should includeuser_impersonation(this confirms the permission is included)
Step 3: Use the Token with @azure/storage-blob
Once you have the correct access token, wrap it in a TokenCredential to use with BlobServiceClient. You can use AccessTokenCredential from @azure/identity for this:
import { BlobServiceClient } from "@azure/storage-blob"; import { AccessTokenCredential } from "@azure/identity"; // Get the valid token from your MSAL function above const accessToken = await getStorageAccessToken(); // Create the credential and BlobServiceClient const storageCredential = new AccessTokenCredential(accessToken); const blobServiceClient = new BlobServiceClient( `https://your-storage-account.blob.core.windows.net`, storageCredential ); // Now you can use blobServiceClient to interact with blobs const containerClient = blobServiceClient.getContainerClient("your-container"); const blobs = await containerClient.listBlobsFlat().byPage().next();
Have Other Developers Tried This?
Absolutely—this is the recommended approach for SPAs that need direct access to Azure Storage without server-side SAS token generation. As long as you get the scope right and ensure your app registration has the correct delegated permission (with admin consent if required for your tenant), this setup works reliably.
Quick Additional Checks
- Make sure your app registration's redirect URI matches what's configured in MSAL (critical for SPA auth flow)
- If your tenant requires admin consent for permissions, ensure the
user_impersonationpermission has been granted by an admin (you can check this in the Azure Portal under your app registration's "API Permissions" tab) - Remember that access tokens expire (usually after 1 hour)—MSAL's
acquireTokenSilentwill automatically refresh them as long as the user is still logged in, so you don't have to handle refresh tokens manually
Hopefully this gets your file manager up and running smoothly!
内容的提问来源于stack exchange,提问作者Rasmus Edvardsen

