如何使用Django-REST-framework验证AzureAD访问令牌?
用Django/DRF验证AzureAD Access Token的实现方案
一、AzureAD端前置配置
- 确保前端Angular应用已在AzureAD完成注册,同时将后端API配置为前端的受保护资源:
- 在后端API的AzureAD应用注册中,设置
应用ID URI(示例格式:api://{backend-client-id}) - 前端应用注册里,添加对后端API的
Delegated permissions,并完成管理员同意授权 - 前端请求token时,需指定正确的
scope(示例:api://{backend-client-id}/access_as_user),保证返回的token中aud字段与后端的应用ID URI或客户端ID匹配
- 在后端API的AzureAD应用注册中,设置
二、后端依赖安装
安装验证所需的Python包:
pip install pyjwt cryptography requests
三、核心验证逻辑实现
1. 动态获取AzureAD公钥
从AzureAD元数据端点获取JWKS(JSON Web Key Set),避免硬编码公钥:
import jwt from jwt import PyJWKClient def get_azuread_signing_key(tenant_id, token): jwks_url = f"https://login.microsoftonline.com/{tenant_id}/discovery/v2.0/keys" jwks_client = PyJWKClient(jwks_url) return jwks_client.get_signing_key_from_jwt(token)
2. 编写DRF自定义认证类
创建用于验证AzureAD令牌的认证类,集成到DRF的认证流程:
from rest_framework import authentication from rest_framework.exceptions import AuthenticationFailed class AzureADAuthentication(authentication.BaseAuthentication): def authenticate(self, request): # 从请求头提取Bearer令牌 auth_header = request.headers.get('Authorization') if not auth_header or not auth_header.startswith('Bearer '): return None token = auth_header.split(' ')[1] # 替换为你的AzureAD租户ID、后端应用受众标识 tenant_id = "你的租户ID" expected_audience = "后端应用ID URI或客户端ID" expected_issuer = f"https://login.microsoftonline.com/{tenant_id}/v2.0" try: # 获取对应令牌的签名公钥 signing_key = get_azuread_signing_key(tenant_id, token) # 解码并验证令牌的核心字段 payload = jwt.decode( token, signing_key.key, algorithms=["RS256"], audience=expected_audience, issuer=expected_issuer, options={"verify_exp": True} ) except jwt.InvalidTokenError as e: raise AuthenticationFailed(f"无效的AzureAD令牌: {str(e)}") # 根据令牌中的用户标识(如sub、email)关联或创建Django用户 from django.contrib.auth.models import User user, _ = User.objects.get_or_create(username=payload['sub']) return (user, token)
3. 配置DRF启用认证
在项目settings.py中指定DRF的认证类:
REST_FRAMEWORK = { 'DEFAULT_AUTHENTICATION_CLASSES': [ 'your_app.authentication.AzureADAuthentication', # 替换为你的认证类路径 'rest_framework.authentication.SessionAuthentication', ], }
四、关键验证要点
- 签名验证:通过AzureAD的JWKS动态获取公钥,适配AzureAD的密钥更新机制
- 受众校验:确保令牌的
aud字段与后端应用标识一致,防止令牌被滥用 - 发行者校验:验证令牌确实来自你的AzureAD租户
- 有效期校验:自动过滤过期令牌
- 用户映射:利用令牌payload中的
sub(全局唯一用户ID)等字段,关联到Django用户模型,实现身份同步
内容的提问来源于stack exchange,提问作者miloshIra
相关产品推荐
相关产品推荐

