如何将已有的Azure Function令牌用作凭据访问资源?
问题:Azure函数应用中使用已认证用户身份访问存储资源
我有启用Active Directory认证的Azure Linux函数应用,以及启用Active Directory认证的Azure静态Web应用。静态Web应用生成的Bearer令牌可正常调用函数,但在函数体内,无法通过DefaultAzureCredential识别已认证用户信息,进而无法使用用户身份读写存储等资源。
现有代码
函数触发代码
const httpTrigger: AzureFunction = async function (context: Context, req: HttpRequest): Promise<void> { // req.user 内容如下 await readFile(...) context.res = { status: 200, body: { apps } }; }; export default httpTrigger;
req.user 已认证信息(精简)
{ "type": "AppService", "id": "...", "username": "...@....com", "identityProvider": "aad", "claimsPrincipalData": { "auth_typ": "aad", "claims": [ ... ], "name_typ": "...", "role_typ": "..." } }
期望的Blob读取代码
const readFile = async (...) => { const credential = new DefaultAzureCredential() const blobServiceClient = new BlobServiceClient( `https://${accountName}.blob.core.windows.net`, credential ); const containerClient = blobServiceClient.getContainerClient(containerName); const blobClient = containerClient.getBlobClient(blobName); const downloadBlockBlobResponse = await blobClient.download(); ... }
遇到的错误
Exception: ChainedTokenCredential authentication failed. CredentialUnavailableError: EnvironmentCredential is unavailable. No underlying credential could be used.
解决方案
1. 获取用户的访问令牌
DefaultAzureCredential是用于获取函数应用自身的托管标识,无法直接关联当前请求的用户身份。需要从请求头中提取用户的原始访问令牌:
- 从
Authorization头提取:去掉Bearer前缀,获得令牌内容 - 若函数应用认证设置开启了令牌存储,可直接从
x-ms-token-aad-access-token请求头读取令牌
2. 使用AccessTokenCredential创建用户凭据
通过@azure/identity包中的AccessTokenCredential,用用户令牌创建可用于Azure SDK的凭据,代表用户身份访问资源。
修改后的完整代码
函数触发逻辑
const httpTrigger: AzureFunction = async function (context: Context, req: HttpRequest): Promise<void> { // 提取用户访问令牌 const accessToken = req.headers["x-ms-token-aad-access-token"] || req.headers.authorization?.replace("Bearer ", ""); if (!accessToken) { context.res = { status: 401, body: "无法获取用户认证令牌" }; return; } await readFile(accessToken, accountName, containerName, blobName); context.res = { status: 200, body: { apps } }; }; export default httpTrigger;
Blob读取逻辑
import { AccessTokenCredential } from "@azure/identity"; import { BlobServiceClient } from "@azure/storage-blob"; const readFile = async (accessToken: string, accountName: string, containerName: string, blobName: string) => { // 基于用户令牌创建凭据 const credential = new AccessTokenCredential(accessToken); const blobServiceClient = new BlobServiceClient( `https://${accountName}.blob.core.windows.net`, credential ); const containerClient = blobServiceClient.getContainerClient(containerName); const blobClient = containerClient.getBlobClient(blobName); const downloadBlockBlobResponse = await blobClient.download(); // 后续数据处理逻辑 };
3. 权限配置
- 确保已给AD用户分配对应存储资源的RBAC角色(如存储Blob数据读者、存储Blob数据参与者)
- 确保静态Web应用请求的令牌包含目标资源的scope(如
https://storage.azure.com/.default)
额外注意
- 需安装依赖包:
npm install @azure/identity @azure/storage-blob - 在Azure门户的函数应用→认证→身份提供者→Azure AD设置中,勾选“将访问令牌存储在请求头中”,确保
x-ms-token-aad-access-token头存在
内容的提问来源于stack exchange,提问作者jared_hexagon
相关产品推荐
相关产品推荐

