本文内容
本文介绍如何为令牌颁发启动事件 配置自定义声明提供程序。 使用现有的 Azure Functions REST API,你将注册自定义身份验证扩展并添加预期它从 REST API 分析的属性。 要测试自定义身份验证扩展,需要注册一个示例 OpenID Connect 应用程序以获取令牌并查看声明。
先决条件
步骤 1:注册自定义身份验证扩展
现在,你将配置自定义身份验证扩展,以供 Microsoft Entra ID 用于调用你的 Azure 函数。 该自定义身份验证扩展包含有关 REST API 终结点、它从 REST API 分析的声明以及如何对 REST API 进行身份验证的信息。 按照以下步骤将自定义身份验证扩展注册到 Azure 函数应用。
注册自定义身份验证扩展
至少以应用程序管理员 或身份验证管理员 身份登录到 Azure 门户 。
搜索并选择“Microsoft Entra ID”,然后选择“企业应用程序” 。
选择“自定义身份验证扩展”,然后选择“创建自定义扩展” 。
在“基本信息”中选择“TokenIssuanceStart”事件类型,然后选择“下一步” 。
在“终结点配置”中填写以下属性 :
名称 - 自定义身份验证扩展的名称。 例如“令牌颁发事件”。
目标 URL - Azure 函数 URL 的 。 导航到 Azure 函数应用的“概述”页,然后选择创建的函数 。 在函数“概述 ”页中,选择“获取函数 URL ”,并使用复制图标复制 customauthenticationextension_extension(系统密钥) URL。
说明 - 自定义身份验证扩展的说明。
选择“下一页 ”。
在“API 身份验证”中,选择“创建新的应用注册”选项以创建代表你的函数应用的应用注册。
为应用命名,例如“Azure Functions 身份验证事件 API”。
选择“下一页 ”。
在声明 中,输入自定义身份验证扩展预期从 REST API 分析的、将合并到令牌中的属性。 添加以下声明:
dateOfBirth
customRoles
apiVersion
correlationId
依次选择“下一步”和“创建”,这会注册该自定义身份验证扩展和关联的应用程序注册 。
请注意“API 身份验证”下的“应用 ID” ,需要在 Azure 函数应用中“为 Azure 函数配置身份验证” 。
注册应用程序
使用帐户登录到 Graph 浏览器 ,该帐户的主租户就是你希望在其中管理自定义身份验证扩展的租户。 此帐户必须有权在租户中创建和管理应用程序注册。
运行以下请求。
POST https://graph.microsoft.com/v1.0/applications
Content-type: application/json
{
"displayName": "authenticationeventsAPI"
}
在响应中,记录新创建的应用注册的 id 和 appId 的值。 这些值在本文中分别称为 {authenticationeventsAPI_ObjectId}
和 {authenticationeventsAPI_AppId}
。
在租户中为 authenticationeventsAPI 应用注册创建一个服务主体。
在 Graph 浏览器中,运行以下请求。 将 {authenticationeventsAPI_AppId}
替换为在上一步中记录的 appId 值。
POST https://graph.microsoft.com/v1.0/servicePrincipals
Content-type: application/json
{
"appId": "{authenticationeventsAPI_AppId}"
}
设置应用 ID URI、访问令牌版本和所需的资源访问权限
更新新建的应用程序以设置应用程序 ID URI 值、访问令牌版本和所需的资源访问权限。
在 Graph 浏览器中,运行以下请求。
在 identifierUris 属性中设置应用程序 ID URI 值。 将 {Function_Url_Hostname}
替换为前面记下的 {Function_Url}
的主机名。
使用前面记录的 appId 设置 {authenticationeventsAPI_AppId}
值。
示例值如下:api://authenticationeventsAPI.azurewebsites.net/00001111-aaaa-2222-bbbb-3333cccc4444
。 记下此值,因为本文稍后将使用它来代替 {functionApp_IdentifierUri}
。
POST https://graph.microsoft.com/v1.0/applications/{authenticationeventsAPI_ObjectId}
Content-type: application/json
{
"identifierUris": [
"api://{Function_Url_Hostname}/{authenticationeventsAPI_AppId}"
],
"api": {
"requestedAccessTokenVersion": 2,
"acceptMappedClaims": null,
"knownClientApplications": [],
"oauth2PermissionScopes": [],
"preAuthorizedApplications": []
},
"requiredResourceAccess": [
{
"resourceAppId": "00000003-0000-0000-c000-000000000000",
"resourceAccess": [
{
"id": "00aa00aa-bb11-cc22-dd33-44ee44ee44ee",
"type": "Role"
}
]
}
]
}
注册自定义身份验证扩展
要注册自定义身份验证扩展,可将其与 Azure 函数的应用注册以及 Azure 函数终结点 {Function_Url}
相关联。
在 Graph 浏览器中,运行以下请求。 将 {Function_Url}
替换为 Azure 函数应用的主机名。 将 {functionApp_IdentifierUri}
替换为在上一步骤中使用的 identifierUri。
需要 CustomAuthenticationExtension.ReadWrite.All 委托权限。
POST https://graph.microsoft.com/beta/identity/customAuthenticationExtensions
Content-type: application/json
{
"@odata.type": "#microsoft.graph.onTokenIssuanceStartCustomExtension",
"displayName": "onTokenIssuanceStartCustomExtension",
"description": "Fetch additional claims from custom user store",
"endpointConfiguration": {
"@odata.type": "#microsoft.graph.httpRequestEndpoint",
"targetUrl": "{Function_Url}"
},
"authenticationConfiguration": {
"@odata.type": "#microsoft.graph.azureAdTokenAuthentication",
"resourceId": "{functionApp_IdentifierUri}"
},
"claimsForTokenConfiguration": [
{
"claimIdInApiResponse": "DateOfBirth"
},
{
"claimIdInApiResponse": "CustomRoles"
}
]
}
记下创建的自定义声明提供程序对象的 id
值。 本教程稍后将使用该值来代替 {customExtensionObjectId}
。
1.2 授予管理员同意
创建自定义身份验证扩展后,需要向 API 授予权限。 自定义身份验证扩展使用client_credentials
和Receive custom authentication extension HTTP requests
权限对 Azure 函数应用进行身份验证。
打开新自定义身份验证扩展的“概述”页 。 记下“API 身份验证下”的应用 ID,因为添加标识提供者时会需要它 。
在“API 身份验证”下 ,选择“授予权限” 。
此时会打开一个新窗口,登录后,它会请求权限以接收自定义身份验证扩展 HTTP 请求。 通过此操作,自定义身份验证扩展可以向 API 进行身份验证。 选择“接受”。
要获取令牌并测试自定义身份验证扩展,可以使用https://jwt.ms 应用。 它是 Microsoft 拥有的一个 Web 应用程序,可显示令牌的解码内容(令牌内容永远不会离开你的浏览器)。
2.1 注册测试 Web 应用
按照以下步骤注册 jwt.ms Web 应用程序:
在 Azure 门户的“开始”页中 ,选择“Microsoft Entra ID” 。
选择“应用注册” “新建注册”。
输入应用程序的“名称”。 例如“我的测试应用程序”。
在“支持的帐户类型”下,选择“仅此组织目录中的帐户” 。
在“重定向 URI”中的“选择平台”下拉列表中选择“Web”,然后在“URL”文本框中输入 。
选择“注册”以完成应用注册。
在应用注册的“概述”页中,复制应用程序(客户端)ID 。 在后续步骤中,该应用 ID 将引用为 {App_to_enrich_ID}
。 在 Microsoft Graph 中,appId 属性引用了它 。
2.2 启用隐式流
jwt.ms 测试应用程序使用隐式流。 在“我的测试应用程序”注册中启用隐式流:
在“管理”下,选择“身份验证”。
在“隐式授权和混合流”下,选中“ID 令牌(用于隐式流和混合流)”复选框。
选择“保存”。
2.3 为声明映射策略启用应用
声明映射策略用于选择要将自定义身份验证扩展返回的哪些属性映射到令牌。 若要允许扩充令牌,必须显式启用应用程序注册以接受映射的声明:
在“我的测试应用程序”注册中,在“管理”下选择“清单”。
在清单中找到 acceptMappedClaims
属性,并将值设置为 true
。
将 requestedAccessTokenVersion
设置为 2
。
选择“保存” ,保存更改。
以下 JSON 代码片段演示如何配置这些属性。
{
"id": "22222222-0000-0000-0000-000000000000",
"acceptMappedClaims": true,
"requestedAccessTokenVersion": 2,
...
}
警告
对于多租户应用,请勿将 acceptMappedClaims
属性设置为 true
,这可能会允许恶意参与者为应用创建声明映射策略。 应该配置自定义签名密钥 。
3.4 将应用与用户流关联
对于外部租户,需要将应用与用户流相关联。 用户流定义客户可用于登录应用程序的身份验证方法,以及他们在注册期间需要提供的信息。 在继续向用户流添加“我的测试应用程序”之前,请确保完成“向用户流添加应用程序”中的步骤 。
步骤 3:将自定义声明提供程序分配到应用
对于要使用自定义身份验证扩展传入的声明颁发的令牌,必须将自定义声明提供程序分配到应用程序。 这基于令牌受众,因此必须向客户端应用程序分配提供程序以接收 ID 令牌中的声明,并向资源应用程序分配提供程序以接收访问令牌中的声明。 该自定义声明提供程序依赖于使用令牌颁发启动 事件侦听器配置的自定义身份验证扩展。 可以选择是要将自定义声明提供程序提供的所有还是一部分声明映射到令牌。
注意
只能在应用程序和自定义扩展之间创建 250 个唯一分配。 如果你希望将同一个自定义扩展调用应用于多个应用,我们建议使用 authenticationEventListeners Microsoft Graph API 为多个应用程序创建侦听器。 Azure 门户中不支持此功能。
按照以下步骤将我的测试应用程序 与自定义身份验证扩展相连接:
将自定义身份验证扩展分配为自定义声明提供程序源;
在 Azure 门户的“开始”页中 ,选择“Microsoft Entra ID” 。
选择“启用应用程序”,然后在“管理”下面选择“所有应用程序” 。 在列表中查找并选择“我的测试应用程序” 。
在“我的测试应用程序”的“概述”页中 ,导航到“管理”,然后选择“单一登录” 。
在“属性和声明” 下,选择“编辑” 。
展开“高级设置”菜单。
在“自定义声明提供程序”旁边,选择“配置” 。
展开“自定义声明提供程序”下拉框,然后选择之前创建的“令牌颁发事件”。
选择“保存”。
接下来,从自定义声明提供程序分配属性,这些属性应作为声明颁发到令牌中:
选择“添加新声明”以添加新声明。 提供要颁发的声明的名称,例如 dateOfBirth。
在“源”下 ,选择“属性”,然后从“源属性”下拉列表框中选择“customClaimsProvider.dateOfBirth” 。
选择“保存”。
重复此过程以添加“customClaimsProvider.customRoles” 、“customClaimsProvider.apiVersion” 和“customClaimsProvider.correlationId”属性以及相应的名称 。 最好将声明的名称与属性的名称匹配。
首先创建事件侦听器,以使用令牌颁发启动事件针对“我的测试应用程序”触发自定义身份验证扩展。
使用帐户登录到 Graph 浏览器 ,该帐户的主租户是要在其中管理自定义身份验证扩展的租户。
运行以下请求。 将 {App_to_enrich_ID}
替换为前面记下的“我的测试应用程序”应用 ID。 将{customExtensionObjectId}
替换为前面记下的自定义身份验证扩展 ID。
需要 EventListener.ReadWrite.All 委托权限。
POST https://graph.microsoft.com/beta/identity/authenticationEventListeners
Content-type: application/json
{
"@odata.type": "#microsoft.graph.onTokenIssuanceStartListener",
"conditions": {
"applications": {
"includeAllApplications": false,
"includeApplications": [
{
"appId": "{App_to_enrich_ID}"
}
]
}
},
"priority": 500,
"handler": {
"@odata.type": "#microsoft.graph.onTokenIssuanceStartCustomExtensionHandler",
"customExtension": {
"id": "{customExtensionObjectId}"
}
}
}
接下来创建声明映射策略,该策略描述可以从自定义声明提供程序将哪些声明颁发给应用程序。
仍旧在 Graph 浏览器中,运行以下请求。 需要 Policy.ReadWrite.ApplicationConfiguration 委托权限。
POST https://graph.microsoft.com/v1.0/policies/claimsMappingPolicies
Content-type: application/json
{
"definition": [
"{\"ClaimsMappingPolicy\":{\"Version\":1,\"IncludeBasicClaimSet\":\"true\",\"ClaimsSchema\":[{\"Source\":\"CustomClaimsProvider\",\"ID\":\"DateOfBirth\",\"JwtClaimType\":\"dob\"},{\"Source\":\"CustomClaimsProvider\",\"ID\":\"CustomRoles\",\"JwtClaimType\":\"my_roles\"},{\"Source\":\"CustomClaimsProvider\",\"ID\":\"CorrelationId\",\"JwtClaimType\":\"correlationId\"},{\"Source\":\"CustomClaimsProvider\",\"ID\":\"ApiVersion\",\"JwtClaimType\":\"apiVersion \"},{\"Value\":\"tokenaug_V2\",\"JwtClaimType\":\"policy_version\"}]}}"
],
"displayName": "MyClaimsMappingPolicy",
"isOrganizationDefault": false
}
请记下响应中生成的 ID
,稍后它将引用为 {claims_mapping_policy_ID}
。
获取服务主体对象 ID:
在 Graph 浏览器中运行以下请求。 将 {App_to_enrich_ID}
替换为“我的测试应用程序”的 appId。
GET https://graph.microsoft.com/v1.0/servicePrincipals(appId='{App_to_enrich_ID}')
请记录 id 值。
将声明映射策略分配给“我的测试应用程序”的服务主体。
在 Graph 浏览器中运行以下请求。 需要 Policy.ReadWrite.ApplicationConfiguration 和 Application.ReadWrite.All 委托权限。
POST https://graph.microsoft.com/v1.0/servicePrincipals/{test_App_Service_Principal_ObjectId}/claimsMappingPolicies/$ref
Content-type: application/json
{
"@odata.id": "https://graph.microsoft.com/v1.0/policies/claimsMappingPolicies/{claims_mapping_policy_ID}"
}
步骤 4:保护 Azure 函数
Microsoft Entra 自定义身份验证扩展使用服务器到服务器的流来获取在 HTTP Authorization
标头中发送到 Azure 函数的访问令牌。 将函数发布到 Azure 时(尤其是在生产环境中),需要验证在授权标头中发送的令牌。
要保护 Azure 函数,请按照以下步骤集成 Microsoft Entra 身份验证,以便使用Azure Functions 身份验证事件 API 应用程序注册来验证传入的令牌。 根据租户类型选择以下选项卡之一。
注意
如果托管 Azure 函数应用的 Azure 租户不同于注册自定义身份验证扩展的租户,请选择“OpenID Connect” 选项卡。
4.1 使用 Microsoft Entra 标识提供者
使用以下步骤将 Microsoft Entra 作为标识提供者添加到 Azure 函数应用。
在 Azure 门户 中,查找并选择之前发布的函数应用。
在“设置”下选择“身份验证” 。
选择“添加标识提供者”。
选择“Microsoft”作为标识提供者。
选择“员工” 作为租户类型。
在“应用注册”下,选择“选取此目录中的现有应用注册”作为“应用注册类型” ,然后选取先前 在注册自定义声明提供程序时创建的“Azure Functions 身份验证事件 API”应用注册 。
输入以下颁发者 URL https://login.microsoftonline.com/{tenantId}/v2.0
,其中 {tenantId}
是员工租户的租户 ID。
在“客户端应用程序要求 ”下,选择“允许来自特定客户端应用程序的请求 ”,然后输入 99045fe1-7639-4a75-9d4a-577b6ca3810f
。
在“租户要求 ”下,选择“允许来自特定租户的请求 ”并输入工作人员租户 ID。
在“未经身份验证的请求 ”下,选择“HTTP 401 未授权 ”作为标识提供者。
取消选择“令牌存储”选项。
选择“添加”以将身份验证添加到 Azure 函数。
在 Azure 门户 中,查找并选择之前发布的函数应用。
在“设置”下选择“身份验证” 。
选择“添加标识提供者”。
选择“Microsoft”作为标识提供者。
选择“外部配置 ”作为租户类型。
在“应用注册 ”下,针对“应用注册类型 ”选择“提供现有应用注册的详细信息 ”,然后在注册自定义声明提供程序时输入client_id
的“Azure Functions 身份验证事件 API ”应用注册的 。
对于“颁发者 URL”,输入以下 URL ,其中https://{domainName}.ciamlogin.com/{tenant_id}/v2.0
{domainName}
是外部租户的域名,采用 {domainName}.contoso.com
格式。
{tenantId}
是外部租户的租户 ID。
在“客户端应用程序要求 ”下,选择“允许来自特定客户端应用程序的请求 ”,然后输入 99045fe1-7639-4a75-9d4a-577b6ca3810f
。
在“租户要求 ”下,选择“允许来自特定租户的请求 ”并输入外部租户 ID。
在“未经身份验证的请求 ”下,选择“HTTP 401 未授权 ”作为标识提供者。
取消选择“令牌存储”选项。
选择“添加”以将身份验证添加到 Azure 函数。
4.2 使用 OpenID Connect 标识提供者
如果你配置了 Microsoft 标识提供者 ,请跳过此步骤。 否则,如果 Azure 函数所在的租户不同于注册自定义身份验证扩展的租户,请执行以下步骤保护函数:
创建客户端机密
在 Azure 门户的“开始”页中 ,选择“Microsoft Entra ID” “应用注册”> 。
选择先前创建 的“Azure Functions 身份验证事件 API”应用注册。
选择“证书和机密” “客户端密码”>“新建客户端密码” > 。
选择机密的过期时间或指定自定义生存期,添加说明,然后选择“添加” 。
请记下机密值,以便在客户端应用程序代码中使用。 退出此页面后,此机密值永不再显示。
将 OpenID Connect 标识提供者添加到 Azure 函数应用。
查找之前发布的函数应用并选择它。
在“设置”下选择“身份验证” 。
选择“添加标识提供者”。
选择“OpenID Connect”作为标识提供者。
提供名称,例如Contoso Microsoft Entra ID 。
在“元数据条目”下的“文档 URL”中输入以下 URL。 将{tenantId}
替换为 Microsoft Entra 租户 ID。
https://login.microsoftonline.com/{tenantId}/v2.0/.well-known/openid-configuration
在“应用注册”下,输入先前创建 的“Azure Functions 身份验证事件 API”应用注册的应用程序 ID(客户端 ID)。
返回 Azure 函数,在“应用注册”下输入“客户端机密” 。
取消选择“令牌存储”选项。
选择“添加”以添加 OpenID Connect 标识提供者。
步骤 5:测试应用程序
要测试自定义声明提供程序,请执行以下步骤:
打开新的隐私浏览器,并通过以下 URL 进行导航和登录。
https://login.microsoftonline.com/{tenantId}/oauth2/v2.0/authorize?client_id={App_to_enrich_ID}&response_type=id_token&redirect_uri=https://jwt.ms&scope=openid&state=12345&nonce=12345
将 {tenantId}
替换为你的租户 ID、租户名称或已验证的域名之一。 例如 contoso.onmicrosoft.com
。
将 {App_to_enrich_ID}
替换为“我的测试应用程序” 客户端 ID。
登录后,你将在 https://jwt.ms
上看到解码的令牌。 验证来自 Azure 函数的声明是否显示在解码的令牌中,例如 dateOfBirth
。
打开新的隐私浏览器,并通过以下 URL 进行导航和登录。
https://{domainName}.ciamlogin.com/{tenantId}/oauth2/v2.0/authorize?client_id={App_to_enrich_ID}&response_type=id_token&redirect_uri=https://jwt.ms&scope=openid&state=12345&nonce=12345
将 {domainName}
替换为域名,例如 contoso
。
将 {tenantId}
替换为你的租户 ID、租户名称或已验证的域名之一。 例如 contoso.onmicrosoft.com
。
将 {App_to_enrich_ID}
替换为“我的测试应用程序” 客户端 ID。
浏览已配置的登录用户流,并接受请求的权限。
登录后,你将在 https://jwt.ms
上看到解码的令牌。 验证来自 Azure 函数的声明是否显示在解码的令牌中,例如 dateOfBirth
。
另请参阅