Troubleshoot your custom authentication extension

Authentication events and custom claims providers allow you to customize the Microsoft Entra authentication experience by integrating with external systems. For example, you can create a custom claims provider API and configure an OpenID Connect app or SAML app to receive tokens with claims from an external store.

Error behavior

When an API call fails, the error behavior is as follows:

  • For OpenId Connect apps - Microsoft Entra ID redirects the user back to the client application with an error. A token isn't minted.
  • For SAML apps - Microsoft Entra ID shows the user an error screen in the authentication experience. The user isn't redirected back to the client application.

The error code sent back to the application or the user is generic. To troubleshoot, check the sign-in logs for the error codes.

Logging

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.

Microsoft Entra sign-in logs

Tip

Steps in this article might vary slightly based on the portal you start from.

You can also use Microsoft Entra sign-in logs in addition to your REST API logs, and hosting environment diagnostics solutions. Using Microsoft Entra sign-in logs, you can find errors, which may affect the users' sign-ins. The Microsoft Entra sign-in logs provide information about the HTTP status, error code, execution duration, and number of retries that occurred the API was called by Microsoft Entra ID.

Microsoft Entra sign-in logs also integrate with 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.

To access the Microsoft Entra sign-in logs:

  1. Sign in to the Microsoft Entra admin center as at least a Cloud Application Administrator.

  2. Browse to Identity > Applications > Enterprise applications.

  3. Select Sign-in logs, and then select the latest sign-in log.

  4. For more details, select the Authentication Events tab. Information related to the custom authentication extension REST API call is displayed, including any error codes.

    Screenshot that shows the authentication events information.

Error codes reference

Use the following table to diagnose an error code.

Error code Error name Description
1003000 EventHandlerUnexpectedError There was an unexpected error when processing an event handler.
1003001 CustomExtenstionUnexpectedError There was an unexpected error while calling a custom extension API.
1003002 CustomExtensionInvalidHTTPStatus The custom extension API returned an invalid HTTP status code. Check that the API returns an accepted status code defined for that custom extension type.
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.
1003004 CustomExtensionThrottlingError There are too many custom extension requests. This exception is thrown for custom extension API calls when throttling limits are reached.
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.
1003006 CustomExtensionInvalidResponseContentType The custom extension's response content-type isn't 'application/json'.
1003007 CustomExtensionNullClaimsResponse The custom extension API responded with a null claims bag.
1003008 CustomExtensionInvalidResponseApiSchemaVersion The custom extension API didn't respond with the same apiSchemaVersion that it was called for.
1003009 CustomExtensionEmptyResponse The custom extension API response body was null when that wasn't expected.
1003010 CustomExtensionInvalidNumberOfActions The custom extension API response included a different number of actions than those supported for that custom extension type.
1003011 CustomExtensionNotFound The custom extension associated with an event listener couldn't be found.
1003012 CustomExtensionInvalidActionType The custom extension returned an invalid action type defined for that custom extension type.
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 The targetUrl and resourceId of the custom extension should have the same fully qualified domain name.
1003016 CustomExtensionResourceServicePrincipalNotFound The appId of the custom extension resourceId should correspond to a real service principal in the tenant.
1003017 CustomExtensionClientServicePrincipalNotFound The custom extension resource service principal is not found in the tenant.
1003018 CustomExtensionClientServiceDisabled The custom extension resource service principal is disabled in this tenant.
1003019 CustomExtensionResourceServicePrincipalDisabled The custom extension resource service principal is disabled in this tenant.
1003020 CustomExtensionIncorrectTargetUrlFormat The target URL is in an improper format. It must be a valid URL that starts with https.
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.
1003022 CustomExtensionMsGraphServicePrincipalDisabledOrNotFound The MS Graph service principal is disabled or not found in this tenant.
1003023 CustomExtensionBlocked The endpoint used for the custom extension is blocked by the service.
1003024 CustomExtensionResponseSizeExceeded The custom extension response size exceeded the maximum limit.
1003025 CustomExtensionResponseClaimsSizeExceeded The total size of claims in the custom extension response exceeded the maximum limit.
1003026 CustomExtensionNullOrEmptyClaimKeyNotSupported The custom extension API responded with claims containing null or empty key'
1003027 CustomExtensionConnectionError Error connecting to the custom extension API.

Call your REST API directly

Your REST API is protected by a Microsoft Entra access token. You can test your API by;

  • Obtaining an access token with an application registration associated with the custom authentication extensions
  • Test your API locally using an API testing tool.
  1. 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.

  2. Using your preferred API testing tool, create a new HTTP request and set the HTTP method to POST.

  3. Use the following JSON body that imitates the request Microsoft Entra ID sends to your 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.

  4. 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" 
                        ]
                    }
                }
    
            ]
        }
    }
    

Common performance improvements

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. To improve the performance of your REST API, follow the below suggestions:

  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.
  2. Performance issues are often related to downstream services. Add logging, which records the process time to call to any downstream services.
  3. 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.
  4. Run automated integration tests for your authentications. You can also use API testing tools to test just your API performance.

See also