Azure Function AD认证:为何用ClientID作Resource而非URI?
这个问题其实和Azure AD中**资源标识符(Resource Identifier)**的作用,以及Azure Function AD认证的默认配置有关,我来帮你拆解清楚:
1. Resource参数的核心作用
resource参数告诉Azure AD:你要请求的令牌是用于访问哪个目标服务的。Azure AD会在颁发的令牌中设置aud(受众)字段为这个resource的值,而目标服务(你的Azure Function)在验证令牌时,会检查令牌的aud是否匹配自己的合法标识符——不匹配就会返回401。
2. 为什么用Function的ClientID能正常工作
当你为Azure Function启用AD登录认证时,背后对应的Azure AD应用(无论是自动创建的还是你手动注册的)的ClientID本身就是该服务的一个合法资源标识符。
你代码中把resource设为ClientID时,Azure AD颁发的令牌aud字段就是这个ClientID,Function的认证系统会默认识别这个值,所以能顺利通过验证。
3. 为什么用Function URI会返回401
在线示例中用URI作为resource,是因为那些示例里的目标服务(比如自定义Web API)已经将自己的URI配置为Azure AD应用的应用ID URI(在Azure AD应用注册的「公开API」页面设置)。但Azure Function默认不会把自己的网站URI自动注册为应用ID URI:
- 当你用
https://www.xxxxxx.azurewebsites.com作为resource请求令牌时,Azure AD会颁发一个aud为该URI的令牌。 - 但你的Function的认证系统默认只认可自身的ClientID作为合法的
aud值,所以令牌验证失败,返回401。
如果想让URI作为resource也能生效,你需要手动到对应的Azure AD应用注册页面,在「公开API」选项卡中添加这个URI作为应用ID URI,同时确保Function的认证配置中允许这个受众(aud)。
附你提供的格式化后代码:
var tokenendpoint = "https://login.microsoftonline.com/172f05a2-f956-4856-b4c8-9580a54dbd56/oauth2/token"; string clientID = "eaeff78a-26ef-4bcb-b977-638316ff15b7"; string clientSecret = "HvVlipQkpuezmD4YiUcWVpZ5Cn1cP3vxiW61pSpDo8k="; string resource = "eaeff78a-26ef-4bcb-b977-638316ff15b7"; //ClientID string grantType = "client_credentials"; using (var reqToken = new WebClient()) { NameValueCollection parameters = new NameValueCollection(); parameters.Add("client_id", clientID); parameters.Add("client_secret", clientSecret); parameters.Add("resource", resource); parameters.Add("grant_type", grantType); var responseTokenBytes = reqToken.UploadValues(tokenendpoint, "POST", parameters); string responseTokenContent = Encoding.UTF8.GetString(responseTokenBytes).Replace(@"\", ""); azureFunctionTokenResponse = responseTokenContent.Deserialize<AzureFunctionTokenResponseBase>(); AzureFunctionToken = azureFunctionTokenResponse.access_token; }
内容的提问来源于stack exchange,提问作者Stanza

