Skip to content

Commit f299495

Browse files
authored
[Azure AD] Custom extension feature
1 parent bbe30b0 commit f299495

File tree

1 file changed

+186
-0
lines changed

1 file changed

+186
-0
lines changed
Lines changed: 186 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,186 @@
1+
---
2+
title: Troubleshoot a custom claims provider
3+
titleSuffix: Microsoft identity platform
4+
description: Troubleshoot and monitor your custom claims provider API. Learn how to use logging and Azure AD sign-in logs to find errors and issues in your custom claims provider API.
5+
services: active-directory
6+
author: yoelhor
7+
manager: CelesteDG
8+
9+
ms.service: active-directory
10+
ms.subservice: develop
11+
ms.topic: how-to
12+
ms.workload: identity
13+
ms.date: 03/06/2023
14+
ms.author: ryanwi
15+
ms.custom: aaddev
16+
ms.reviewer: JasSuri
17+
#Customer intent: As an application developer, I want to find errors and issues in my custom claims provider API.
18+
---
19+
20+
# Troubleshoot your custom claims provider API (preview)
21+
22+
Authentication events and [custom claims providers](custom-claims-provider-overview.md) allow you to customize the Azure Active Directory (Azure AD) authentication experience by integrating with external systems. For example, you can create a custom claims provider API and configure an [OpenID Connect app](./custom-extension-get-started.md) or [SAML app](custom-extension-configure-saml-app.md) to receive tokens with claims from an external store.
23+
24+
## Error behavior
25+
26+
When an API call fails, the error behavior is as follows:
27+
28+
- For OpenId Connect apps - Azure AD redirects the user back to the client application with an error. A token isn't minted.
29+
- For SAML apps - Azure AD shows the user an error screen in the authentication experience. The user isn't redirected back to the client application.
30+
31+
The error code sent back to the application or the user is generic. To troubleshoot, check the [sign-in logs](#azure-ad-sign-in-logs) for the [error codes](#error-codes-reference).
32+
33+
## Logging
34+
35+
In order to troubleshoot issues with your custom claims provider REST API endpoint, the REST API must handle logging. Azure Functions and other API-development platforms provide in-depth logging solutions. Use those solutions to get detailed information on your APIs behavior and troubleshoot your API logic.
36+
37+
## Azure AD sign-in logs
38+
39+
You can also use [Azure AD sign-in logs](/azure/active-directory/reports-monitoring/concept-sign-ins) in addition to your REST API logs, and hosting environment diagnostics solutions. Using Azure AD sign-in logs, you can find errors, which may affect the users' sign-ins. The Azure AD sign-in logs provide information about the HTTP status, error code, execution duration, and number of retries that occurred the API was called by Azure AD.
40+
41+
Azure AD sign-in logs also integrate with [Azure Monitor](/azure/azure-monitor/). You can set up alerts and monitoring, visualize the data, and integrate with security information and event management (SIEM) tools. For example, you can set up notifications if the number of errors exceed a certain threshold that you choose.
42+
43+
To access the Azure AD sign-in logs:
44+
45+
1. Sign in to the [Azure portal](https://portal.azure.com).
46+
1. In the **Enterprise apps** experience for your given application, select on the **Sign-in** logs tab.
47+
1. Select the latest sign-in log.
48+
1. For more details, select the **Authentication Events** tab. Information related to the custom extension REST API call is displayed, including any [error codes](#error-codes-reference).
49+
50+
:::image type="content" source="media/custom-extension-troubleshoot/authentication-events.png" alt-text="Screenshot that shows the authentication events information." :::
51+
52+
## Error codes reference
53+
54+
Use the following table to diagnose an error code.
55+
56+
|Error code |Error name |Description |
57+
|----|----|----|
58+
|1003000 | EventHandlerUnexpectedError | There was an unexpected error when processing an event handler.|
59+
|1003001 | CustomExtenstionUnexpectedError | There was an unexpected error while calling a custom extension API.|
60+
|1003002 | CustomExtensionInvalidHTTPStatus | The custom extension API returned an invalid error code. Check that the API returns an accepted status code defined for that custom extension type.|
61+
|1003003 | CustomExtensionInvalidResponseBody | There was a problem parsing the custom extension's response body. Check that the API response body is in an acceptable schema for that custom extension type.|
62+
|1003004 | CustomExtenstionThrottlingError | There are too many custom extension requests. This exception is thrown for custom extension API calls when throttling limits are reached.|
63+
|1003005 | CustomExtensionTimedOut | The custom extension didn't respond within the allowed timeout. Check that your API is responding within the configured timeout for the custom extension. It can also indicate that the access token is invalid. Follow the steps to [call your REST API directly](#call-your-rest-api-directly). |
64+
|1003006 | CustomExtensionInvalidResponseContentType | The custom extension's response content-type isn't 'application/json'.|
65+
|1003007 | CustomExtensionInvalidResponseEventType | The custom extension API didn't respond with the same eventType that it was called for.|
66+
|1003008 | CustomExtensionInvalidResponseApiSchemaVersion | The custom extension API didn't respond with the same apiSchemaVersion that it was called for.|
67+
|1003009 | CustomExtensionNoResponse | The custom extension API response body was null when that wasn't expected.|
68+
|1003010 | CustomExtensionInvalidNumberOfActions | The custom extension API response included a different number of actions than those supported for that custom extension type.|
69+
|1003011 | CustomExtensionNotFound | The custom extension associated with an event listener couldn't be found.|
70+
|1003012 | CustomExtensionInvalidActionType | The custom extension returned an invalid action type defined for that custom extension type.|
71+
|1003014 | IntermediateAccessTokenFQDNValidationFailed | ResourceId should be in the format of "api://{fully qualified domain name}/{appid}|
72+
|1003015 | IntermediateAccessTokenFQDNValidationFailed | The fully qualified domain name in resourceId should match that of the targetUrl|
73+
|1003016 | PrincipalNotFoundWithIdSpecified | The appId of the resourceId should correspond to a real service principal in the tenant.|
74+
|1003019 | PrincipalNotFoundWithIdSpecified | The resourceId isn't found in the IdentifierUris property of the app or is disabled.|
75+
|1003021 | CustomExtensionPermissionNotGrantedToServicePrincipal | The service principal doesn't have admin consent for the Microsoft Graph CustomAuthenticationExtensions.Receive.Payload app role (also known as application permission) which is required for the app to receive custom authentication extension HTTP requests.|
76+
|1003017 | PrincipalNotFoundWithIdSpecified | The Azure Active Directory Authentication Extensions service principal not found in tenant|
77+
|1003018 | InvalidResourceServicePrincipalDisabled | The Azure Active Directory Authentication Extensions service principal is disabled in this tenant|
78+
|1003022 | CustomExtensionMsGraphServicePrincipalNotFoundOrDisabled | The MS Graph service principal isn't found or is disabled in this tenant.|
79+
80+
## Call your REST API directly
81+
82+
Your REST API is protected by Azure AD access token. You can test your API by obtaining an access token with the [application registration](custom-extension-get-started.md#22-grant-admin-consent-and-copy-the-ids) associated with the custom extensions. After you acquire an access token, pass it the HTTP `Authorization` header. To obtain an access token, follow these steps:
83+
84+
1. Sign in to the [Azure portal](https://portal.azure.com/) with your Azure administrator account.
85+
1. Select **Azure Active Directory** > **App registrations**.
86+
1. Select the *Azure Functions authentication events API* app registration [you created previously](custom-extension-get-started.md#step-2-register-a-custom-extension).
87+
1. Copy the [application ID](custom-extension-get-started.md#22-grant-admin-consent-and-copy-the-ids).
88+
1. If you haven't created an app secret, follow these steps:
89+
1. Select **Certificates & secrets** > **Client secrets** > **New client secret**.
90+
1. Add a description for your client secret.
91+
1. Select an expiration for the secret or specify a custom lifetime.
92+
1. Select **Add**.
93+
1. Record the **secret's value** for use in your client application code. This secret value is never displayed again after you leave this page.
94+
1. From the menu, select **Expose an API** and copy the value of the **Application ID URI**. For example, `api://contoso.azurewebsites.net/11111111-0000-0000-0000-000000000000`.
95+
1. Open Postman and create a new HTTP query.
96+
1. Change the **HTTP method** to `POST`.
97+
1. Enter the following URL. Replace the `{tenantID}` with your tenant ID.
98+
99+
```http
100+
https://login.microsoftonline.com/{tenantID}/oauth2/v2.0/token
101+
```
102+
103+
1. Under the **Body**, select **form-data** and add the following keys:
104+
105+
|Key |Value |
106+
|---------|---------|
107+
|`grant_type`| `client_credentials`|
108+
|`client_id`| The **Client ID** of your application.|
109+
|`client_secret`|The **Client Secret** of your application.|
110+
|`scope`| The **Application ID URI** of your application, then add `.default`. For example, `api://contoso.azurewebsites.net/11111111-0000-0000-0000-000000000000/.default`|
111+
112+
1. Run the HTTP query and copy the `access_token` into the <https://jwt.ms> web app.
113+
1. Compare the `iss` with the issuer name you [configured in your API](custom-extension-get-started.md#step-5-protect-your-azure-function).
114+
1. Compare the `aud` with the client ID you [configured in your API](custom-extension-get-started.md#step-5-protect-your-azure-function).
115+
116+
To test your API directly from the Postman, follow these steps:
117+
118+
1. In your REST API, disable the `appid` or `azp` [claim validation](custom-extension-overview.md#protect-your-rest-api). Check out how to [edit the function API](custom-extension-get-started.md#12-edit-the-function) you created earlier.
119+
1. In Postman, create new HTTP request
120+
1. Set the **HTTP method** to `POST`
121+
1. In the **Body**, select **Raw** and then select **JSON**.
122+
1. Pase the following JSON that imitates the request Azure AD sends to your REST API.
123+
124+
```json
125+
{
126+
"type": "microsoft.graph.authenticationEvent.tokenIssuanceStart",
127+
"source": "/tenants/<Your tenant GUID>/applications/<Your Test Application App Id>",
128+
"data": {
129+
"@odata.type": "microsoft.graph.onTokenIssuanceStartCalloutData",
130+
"tenantId": "<Your tenant GUID>",
131+
"authenticationEventListenerId": "<GUID>",
132+
"customAuthenticationExtensionId": "<Your custom extension ID>",
133+
"authenticationContext": {
134+
"correlationId": "fcef74ef-29ea-42ca-b150-8f45c8f31ee6",
135+
"client": {
136+
"ip": "127.0.0.1",
137+
"locale": "en-us",
138+
"market": "en-us"
139+
},
140+
"protocol": "OAUTH2.0",
141+
"clientServicePrincipal": {
142+
"id": "<Your Test Applications servicePrincipal objectId>",
143+
"appId": "<Your Test Application App Id>",
144+
"appDisplayName": "My Test application",
145+
"displayName": "My Test application"
146+
},
147+
"resourceServicePrincipal": {
148+
"id": "<Your Test Applications servicePrincipal objectId>",
149+
"appId": "<Your Test Application App Id>",
150+
"appDisplayName": "My Test application",
151+
"displayName": "My Test application"
152+
},
153+
"user": {
154+
"createdDateTime": "2016-03-01T15:23:40Z",
155+
"displayName": "John Smith",
156+
"givenName": "John",
157+
"id": "90847c2a-e29d-4d2f-9f54-c5b4d3f26471",
158+
"mail": "[email protected]",
159+
"preferredLanguage": "en-us",
160+
"surname": "Smith",
161+
"userPrincipalName": "[email protected]",
162+
"userType": "Member"
163+
}
164+
}
165+
}
166+
}
167+
```
168+
169+
1. Select **Authorization** and then select **Bearer token**.
170+
1. Paste the access token you received from Azure AD, and run the query.
171+
172+
173+
## Common performance improvements
174+
175+
One of the most common issues is that your custom claims provider API doesn't respond within the two-seconds timeout. If your REST API doesn't respond in subsequent retries, then the authentication fails and the token won't be issued. To improve the performance of your REST API, follow the below suggestions:
176+
177+
1. If your API accesses any downstream APIs, cache the access token used to call these APIs, so a new token doesn't have to be acquired on every execution.
178+
1. Performance issues will often be in a downstream service. Add logging, which records the process time to call to any downstream services.
179+
1. If you use a cloud provider to host your API, use a hosting plan that keeps the API always "warm". For Azure Functions, it can be either [the Premium plan or Dedicated plan](../../azure-functions/functions-scale.md).
180+
1. [Run automated integration tests](test-automate-integration-testing.md) for your authentications. You can also use Postman or other tools to test just your API performance.
181+
182+
## Next steps
183+
184+
- Learn how to [create and register a custom claims provider](custom-extension-get-started.md) with a sample Open ID Connect application.
185+
- If you already have a custom claims provider registered, you can configure a [SAML application](custom-extension-configure-saml-app.md) to receive tokens with claims sourced from an external store.
186+
- Learn more about custom claims providers with the [custom claims provider reference](custom-claims-provider-reference.md) article.

0 commit comments

Comments
 (0)