Azure Error Guide: 'AADSTS7000215' Invalid Client Secret Provided
Fix the AADSTS7000215 invalid client secret error in Entra ID, covering expired secrets, secret ID vs value, wrong tenant, and encoding issues.
- #azure
- #troubleshooting
- #errors
- #entra-id
Exact Error Message
When an app registration authenticates with the OAuth 2.0 client credentials flow, Microsoft Entra ID (formerly Azure AD) returns this error when the secret is wrong:
AADSTS7000215: Invalid client secret provided. Ensure the secret being sent
in the request is the client secret value, not the client secret ID, for a
secret added to app 'a1b2c3d4-1111-2222-3333-444455556666'.
Trace ID: 7f8e9d0c-aaaa-bbbb-cccc-1234567890ab
Correlation ID: 0c1d2e3f-9999-8888-7777-fedcba987654
Timestamp: 2026-06-27 14:32:07Z
The same root cause surfaces differently depending on the tool. The Azure CLI service-principal login fails like this:
$ az login --service-principal -u <appId> -p <secret> --tenant <tenantId>
ERROR: AADSTS7000215: Invalid client secret provided. Ensure the secret being
sent in the request is the client secret value, not the client secret ID...
And a raw token request against the /oauth2/v2.0/token endpoint returns HTTP 401 with an invalid_client body:
HTTP/1.1 401 Unauthorized
Content-Type: application/json
{
"error": "invalid_client",
"error_description": "AADSTS7000215: Invalid client secret provided...",
"error_codes": [7000215],
"timestamp": "2026-06-27 14:32:07Z"
}
What the Error Means
AADSTS7000215 is Entra ID telling you that the credential it received does not match any active client secret on the named app registration (appId). The OAuth client credentials grant authenticates a confidential client (your service principal) using a secret. When that secret is missing, expired, malformed, or simply wrong for that appId + tenant combination, the token endpoint rejects the request before issuing an access token.
The error is deliberately specific: it names the appId and explicitly warns that you may be sending the secret ID rather than the secret value. That hint exists because it is, by far, the most common cause. The secret value is shown only once at creation time; afterward the portal displays only the ID, and people copy the wrong field.
Common Causes
- Using the secret ID instead of the secret VALUE. The portal lists “Secret ID” (a GUID) and “Value” side by side. The token endpoint wants the value, never the ID.
- Expired secret. Client secrets have a finite lifetime (max 24 months). Once the
endDateTimepasses, the secret stops working. - Secret rotated or deleted. A secret was regenerated or removed, but the pipeline variable / Key Vault entry still holds the old one.
- Wrong client (
appId) for the tenant. The secret is valid but paired with the wrong application ID, or the app registration lives in a different tenant. - Trailing whitespace or truncation. The value was copied with a leading/trailing space, newline, or got cut off (secrets contain characters like
~and.that some scripts mishandle). - Secret belongs to a different app registration. Multi-app environments make it easy to grab a secret from the neighbouring registration.
- Wrong tenant authority. Authenticating against
login.microsoftonline.com/commonor the wrong tenant GUID instead of the home tenant of the app. - Certificate vs secret mismatch. The app is configured for certificate auth, but the client is sending a password secret (or vice versa).
How to Reproduce the Error
The fastest way to reproduce it is to authenticate with the secret ID instead of the value:
# Grab the SECRET ID (the GUID) - this is the WRONG field to send
az ad app credential list --id <appId> --query "[0].keyId" -o tsv
# Now try to log in using that GUID as the password
az login --service-principal -u <appId> -p <keyId-guid> --tenant <tenantId>
# -> AADSTS7000215: Invalid client secret provided...
You can reproduce the expired-secret variant by attempting to log in with a secret whose endDateTime is in the past, or the wrong-tenant variant by passing a --tenant value that does not own the app registration.
Diagnostic Commands
All of the following are read-only. They inspect state without changing credentials, so they are safe to run during an active incident.
# 1. List all credentials on the app and check their expiry windows
az ad app credential list --id <appId> \
--query "[].{keyId:keyId, end:endDateTime}" -o table
# 2. Confirm the service principal exists and resolve its appId
az ad sp show --id <appId> \
--query "{displayName:displayName, appId:appId, spId:id}" -o table
# 3. Verify which tenant and account your CLI session is pointed at
az account show \
--query "{tenantId:tenantId, subscription:name, user:user.name}" -o table
# 4. Inspect the app registration itself (audience, key/secret config)
az ad app show --id <appId> \
--query "{displayName:displayName, appId:appId, signInAudience:signInAudience, passwordCount:length(passwordCredentials), certCount:length(keyCredentials)}" \
-o table
Use command 1 to confirm at least one secret is active and not past its endDateTime. Command 4 distinguishes password secrets (passwordCount) from certificates (certCount) so you can tell whether you should be sending a secret at all.
Step-by-Step Resolution
-
Confirm the
appIdand tenant. Make sure the application ID and tenant GUID you are authenticating with actually own the app registration. Cross-checkaz ad app showoutput and your CLI’saz account showtenant. -
List the credentials and check expiry. Run the diagnostic
az ad app credential listabove. If every secret’sendDateTimeis in the past, the secret is expired and must be replaced. -
Create a NEW secret. Generate a fresh secret and capture its value immediately. The value is printed only once:
az ad app credential reset --id <appId> \ --display-name "ci-pipeline-2026" \ --years 1 \ --query "{appId:appId, password:password, tenant:tenant}" -o jsonThe
passwordfield in the output is the value. Do not use--appendif you intend to roll the credential; omit it only when you are sure you want to keep prior secrets. -
Use the VALUE, not the ID. Take the
passwordvalue from step 3, not thekeyIdGUID. Verify the length and that there is no trailing whitespace or hidden newline before storing it. -
Update the secret store / pipeline variable. Push the new value into Azure Key Vault, your CI secret store, or the pipeline variable group. Update every consumer that referenced the old secret.
-
Re-test the login. Confirm the fix:
az login --service-principal -u <appId> -p <new-secret-value> --tenant <tenantId> -
Prefer certificates or federated credentials. Move away from passwords entirely. Workload identity federation (federated credentials) lets GitHub Actions, GitLab, or AKS pods exchange a short-lived OIDC token for an Entra access token, so there is no long-lived secret to expire or leak. Certificates are the next-best option where federation is unavailable.
Prevention and Best Practices
- Use workload identity federation for CI/CD and Kubernetes workloads. It eliminates the secret entirely, which removes this error class outright.
- Set short secret lifetimes and rotate automatically. A 6-month secret with an automated rotation job is far safer than a 24-month one nobody tracks.
- Alert on upcoming expiry. Query
endDateTimeacross all app registrations on a schedule and warn before secrets lapse. - Store secrets in Key Vault, never in code or plain pipeline variables. Reference them at runtime so rotation is a single update.
- Document which field is the value. Most outages here are human error at copy time. A one-line runbook note (“use Value, not Secret ID”) prevents repeats. For broader credential-hygiene patterns, see our Azure troubleshooting guides.
Related Errors
- AADSTS700016 - Application with the given
appIdwas not found in the tenant. Usually the wrongappIdor wrong tenant authority. - AADSTS700027 - Client assertion (certificate) failed signature validation. Indicates a certificate problem rather than a secret problem.
- AADSTS50012 - A broader
invalid_clientfamily error; one subvariant reports an invalid client secret, often alongsideAADSTS7000215. - AADSTS7000222 - The provided client secret keys are expired. This is the explicit expired-secret variant of
AADSTS7000215. - AADSTS900023 - Specified tenant identifier is neither a valid GUID nor a valid domain name. Points to a malformed tenant authority.
Frequently Asked Questions
What is the difference between the secret ID and the secret value?
The secret ID (keyId) is a GUID that identifies the credential entry; it is shown permanently in the portal and CLI. The secret value is the actual password used to authenticate, and it is displayed only once at creation. Entra rejects requests that send the ID, which is exactly what AADSTS7000215 warns about.
What is the maximum lifetime for a client secret?
The Entra portal caps custom client secrets at 24 months. You can set shorter durations, and many security baselines recommend 90 days or less combined with automated rotation. The CLI’s --years and --end-date flags control the lifetime at creation.
How do I avoid client secrets entirely? Use workload identity federation (federated credentials). Your CI runner or AKS pod presents a short-lived OIDC token, and Entra exchanges it for an access token, so there is no stored secret to expire, leak, or rotate. This is the recommended approach for GitHub Actions, GitLab CI, and Kubernetes workloads.
My secret looks correct but still fails - what now? Check for trailing whitespace, a stray newline, or truncation in however you stored it. Secrets contain special characters that some shells and templating engines mangle. Re-create the secret, copy the value carefully, and verify its character length matches before redeploying.
Download the Free 500-Prompt DevOps AI Toolkit
500 battle-tested, copy-paste AI prompts engineered by a senior systems engineer — every one with fill-in placeholders and safety/back-out notes. Drop your email and it's yours.
- 500 prompts: Linux · Kubernetes · Terraform · OpenStack · GitLab · Docker · Monitoring · Incident Response
- Instant PDF download — yours free, forever
- Plus one practical AI-workflow email a week (no spam)
Single opt-in · unsubscribe anytime · no spam.