AADSTS70011 - Invalid Scope
Azure AADSTS70011 is a request-shape failure indicating that the `scope` parameter in the authentication request is malformed, misspelled, or contains scopes from multiple unrelated resources in a single token request.
Last reviewed: April 7, 2026|Editorial standard: source-backed technical guidance
What Does Invalid Scope Mean?
AADSTS70011 is a semantic mismatch. Under OAuth 2.0 and OpenID Connect, a single access token is generally issued for a single resource or audience. If the application requests User.Read for Microsoft Graph and api://my-custom-api/access for a custom API in the same token request, Entra ID returns AADSTS70011. It also appears when the wrong scope type is used for the selected flow, such as requesting a delegated scope in a daemon-style client-credentials flow.
Common Causes
- -Multi-Resource Scope Mix: Combining Microsoft Graph scopes with custom API scopes in one request string.
- -Spelling Errors: Typographical mistakes such as
Directory.Read.Alllor invalid permission names. - -Malformed `/.default` Usage: Static scope requests are formatted incorrectly, for example by omitting the resource prefix or misusing
/.defaultin the wrong flow. - -Flow And Scope Mismatch: Delegated permissions are requested during a client-credentials flow, or application-style
/.defaultis used where a delegated user scope is expected. - -Invalid Separators: Scopes are separated with commas or semicolons instead of spaces in the raw request.
How to Fix Invalid Scope
- 1Split The Requests: If you need tokens for Microsoft Graph and a custom API, make two separate token requests.
- 2Check The Resource Prefix: Ensure custom scopes are fully qualified, for example
api://{client-id}/scope_name. - 3Use `/.default` For Daemons: If the app is a background service using client credentials, request
https://graph.microsoft.com/.defaultinstead of delegated scope names. - 4Validate In The Portal: In App Registration > Expose an API, copy the scope URI exactly as configured rather than rebuilding it manually.
Step-by-Step Diagnosis for Invalid Scope
- 1Inspect the network trace or debugger and look directly at the
scopeparameter in the authorize or token request. - 2Count the resources referenced in the scope list. If more than one base resource or App ID URI appears, that is usually the root cause.
- 3Verify the OAuth flow type and match the scope style to that flow: delegated for interactive user flows,
/.defaultfor client credentials. - 4Check for invisible characters, bad URL encoding, or incorrect separators in the scope string.
AADSTS70011 vs AADSTS65001
- -AADSTS70011: The scope request itself is structurally or semantically invalid.
- -AADSTS65001: The scope is meaningful, but consent is missing for it.
The Single Resource Rule
- -An access token is usually a key for one specific door. You cannot request a single token that simultaneously targets Microsoft Graph and your custom backend API.
Implementation Examples
// Incorrect: mixing Microsoft Graph and custom API scopes
const request = { scopes: ["User.Read", "api://my-backend/access"] };
// Correct: get a Graph token first
const graphResponse = await msalInstance.acquireTokenSilent({ scopes: ["User.Read"] });
// Then request a token for your API separately
const apiResponse = await msalInstance.acquireTokenSilent({ scopes: ["api://my-backend/access"] });# Use /.default to request all pre-configured application permissions
curl -X POST "https://login.microsoftonline.com/{tenant}/oauth2/v2.0/token" \
-d "client_id={id}" \
-d "scope=https://graph.microsoft.com/.default" \
-d "grant_type=client_credentials" \
-d "client_secret={secret}"How to Verify the Fix
- -Confirm the application now makes distinct token requests for each unique resource.
- -Verify the token response contains the expected
scporrolesclaims for the corrected request. - -Ensure the
audclaim in the resulting JWT matches the intended resource.
How to Prevent Recurrence
- -Centralize Scope Constants: Keep Graph scopes and custom API scopes in separate configuration arrays.
- -Use SDK Best Practices: Let MSAL manage formatting, but never pass a mixed-resource scope array into a single request.
- -Add CI Validation: Include tests that validate scope structure and flow compatibility before deployment.
- -Pro tip: If AADSTS70011 appears right after migrating from ADAL to MSAL, inspect how old resource parameters were converted into scope strings. This is a very common migration pitfall.
Decision Support
Compare Guide
HTTP 400 vs 422: Bad Request vs Unprocessable Content
Fix API payload issues faster by using 400 for malformed syntax and 422 for semantic validation failures, so clients correct format before business rules.
Playbook
CORS Error Fix Playbook (Preflight / Origin / Credentials)
Use this playbook to separate browser-enforced cross-origin policy failures from server-side CORS header and route defects and apply strict origin and credential controls safely.
Playbook
Validation Failure Playbook (400 / 422 / INVALID_ARGUMENT)
Use this playbook to separate malformed-request failures from semantic validation failures, then fix request contracts without broad server-side bypasses.
Official References
Provider Context
This guidance is specific to Azure services. Always validate implementation details against official provider documentation before deploying to production.