{
  "schemaVersion": "1.0",
  "code": "51004",
  "name": "UserAccountNotInDirectory",
  "title": "AADSTS51004 fix: user account not in the directory",
  "url": "https://brambrinkmeier.com/entra/aadsts/51004/",
  "alternates": {
    "markdown": "https://brambrinkmeier.com/entra/aadsts/51004.md",
    "json": "https://brambrinkmeier.com/api/aadsts/51004.json",
    "html": "https://brambrinkmeier.com/entra/aadsts/51004/"
  },
  "description": "AADSTS51004: the user has no account in the tenant the app chose. Wrong tenant, missing guest invite or a federation ID mismatch. Low attack value.",
  "summary": "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.",
  "inMicrosoftReference": true,
  "unlistedChecked": null,
  "meaningText": "Microsoft's description:\n\n> **UserAccountNotInDirectory**: The user account doesn’t exist in the directory. An application likely chose the wrong tenant to sign into, and the currently logged in user was prevented from doing so since they did not exist in your tenant. If this user should be able to log in, add them as a guest. For further information, please visit add B2B users.\n\nThe user is known somewhere, but not in the tenant this sign-in went to. Microsoft's first guess is an app that sent the user to the wrong tenant.\n\nThe message users see reads like this example from Microsoft Q&A: *\"AADSTS51004: The user account {id} does not exist in the {tenant ID} directory. To sign into this application, the account must be added to the directory.\"* The tenant ID in the message tells you which directory was asked.\n\n### 51004 or 50034?\nThe wording is almost the same, so the code is what tells them apart. [50034](https://brambrinkmeier.com/entra/aadsts/50034/) (*UserAccountNotFound*) is the one Microsoft ties to a mistyped username. When a token request was sent for a username that doesn't exist in a lab tenant, Entra returned 50034, not 51004 (see the 50034 page). Microsoft's 51004 description talks about *\"the currently logged in user\"*. Our reading: 51004 tends to come after the user has already been identified, by their home tenant or by a federated identity provider, and Entra then can't find a matching account in the target tenant. 50034 is the plain \"no such username\" answer. Microsoft doesn't document the split in those words.\n\n[50020](https://brambrinkmeier.com/entra/aadsts/50020/) is a close neighbour too: an account from another identity provider that isn't a user or guest in the tenant. Both point to the same fix for outside users: add them as a guest.",
  "sections": [
    {
      "heading": "What does AADSTS51004 mean?",
      "text": "Microsoft's description:\n\n> **UserAccountNotInDirectory**: The user account doesn’t exist in the directory. An application likely chose the wrong tenant to sign into, and the currently logged in user was prevented from doing so since they did not exist in your tenant. If this user should be able to log in, add them as a guest. For further information, please visit add B2B users.\n\nThe user is known somewhere, but not in the tenant this sign-in went to. Microsoft's first guess is an app that sent the user to the wrong tenant.\n\nThe message users see reads like this example from Microsoft Q&A: *\"AADSTS51004: The user account {id} does not exist in the {tenant ID} directory. To sign into this application, the account must be added to the directory.\"* The tenant ID in the message tells you which directory was asked.\n\n### 51004 or 50034?\nThe wording is almost the same, so the code is what tells them apart. [50034](https://brambrinkmeier.com/entra/aadsts/50034/) (*UserAccountNotFound*) is the one Microsoft ties to a mistyped username. When a token request was sent for a username that doesn't exist in a lab tenant, Entra returned 50034, not 51004 (see the 50034 page). Microsoft's 51004 description talks about *\"the currently logged in user\"*. Our reading: 51004 tends to come after the user has already been identified, by their home tenant or by a federated identity provider, and Entra then can't find a matching account in the target tenant. 50034 is the plain \"no such username\" answer. Microsoft doesn't document the split in those words.\n\n[50020](https://brambrinkmeier.com/entra/aadsts/50020/) is a close neighbour too: an account from another identity provider that isn't a user or guest in the tenant. Both point to the same fix for outside users: add them as a guest."
    },
    {
      "heading": "Is it an attack?",
      "text": "Usually not. Our reading: the user has already proven who they are somewhere; they just aren't in this directory.\n\n| Pattern | Likely meaning |\n|---|---|\n| A user from another organisation opening your app, or Teams switching into your tenant | Wrong tenant or no guest account. Users report this often in Teams and other Microsoft 365 apps. Benign. Invite them as a guest if they need access. |\n| Users of a federated domain (Okta, Google Workspace, other SAML IdP) failing after the IdP login | The IdP authenticated them, but no Entra user matches what the IdP sent. Okta and Microsoft Q&A users report this. A provisioning or ImmutableId problem, not an attack. |\n| New hires failing while existing users work, on a federated domain | The account was created at the IdP but never provisioned to Entra ID. |\n| A former employee or a renamed user | Something still uses the old identity. Find and update it. |\n\nUnlike [50034](https://brambrinkmeier.com/entra/aadsts/50034/), there is no documented enumeration pattern for 51004. Our reading is that it has low value for an attacker testing usernames, because it follows a sign-in that already happened somewhere else. A burst of 51004 for many different users from one IP is still worth a look; the KQL below finds it."
    },
    {
      "heading": "How do I find it in my logs (KQL)?",
      "text": "Microsoft doesn't document which sign-in table 51004 lands in. Check where it lands:\n\n```kusto\nunion withsource=SourceTable SigninLogs, AADNonInteractiveUserSignInLogs\n| where TimeGenerated > ago(7d)\n| where ResultType == \"51004\"\n| summarize Rows = count(), Users = dcount(UserPrincipalName) by SourceTable\n```\n\nWhich apps send users to a tenant they're not in, and where the users come from:\n\n```kusto\nSigninLogs\n| where TimeGenerated > ago(30d)\n| where ResultType == \"51004\"\n| summarize Rows = count(),\n            Users = dcount(UserPrincipalName),\n            SampleUsers = make_set(UserPrincipalName, 10),\n            HomeTenants = make_set(HomeTenantId, 5),\n            Protocols = make_set(AuthenticationProtocol, 3)\n          by AppDisplayName, AppId\n| sort by Users desc\n```\n\nMany different accounts from one IP, the shape worth a second look (10 is a starting point; tune it to your tenant):\n\n```kusto\nSigninLogs\n| where TimeGenerated > ago(1d)\n| where ResultType == \"51004\"\n| summarize Accounts = dcount(UserPrincipalName),\n            Attempts = count(),\n            Sample = make_set(UserPrincipalName, 20)\n          by IPAddress\n| where Accounts >= 10\n| sort by Accounts desc\n```\n\nFor a user who doesn't exist in the tenant, which column holds the name is not documented. `UserPrincipalName` is a reasonable first guess; also check `SignInIdentifier`. A federated domain with many 51004 rows from your own egress IPs points at provisioning, not an attacker. `ResultType` is a **string** column, so compare it with `\"51004\"`."
    },
    {
      "heading": "How does Conditional Access affect it?",
      "text": "- Our reading: Conditional Access plays no part, because there is no user object in the tenant for a policy to match.\n- If the user is later added as a guest, the target tenant's Conditional Access policies apply to them from then on."
    },
    {
      "heading": "How do I fix AADSTS51004?",
      "text": "**For the user:** check that you are signed in with the right account. In Teams or a browser with several accounts, sign out and sign in again with the account your organisation gave you. If you are from another organisation, ask the app owner to invite you as a guest.\n\n**For developers:** check which tenant your app sends users to. Likely, but not documented: an app hard-wired to one tenant ID sends outside users there, and they fail. Use the tenant the user belongs to, or ask the tenant owner to invite them.\n\n**For admins:**\n1. External user who needs access: add them as a guest, as Microsoft's description says. In the Entra admin center (at least User Administrator): **Users** > **New user** > **Invite external user**. Microsoft notes *\"The guest user must then redeem their invitation to access resources.\"*\n2. Federated domain (Okta, Google Workspace, other SAML IdP): the user must exist in Entra ID first. Microsoft's federated sign-in docs for Windows devices state that *\"each Google Workspace user requires a matching account defined in Microsoft Entra ID\"*, and that Entra *\"searches for a matching user object in the tenant by using an attribute called ImmutableId\"*. The match is case-sensitive. Check the account exists and that its `OnPremisesImmutableId` matches what the IdP sends. Okta's KB describes this exact mismatch as a cause of 51004.\n3. New users failing only: check provisioning from the IdP actually created them in Entra ID.\n4. Renamed or removed user: find what still uses the old identity and update it."
    }
  ],
  "microsoftWording": {
    "text": "**UserAccountNotInDirectory**: The user account doesn’t exist in the directory. An application likely chose the wrong tenant to sign into, and the currently logged in user was prevented from doing so since they did not exist in your tenant. If this user should be able to log in, add them as a guest. For further information, please visit add B2B users.",
    "source": "Microsoft's error code reference, as quoted on the page",
    "sourceUrl": "https://learn.microsoft.com/en-us/entra/identity-platform/reference-error-codes"
  },
  "securityReading": {
    "category": {
      "id": "b2b-tenant",
      "label": "Guests and tenants"
    },
    "kind": {
      "id": "failure",
      "label": "Failure"
    },
    "attackSignal": {
      "level": "low",
      "label": "Low: usually configuration or user error"
    },
    "mitre": [],
    "tables": [],
    "isItAnAttack": "Usually not. Our reading: the user has already proven who they are somewhere; they just aren't in this directory.\n\n| Pattern | Likely meaning |\n|---|---|\n| A user from another organisation opening your app, or Teams switching into your tenant | Wrong tenant or no guest account. Users report this often in Teams and other Microsoft 365 apps. Benign. Invite them as a guest if they need access. |\n| Users of a federated domain (Okta, Google Workspace, other SAML IdP) failing after the IdP login | The IdP authenticated them, but no Entra user matches what the IdP sent. Okta and Microsoft Q&A users report this. A provisioning or ImmutableId problem, not an attack. |\n| New hires failing while existing users work, on a federated domain | The account was created at the IdP but never provisioned to Entra ID. |\n| A former employee or a renamed user | Something still uses the old identity. Find and update it. |\n\nUnlike [50034](https://brambrinkmeier.com/entra/aadsts/50034/), there is no documented enumeration pattern for 51004. Our reading is that it has low value for an attacker testing usernames, because it follows a sign-in that already happened somewhere else. A burst of 51004 for many different users from one IP is still worth a look; the KQL below finds it.",
    "conditionalAccess": {
      "heading": "How does Conditional Access affect it?",
      "text": "- Our reading: Conditional Access plays no part, because there is no user object in the tenant for a policy to match.\n- If the user is later added as a guest, the target tenant's Conditional Access policies apply to them from then on."
    }
  },
  "kql": [
    {
      "title": null,
      "leadIn": "Microsoft doesn't document which sign-in table 51004 lands in. Check where it lands:",
      "query": "union withsource=SourceTable SigninLogs, AADNonInteractiveUserSignInLogs\n| where TimeGenerated > ago(7d)\n| where ResultType == \"51004\"\n| summarize Rows = count(), Users = dcount(UserPrincipalName) by SourceTable"
    },
    {
      "title": null,
      "leadIn": "Which apps send users to a tenant they're not in, and where the users come from:",
      "query": "SigninLogs\n| where TimeGenerated > ago(30d)\n| where ResultType == \"51004\"\n| summarize Rows = count(),\n            Users = dcount(UserPrincipalName),\n            SampleUsers = make_set(UserPrincipalName, 10),\n            HomeTenants = make_set(HomeTenantId, 5),\n            Protocols = make_set(AuthenticationProtocol, 3)\n          by AppDisplayName, AppId\n| sort by Users desc"
    },
    {
      "title": null,
      "leadIn": "Many different accounts from one IP, the shape worth a second look (10 is a starting point; tune it to your tenant):",
      "query": "SigninLogs\n| where TimeGenerated > ago(1d)\n| where ResultType == \"51004\"\n| summarize Accounts = dcount(UserPrincipalName),\n            Attempts = count(),\n            Sample = make_set(UserPrincipalName, 20)\n          by IPAddress\n| where Accounts >= 10\n| sort by Accounts desc"
    }
  ],
  "kqlSectionText": "Microsoft doesn't document which sign-in table 51004 lands in. Check where it lands:\n\n```kusto\nunion withsource=SourceTable SigninLogs, AADNonInteractiveUserSignInLogs\n| where TimeGenerated > ago(7d)\n| where ResultType == \"51004\"\n| summarize Rows = count(), Users = dcount(UserPrincipalName) by SourceTable\n```\n\nWhich apps send users to a tenant they're not in, and where the users come from:\n\n```kusto\nSigninLogs\n| where TimeGenerated > ago(30d)\n| where ResultType == \"51004\"\n| summarize Rows = count(),\n            Users = dcount(UserPrincipalName),\n            SampleUsers = make_set(UserPrincipalName, 10),\n            HomeTenants = make_set(HomeTenantId, 5),\n            Protocols = make_set(AuthenticationProtocol, 3)\n          by AppDisplayName, AppId\n| sort by Users desc\n```\n\nMany different accounts from one IP, the shape worth a second look (10 is a starting point; tune it to your tenant):\n\n```kusto\nSigninLogs\n| where TimeGenerated > ago(1d)\n| where ResultType == \"51004\"\n| summarize Accounts = dcount(UserPrincipalName),\n            Attempts = count(),\n            Sample = make_set(UserPrincipalName, 20)\n          by IPAddress\n| where Accounts >= 10\n| sort by Accounts desc\n```\n\nFor a user who doesn't exist in the tenant, which column holds the name is not documented. `UserPrincipalName` is a reasonable first guess; also check `SignInIdentifier`. A federated domain with many 51004 rows from your own egress IPs points at provisioning, not an attacker. `ResultType` is a **string** column, so compare it with `\"51004\"`.",
  "fix": {
    "short": "User: check you are signed in with the right account and opening your organisation's link, not another tenant's. Admin: if the user should have access, invite them as a guest (B2B). With federation, check the user exists in Entra ID and that their ImmutableId matches what the IdP sends.",
    "steps": "**For the user:** check that you are signed in with the right account. In Teams or a browser with several accounts, sign out and sign in again with the account your organisation gave you. If you are from another organisation, ask the app owner to invite you as a guest.\n\n**For developers:** check which tenant your app sends users to. Likely, but not documented: an app hard-wired to one tenant ID sends outside users there, and they fail. Use the tenant the user belongs to, or ask the tenant owner to invite them.\n\n**For admins:**\n1. External user who needs access: add them as a guest, as Microsoft's description says. In the Entra admin center (at least User Administrator): **Users** > **New user** > **Invite external user**. Microsoft notes *\"The guest user must then redeem their invitation to access resources.\"*\n2. Federated domain (Okta, Google Workspace, other SAML IdP): the user must exist in Entra ID first. Microsoft's federated sign-in docs for Windows devices state that *\"each Google Workspace user requires a matching account defined in Microsoft Entra ID\"*, and that Entra *\"searches for a matching user object in the tenant by using an attribute called ImmutableId\"*. The match is case-sensitive. Check the account exists and that its `OnPremisesImmutableId` matches what the IdP sends. Okta's KB describes this exact mismatch as a cause of 51004.\n3. New users failing only: check provisioning from the IdP actually created them in Entra ID.\n4. Renamed or removed user: find what still uses the old identity and update it."
  },
  "labReproduced": null,
  "labSectionText": null,
  "labRuns": [],
  "verification": "documentation",
  "related": [
    "50034",
    "50020",
    "90072",
    "700016"
  ],
  "coveredBy": [],
  "sources": [
    {
      "title": "Microsoft Entra authentication and authorization error codes",
      "url": "https://learn.microsoft.com/en-us/entra/identity-platform/reference-error-codes"
    },
    {
      "title": "Add Microsoft Entra B2B collaboration users in the Microsoft Entra admin center",
      "url": "https://learn.microsoft.com/en-us/entra/external-id/add-users-administrator"
    },
    {
      "title": "Configure federated sign-in for Windows devices (identity matching in Microsoft Entra ID)",
      "url": "https://learn.microsoft.com/en-us/education/windows/federated-sign-in#identity-matching-in-microsoft-entra-id"
    },
    {
      "title": "Configure federation between Google Workspace and Microsoft Entra ID",
      "url": "https://learn.microsoft.com/en-us/education/windows/configure-aad-google-trust"
    },
    {
      "title": "SigninLogs table reference (Azure Monitor)",
      "url": "https://learn.microsoft.com/en-us/azure/azure-monitor/reference/tables/signinlogs"
    },
    {
      "title": "Microsoft Q&A: AADSTS51004 the user account does not exist in the directory (user report)",
      "url": "https://learn.microsoft.com/en-us/answers/questions/1581749/aadsts51004-the-user-account-it-does-not-exist-in"
    },
    {
      "title": "Okta KB: AADSTS51004 during Microsoft Office 365 single sign-on (vendor KB)",
      "url": "https://support.okta.com/help/s/article/error-during-microsoft-office-365-single-sign-on-aadsts51004-the-user-account-does-not-exist-in-the-directory"
    },
    {
      "title": "Windows Report: AADSTS51004 error on Teams (user reports)",
      "url": "https://windowsreport.com/aadsts51004-teams-error/"
    }
  ],
  "published": "2026-11-01",
  "lastUpdated": "2026-11-01",
  "lastVerified": null,
  "license": "CC BY 4.0",
  "licenseUrl": "https://creativecommons.org/licenses/by/4.0/",
  "licenseNote": "CC BY 4.0 covers the author's own text and classification fields. Quoted Microsoft error wording belongs to Microsoft, is quoted with its source and can change.",
  "attribution": "Bram Brinkmeier, \"AADSTS51004 fix: user account not in the directory\", https://brambrinkmeier.com/entra/aadsts/51004/ (CC BY 4.0)",
  "microsoftErrorLookup": "https://login.microsoftonline.com/error?code=51004"
}
