Skip to content

AADSTS7000215: Invalid client secret is provided

Short answer: AADSTS7000215 means an app or service principal sent a client secret that Microsoft Entra ID didn't accept. Usually it is a developer or rotation mistake. The security signal is repeated failures for one app ID from an IP you don't own, which suggests someone trying a leaked or old secret. Hunt it in AADServicePrincipalSignInLogs.

At a glance
CodeAADSTS7000215
Microsoft nameInvalid client secret
CategoryApp configuration
TypeFailure
Attack signalMedium: worth a look in context
MITRE ATT&CKT1078.004 Valid Accounts: Cloud Accounts
Where to lookAADServicePrincipalSignInLogs
Microsoft lookuplogin.microsoftonline.com/error?code=7000215

Invalid client secret is provided. Developer error - the app is attempting to sign in without the necessary or correct authentication parameters.

The reference table gives this code no PascalCase name. Two siblings help you tell the cases apart:

  • 7000222 InvalidClientSecretExpiredKeysProvided: “The provided client secret keys are expired. Create new keys for your app, or consider using certificate credentials for added security”
  • 7000218: “The request body must contain the following parameter: ‘client_assertion’ or ‘client_secret’.”

So 7000222 means the secret was right but expired, 7000218 means no secret or assertion was sent at all, and 7000215 means a secret was sent and it was wrong.

Usually not. Microsoft labels it a developer error, and most 7000215 comes from a typo in configuration or a system that still holds a secret you rotated. The security reading depends on where the requests come from.

Pattern Likely meaning
7000215 for one app from your own servers or build agents, starting right after a secret rotation A system still holding the old secret. Benign, but it tells you exactly which systems to update.
7000215 for one app from an IP you don’t own and have never seen succeed for that app Someone trying a secret for your app from outside. A leaked or old secret is the likely source. Investigate.
7000215 followed by a success (ResultType "0") for the same app from the same unknown IP The attacker found a working secret. Treat the app as compromised.
7000215 spread across many app IDs from one IP Someone testing a set of credentials against your tenant. Investigate the source.

Failures by app and source IP:

AADServicePrincipalSignInLogs
| where TimeGenerated > ago(7d)
| where ResultType == "7000215"
| summarize Attempts = count(),
FirstSeen = min(TimeGenerated),
LastSeen = max(TimeGenerated),
KeyIds = make_set(ServicePrincipalCredentialKeyId, 10)
by AppId, ServicePrincipalName, IPAddress
| sort by Attempts desc

Failures from IPs that never had a success for the same app in the last 30 days:

let knownAppIPs =
AADServicePrincipalSignInLogs
| where TimeGenerated > ago(30d)
| where ResultType == "0"
| distinct AppId, IPAddress;
AADServicePrincipalSignInLogs
| where TimeGenerated > ago(1d)
| where ResultType == "7000215"
| join kind=leftanti knownAppIPs on AppId, IPAddress
| summarize Attempts = count(), LastSeen = max(TimeGenerated) by AppId, ServicePrincipalName, IPAddress
| sort by Attempts desc

Any IP from that list that later succeeds for the same app:

let failedFrom =
AADServicePrincipalSignInLogs
| where TimeGenerated > ago(7d)
| where ResultType == "7000215"
| summarize FirstFail = min(TimeGenerated) by AppId, IPAddress;
AADServicePrincipalSignInLogs
| where TimeGenerated > ago(7d)
| where ResultType == "0"
| join kind=inner failedFrom on AppId, IPAddress
| where TimeGenerated > FirstFail
| project TimeGenerated, AppId, ServicePrincipalName, IPAddress, ServicePrincipalCredentialKeyId, FirstFail
| sort by TimeGenerated asc

Check two things in your own workspace before relying on these queries:

  • The Azure Monitor reference for AADServicePrincipalSignInLogs describes ResultType as “Success or Failure”, while the user sign-in tables document it as the numeric error code as a string. Look at a few failed rows and confirm they carry "7000215" and that successes carry "0". If they don’t, filter on ResultSignature (“Contains the error code, if any, for the sign-in operation”) instead.
  • Whether ServicePrincipalCredentialKeyId is filled in on a failed secret isn’t documented. A wrong secret may not match any key, so the column may be empty. On successes it tells you which credential was used.
  • A service principal using a client secret has no MFA step.
  • 7000215 is a failed credential check. For user sign-ins, Conditional Access only evaluates after the first factor succeeds; the same logic suggests no policy was evaluated here. That is reasoning from the user case, not a documented statement for service principals.
  • So the controls that matter are on the credential itself: who can read it, where it is stored, and whether it is a secret at all.

For developers: check that the app sends the current secret for the right app registration and tenant. If the secret expired, you get 7000222, not 7000215.

For admins:

  1. After a rotation, use the first query to list every IP still failing for that app, and update those systems.
  2. If failures come from an IP you don’t own, treat the app’s existing secrets as exposed: create a new credential, remove the old ones from the app registration, and update your own systems.
  3. If the third query returns a row, the app was used by someone else. Review what the app’s permissions allow and what it accessed after that time.
  4. Follow Microsoft’s own hint in the 7000222 message and “consider using certificate credentials for added security”.

Sources

  1. Microsoft Entra authentication and authorization error codes
  2. AADServicePrincipalSignInLogs table reference (Azure Monitor)