You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何通过Azure获取用户及服务账号Token实现Web API认证?

适配Azure AD的FastAPI认证方案

针对你需要替换LDAP、支持人类用户交互式+Jenkins非交互式认证、无需客户端密钥/明文密码的需求,以下是直接可用的实现方案:

一、人类用户认证(支持curl调用)

用授权码流(无客户端密钥),用户通过浏览器就能获取token,不用依赖MSAL类库:

  1. 在Azure AD注册一个「公共客户端应用」(无需设置客户端密钥)
  2. 用户打开浏览器访问Azure AD授权地址,登录后拿到授权码,再用curl交换token:
    # 替换占位符为你的租户ID、客户端ID、浏览器获取的授权码
    curl -X POST https://login.microsoftonline.com/{tenant-id}/oauth2/v2.0/token \
      -d "client_id={client-id}" \
      -d "grant_type=authorization_code" \
      -d "code={浏览器拿到的授权码}" \
      -d "redirect_uri=http://localhost" \
      -d "scope=api://{你的API客户端ID}/access_as_user"
    
  3. 拿到access token后,直接用curl调用API:
    curl -H "Authorization: Bearer {获取到的access-token}" https://你的FastAPI地址/任务接口
    
  4. 优势:用户仅需浏览器登录一次,refresh token可自动续期token,全程无需存储密钥或明文密码。

二、Jenkins等服务账号非交互式认证

推荐两种无密钥方案,根据部署环境选择:

方案1:Azure托管身份(适合Azure上的Jenkins)

如果Jenkins运行在Azure VM/AKS/App Service上,直接启用托管身份:

  1. 给托管身份授予你的API访问权限(在Azure AD的API权限中添加托管身份的权限)
  2. Jenkins脚本通过Azure元数据服务获取token,完全无需密钥:
    # 替换为你的API客户端ID
    curl -H "Metadata: true" "http://169.254.169.254/metadata/identity/oauth2/token?api-version=2018-02-01&resource=api://{你的API客户端ID}"
    
  3. 拿到token后和人类用户的调用方式一致即可。

方案2:联邦身份凭据(适合非Azure环境的Jenkins)

如果Jenkins不在Azure上,用联邦身份凭据实现无密钥认证:

  1. 在Azure AD注册服务主体,添加联邦身份凭据,关联Jenkins的OIDC提供者(比如Jenkins自身的OIDC服务)
  2. Jenkins用自身生成的OIDC令牌向Azure AD交换access token,无需存储任何密钥:
    # 替换占位符
    curl -X POST https://login.microsoftonline.com/{tenant-id}/oauth2/v2.0/token \
      -d "client_id={服务主体客户端ID}" \
      -d "grant_type=client_credentials" \
      -d "client_assertion_type=urn:ietf:params:oauth:client-assertion-type:jwt-bearer" \
      -d "client_assertion={Jenkins生成的OIDC令牌}" \
      -d "scope=api://{你的API客户端ID}/access_as_service"
    
  3. 优势:无需维护任何密钥或证书,自动化流程完全无交互。

三、FastAPI的Token验证代码

直接调用Azure AD的JWKS端点验证token合法性,仅依赖基础库:

from fastapi import FastAPI, Depends, HTTPException
from fastapi.security import OAuth2PasswordBearer
from jose import JWTError, jwt
import requests

app = FastAPI()
oauth2_scheme = OAuth2PasswordBearer(tokenUrl="token")

# 替换为你的配置
TENANT_ID = "你的租户ID"
API_CLIENT_ID = "你的API客户端ID"
JWKS_URL = f"https://login.microsoftonline.com/{TENANT_ID}/discovery/v2.0/keys"

async def validate_azure_token(token: str = Depends(oauth2_scheme)):
    try:
        # 从Azure获取JWKS密钥
        jwks_response = requests.get(JWKS_URL)
        jwks_response.raise_for_status()
        jwks = jwks_response.json()
        
        # 匹配token的签名密钥
        header = jwt.get_unverified_header(token)
        signing_key = next(k for k in jwks["keys"] if k["kid"] == header["kid"])
        
        # 验证token的签名、受众、颁发者
        payload = jwt.decode(
            token,
            signing_key,
            algorithms=["RS256"],
            audience=API_CLIENT_ID,
            issuer=f"https://login.microsoftonline.com/{TENANT_ID}/v2.0"
        )
        return payload
    except (JWTError, StopIteration, requests.exceptions.RequestException):
        raise HTTPException(status_code=401, detail="无效的token")

# 受保护的API示例
@app.get("/run-task")
async def run_protected_task(user_info: dict = Depends(validate_azure_token)):
    return {"status": "success", "executed_by": user_info.get("name", "service-account")}

关键注意点

  • 给API设置不同的权限范围(比如access_as_user和access_as_service),区分人类用户和服务账号的操作权限
  • 所有token的生命周期由Azure AD管理,无需自行存储token到数据库,过期可自动续期
  • 联邦身份凭据是微软推荐的无密钥认证方案,完全符合企业安全政策

内容的提问来源于stack exchange,提问作者khoshahmad

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.11 17:35:17