{
  "schemaVersion": "1.0",
  "code": "65004",
  "name": "UserDeclinedConsent",
  "title": "AADSTS65004: User declined to consent to access the app",
  "url": "https://brambrinkmeier.com/entra/aadsts/65004/",
  "alternates": {
    "markdown": "https://brambrinkmeier.com/entra/aadsts/65004.md",
    "json": "https://brambrinkmeier.com/api/aadsts/65004.json",
    "html": "https://brambrinkmeier.com/entra/aadsts/65004/"
  },
  "description": "AADSTS65004: user declined to consent to access the app. Expected after an admin consent request, or the user said no. Fixes and KQL.",
  "summary": "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.",
  "inMicrosoftReference": true,
  "unlistedChecked": null,
  "meaningText": "Microsoft's description:\n\n> **UserDeclinedConsent**: User declined to consent to access the app. Have the user retry the sign-in and consent to the app\n\nThe app sent the user to a consent prompt and came back without a grant. In the OAuth authorization code flow, Microsoft lists the matching protocol error as `access_denied`, *\"Resource owner denied consent\"*, and says *\"The client application can notify the user that it can't continue unless the user consents.\"*",
  "sections": [
    {
      "heading": "What does AADSTS65004 mean?",
      "text": "Microsoft's description:\n\n> **UserDeclinedConsent**: User declined to consent to access the app. Have the user retry the sign-in and consent to the app\n\nThe app sent the user to a consent prompt and came back without a grant. In the OAuth authorization code flow, Microsoft lists the matching protocol error as `access_denied`, *\"Resource owner denied consent\"*, and says *\"The client application can notify the user that it can't continue unless the user consents.\"*"
    },
    {
      "heading": "What is the quick fix?",
      "text": "First work out which of two cases you are in:\n\n- **The user just submitted an admin consent request.** Microsoft documents this as expected: *\"After a user submits an admin consent approval for an application, another dialog appears with a **Back to app** button. When the user selects the button, Microsoft Entra ID sends an AADSTS65004 error to the redirect URI specified in the original authentication request. This error is an expected part of the admin consent workflow.\"* Wait for the reviewer. After approval, *\"the user needs to begin a new authentication process with the application.\"*\n- **The user said no at the prompt.** If the app is one you trust, have the user sign in again and accept, as Microsoft's description says.\n\nIf the user can't accept because the permissions need an admin, that is a different code: [90094](https://brambrinkmeier.com/entra/aadsts/90094/), or [90095](https://brambrinkmeier.com/entra/aadsts/90095/) with the admin consent workflow on."
    },
    {
      "heading": "Is it an attack?",
      "text": "No, not on its own. 65004 is the absence of a grant. The risky moment in consent phishing is a grant that does happen. Microsoft describes the attack: the attacker *\"tricks an end user into granting that application consent\"*, and after that the app *\"has account-level access to data without the need for an organizational account.\"* The [consent phishing guide](https://brambrinkmeier.com/guides/investigate-consent-phishing-entra-id/) covers that investigation.\n\n| Pattern | Likely meaning |\n|---|---|\n| 65004 shortly after [90095](https://brambrinkmeier.com/entra/aadsts/90095/) for the same user and app | The admin consent workflow as documented. Benign. |\n| 65004 for a known app, then a success after the user retried | The user cancelled once, then accepted. Benign. |\n| 65004 for an app ID you don't recognise, from several users | Users were sent to an app nobody approved, and some said no. Check whether others said yes. |\n\nThe second and third rows are reasoning from what the code means, not Microsoft detections."
    },
    {
      "heading": "How do I find it in my logs (KQL)?",
      "text": "65004 per app, with how many of those users also hit 90095 (the admin consent workflow) for the same app:\n\n```kusto\nlet window = 7d;\nlet declines =\n    SigninLogs\n    | where TimeGenerated > ago(window)\n    | where ResultType == \"65004\"\n    | project DeclineTime = TimeGenerated, UserPrincipalName, AppId, AppDisplayName, IPAddress;\nlet requests =\n    SigninLogs\n    | where TimeGenerated > ago(window)\n    | where ResultType == \"90095\"\n    | distinct UserPrincipalName, AppId\n    | extend RequestedAdminConsent = true;\ndeclines\n| join kind=leftouter requests on UserPrincipalName, AppId\n| summarize Declines = count(),\n            Users = dcount(UserPrincipalName),\n            UsersWithAdminRequest = dcountif(UserPrincipalName, RequestedAdminConsent == true),\n            FirstSeen = min(DeclineTime)\n          by AppId, AppDisplayName\n| sort by Users desc\n```\n\nApps where `Users` is much larger than `UsersWithAdminRequest` are the ones where people said no at the prompt. For an app you don't know, check the [65001 page](https://brambrinkmeier.com/entra/aadsts/65001/) query to see whether anyone later consented.\n\n`ResultType` is a **string** column, so compare it with `\"65004\"`, not `65004`."
    },
    {
      "heading": "How do Conditional Access and consent settings affect it?",
      "text": "- 65004 isn't caused by Conditional Access. It is a consent decision.\n- With user consent restricted, a user who can't grant the permissions gets [90094](https://brambrinkmeier.com/entra/aadsts/90094/). With the admin consent workflow on, they get [90095](https://brambrinkmeier.com/entra/aadsts/90095/), can send a request, and the Back to app step then returns 65004.\n- Microsoft notes that users can't grant consent to apps Microsoft detects as risky. Admins can, but Microsoft says they *\"should evaluate the app carefully and proceed with caution.\"*"
    },
    {
      "heading": "How do I fix AADSTS65004?",
      "text": "**For the user:** if you just sent an admin consent request, wait for approval and then sign in to the app again. If you cancelled by mistake and trust the app, sign in again and accept.\n\n**For developers:** handle `access_denied` by telling the user the app can't continue without consent, as Microsoft recommends.\n\n**For admins:**\n1. Check whether the 65004 followed a 90095 for the same user and app. If yes, review the pending request.\n2. If the app is approved for the organization, grant admin consent so users don't see the prompt.\n3. For an app you don't recognise, find who published it and what it asks for before anyone consents."
    }
  ],
  "microsoftWording": {
    "text": "**UserDeclinedConsent**: User declined to consent to access the app. Have the user retry the sign-in and consent to the app",
    "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": "consent",
      "label": "Consent and app permissions"
    },
    "kind": {
      "id": "failure",
      "label": "Failure"
    },
    "attackSignal": {
      "level": "low",
      "label": "Low: usually configuration or user error"
    },
    "mitre": [],
    "tables": [
      "SigninLogs"
    ],
    "isItAnAttack": "No, not on its own. 65004 is the absence of a grant. The risky moment in consent phishing is a grant that does happen. Microsoft describes the attack: the attacker *\"tricks an end user into granting that application consent\"*, and after that the app *\"has account-level access to data without the need for an organizational account.\"* The [consent phishing guide](https://brambrinkmeier.com/guides/investigate-consent-phishing-entra-id/) covers that investigation.\n\n| Pattern | Likely meaning |\n|---|---|\n| 65004 shortly after [90095](https://brambrinkmeier.com/entra/aadsts/90095/) for the same user and app | The admin consent workflow as documented. Benign. |\n| 65004 for a known app, then a success after the user retried | The user cancelled once, then accepted. Benign. |\n| 65004 for an app ID you don't recognise, from several users | Users were sent to an app nobody approved, and some said no. Check whether others said yes. |\n\nThe second and third rows are reasoning from what the code means, not Microsoft detections.",
    "conditionalAccess": {
      "heading": "How do Conditional Access and consent settings affect it?",
      "text": "- 65004 isn't caused by Conditional Access. It is a consent decision.\n- With user consent restricted, a user who can't grant the permissions gets [90094](https://brambrinkmeier.com/entra/aadsts/90094/). With the admin consent workflow on, they get [90095](https://brambrinkmeier.com/entra/aadsts/90095/), can send a request, and the Back to app step then returns 65004.\n- Microsoft notes that users can't grant consent to apps Microsoft detects as risky. Admins can, but Microsoft says they *\"should evaluate the app carefully and proceed with caution.\"*"
    }
  },
  "kql": [
    {
      "title": null,
      "leadIn": "65004 per app, with how many of those users also hit 90095 (the admin consent workflow) for the same app:",
      "query": "let window = 7d;\nlet declines =\n    SigninLogs\n    | where TimeGenerated > ago(window)\n    | where ResultType == \"65004\"\n    | project DeclineTime = TimeGenerated, UserPrincipalName, AppId, AppDisplayName, IPAddress;\nlet requests =\n    SigninLogs\n    | where TimeGenerated > ago(window)\n    | where ResultType == \"90095\"\n    | distinct UserPrincipalName, AppId\n    | extend RequestedAdminConsent = true;\ndeclines\n| join kind=leftouter requests on UserPrincipalName, AppId\n| summarize Declines = count(),\n            Users = dcount(UserPrincipalName),\n            UsersWithAdminRequest = dcountif(UserPrincipalName, RequestedAdminConsent == true),\n            FirstSeen = min(DeclineTime)\n          by AppId, AppDisplayName\n| sort by Users desc"
    }
  ],
  "kqlSectionText": "65004 per app, with how many of those users also hit 90095 (the admin consent workflow) for the same app:\n\n```kusto\nlet window = 7d;\nlet declines =\n    SigninLogs\n    | where TimeGenerated > ago(window)\n    | where ResultType == \"65004\"\n    | project DeclineTime = TimeGenerated, UserPrincipalName, AppId, AppDisplayName, IPAddress;\nlet requests =\n    SigninLogs\n    | where TimeGenerated > ago(window)\n    | where ResultType == \"90095\"\n    | distinct UserPrincipalName, AppId\n    | extend RequestedAdminConsent = true;\ndeclines\n| join kind=leftouter requests on UserPrincipalName, AppId\n| summarize Declines = count(),\n            Users = dcount(UserPrincipalName),\n            UsersWithAdminRequest = dcountif(UserPrincipalName, RequestedAdminConsent == true),\n            FirstSeen = min(DeclineTime)\n          by AppId, AppDisplayName\n| sort by Users desc\n```\n\nApps where `Users` is much larger than `UsersWithAdminRequest` are the ones where people said no at the prompt. For an app you don't know, check the [65001 page](https://brambrinkmeier.com/entra/aadsts/65001/) query to see whether anyone later consented.\n\n`ResultType` is a **string** column, so compare it with `\"65004\"`, not `65004`.",
  "fix": {
    "short": "User: if you just sent an admin consent request, wait for approval, then sign in again. If you cancelled by mistake and trust the app, sign in again and accept. Admin: check for a 90095 from the same user and app and review the pending request, or grant admin consent to an approved app.",
    "steps": "**For the user:** if you just sent an admin consent request, wait for approval and then sign in to the app again. If you cancelled by mistake and trust the app, sign in again and accept.\n\n**For developers:** handle `access_denied` by telling the user the app can't continue without consent, as Microsoft recommends.\n\n**For admins:**\n1. Check whether the 65004 followed a 90095 for the same user and app. If yes, review the pending request.\n2. If the app is approved for the organization, grant admin consent so users don't see the prompt.\n3. For an app you don't recognise, find who published it and what it asks for before anyone consents."
  },
  "labReproduced": null,
  "labSectionText": null,
  "labRuns": [],
  "verification": "documentation",
  "related": [
    "65001",
    "90095",
    "90094",
    "650056"
  ],
  "coveredBy": [
    {
      "title": "How to investigate consent phishing (illicit consent grants) in Entra ID",
      "url": "https://brambrinkmeier.com/guides/investigate-consent-phishing-entra-id/"
    }
  ],
  "sources": [
    {
      "title": "Microsoft Entra authentication and authorization error codes",
      "url": "https://learn.microsoft.com/en-us/entra/identity-platform/reference-error-codes"
    },
    {
      "title": "Unexpected error when performing consent to an application",
      "url": "https://learn.microsoft.com/en-us/entra/identity/enterprise-apps/application-sign-in-unexpected-user-consent-error"
    },
    {
      "title": "Microsoft identity platform and OAuth 2.0 authorization code flow",
      "url": "https://learn.microsoft.com/en-us/entra/identity-platform/v2-oauth2-auth-code-flow"
    },
    {
      "title": "Detect and remediate illicit consent grants",
      "url": "https://learn.microsoft.com/en-us/defender-office-365/detect-and-remediate-illicit-consent-grants"
    },
    {
      "title": "SigninLogs table reference (Azure Monitor)",
      "url": "https://learn.microsoft.com/en-us/azure/azure-monitor/reference/tables/signinlogs"
    }
  ],
  "published": "2026-10-25",
  "lastUpdated": "2026-10-25",
  "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, \"AADSTS65004: User declined to consent to access the app\", https://brambrinkmeier.com/entra/aadsts/65004/ (CC BY 4.0)",
  "microsoftErrorLookup": "https://login.microsoftonline.com/error?code=65004"
}
