# AADSTS9010010: Resource parameter doesn't match the requested scopes (fix)

Canonical: https://brambrinkmeier.com/entra/aadsts/9010010/
By Bram Brinkmeier. JSON: https://brambrinkmeier.com/api/aadsts/9010010.json

**Short answer:** AADSTS9010010 means a token request carried a resource parameter that doesn't match the resource named in its scopes. Microsoft documents it for MCP clients: the resource value must exactly match the Application ID URI, and the scopes must belong to that same app. A trailing slash is a common cause. It is a client configuration error with low attack value.

**Fix:** Developer: send `resource` exactly as the Application ID URI (no trailing slash, same case and path), and keep every scope on that API. If you don't need RFC 8707, drop `resource` and name the API only in `scope`. MCP server owner: use v2 access tokens and publish the same value in your metadata.

| Field | Value |
|---|---|
| Code | AADSTS9010010 |
| Category | App configuration |
| Type | Configuration error |
| Attack signal | Low: usually configuration or user error |
| In Microsoft's error reference | No (checked 2026-10-30) |
| Verification | lab-reproduced (2026-10-30) |
| Last updated | 2026-10-30 |

## What does AADSTS9010010 mean?

Microsoft's [error code reference](https://learn.microsoft.com/entra/identity-platform/reference-error-codes) doesn't list AADSTS9010010 (checked 30 October 2026).

My lab tenant returned this message for a client-credentials token request that carried both `scope=https://graph.microsoft.com/.default` and `resource=https://management.azure.com/`:

> AADSTS9010010: The resource parameter provided in the request doesn't match with the requested scopes.

Microsoft does explain the code, on its page about securing an MCP server with Entra ID:

> `AADSTS9010010` means the **Application ID URI configured on your app registration doesn't exactly match the value of the `resource` parameter** in the client's OAuth request.

The same page gives a second cause: *"This error also occurs when the client sends a scope that's defined on a different app registration than the one referenced by the `resource` parameter. Microsoft Entra ID resolves the `resource` and the scope to the same resource app; if they point at different app registrations, the request fails."* That second cause is what the lab request did: the scope names Microsoft Graph, the resource names Azure Resource Manager.

Background. On the v2.0 endpoint the resource is normally named inside the scope. Microsoft's scopes page: *"Using `scope={resource-identifier}/.default` is functionally the same as `resource={resource-identifier}` on the v1.0 endpoint."* The `resource` parameter comes back through RFC 8707 (Resource Indicators), which the MCP authorization spec requires. Microsoft's MCP page: *"The MCP specification requires the client to identify the protected resource it wants a token for by sending the `resource` parameter (from RFC 8707) in its token request."* So a request now carries the resource twice, and the two must agree.

The match is exact. Microsoft: *"The `resource` value the client sends must match the Application ID URI character for character, including the scheme (`https://`), casing of the host, and path. A trailing slash is a common culprit: because an Application ID URI can't end with a slash, a client that sends `resource=https://mcp.contoso.com/` never matches the registered `https://mcp.contoso.com`."*

## Reproduced in the lab

On 30 October 2026 an automated lab run sent a client-credentials request to the token endpoint with `scope=https://graph.microsoft.com/.default` and `resource=https://management.azure.com/`. Entra returned `AADSTS9010010` with this first line:

> AADSTS9010010: The resource parameter provided in the request doesn't match with the requested scopes.

