# Bram Brinkmeier: Entra ID sign-in errors, read for security > Microsoft Entra ID sign-in error codes (AADSTS) explained for security teams: attack signal, MITRE ATT&CK technique, Conditional Access interaction and KQL for SigninLogs. Pages quote Microsoft documentation and are marked lab-reproduced only after reproduction in a lab tenant; 35 of 118 are so far. ## Guides - [Azure CLI: "Resource was disallowed by policy. Reasons: MFA is required"](https://brambrinkmeier.com/guides/azure-cli-mfa-required-resource-disallowed-by-policy/): Azure CLI, PowerShell or IaC fails with RequestDisallowedByPolicy and MFA is required. What mandatory MFA phase 2 means and how to fix people and automation. - [How to detect MFA fatigue (push bombing) in Microsoft Entra ID](https://brambrinkmeier.com/guides/detect-mfa-fatigue-entra-id/): Detect MFA fatigue in Entra ID: read 500121, 50074, 50076 and 50079, parse AuthenticationDetails with KQL, spot an approved prompt, and respond. - [How to detect password spraying in Microsoft Entra ID (with KQL)](https://brambrinkmeier.com/guides/detect-password-spray-entra-id/): Find password spraying in Entra ID sign-in logs: which AADSTS codes to read, how smart lockout behaves, four KQL queries, and how to respond. - [Token replay attack on Microsoft 365: check Entra ID for the 1337 Services campaign](https://brambrinkmeier.com/guides/detect-token-replay-m365-session-hijack-entra-id/): Stolen M365 sessions replayed from 193.26.115.0/24: KQL for sign-ins, rogue DESKTOP- devices and swapped MFA methods, and what a password reset misses. - [After a web-server breach like PHP2Shell: patch, then hunt credential reuse in Entra ID](https://brambrinkmeier.com/guides/hunt-credential-reuse-after-web-server-breach/): PHP2Shell (CVE-2026-109618/109619): fixed versions, interim mitigations, then KQL to find stolen server credentials in Entra ID and Defender for Identity. - [ConnectWise Cloud Backup compromise: check your Entra ID tenant for a compromised vendor app](https://brambrinkmeier.com/guides/investigate-compromised-vendor-app-entra-id/): Was the ConnectWise (SkyKick) app abused in your tenant? App IDs, KQL for sign-ins, roles and new secrets, and why you disable the app instead of deleting it. - [How to investigate consent phishing (illicit consent grants) in Entra ID](https://brambrinkmeier.com/guides/investigate-consent-phishing-entra-id/): Find the consent event, read the sign-in codes around it, and remove an attacker's app from Entra ID. Why a password reset and MFA don't fix it. - [After a compromise: revoke Entra ID sessions and prove it worked](https://brambrinkmeier.com/guides/revoke-sessions-and-verify-entra-id/): Revoke a compromised user's Entra ID sessions, disable their devices, and use 50173, 50133 and 135011 sign-in rows to prove the attacker was cut off. - [SMTP AUTH basic authentication is being disabled in Exchange Online (end of December 2026): find and fix the apps and scanners that still use it](https://brambrinkmeier.com/guides/smtp-auth-basic-auth-retirement-exchange-online/): Exchange Online turns SMTP AUTH basic auth off by default for existing tenants at the end of December 2026. Find what uses it with KQL and PowerShell. - [Why is the user asked to sign in again? AADSTS70043, 700082, 50173, 50133, 50076](https://brambrinkmeier.com/guides/why-user-asked-to-sign-in-again-entra-id/): Tell five Entra ID re-sign-in codes apart: 70043, 700082, 50173, 50133 and 50076. Cause, attack signal, log table and what to check first, plus KQL. ## AADSTS change tracker - [AADSTS error code changes](https://brambrinkmeier.com/aadsts-changes/): weekly snapshot and diff of Microsoft's Entra AADSTS error code reference; new, removed, renamed and reworded codes with before/after text - [AADSTS changes as JSON](https://brambrinkmeier.com/aadsts-changes.json): every change event with date, code, type, before and after - [AADSTS changes RSS feed](https://brambrinkmeier.com/aadsts-changes.xml): one item per change ## AADSTS codes - [AADSTS code map](https://brambrinkmeier.com/entra/aadsts/): every code with attack signal, MITRE technique and category - [AADSTS16000 InteractionRequired](https://brambrinkmeier.com/entra/aadsts/16000/): AADSTS16000 means a user signed in with an account that doesn't exist in the tenant the app sent them to, so it can't use that app there. Usually it's a personal Microsoft account, the wrong account in the browser, or an external user who was never added as a guest. It has low attack value. The fix is to sign in with the right account or invite the user. - [AADSTS50001 InvalidResource](https://brambrinkmeier.com/entra/aadsts/50001/): AADSTS50001 means an app asked Microsoft Entra ID for a token to a resource (an API) that is disabled or doesn't exist. Usually the resource URL in the app's code or settings is wrong. Users report it in Nintex, Power BI and custom web APIs. It is a configuration error with low attack value. 500011 is the related code for a resource with no service principal in the tenant. - [AADSTS50011 InvalidReplyTo](https://brambrinkmeier.com/entra/aadsts/50011/): AADSTS50011 means the redirect (reply) URI in the sign-in request doesn't exactly match one registered for the application. It is almost always a configuration mistake: http instead of https, a trailing slash, a wrong port. The exact-match rule is also what stops attackers redirecting authorization codes and tokens to their own server. - [AADSTS50013 InvalidAssertion](https://brambrinkmeier.com/entra/aadsts/50013/): AADSTS50013 means Entra rejected an assertion, usually the user's access token that a middle-tier API tried to exchange in the on-behalf-of (OBO) flow. Microsoft lists issuer mismatch, expiry and malformed tokens as causes. One reported cause is an API that was handed a token meant for Microsoft Graph instead of for itself. Low attack value; fix the token the API receives. - [AADSTS50020 UserUnauthorized](https://brambrinkmeier.com/entra/aadsts/50020/): AADSTS50020 means an account from another identity provider or tenant tried to sign in to an app in your tenant, and that account isn't a user or guest there. It is usually a B2B or app misconfiguration: wrong tenant, uninvited guest, single-tenant app. Repeated hits can also reveal orphaned guest accounts that need cleanup. - [AADSTS50027 InvalidJwtToken](https://brambrinkmeier.com/entra/aadsts/50027/): AADSTS50027 means Microsoft Entra ID received a JWT it would not accept: wrong format, missing or duplicated claims, unexpected issuer or audience, outside its valid time range, or a failed signature check on an external ID token. It is usually a developer error. The two common sources are a hand-built client assertion and a federated identity provider's ID token. - [AADSTS50034 UserAccountNotFound](https://brambrinkmeier.com/entra/aadsts/50034/): AADSTS50034 means the username doesn't exist in the Microsoft Entra tenant the sign-in went to. Usually it's a typo or the wrong tenant. The security signal is volume from one source: many different non-existent usernames from one IP suggests an attacker testing a guessed or leaked user list. Hunt it with ResultType == "50034". - [AADSTS50052 InvalidPasswordExceedsMaxLength](https://brambrinkmeier.com/entra/aadsts/50052/): AADSTS50052 means the password sent was longer than Entra's limit of 256 characters. Microsoft's error reference doesn't list it, but a Microsoft change notice from 2020 names it InvalidPasswordExceedsMaxLength. Usually a user with an old over-long password, or a tool that sends garbage. Low attack value. Reset the password to 256 characters or fewer. - [AADSTS50053 IdsLocked](https://brambrinkmeier.com/entra/aadsts/50053/): AADSTS50053 covers two different blocks. Smart lockout locked the account after too many wrong passwords, or Microsoft's built-in protections blocked a high-confidence risky sign-in regardless of the password. The failure reason tells them apart. A burst across many accounts usually means a password spray tripped lockout. - [AADSTS50054 undefined](https://brambrinkmeier.com/entra/aadsts/50054/): AADSTS50054 means a sign-in used an old password. Microsoft doesn't list the code. Its Entra Connect docs show it for the Connector account, often with AADSTS70002, and fix it with Add-ADSyncAADServiceAccount. For a normal user, our reading is that someone or something still holds a former password; treat repeated rows from unknown IPs like failed passwords. - [AADSTS50055 InvalidPasswordExpiredPassword](https://brambrinkmeier.com/entra/aadsts/50055/): AADSTS50055 means the user's password has expired, so Microsoft Entra ID ended the sign-in and offers a reset. For a real user it is routine. During a password spray it matters more: the wording implies the password entered was correct, just expired, so the attacker likely holds a valid credential. - [AADSTS50057 UserDisabled](https://brambrinkmeier.com/entra/aadsts/50057/): AADSTS50057 means the user account is disabled in Microsoft Entra ID, so sign-in was refused. After an offboarding it is expected. The security signal is volume and source: many disabled accounts tried from one IP suggests a password spray working from an old user list. Hunt it with ResultType == "50057". - [AADSTS50058 UserInformationNotProvided](https://brambrinkmeier.com/entra/aadsts/50058/): AADSTS50058 means an app tried to sign a user in silently (single sign-on, often with prompt=none) but there was no valid session to use. Microsoft calls it a common, expected error. It is one of the noisiest codes in most tenants and has low attack value. The app should fall back to an interactive sign-in. Filter it out of failure dashboards. - [AADSTS50059 MissingTenantRealmAndNoUserInformationProvided](https://brambrinkmeier.com/entra/aadsts/50059/): AADSTS50059 means the request named no tenant and carried nothing Entra could use to work one out. It happens when a single-tenant app calls /common or /organizations without a user hint, for example in the device code flow. It is a configuration error with low attack value. Put your tenant ID or domain in the authority URL. - [AADSTS50072 UserStrongAuthEnrollmentRequiredInterrupt](https://brambrinkmeier.com/entra/aadsts/50072/): AADSTS50072 is an interrupt: the user must enroll a second factor before the sign-in can finish. For a new user it is expected. Microsoft's password spray playbook lists it among the codes to monitor. From an unfamiliar IP it can mean someone with the correct password is being asked to set up MFA on the account. - [AADSTS50074 UserStrongAuthClientAuthNRequiredInterrupt](https://brambrinkmeier.com/entra/aadsts/50074/): AADSTS50074 means MFA was required and the user did not pass the challenge. The first factor (usually the password) had already succeeded. One or two are normal. Many for one user in a short window from an unfamiliar IP is the MFA fatigue pattern: someone with the correct password is pushing prompts and waiting for an approval. - [AADSTS50076 UserStrongAuthClientAuthNRequired](https://brambrinkmeier.com/entra/aadsts/50076/): AADSTS50076 means the password was accepted but the sign-in now needs multifactor authentication, usually because of a Conditional Access policy, per-user MFA, or a new location. It is an expected interrupt. The signal is who reached it: a 50076 from an IP that was just failing passwords means an attacker has a working password. - [AADSTS50079 UserStrongAuthEnrollmentRequired](https://brambrinkmeier.com/entra/aadsts/50079/): AADSTS50079 means MFA is required but the user has not registered security info yet, so Entra ID sends them to register. For a real new user it is expected. If the sign-in came from an attacker IP, the attacker has a correct password and is being invited to register their own MFA method on the account. - [AADSTS50089 undefined](https://brambrinkmeier.com/entra/aadsts/50089/): AADSTS50089 means a sign-in failed because a token that was part of the sign-in had expired. Microsoft calls it expected: auth codes, refresh tokens and sessions expire or get revoked, and the app asks the user to sign in again. It has low attack value. Filter it out of failure dashboards and look only at users who can't get past it. - [AADSTS50097 DeviceAuthenticationRequired](https://brambrinkmeier.com/entra/aadsts/50097/): AADSTS50097 means Microsoft Entra ID asked the client to prove the device's identity because a device-based Conditional Access policy applies. Managed clients answer it silently. Clients that can't prove a device identity stop here. A spike for one user from a new IP can mean a valid credential is being used on an unmanaged device. - [AADSTS50105 EntitlementGrantsNotFound](https://brambrinkmeier.com/entra/aadsts/50105/): AADSTS50105 means the user signed in successfully but isn't assigned to the application, and the app has "Assignment required" set to Yes. That is least privilege working. Fix it by assigning the user or a group, not by switching assignment off. Watch for repeated 50105 on sensitive apps. - [AADSTS50125 PasswordResetRegistrationRequiredInterrupt](https://brambrinkmeier.com/entra/aadsts/50125/): AADSTS50125 means sign-in was paused so the user could register for, or go through, self-service password reset. It is an expected interrupt and the password had already been accepted. If the sign-in came from an attacker IP, the attacker may be choosing the recovery details for the account. - [AADSTS50126 InvalidUserNameOrPassword](https://brambrinkmeier.com/entra/aadsts/50126/): AADSTS50126 means Microsoft Entra ID rejected the username or password. A few per day are normal typos. The security signal is the shape: many accounts failing from one IP is password spraying, many failures on one account is brute force. Hunt it in SigninLogs with ResultType == "50126". - [AADSTS50133 SsoArtifactRevoked](https://brambrinkmeier.com/entra/aadsts/50133/): AADSTS50133 means Microsoft Entra ID rejected an existing sign-in session because the user's password expired or was recently changed. It is normally a one-off after a password change. After a compromise, rows from IPs or devices the user doesn't own show where an old session was still in use. Hunt it in SigninLogs and AADNonInteractiveUserSignInLogs. - [AADSTS50140 KmsiInterrupt](https://brambrinkmeier.com/entra/aadsts/50140/): AADSTS50140 is the "Keep me signed in?" prompt, logged as an interrupt. Microsoft calls it an expected part of the sign-in flow, so it is noise on failure dashboards. Its one investigative use: the prompt comes after authentication, so a 50140 from an attacker IP almost certainly means the password and any required MFA were accepted. - [AADSTS50146 MissingCustomSigningKey](https://brambrinkmeier.com/entra/aadsts/50146/): AADSTS50146 means Microsoft Entra ID refused to issue a token because the app's claims were customized but the app hasn't accepted that: it has no app-specific signing key (or the key expired), and it doesn't set acceptMappedClaims. It usually starts right after someone adds a claim to an app. It is a configuration error and a deliberate safeguard. Low attack value. - [AADSTS50155 DeviceAuthenticationFailed](https://brambrinkmeier.com/entra/aadsts/50155/): AADSTS50155 means Microsoft Entra ID couldn't authenticate the user's device, so it can't issue a Primary Refresh Token. Microsoft's main cause is a device that was deleted or disabled in Entra ID. The fix is to re-enable or re-register the device. Attack value is low, but 50155 from a device you disabled because it was lost is worth a look. - [AADSTS50158 External security challenge not satisfied](https://brambrinkmeier.com/entra/aadsts/50158/): AADSTS50158 means the user was redirected to satisfy an extra requirement, such as terms of use or a third-party MFA provider, before sign-in could finish. Microsoft says the code alone does not indicate a failure. Read it like an MFA interrupt: from an attacker IP, it means the password worked and the external challenge is the remaining barrier. - [AADSTS50173 Grant expired due to revocation](https://brambrinkmeier.com/entra/aadsts/50173/): AADSTS50173 means a refresh token was rejected because it was issued before the user's TokensValidFrom date, usually after a password change, reset or admin session revocation. After an incident it is the row you want: each client still holding an old token, attacker included, fails with 50173 in AADNonInteractiveUserSignInLogs, exposing its IP and device. - [AADSTS50194 undefined](https://brambrinkmeier.com/entra/aadsts/50194/): AADSTS50194 means a single-tenant app registration sent its sign-in to the /common endpoint, which Microsoft Entra ID doesn't allow for single-tenant apps created after a cut-off date. It is a configuration error with low attack value. Fix it by putting your tenant ID in the app's authority URL, or make the app multitenant if it really must serve other tenants. - [AADSTS50196 LoopDetected](https://brambrinkmeier.com/entra/aadsts/50196/): AADSTS50196 means Entra detected a client loop: the app sent the same request too many times in a short period. Microsoft says the usual cause is missing or broken token caching. It points to a faulty app, not usually to an attacker. The fix is in the app: cache tokens, call the silent method first, and stop retrying on errors. - [AADSTS51004 UserAccountNotInDirectory](https://brambrinkmeier.com/entra/aadsts/51004/): AADSTS51004 means the signing-in user has no account in the tenant the app chose. Microsoft says the app likely picked the wrong tenant; if the user should have access, add them as a guest. Users also report it with federated sign-in (Okta, Google Workspace) when the identity from the IdP matches no Entra user. Low attack value. - [AADSTS53000 DeviceNotCompliant](https://brambrinkmeier.com/entra/aadsts/53000/): AADSTS53000 means a Conditional Access policy requires a compliant device and the device signing in isn't compliant. The password was already accepted. Usually it is a user on a personal or unenrolled device. For a privileged account on a new device or IP, treat it as a valid credential in the wrong hands. - [AADSTS53001 DeviceNotDomainJoined](https://brambrinkmeier.com/entra/aadsts/53001/): AADSTS53001 means a Conditional Access policy requires a domain-joined (hybrid joined) device and the device signing in isn't one. The password was already accepted. Usually it is a user on a personal or cloud-only device. From an unknown device on an unfamiliar IP, it means a working credential is being used outside your estate. - [AADSTS53003 BlockedByConditionalAccess](https://brambrinkmeier.com/entra/aadsts/53003/): AADSTS53003 means a Conditional Access policy blocked the sign-in or its grant controls weren't met. The first factor was already accepted, because Conditional Access runs after it. From an unknown IP or country, read it as a valid first factor (password or passwordless) in someone else's hands, stopped by policy. The ConditionalAccessPolicies column names the policy. - [AADSTS54005 undefined](https://brambrinkmeier.com/entra/aadsts/54005/): AADSTS54005 means an app tried to redeem an OAuth 2.0 authorization code that had already been redeemed. Usually the app sent the same code twice: a double callback, a retry, or a page reload. It is mostly an app bug with low attack value. The app should get a new code, or use the refresh token it already has. - [AADSTS65001 DelegationDoesNotExist](https://brambrinkmeier.com/entra/aadsts/65001/): AADSTS65001 means an app asked for a token for permissions that no user or admin has consented to. For a new or misconfigured app it is routine. The security angle is consent phishing: watch for an unfamiliar app that flips from 65001 to success, then check the audit log for "Consent to application" and IsAdminConsent. - [AADSTS65002 undefined](https://brambrinkmeier.com/entra/aadsts/65002/): AADSTS65002 means a Microsoft-owned client app asked for a token for a Microsoft-owned API it isn't preauthorized for. Nobody in your tenant can grant that consent. Users hit it from Visual Studio sign-in in the Azure SDK, from scripts that borrow a Microsoft client ID, and from an old Azure Virtual Desktop web client URL. Use your own app registration or the current client. - [AADSTS65004 UserDeclinedConsent](https://brambrinkmeier.com/entra/aadsts/65004/): AADSTS65004 means the app asked for consent and the user did not give it. Microsoft also documents it as an expected part of the admin consent workflow: after a user submits a request and selects Back to app, the app receives 65004. It has low attack value on its own. Check the app if one unfamiliar app collects declines from many users. - [AADSTS65005 MisconfiguredApplication](https://brambrinkmeier.com/entra/aadsts/65005/): AADSTS65005 means an app asked for access to a resource (an API) that isn't in the app's registered permissions, or that isn't available in the tenant. For SAML apps it can also mean a wrong Identifier (Entity ID). Users hit it on company apps, scripts and integrations that sign in to Microsoft 365, Intune or Dynamics. It is a configuration error with low attack value. - [AADSTS70002 InvalidClient](https://brambrinkmeier.com/entra/aadsts/70002/): AADSTS70002 means Microsoft Entra ID couldn't validate the credentials an app sent, typically a client secret that doesn't match. A wrong secret today often comes back as 7000215 instead. 70002 is also seen as an outer code in front of a more specific one, so read the whole message. Usually a setup mistake; repeated failures from IPs you don't own deserve a look. - [AADSTS70008 ExpiredOrRevokedGrant](https://brambrinkmeier.com/entra/aadsts/70008/): AADSTS70008 means an app tried to use a refresh token or grant that is no longer valid. Microsoft's text names inactivity; the code name also says revoked. It is usually part of the normal token lifecycle and has low attack value. The app should send the user to an interactive sign-in. Hunt it in the non-interactive sign-in logs. - [AADSTS70016 AuthorizationPending](https://brambrinkmeier.com/entra/aadsts/70016/): AADSTS70016 means a device code flow is waiting for the user to sign in. The app polls the token endpoint, nobody has entered the code yet, and Entra answers with 70016. It is the normal reply while a device code is outstanding, not a failure. For defenders it marks the window in which a device code phishing victim has been shown a code but has not used it. - [AADSTS70021 undefined](https://brambrinkmeier.com/entra/aadsts/70021/): AADSTS70021 means a workload sent an external token (from GitHub, Azure DevOps, Kubernetes or another identity provider) and Entra found no federated identity credential on the app or managed identity that matches it. Usually the issuer or subject is wrong, or the credential was created minutes ago and hasn't propagated. It is a configuration error with low attack value. - [AADSTS70025 undefined](https://brambrinkmeier.com/entra/aadsts/70025/): AADSTS70025 means a workload presented an external token for an app registration or managed identity that has no federated identity credentials at all. Usually the credential was never created, was deleted, or the pipeline points at the wrong client ID. Users also report it when a certificate assertion was expected. A configuration error with low attack value. - [AADSTS70043 BadTokenDueToSignInFrequency](https://brambrinkmeier.com/entra/aadsts/70043/): AADSTS70043 means a refresh token was refused because a Conditional Access sign-in frequency policy says the user must authenticate again. It is the session control working as configured, so it is expected and has low attack value. Volume tracks how strict your policy is. Hunt it in AADNonInteractiveUserSignInLogs with ResultType == "70043". - [AADSTS70044 undefined](https://brambrinkmeier.com/entra/aadsts/70044/): AADSTS70044 means a Conditional Access sign-in frequency check ended the user's session, so the app must send the user to an interactive sign-in. Microsoft's error reference doesn't list it; the wording comes from a Microsoft Q&A answer. It is the session control working, with low attack value. The app should handle it by prompting, not by retrying silently. - [AADSTS75011 NoMatchedAuthnContextInOutputClaims](https://brambrinkmeier.com/entra/aadsts/75011/): AADSTS75011 means a SAML app asked for a specific authentication method in its request, and the method the user already signed in with is different. Microsoft Entra ID reuses the existing session instead of signing the user in again, so the two don't match. It is a configuration problem with low attack value. Fix it by removing RequestedAuthnContext or adding ForceAuthn. - [AADSTS76021 ApplicationRequiresSignedRequests](https://brambrinkmeier.com/entra/aadsts/76021/): AADSTS76021 means a SAML app in Microsoft Entra ID is set to require signed authentication requests, and the request it received wasn't signed, or the signature wasn't where the SAML binding expects it. It follows an admin enabling Require verification certificates. It is a configuration error and the check is working as intended. Low attack value. - [AADSTS90002 InvalidTenantName](https://brambrinkmeier.com/entra/aadsts/90002/): AADSTS90002 means the sign-in request named a tenant that Entra can't find. Usually the tenant ID or domain in the app's settings is wrong, the app talks to the wrong cloud, or the domain was derived from an email address and isn't registered. It is a configuration error with low attack value. Check the tenant ID and the cloud endpoint. - [AADSTS90009 TokenForItselfMissingIdenticalAppIdentifier](https://brambrinkmeier.com/entra/aadsts/90009/): AADSTS90009 means an app asked Microsoft Entra ID for a token where the resource is the app itself, but named itself with an App ID URI or other string instead of its GUID application ID. Microsoft supports that only with the GUID. It is a developer error with no attack value. Use the client ID GUID as the resource, or call the right API. - [AADSTS90014 MissingRequiredField](https://brambrinkmeier.com/entra/aadsts/90014/): AADSTS90014 means Entra expected a field in the request or credential and it wasn't there. The message names the field: users report 'scope' from integrations such as ServiceNow, and 'request' when a browser app navigated back during sign-in. Microsoft gives no more detail. Low attack value. Read the field name and fix the request or the sign-in flow. - [AADSTS90015 QueryStringTooLong](https://brambrinkmeier.com/entra/aadsts/90015/): AADSTS90015 means the sign-in request URL Entra received had a query string that was too long. Sign-in requests travel as URL parameters, so a large state value, a long return URL or a chain of identity providers can push it over the limit. Users report it from Jira Cloud for Outlook, Azure Databricks and chained Okta setups. Low attack value. - [AADSTS90019 MissingTenantRealm](https://brambrinkmeier.com/entra/aadsts/90019/): AADSTS90019 means Microsoft Entra ID couldn't work out which tenant a sign-in was for: the request didn't name one and the credentials didn't imply one. Users often see it in Outlook or the browser after typing a short username. Our reading: developers can hit it when an app uses the `common` endpoint with no user or tenant hint. It is a configuration or input error with low attack value. - [AADSTS90023 InvalidRequest](https://brambrinkmeier.com/entra/aadsts/90023/): AADSTS90023 means Microsoft Entra ID rejected the token request as invalid. Microsoft's reference describes it only as InvalidRequest. The lab has returned it for two different causes with two different messages: a client_assertion_type that is not the JWT bearer URN, and a device code polled with a different client_id than the one that requested it. Read the message, not just the code. - [AADSTS90072 PassThroughUserMfaError](https://brambrinkmeier.com/entra/aadsts/90072/): AADSTS90072 means a user signed in with an external account that doesn't exist in the tenant they tried to reach, so they can't satisfy that tenant's MFA. It also appears for synced users when the ImmutableID (sourceAnchor) in Active Directory and Microsoft Entra ID don't match. It is a B2B or sync configuration problem with low attack value. - [AADSTS90094 AdminConsentRequired](https://brambrinkmeier.com/entra/aadsts/90094/): AADSTS90094 means a user tried to consent to an app, but the permissions it asks for need an administrator. Your user-consent restriction is holding. Usually it is a legitimate new app. The security signal is an unfamiliar app hitting 90094 for several users, which fits a consent-phishing attempt. Hunt it in SigninLogs by AppId. - [AADSTS90095 AdminConsentRequiredRequestAccess](https://brambrinkmeier.com/entra/aadsts/90095/): AADSTS90095 is an interrupt: a user hit a consent prompt for permissions that need an admin, and because the admin consent workflow is on, they are told to request approval. This is the recommended setup. The review queue becomes your consent-phishing triage queue. Hunt unfamiliar apps in SigninLogs with ResultType == "90095". - [AADSTS90133 undefined](https://brambrinkmeier.com/entra/aadsts/90133/): AADSTS90133 means a device code request went to the /common or /consumers endpoint, where Entra didn't support it for that app. Microsoft doesn't list the code, but a code comment in its device code docs gives the message and the fix: use a tenant-specific authority. It is a configuration error with low attack value. - [AADSTS135011 Device disabled](https://brambrinkmeier.com/entra/aadsts/135011/): AADSTS135011 means the device used for the sign-in is disabled in Microsoft Entra ID. Usually an admin disabled it during cleanup or incident response, and something on that device still tries to get tokens. After an incident, these rows show where the quarantined device is and when it reconnects. - [AADSTS165000 undefined](https://brambrinkmeier.com/entra/aadsts/165000/): AADSTS165000 means the browser lost or didn't send the cookies, form fields or headers that keep one sign-in together, so the sign-in page stops. Microsoft's error reference doesn't list it. Users report it on iPads, a Mac and in Edge. Two users fixed it on iPads by setting the device clock to automatic. Low attack value. - [AADSTS500011 InvalidResourceServicePrincipalNotFound](https://brambrinkmeier.com/entra/aadsts/500011/): AADSTS500011 means an app asked for a token for an API (the resource) that has no service principal in the tenant the request went to. It is a configuration error: wrong resource URL or scope, wrong tenant, or an API nobody has provisioned or consented to. It has low attack value. Hunt it in SigninLogs and AADServicePrincipalSignInLogs. - [AADSTS500014 InvalidResourceServicePrincipalDisabled](https://brambrinkmeier.com/entra/aadsts/500014/): AADSTS500014 means the API a token was requested for (the resource) has a disabled service principal in the tenant, so Microsoft Entra ID won't issue tokens for it. Microsoft gives two causes: a lapsed subscription or an admin who disabled it. If the resource is a Microsoft service such as Exchange Online, sign-ins break for everyone. Find who disabled it before re-enabling. - [AADSTS500021 undefined](https://brambrinkmeier.com/entra/aadsts/500021/): AADSTS500021 means tenant restrictions (v1) are on in the user's network: a proxy adds a list of allowed tenants to sign-in traffic, and the tenant the user tried to reach isn't on it. It is a control doing its job, with low attack value. The fix is on the side of whoever runs the proxy, usually the user's own organisation, not the app's tenant. - [AADSTS500031 undefined](https://brambrinkmeier.com/entra/aadsts/500031/): AADSTS500031 means Entra couldn't find a signing certificate configured for the app. Microsoft doesn't list the code. The one user report we found was fixed by adding a SAML signing certificate to the enterprise app. It is a configuration error with low attack value. Check the app's SAML Certificates section and make sure a valid certificate is active. - [AADSTS500113 undefined](https://brambrinkmeier.com/entra/aadsts/500113/): AADSTS500113 means a sign-in request went to the authorize endpoint for an app registration that has no redirect URI (reply address) at all. Entra has no allowed place to send the result and refuses the request, even before anyone signs in. It is a configuration error with low attack value. Add the right platform and redirect URI to the app registration. - [AADSTS500121 MFA prompt not completed](https://brambrinkmeier.com/entra/aadsts/500121/): AADSTS500121 means the user didn't complete the MFA prompt: it was denied, ignored, timed out, or MFA setup was unfinished. The password had already been accepted. A few are normal. Many for one user in a short window, especially from an unfamiliar IP, is the MFA fatigue pattern. - [AADSTS500200 undefined](https://brambrinkmeier.com/entra/aadsts/500200/): AADSTS500200 means someone signed in with a personal Microsoft account (for example Outlook.com, or a Gmail address used as a Microsoft account) to an app or tenant that only accepts work or school accounts. Microsoft's error reference doesn't list it. It has low attack value. Sign in with a work account, invite the person as a guest, or change the app's supported account types. - [AADSTS500341 undefined](https://brambrinkmeier.com/entra/aadsts/500341/): AADSTS500341 means the account signing in has been deleted from the Microsoft Entra tenant. Microsoft's error reference doesn't list it; a Microsoft Viva Goals page does. Something still uses the old account: a saved sign-in, a connection or a script. Restore the user within 30 days if the deletion was a mistake, otherwise reconnect with an active account. - [AADSTS500571 undefined](https://brambrinkmeier.com/entra/aadsts/500571/): AADSTS500571 means a guest (B2B) user tried to sign in to an app in a tenant where their guest account is disabled. Microsoft's error reference doesn't list it, but a Microsoft troubleshooting article does. Their home account can be fine. It has low attack value. The resource tenant decides: leave it blocked, or re-enable the guest object. - [AADSTS501051 undefined](https://brambrinkmeier.com/entra/aadsts/501051/): AADSTS501051 means a client app asked for an access token to a web API whose enterprise app has "Assignment required" set to Yes, and the client holds no app role on that API. Microsoft's error reference doesn't list it, but its protected web API docs do. Low attack value. Assign an app role to the client; don't switch assignment off. - [AADSTS530002 undefined](https://brambrinkmeier.com/entra/aadsts/530002/): AADSTS530002 means a Conditional Access policy requires a compliant device and the device isn't compliant. Microsoft's error reference doesn't list it; a Viva Goals troubleshooting page does, for stored connections whose device fell out of compliance. Most user reports of compliant-device blocks quote the listed code 53000 instead. Usually benign drift out of compliance. - [AADSTS530003 undefined](https://brambrinkmeier.com/entra/aadsts/530003/): AADSTS530003 means a Conditional Access policy requires a managed device and the device asking for the token isn't one, or can't prove it. Microsoft's error reference doesn't list it. Users report it from the Azure CLI, Terraform and Cloud Shell. Usually it is a tool on an unmanaged machine. From a new device or IP, check whether the account is in the right hands. - [AADSTS530004 undefined](https://brambrinkmeier.com/entra/aadsts/530004/): AADSTS530004 means a guest user hit a device-based Conditional Access policy in the resource tenant, and that tenant doesn't trust device claims from the guest's home tenant. Microsoft's error reference doesn't list it, but a Microsoft troubleshooting article does. It is a B2B configuration gap with low attack value. The fix is the inbound trust settings in cross-tenant access. - [AADSTS530031 undefined](https://brambrinkmeier.com/entra/aadsts/530031/): AADSTS530031 means a policy in the tenant refused to issue the token. Microsoft's error reference doesn't list it and we found no Microsoft page that does; the wording comes from user reports. Users see it where Conditional Access blocks a sign-in, and the same phrase appears in some 53003 messages. Treat it like 53003: find the policy in the sign-in log. - [AADSTS530032 BlockedByConditionalAccessOnSecurityPolicy](https://brambrinkmeier.com/entra/aadsts/530032/): AADSTS530032 means a security policy set at the tenant level blocked the request, rather than a named Conditional Access policy. Microsoft's spray playbook lists it among events to review. Its sibling 530035 is the security defaults block, which legacy-auth sprays hit in tenants that use security defaults. - [AADSTS650052 undefined](https://brambrinkmeier.com/entra/aadsts/650052/): AADSTS650052 means an app asked for access to an API (a service) that has no service principal in your tenant, so consent or sign-in can't go ahead. It is a configuration gap with low attack value. Users report it most with the Microsoft Advertising API. An admin fixes it by granting admin consent, which Microsoft says adds the missing app to the tenant. - [AADSTS650056 undefined](https://brambrinkmeier.com/entra/aadsts/650056/): AADSTS650056 means Microsoft Entra ID refused a sign-in because the app is misconfigured: it doesn't list the permissions it asks for, an admin hasn't consented, or (for SAML) the issuer in the request doesn't match the app's identifier. It is a configuration error with low attack value. Fix the app's API permissions or SAML identifier, then grant consent. - [AADSTS700003 undefined](https://brambrinkmeier.com/entra/aadsts/700003/): AADSTS700003 means the device used for the sign-in no longer exists in the user's home tenant, usually because an admin or a cleanup job deleted it. Microsoft's error reference doesn't list it, but a Microsoft troubleshooting article does. Low attack value. The fix is to re-register or re-join the device; the audit log shows who deleted it. - [AADSTS700016 UnauthorizedClient_DoesNotMatchRequest](https://brambrinkmeier.com/entra/aadsts/700016/): AADSTS700016 means the client application ID in the request isn't found in the tenant the request was sent to. It is almost always a developer error: wrong client ID, wrong tenant, or an app never added to the tenant. Unknown client IDs or a deleted malicious app still trying to sign in are worth a look. - [AADSTS700024 undefined](https://brambrinkmeier.com/entra/aadsts/700024/): AADSTS700024 means an app signed in with a client assertion (a signed JWT, or a federated token from GitHub Actions or Azure DevOps) that was expired or not yet valid. Microsoft's error reference doesn't list it. The usual cause is a long CI/CD job that reuses its first token. Low attack value. Fetch a fresh token right before each use. - [AADSTS700051 undefined](https://brambrinkmeier.com/entra/aadsts/700051/): AADSTS700051 means an app asked the authorize endpoint for an access token directly (response_type=token, the implicit flow) but its app registration doesn't allow access tokens through the implicit flow. It is a configuration error with low attack value. Microsoft recommends against the implicit flow: move the app to the authorization code flow, or tick Access tokens if you can't yet. - [AADSTS700054 undefined](https://brambrinkmeier.com/entra/aadsts/700054/): AADSTS700054 means an app asked the authorize endpoint for an ID token (response_type id_token) but its app registration doesn't allow ID tokens through the implicit or hybrid flow. It is a configuration error with low attack value. Either tick ID tokens in the app registration, or better, move the app to the authorization code flow. - [AADSTS700081 undefined](https://brambrinkmeier.com/entra/aadsts/700081/): AADSTS700081 means the app tried to use a refresh token that is past its maximum lifetime. Users report it in single-page apps, where Microsoft caps refresh tokens at 24 hours. Microsoft's error reference doesn't list it. It is an expected part of the token lifecycle with low attack value. The app must send the user through sign-in again. - [AADSTS700082 ExpiredOrRevokedGrantInactiveToken](https://brambrinkmeier.com/entra/aadsts/700082/): AADSTS700082 means an app tried to use a refresh token that expired because nobody used it for too long. Microsoft calls it an expected part of the token lifecycle, so it has low attack value. One useful reading: a stolen refresh token that sat unused long enough fails here too. Hunt it in AADNonInteractiveUserSignInLogs with ResultType == "700082". - [AADSTS700211 undefined](https://brambrinkmeier.com/entra/aadsts/700211/): AADSTS700211 means a workload sent an external token whose issuer matches none of the federated identity credentials on the app or managed identity. Usually the credential has the wrong issuer URL (a typo, a trailing slash, the wrong cluster or Azure DevOps issuer), or no credential exists for that provider. It is a configuration error with low attack value. - [AADSTS700212 undefined](https://brambrinkmeier.com/entra/aadsts/700212/): AADSTS700212 means a workload sent an external token whose audience (aud claim) matches none of the federated identity credentials on the app or managed identity. Usually the token was requested for the wrong audience, for example a Kubernetes token not projected for api://AzureADTokenExchange. It is a configuration error with low attack value. - [AADSTS700213 undefined](https://brambrinkmeier.com/entra/aadsts/700213/): AADSTS700213 means a workload sent an external token whose subject matches none of the federated identity credentials on the app or managed identity. Typical causes: a GitHub job that uses an environment while the credential trusts a branch, a renamed repo or service account, or a typo. Microsoft says the same message is also used for issuer and audience mismatches. Low attack value. - [AADSTS700226 undefined](https://brambrinkmeier.com/entra/aadsts/700226/): AADSTS700226 means a federated identity credential whose issuer is a Microsoft Entra tenant was presented with a token that is not a managed identity token. Microsoft's error reference doesn't list it. The Entra ID issuer exists for the managed identity scenario only, so you can't federate one app registration to another this way. Low attack value. - [AADSTS750054 undefined](https://brambrinkmeier.com/entra/aadsts/750054/): AADSTS750054 means Microsoft Entra ID received a SAML sign-in request without a SAMLRequest or SAMLResponse in the URL query string. The app didn't use the SAML HTTP Redirect binding, or the user landed on Entra's SAML endpoint without a request, for example from a sign-on URL set for an app that only supports IdP-initiated SSO. A configuration error with low attack value. - [AADSTS900023 undefined](https://brambrinkmeier.com/entra/aadsts/900023/): AADSTS900023 means the tenant part of the sign-in URL isn't a valid tenant ID or domain name at all, for example 'undefined', a stray character or an empty setting. Microsoft's error reference doesn't list it. It is a configuration error with no attack value. Put the real tenant ID (a GUID) or a verified domain in the app's settings. - [AADSTS900144 undefined](https://brambrinkmeier.com/entra/aadsts/900144/): AADSTS900144 means an app sent a request to Microsoft Entra ID without a parameter the flow requires, such as password, client_id or grant_type. Microsoft calls it a developer error. The error names the missing parameter. It has low attack value; fix the request the app builds. Look for it by app and error text in all three sign-in tables. - [AADSTS900439 USGClientNotSupportedOnPublicEndpoint](https://brambrinkmeier.com/entra/aadsts/900439/): AADSTS900439 means an app registered in the Azure Government cloud tried to sign in through a public-cloud endpoint. Microsoft's error reference doesn't list it; a Microsoft troubleshooting article does. It also covers Microsoft 365 GCC High and DoD. It is a configuration error with no attack value. Point the app at login.microsoftonline.us. - [AADSTS900561 BadResourceRequestInvalidRequest](https://brambrinkmeier.com/entra/aadsts/900561/): AADSTS900561 means a Microsoft Entra endpoint that only takes POST requests received a GET. Microsoft says it can come from a developer error or from a user pressing the browser back button, and that it can be ignored. Users also report it with external MFA providers. It has low attack value. - [AADSTS901002 undefined](https://brambrinkmeier.com/entra/aadsts/901002/): AADSTS901002 means an app sent the v1.0 `resource` parameter to the Microsoft identity platform (v2.0) endpoint, which only takes `scope`. It is a configuration mismatch, often in third-party products set up with v2.0 URLs. Low attack value. Replace `resource=` with `scope=/.default`, or point the app at the v1.0 endpoints it was built for. - [AADSTS1002016 undefined](https://brambrinkmeier.com/entra/aadsts/1002016/): AADSTS1002016 means the client connected to Entra with TLS 1.0, TLS 1.1 or the 3DES cipher, which Entra no longer accepts. Microsoft doesn't list the code; a user reports it from an older .NET app. Microsoft retired legacy TLS for public Entra instances on 31 January 2022. It is a client configuration error with low attack value. Enable TLS 1.2. - [AADSTS1003031 undefined](https://brambrinkmeier.com/entra/aadsts/1003031/): AADSTS1003031 means admin consent failed because the app registration's required resource access is misconfigured. Microsoft doesn't list the code. Users report it on the tenant-wide /adminconsent URL, and a Microsoft employee says the app registration had no API permissions. It is a configuration error with low attack value. Add at least one API permission to the app. - [AADSTS5000211 undefined](https://brambrinkmeier.com/entra/aadsts/5000211/): AADSTS5000211 means a tenant restrictions v2 policy, added to the request by a corporate proxy, a managed Windows device or Global Secure Access, doesn't allow sign-in to the tenant the request was for. Microsoft's error reference doesn't list it; Microsoft's tenant restrictions v2 page shows it. It is a control doing its job. Use an allowed tenant or change the policy. - [AADSTS5000224 NotAllowedTenantBlockedTenantFraud](https://brambrinkmeier.com/entra/aadsts/5000224/): AADSTS5000224 means the Microsoft Entra tenant is blocked, and Microsoft's internal name points to fraud. Nobody can sign in to it. Microsoft documents no setting an admin can change to undo it: the error text says to contact Microsoft support. If you see it for a foreign tenant in your own logs, check which tenant and app your users were reaching. - [AADSTS5000225 undefined](https://brambrinkmeier.com/entra/aadsts/5000225/): AADSTS5000225 means Microsoft made the whole Microsoft Entra tenant inaccessible because it was inactive. Nobody can sign in to it, admins included. Microsoft's error reference doesn't list it; Microsoft's inactive-tenant page does. An admin can ask Microsoft to reactivate it within 20 days. After that the tenant is deleted and can't be recovered. - [AADSTS5000611 undefined](https://brambrinkmeier.com/entra/aadsts/5000611/): AADSTS5000611 means a Windows device tried to authenticate with the retired KDFv1 algorithm, which Microsoft Entra ID now blocks because of CVE-2021-33781. Microsoft's error reference doesn't list it, but a Microsoft deprecation notice does. It hits joined and hybrid joined devices on Windows builds without the July 2021 fix. Low attack value; update the device. - [AADSTS5002730 undefined](https://brambrinkmeier.com/entra/aadsts/5002730/): AADSTS5002730 means Entra rejected a JWT because its signing algorithm doesn't fit the key. Microsoft doesn't list the code. The MSAL.NET 4.60.1 release notes tie it to certificate sign-in with SHA2 and PSS signing and an Entra bug; the fix was to upgrade MSAL.NET. Users also report it for OBO with an HS256 token. Low attack value. - [AADSTS7000014 undefined](https://brambrinkmeier.com/entra/aadsts/7000014/): AADSTS7000014 means a device code token request carried a device_code value that Entra doesn't accept. In the lab it came back for a device_code that was never issued. Microsoft doesn't document the code; most likely the app sent a wrong, cut-off or made-up value, not an expired one (that is 70020, per user reports). It has low attack value. Fix how the app stores and sends the code. - [AADSTS7000110 undefined](https://brambrinkmeier.com/entra/aadsts/7000110/): AADSTS7000110 means an authorization code or refresh token was redeemed with a client ID other than the one it was issued to. Microsoft's error reference doesn't list it, but a Microsoft troubleshooting article does. Usually a config mix-up between two app registrations. Low attack value, but check unfamiliar IPs. Use the same client ID. - [AADSTS7000112 UnauthorizedClientApplicationDisabled](https://brambrinkmeier.com/entra/aadsts/7000112/): AADSTS7000112 means the app's service principal is disabled in the tenant, so Microsoft Entra ID won't issue tokens for it. Often an admin did it on purpose, for example to cut off a suspicious app. If it hits a Microsoft app such as Exchange Online, sign-ins break tenant-wide. Find who disabled it in the audit log and re-enable it only if that was a mistake. - [AADSTS7000215 Invalid client secret](https://brambrinkmeier.com/entra/aadsts/7000215/): 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. - [AADSTS7000216 undefined](https://brambrinkmeier.com/entra/aadsts/7000216/): AADSTS7000216 means a token request used grant_type=client_credentials but carried no client_secret, no client_assertion and no request parameter, so Entra had nothing to authenticate the app with. Microsoft's error reference doesn't list it. It is a developer error with low attack value. Send the app's secret or a signed client assertion. - [AADSTS7000218 undefined](https://brambrinkmeier.com/entra/aadsts/7000218/): 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. - [AADSTS7000222 InvalidClientSecretExpiredKeysProvided](https://brambrinkmeier.com/entra/aadsts/7000222/): AADSTS7000222 means an app or service principal sent a client secret that has passed its expiry date. It is almost always a missed rotation, not an attack. The security angle is secret hygiene: an expired secret still sitting in config files shows where secrets live. Microsoft recommends managed identities or certificates instead. Hunt it in AADServicePrincipalSignInLogs. - [AADSTS7002121 undefined](https://brambrinkmeier.com/entra/aadsts/7002121/): AADSTS7002121 means a workload presented an external token whose aud claim matches no federated identity credential on the app or managed identity. Microsoft's error reference doesn't list it. Usually the token was requested for the wrong audience instead of api://AzureADTokenExchange, or the case differs. It is a configuration error with low attack value. - [AADSTS7002138 undefined](https://brambrinkmeier.com/entra/aadsts/7002138/): AADSTS7002138 means the subject in a workload's external token matches a federated identity credential only when letter case is ignored. Since Microsoft's 2024 change, matching is case-sensitive, so the exchange fails. Typical case: a GitHub environment named Production while the credential says production. A configuration error with low attack value. - [AADSTS9002313 InvalidRequest](https://brambrinkmeier.com/entra/aadsts/9002313/): AADSTS9002313 means Microsoft Entra ID couldn't process a sign-in or token request because the request itself was malformed. It is a developer or integration error, not a credential failure. Microsoft's own advice is to capture a Fiddler trace and check how the request is built. It has low attack value. Find which app sends the bad requests and fix the request. - [AADSTS9002326 undefined](https://brambrinkmeier.com/entra/aadsts/9002326/): AADSTS9002326 means a browser sent a token request (it carried an Origin header) for an app that isn't registered as a single-page application. Microsoft's error reference doesn't list it. Typical causes: client credentials or a secret called from JavaScript, or an SPA whose redirect URI isn't the spa type. Low attack value. Fix the app registration or move the call to a backend. - [AADSTS9002327 undefined](https://brambrinkmeier.com/entra/aadsts/9002327/): AADSTS9002327 means a token request used an authorization code or refresh token issued to a single-page app, but the request had no Origin header, so it didn't come from a browser. Microsoft's error reference doesn't list it. A Q&A answerer links it to redemption from server-side code. Low attack value. Redeem in the browser, or register a Web platform. - [AADSTS9002331 undefined](https://brambrinkmeier.com/entra/aadsts/9002331/): AADSTS9002331 means the app is registered for personal Microsoft accounts only, but the sign-in didn't use the /consumers endpoint, or a work account tried to use it. Microsoft's error reference doesn't list it. Low attack value. Use the /consumers endpoint, or change the app's supported account types. - [AADSTS9002341 undefined](https://brambrinkmeier.com/entra/aadsts/9002341/): AADSTS9002341 means the user hasn't given permission for an app to use their Windows sign-in for single sign-on. Microsoft links it to the Windows SSO change in the European Economic Area, where Windows asks before reusing the Windows account in other apps. It has low attack value. Users accept the prompt; admins can auto-accept it on managed Windows 11 devices. - [AADSTS9002346 undefined](https://brambrinkmeier.com/entra/aadsts/9002346/): AADSTS9002346 means the app registration is set to personal Microsoft accounts only, and the request went to a tenant endpoint instead of /consumers. Microsoft's error reference doesn't list it. It is a configuration error with low attack value. Either call /consumers, or change Supported account types on the app registration. - [AADSTS9010010 undefined](https://brambrinkmeier.com/entra/aadsts/9010010/): 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. ## Microsoft Graph error codes - [All Microsoft Graph error codes](https://brambrinkmeier.com/entra/graph/): named Graph error codes with the exact message, HTTP status and the request that produces each one, measured in a lab tenant; Microsoft's current Graph error reference lists HTTP statuses only - [AccessDenied (HTTP 403)](https://brambrinkmeier.com/entra/graph/accessdenied/): AccessDenied is the third of Microsoft Graph's three permission-denied codes. It comes from services behind Graph that have their own authorisation layer, such as the Conditional Access policy endpoints, and its message says only that scopes are missing without naming them. The endpoint you called is what tells you which permission to add. - [Authentication_MSGraphPermissionMissing (HTTP 403)](https://brambrinkmeier.com/entra/graph/authentication-msgraphpermissionmissing/): Authentication_MSGraphPermissionMissing means your app called a Microsoft Graph endpoint without a permission that endpoint requires, and unlike the other 403 codes, the message names the permission. It is the most useful of Graph's three permission-denied codes because the fix is written into the response. - [Authorization_RequestDenied (HTTP 403)](https://brambrinkmeier.com/entra/graph/authorization-requestdenied/): Authorization_RequestDenied means the directory refused the request because the caller does not have enough privilege. The message is always the same seven words and names nothing, so the useful information is which endpoint you called and whether your caller is an app or a user. It also appears on reads, where it hides whether the object exists. - [BadRequest (HTTP 400)](https://brambrinkmeier.com/entra/graph/badrequest/): BadRequest, without the Request_ prefix, is what Microsoft Graph returns when the request fails before the directory ever sees it: a path segment that is not a Graph resource, or a body that is not valid JSON. The prefix is the tell. Request_BadRequest comes from the directory; a bare BadRequest comes from the layer in front of it. - [InvalidAuthenticationToken (HTTP 401)](https://brambrinkmeier.com/entra/graph/invalidauthenticationtoken/): InvalidAuthenticationToken means Microsoft Graph would not accept the access token in the Authorization header. The message after it says why: a missing header, a token for a different audience, a bad signature, or an expired token. It is always HTTP 401, and it is about the token itself, never about which permissions the token carries. - [Request_BadRequest (HTTP 400)](https://brambrinkmeier.com/entra/graph/request-badrequest/): Request_BadRequest means Microsoft Graph refused the request because of its content or shape: a missing required property, a value that conflicts with an existing object, or a method the target does not allow. The message names the specific problem. It is also the code returned with HTTP 405, which is worth knowing if you match on status codes. - [Request_ResourceNotFound (HTTP 404)](https://brambrinkmeier.com/entra/graph/request-resourcenotfound/): Request_ResourceNotFound means Microsoft Graph could not find the object the URL names. It covers a deleted object, a GUID that was never used, a value that is not a GUID at all, and a reference property pointing at something gone. A 404 also tells you something useful: your app does have read permission on that collection. - [Request_UnsupportedQuery (HTTP 400)](https://brambrinkmeier.com/entra/graph/request-unsupportedquery/): Request_UnsupportedQuery means Microsoft Graph understood the request but will not run the query in it. It covers a property that does not exist, an operator that needs the ConsistencyLevel header, a page size out of range, and $search without that header. The message names the exact problem, which makes this one of the more helpful Graph errors. ## Writeups - [All writeups](https://brambrinkmeier.com/writeups/): CTF writeups and security research (CTF and authorized-lab work only) - [401 Authorized Beta: HKCERT CTF 2026 writeup (three broken guards)](https://brambrinkmeier.com/writeups/401-authorized-beta-hkcert-1126/): Three bugs in one HKCERT CTF 2026 challenge: a token leaked on the denial path, a published 16-bit LCG and SQLi through PyMySQL %-substitution. - [Halloween Store: Intigriti CTF 1026 writeup (coupon guard business logic)](https://brambrinkmeier.com/writeups/halloween-store-intigriti-1026/): A coupon guard that remembers one code, not the set: alternate two public codes for 100% off. Intigriti CTF 1026 business-logic writeup. - [OAuth2 / OIDC discovery playbook for authorized testing](https://brambrinkmeier.com/writeups/oauth-oidc-discovery-playbook/): Read-only OAuth2 and OpenID Connect recon: discovery metadata, provider fingerprints, flow classification, PKCE and redirect_uri tests. - [Critter Gallery: Intigriti CTF 0926 writeup (base64-wrapped SQL injection)](https://brambrinkmeier.com/writeups/critter-gallery-intigriti-0926/): A base64-wrapped parameter, a blank-response error oracle and a union-based SQL injection into a hidden table. Intigriti CTF 0926. - [Bad Reception: Intigriti CTF 0826 writeup (DOMPurify, CSP and JSONP)](https://brambrinkmeier.com/writeups/bad-reception-intigriti-0826/): Stored XSS in a moderator bot: a DOMPurify ADD_TAGS gap, a script-src 'self' CSP and a same-origin JSONP gadget. Intigriti CTF 0826. - [Halloween Store, interactive edition](https://brambrinkmeier.com/writeups/halloween-store/interactive/): the coupon-guard model running in the browser - [Three broken guards, interactive edition](https://brambrinkmeier.com/writeups/401-authorized-beta/interactive/): three HKCERT CTF 2026 guards, each one playable in the browser ## KQL - [KQL for sign-in hunting](https://brambrinkmeier.com/kql/): reusable SigninLogs and AADNonInteractiveUserSignInLogs queries - [KQL lookup table for Entra sign-in error codes](https://brambrinkmeier.com/aadsts-kql-lookup/): copy-paste datatable of AADSTS codes with attack signal and page links - [AADSTS dataset (JSON, CC BY 4.0)](https://brambrinkmeier.com/aadsts.json): code, category, attack signal, MITRE, tables, related codes and URL ## Machine-readable data - [For AI agents and tools](https://brambrinkmeier.com/for-agents/): what the files below hold, what each field means, how fresh they are, how to cite them and where corrections go - [AADSTS code index (JSON)](https://brambrinkmeier.com/api/aadsts/index.json): every code page with its HTML, Markdown and JSON URLs and whether it is lab-reproduced; one record per code at /api/aadsts/{code}.json and a Markdown twin at /entra/aadsts/{code}.md - [Lab runs (JSON)](https://brambrinkmeier.com/lab-runs.json): every automated lab run with scenario, expected code, returned code and first message line, lab identifiers replaced with placeholders; append-only - [OpenAPI 3.1 description](https://brambrinkmeier.com/openapi.json): the static files above as an API description with examples from this build - [Full text of all code pages](https://brambrinkmeier.com/llms-full.txt): every code page's Markdown twin in one file - [Checksums](https://brambrinkmeier.com/checksums.json): SHA-256 of every machine-readable file in this build ## About - [How pages are written and checked](https://brambrinkmeier.com/methodology/) - [About the author](https://brambrinkmeier.com/about/) - [Entra sign-in log triage](https://brambrinkmeier.com/tools/signin-triage/): free in-browser tool with heuristic spray, brute-force and MFA-flood flags for a pasted sign-in export - [TenantLens](https://brambrinkmeier.com/tools/tenantlens/): free read-only Microsoft 365 / Entra posture scanner ## Optional - [Sitemap](https://brambrinkmeier.com/sitemap-index.xml) - [RSS feed](https://brambrinkmeier.com/rss.xml)