身份验证事件和自定义声明提供程序支持通过与外部系统集成来自定义 Microsoft Entra 身份验证体验。 例如,可以创建自定义声明提供程序 API,并将 OpenID Connect 应用配置为从外部存储接收包含声明的令牌。
Error behavior
当 API 调用失败时,错误行为如下所示:
- 对于 OpenId Connect 应用 - Microsoft Entra ID 会将用户重定向回客户端应用程序,并显示错误。 不会铸造令牌。
- 对于 SAML 应用 - Microsoft Entra ID 向用户显示身份验证体验中的错误屏幕。 用户不会重定向回客户端应用程序。
发送回应用程序或用户的错误代码为泛型代码。 To troubleshoot, check the sign-in logs for the error codes.
Logging
若要排查自定义声明提供程序 REST API 终结点的问题,REST API 必须处理日志记录。 Azure Functions 和其他 API 开发平台提供深入的日志记录解决方案。 使用这些解决方案获取有关 API 行为的详细信息,并排查 API 逻辑的问题。
Microsoft Entra 登录日志
除了 REST API 日志和托管环境诊断解决方案之外,还可以使用 Microsoft Entra 登录日志。 使用 Microsoft Entra 登录日志,可以找到可能影响用户登录的错误。Microsoft Entra 登录日志提供有关 Microsoft Entra ID 调用 API 时的 HTTP 状态、错误代码、执行持续时间和重试次数的信息。
Microsoft Entra sign-in logs also integrate with Azure Monitor. 可以设置警报和监视、可视化数据,并与安全信息和事件管理 (SIEM) 工具集成。 例如,如果错误数超过所选的特定阈值,则可以设置通知。
访问 Microsoft Entra 登录日志:
至少以云应用程序管理员身份登录到 Microsoft Entra 管理中心。
Browse to Entra ID>Enterprise apps.
Select Sign-in logs, and then select the latest sign-in log.
For more details, select the Authentication Events tab. Information related to the custom authentication extension REST API call is displayed, including any error codes.
错误代码参考
使用下表诊断错误代码。
Error code | Error name | Description |
---|---|---|
1003000 | EventHandlerUnexpectedError | 处理事件处理程序时出现意外错误。 |
1003001 | CustomExtensionUnexpectedError | 调用自定义扩展 API 时出现意外错误。 |
1003002 | CustomExtensionInvalidHTTPStatus | 自定义扩展 API 返回了无效的 HTTP 状态代码。 检查 API 是否返回为该自定义扩展类型定义的接受状态代码。 |
1003003 | CustomExtensionInvalidResponseBody | 分析自定义扩展的响应正文时出现问题。 检查 API 响应正文是否处于该自定义扩展类型的可接受架构中。 |
1003004 | CustomExtensionThrottlingError | 自定义扩展请求过多。 达到限制时,自定义扩展 API 调用将引发此异常。 |
1003005 | CustomExtensionTimedOut | 自定义扩展在允许的超时时间内未响应。 检查 API 是否在为自定义扩展配置的超时时间内响应。 它还可能指示访问令牌无效。 按照步骤直接调用 REST API。 |
1003006 | CustomExtensionInvalidResponseContentType | 自定义扩展的响应内容类型不是“application/json”。 |
1003007 | CustomExtensionNullClaimsResponse | 自定义扩展 API 使用了 null 声明包进行响应。 |
1003008 | CustomExtensionInvalidResponseApiSchemaVersion | 自定义扩展 API 未使用调用它来获取的同一 apiSchemaVersion 进行响应。 |
1003009 | CustomExtensionEmptyResponse | 自定义扩展 API 响应正文在未达到预期时为 null。 |
1003010 | CustomExtensionInvalidNumberOfActions | 自定义扩展 API 响应包含的操作数量与该自定义扩展类型支持的操作数量不同。 |
1003011 | CustomExtensionNotFound | 找不到与事件侦听器关联的自定义扩展。 |
1003012 | CustomExtensionInvalidActionType | 自定义扩展返回了为该自定义扩展类型定义的无效操作类型。 |
1003014 | CustomExtensionIncorrectResourceIdFormat | The identifierUris property in the manifest for the application registration for the custom extension, should be in the format of "api://{fully qualified domain name}/{appid}. |
1003015 | CustomExtensionDomainNameDoesNotMatch | 自定义扩展的 targetUrl 和 resourceId 应具有相同的完全限定域名。 |
1003016 | CustomExtensionResourceServicePrincipalNotFound | 自定义扩展 resourceId 的 appId 应对应于租户中的实际服务主体。 |
1003017 | CustomExtensionClientServicePrincipalNotFound | 在租户中找不到自定义扩展资源服务主体。 |
1003018 | CustomExtensionClientServiceDisabled | 此租户中禁用了自定义扩展资源服务主体。 |
1003019 | CustomExtensionResourceServicePrincipalDisabled | 此租户中禁用了自定义扩展资源服务主体。 |
1003020 | CustomExtensionIncorrectTargetUrlFormat | 目标 URL 的格式不正确。 它必须是以 https 开头的有效 URL。 |
1003021 | CustomExtensionPermissionNotGrantedToServicePrincipal | 服务主体不具有适用于 Microsoft Graph CustomAuthenticationExtensions.Receive.Payload 应用角色(也称为应用程序权限)的管理员同意,而这是应用接收自定义身份验证扩展 HTTP 请求所必需的。 |
1003022 | CustomExtensionMsGraphServicePrincipalDisabledOrNotFound | 此租户中已禁用或找不到 MS Graph 服务主体。 |
1003023 | CustomExtensionBlocked | 服务阻止了用于自定义扩展的终结点。 |
1003024 | CustomExtensionResponseSizeExceeded | 自定义扩展响应大小超出了最大限制。 |
1003025 | CustomExtensionResponseClaimsSizeExceeded | 自定义扩展响应中声明的总大小超出了最大限制。 |
1003026 | CustomExtensionNullOrEmptyClaimKeyNotSupported | 自定义扩展 API 使用包含 null 或空密钥的声明进行响应 |
1003027 | CustomExtensionConnectionError | 连接到自定义扩展 API 时出错。 |
直接调用 REST API
REST API 受 Microsoft Entra 访问令牌保护。 可以通过以下方式测试 API;
- Obtaining an access token with an application registration associated with the custom authentication extensions
- 使用 API 测试工具在本地测试 API。
For local development and testing purposes, open local.settings.json and replace the code with the following JSON:
{ "IsEncrypted": false, "Values": { "AzureWebJobsStorage": "", "AzureWebJobsSecretStorageType": "files", "FUNCTIONS_WORKER_RUNTIME": "dotnet", "AuthenticationEvents__BypassTokenValidation" : false } }
Note
If you used the Microsoft.Azure.WebJobs.Extensions.AuthenticationEvents NuGet package, be sure to set
"AuthenticationEvents__BypassTokenValidation" : true
for local testing purposes.Using your preferred API testing tool, create a new HTTP request and set the HTTP method to
POST
.使用以下 JSON 正文来模仿 Microsoft Entra ID 发送到 REST API 的请求。
{ "type": "microsoft.graph.authenticationEvent.tokenIssuanceStart", "source": "/tenants/aaaabbbb-0000-cccc-1111-dddd2222eeee/applications/00001111-aaaa-2222-bbbb-3333cccc4444", "data": { "@odata.type": "microsoft.graph.onTokenIssuanceStartCalloutData", "tenantId": "aaaabbbb-0000-cccc-1111-dddd2222eeee", "authenticationEventListenerId": "11112222-bbbb-3333-cccc-4444dddd5555", "customAuthenticationExtensionId": "22223333-cccc-4444-dddd-5555eeee6666", "authenticationContext": { "correlationId": "aaaa0000-bb11-2222-33cc-444444dddddd", "client": { "ip": "127.0.0.1", "locale": "en-us", "market": "en-us" }, "protocol": "OAUTH2.0", "clientServicePrincipal": { "id": "aaaaaaaa-0000-1111-2222-bbbbbbbbbbbb", "appId": "00001111-aaaa-2222-bbbb-3333cccc4444", "appDisplayName": "My Test application", "displayName": "My Test application" }, "resourceServicePrincipal": { "id": "aaaaaaaa-0000-1111-2222-bbbbbbbbbbbb", "appId": "00001111-aaaa-2222-bbbb-3333cccc4444", "appDisplayName": "My Test application", "displayName": "My Test application" }, "user": { "companyName": "Casey Jensen", "createdDateTime": "2023-08-16T00:00:00Z", "displayName": "Casey Jensen", "givenName": "Casey", "id": "00aa00aa-bb11-cc22-dd33-44ee44ee44ee", "mail": "casey@contoso.com", "onPremisesSamAccountName": "Casey Jensen", "onPremisesSecurityIdentifier": "<Enter Security Identifier>", "onPremisesUserPrincipalName": "Casey Jensen", "preferredLanguage": "en-us", "surname": "Jensen", "userPrincipalName": "casey@contoso.com", "userType": "Member" } } } }
Tip
If you're using an access token obtained from Microsoft Entra ID, select Authorization and then select Bearer token, then paste the access token you received from Microsoft Entra ID.
Select Send, and you should receive a JSON response similar to the following:
{ "data": { "@odata.type": "microsoft.graph.onTokenIssuanceStartResponseData", "actions": [ { "@odata.type": "microsoft.graph.tokenIssuanceStart.provideClaimsForToken", "claims": { "customClaim1": "customClaimValue1", "customClaim2": [ "customClaimString1", "customClaimString2" ] } } ] } }
常见性能改进
最常见的问题之一是自定义声明提供程序 API 在两秒的超时时间内没有响应。 如果 REST API 在后续重试中未响应,则身份验证会失败。 若要提高 REST API 的性能,请遵循以下建议:
- 如果 API 访问任何下游 API,请缓存用于调用这些 API 的访问令牌,因此不必在每次执行时获取新令牌。
- 性能问题通常与下游服务相关。 添加日志记录,用于记录调用任何下游服务的处理时间。
- 如果使用云提供商托管 API,请使用托管计划保持 API 的热度。 对于 Azure Functions,它可以是高级计划或专用计划。
- 运行自动集成测试以进行身份验证。 还可使用 API 测试工具以仅测试 API 性能。