That confirms the code and its wording at the token endpoint for an app (not a user) request. It lands in **`AADServicePrincipalSignInLogs`** for an app-only request: one row, Failure, client credential type "federatedIdentityCredential", resource Microsoft Graph. The KQL below was run on these rows ([how](https://brambrinkmeier.com/methodology/)). Both queries found the row (the second with its app ID placeholder replaced).

## Is it an attack?

No. It is a mismatch in how the client builds its token request. No token is issued.

| Pattern | Likely meaning |
|---|---|
| An MCP client (Claude Code, an IDE, an agent) fails to connect to an Entra-protected MCP server | The client sends `resource` with a trailing slash, or a URL that differs from the Application ID URI. Users report exactly this in [claude-code issue 52871](https://github.com/anthropics/claude-code/issues/52871), where `resource=https://mcp.businesscentral.dynamics.com/` was sent while the server's metadata declared it without the slash. |
| A script or daemon sends `resource` and `scope` for two different APIs | The scope belongs to another app registration, as in the lab request. |
| A broker or identity provider in front of Entra forwards `resource` with only OIDC scopes (`openid profile`) | Users report this with Auth0 federated to Entra in the same GitHub issue. Our reading: no resource-prefixed scope exists to match. |
| Your own MCP server app is still on v1 access tokens | Microsoft: if `requestedAccessTokenVersion` isn't `2`, *"you can't register an HTTPS Application ID URI that matches your MCP server URL, so the `resource` value can never match."* |

Our reading: the request fails before a token is issued, and only the app's own owner can make it match. There is nothing an attacker gains from triggering it.

## How do I find it in my logs (KQL)?

Microsoft doesn't document which sign-in table 9010010 is logged in. Our reading: user-delegated requests (MCP clients signing in a user) would land in `SigninLogs` or `AADNonInteractiveUserSignInLogs`, and app-only requests like the lab one in `AADServicePrincipalSignInLogs`. That is not verified. Check all three:

```kusto
union withsource=SourceTable SigninLogs, AADNonInteractiveUserSignInLogs, AADServicePrincipalSignInLogs
| where TimeGenerated > ago(30d)
| where ResultType == "9010010"
| summarize Rows = count(), LastSeen = max(TimeGenerated) by SourceTable, AppId, ResourceDisplayName
| sort by Rows desc
```

To fix the request you need the right resource. For an app that fails with 9010010, see which resources it does get tokens for:

```kusto
union withsource=SourceTable SigninLogs, AADNonInteractiveUserSignInLogs, AADServicePrincipalSignInLogs
| where TimeGenerated > ago(30d)
| where AppId == "<app id of the failing client>"
| summarize Successes = countif(ResultType == "0"), Failures9010010 = countif(ResultType == "9010010") by SourceTable, ResourceDisplayName, ResourceIdentity
| sort by Failures9010010 desc
```

A resource with failures and no successes is the one whose `resource` value or scope is wrong. Both queries are starting points; adjust the time window to your retention.

## How do I fix AADSTS9010010?

**For the user:** you can't fix this yourself. Report the app or MCP server name to whoever set it up, and include the full error.

**For developers (client side):**
1. If you talk to the v2.0 endpoint and don't need RFC 8707, drop `resource` and name the API only in `scope`, for example `scope=https://graph.microsoft.com/.default`. Microsoft's scopes page says the two are functionally the same.
2. If you must send `resource` (MCP clients do), send it verbatim from the server's protected resource metadata. Don't normalise it; the reporter of [claude-code issue 52871](https://github.com/anthropics/claude-code/issues/52871) suspects that round-tripping it through a URL parser added the trailing slash. Nobody in the thread confirmed that.
3. Make every scope in the request belong to the same API as `resource`. Remove scopes from other APIs and request them in a separate token request.

**For developers (MCP server side), from Microsoft's MCP page:**
1. Set the app registration to v2 access tokens (`requestedAccessTokenVersion` = `2`).
2. Set the Application ID URI to the exact canonical URL of your MCP server, with no trailing slash.
3. Publish that same value as `resource` in your protected resource metadata, so clients send what Entra expects.

**For admins:** compare the failing app's `resource` value with the Application ID URI of the API's app registration. If they differ by a slash, a case or a path, that is the cause.

## Evidence

Reproduced in a lab tenant on 2026-10-30 (Client-credentials token request against a lab tenant; scenario: Both scope and resource sent). First line returned:

> AADSTS9010010: The resource parameter provided in the request doesn't match with the requested scopes.

Sign-in log row read: 2026-10-30. KQL run against the exported lab rows: 2026-10-30.

Lab-run rows naming this code (8; full list at https://brambrinkmeier.com/lab-runs.json):

| Date | Scenario | Expected | Got | Message (first line) |
|---|---|---|---|---|
| 2026-10-30 | Both scope and resource sent | 9010010 | 9010010 | AADSTS9010010: The resource parameter provided in the request doesn't match with the requested scopes. |
| 2026-10-30 | Both scope and resource sent | 9010010 | 9010010 | AADSTS9010010: The resource parameter provided in the request doesn't match with the requested scopes. |
| 2026-10-30 | Both scope and resource sent | 9010010 | 9010010 | AADSTS9010010: The resource parameter provided in the request doesn't match with the requested scopes. |
| 2026-10-30 | Both scope and resource sent | 9010010 | success |  |
| 2026-10-30 | Both scope and resource sent | 9010010 | success |  |
| 2026-10-30 | Both scope and resource sent | 9010010 | 9010010 | AADSTS9010010: The resource parameter provided in the request doesn't match with the requested scopes. |
| 2026-10-31 | Both scope and resource sent | 9010010 | 9010010 | AADSTS9010010: The resource parameter provided in the request doesn't match with the requested scopes. |
| 2026-10-31 | Both scope and resource sent | 9010010 | success |  |

## Sources

1. [Microsoft Entra authentication and authorization error codes](https://learn.microsoft.com/entra/identity-platform/reference-error-codes)
2. [Secure a Model Context Protocol (MCP) server with Microsoft Entra ID](https://learn.microsoft.com/en-us/entra/agent-id/secure-mcp-server-with-entra-id)
3. [Scopes and permissions in the Microsoft identity platform](https://learn.microsoft.com/entra/identity-platform/scopes-oidc)
4. [anthropics/claude-code issue 52871 (AADSTS9010010 with MCP OAuth)](https://github.com/anthropics/claude-code/issues/52871)
5. [SigninLogs table reference (Azure Monitor)](https://learn.microsoft.com/en-us/azure/azure-monitor/reference/tables/signinlogs)
6. [AADServicePrincipalSignInLogs table reference (Azure Monitor)](https://learn.microsoft.com/en-us/azure/azure-monitor/reference/tables/aadserviceprincipalsigninlogs)

## Related codes

[AADSTS500011](https://brambrinkmeier.com/entra/aadsts/500011/), [AADSTS9002313](https://brambrinkmeier.com/entra/aadsts/9002313/), [AADSTS700016](https://brambrinkmeier.com/entra/aadsts/700016/)

## License and citation

CC BY 4.0 (https://creativecommons.org/licenses/by/4.0/). CC BY 4.0 covers the author's own text and classification fields. Quoted Microsoft error wording belongs to Microsoft, is quoted with its source and can change.

Cite as: Bram Brinkmeier, "AADSTS9010010: Resource parameter doesn't match the requested scopes (fix)", https://brambrinkmeier.com/entra/aadsts/9010010/ (CC BY 4.0), last updated 2026-10-30.
