AADSTS7000218: Client secret or assertion missing from the request (fix)
Short answer: AADSTS7000218 means a token request reached Microsoft Entra ID as a confidential client but carried no client secret and no client assertion. Usually the app forgot the credential, or it uses ROPC, device code or IWA while the app registration is still set to confidential. Low attack value. The fix is to send the credential or, only when it fits, allow public client flows.
Fix: Developer of a web app, API or daemon: send `client_secret` or a certificate-signed `client_assertion` in the token request. App on a user's device: register a Mobile and desktop redirect URI, or have an admin set Allow public client flows to Yes, only for a real public client. Full steps
| Code | AADSTS7000218 |
|---|---|
| Category | App configuration |
| Type | Failure |
| Attack signal | Low: usually configuration or user error |
| Microsoft lookup | login.microsoftonline.com/error?code=7000218 |
What does AADSTS7000218 mean?
Section titled “What does AADSTS7000218 mean?”Microsoft’s description:
The request body must contain the following parameter: ‘client_assertion’ or ‘client_secret’.
The reference table gives this code no PascalCase name.
A token request arrived for an app that Microsoft Entra ID treats as a confidential client, and it carried no proof of the app’s identity. Microsoft’s troubleshooting article says the request fails with invalid_client and that confidential clients must supply a client secret or a client assertion.
Two siblings help you tell the cases apart:
- 7000215: “Invalid client secret is provided.” A secret was sent and it was wrong.
- 7000222: “The provided client secret keys are expired.” The secret was right but expired.
So 7000218 means nothing was sent at all.
How Entra decides the client is confidential
Section titled “How Entra decides the client is confidential”This is the part that catches most people. According to Microsoft’s troubleshooting article:
- If the request has a redirect URI, the platform type of that redirect URI decides. A Web redirect URI makes the app a confidential client. A Mobile and desktop applications redirect URI makes it a public client.
- If the request has no redirect URI (ROPC, device code, Integrated Windows Authentication), Entra uses the Allow public client flows setting on the app registration. Yes means public, No means confidential.
So a desktop tool that uses device code flow, registered with the default setting, gets 7000218 even though it was never meant to have a secret.
Reproduced in the lab
Section titled “Reproduced in the lab”On 30 October 2026 an automated lab run created an app registration without public client flows enabled, then sent a password-grant (ROPC) request with no credential. Entra returned AADSTS7000218:
AADSTS7000218: The request body must contain the following parameter: ‘client_assertion’ or ‘client_secret’.
The same run also sent a client-credentials request with no credential, and that returned a different code, AADSTS7000216 (“‘client_assertion’, ‘client_secret’ or ‘request’ is required for the ‘client_credentials’ grant type”). So the code depends on the grant type: 7000218 comes from a user-credential flow, 7000216 from client credentials.
The sign-in log row isn’t captured yet; see how pages are checked.
In the lab tenant’s sign-in logs the row appears under User sign-ins (interactive), Status Failure, Conditional Access Not Applied, with the Application column naming the confidential app that sent the request without a credential.
Is it an attack?
Section titled “Is it an attack?”Almost never. 7000218 is a configuration mismatch between the app and its registration. The request carried no credential, so it can’t have succeeded.
| Pattern | Likely meaning |
|---|---|
| 7000218 for a new app during testing | The developer hasn’t added the secret or certificate yet, or registered the wrong platform type. |
| 7000218 for a desktop script or CLI tool using device code or ROPC | The registration is confidential (public client flows set to No). Fix the registration or the flow. |
| 7000218 for an app that worked yesterday | Someone changed the redirect URI platform or the public client setting, or a deployment dropped the secret from its configuration. Check the audit log for Update application. |
| 7000218 from an IP you don’t own, for your app ID | Someone outside is trying your app ID without a credential. Our interpretation: they have the client ID, which is public by design, but not the secret. Low risk on its own. |
Microsoft notes that “The client ID is a public value that identifies the application, while the client secret is a confidential value.” Knowing a client ID is not a compromise.
The real security question is the fix, not the error. See the admin steps below before switching an app to a public client.
How do I find it in my logs (KQL)?
Section titled “How do I find it in my logs (KQL)?”Microsoft doesn’t document which sign-in table 7000218 lands in. Our reading: an app-only request (client credentials) would be a service principal sign-in, and a delegated request (device code, ROPC, authorization code) would be a user sign-in. Check where it lands in your workspace:
union withsource=SourceTable SigninLogs, AADNonInteractiveUserSignInLogs, AADServicePrincipalSignInLogs| where TimeGenerated > ago(7d)| where ResultType == "7000218"| summarize Rows = count(), Apps = dcount(AppId) by SourceTableWhich apps hit it, from where, and since when:
union SigninLogs, AADNonInteractiveUserSignInLogs, AADServicePrincipalSignInLogs| where TimeGenerated > ago(30d)| where ResultType == "7000218"| summarize Rows = count(), FirstSeen = min(TimeGenerated), LastSeen = max(TimeGenerated), IPs = make_set(IPAddress, 10), Users = dcount(UserPrincipalName) by AppId, AppDisplayName = coalesce(AppDisplayName, ServicePrincipalName)| sort by Rows descIf an app moved from 7000218 to success, check whether it got there by adding a secret or by being switched to a public client. The audit log shows the change to the app registration:
AuditLogs| where TimeGenerated > ago(30d)| where Category == "ApplicationManagement"| where OperationName startswith "Update application"| project TimeGenerated, OperationName, InitiatedBy, TargetResources| sort by TimeGenerated descMicrosoft’s audit activity reference lists both Update application and Update application - Certificates and secrets management in the ApplicationManagement category. The query uses startswith so it catches both; the exact punctuation in the stored OperationName may differ from the reference. TargetResources holds the changed properties, but which property names a public client switch writes isn’t documented, so read the rows rather than filter on them. Service principal rows are aggregated when the service principal, status, IP address and resource match, so row counts there are not request counts. ResultType is a string column, so compare it with "7000218".
How do I fix AADSTS7000218?
Section titled “How do I fix AADSTS7000218?”For developers:
- If your app is a confidential client (web app, web API, daemon), send the credential. Add
client_secret, or aclient_assertionsigned with a certificate, to the token request. Microsoft’s authorization code reference says the client secret “is required for web apps and web APIs, which can store theclient_secretsecurely on the server side.” - If your app runs on a user’s device (desktop, mobile, CLI, script), it is a public client and must not carry a secret. Microsoft: public clients “can’t be trusted to safely keep application secrets”. Register a Mobile and desktop applications redirect URI, or for flows without a redirect URI, ask an admin to turn on public client flows.
- To find out which flow your code uses, look at
grant_typein the token request (in code or a Fiddler trace). Microsoft’s article listspasswordfor ROPC,urn:ietf:params:oauth:grant-type:device_codefor device code,authorization_code,client_credentials, andurn:ietf:params:oauth:grant-type:jwt-bearerfor on-behalf-of.
For admins:
- For a confidential app, the fix is a credential, not a setting. Prefer a certificate or managed identity over a secret.
- Only for a real public client flow: in App registrations > the app > Authentication > Advanced settings, set Allow public client flows to Yes. Microsoft warns that this changes the client type from confidential to public, with security implications.
- Our reading of those implications, not Microsoft’s wording: once public client flows are on, anyone who knows the client ID can start ROPC or device code flows for that app without a secret. The client ID is public, so the secret no longer stands between an attacker and those flows. Don’t flip the setting just to make the error go away, and don’t flip it on an app that also uses a secret for server-side work.
- If you do allow public client flows, make sure MFA and Conditional Access cover the users who sign in through that app.
Related codes
- AADSTS7000215: Invalid client secret is provided
- AADSTS7000222: The provided client secret keys are expired
- AADSTS700016: Application not found in the directory
- AADSTS500011: The resource principal was not found in the tenant
- AADSTS50027: JWT token is invalid or malformed
- AADSTS70002: error validating client credentials
More: 90023, 90133, 700024, 1002016, 5002730, 7000216, 9002326, 9002327
Sources
- Microsoft Entra authentication and authorization error codes
- Error AADSTS7000218 when a confidential client application authenticates to Microsoft Entra ID
- Public client and confidential client applications
- Microsoft identity platform and OAuth 2.0 authorization code flow
- Microsoft Entra audit log categories and activities
- Service principal sign-ins