Entra consent declined

Severity mediumCloud & SaaSSingle eventstablecloud.identity.entra_consent_declined · v1.0.0

A user was shown an OAuth consent prompt for an application and DECLINED it (Entra sign-in error 65004 — "User declined to consent to access the app").

What it detects

A user was shown an OAuth consent prompt for an application and DECLINED it (Entra sign-in error 65004 — "User declined to consent to access the app").

A refusal is not a compromise, and on its own it is the system working. What makes it worth an alert is what it proves: **a consent-phishing attempt reached a real user in this tenant.** Somebody sent that link, and they did not send it to one person.

Consent phishing is the attack that survives every credential control an MSP deploys. The user is never asked for a password, so MFA is irrelevant; they are asked to approve an application, and approving it hands over a refresh token that keeps working after a password reset. The only reliable place to catch it early is the moment somebody notices and says no.

So the value of this finding is entirely in the pivot, and the rule is written for it: correlate on the application, and find out **who else saw the same app** — and, crucially, who consented.

MITRE ATT&CK mapping

  • T1528Steal Application Access Token· Credential Access
  • T1566.002Phishing: Spearphishing Link· Initial Access

False positives and triage

A user can decline a perfectly legitimate application — they clicked a link from a colleague, did not recognise the publisher, and backed out. That is common and it is the correct instinct.

Triage is about the app, not the user:

* **Resolve the appDisplayName and appId in the evidence.** A known vendor app the organisation is rolling out is a training matter. A generic or plausible-but-wrong name is the consent-phishing shape — the sample this rule was written against was called "Super Legit". * **Search the case for the same appId.** One decline means the campaign is live. What matters is whether any Consent to application. for that same app SUCCEEDED, because that account is the one that is compromised. * **Check the publisher's verification status and the requested scopes** in the tenant's enterprise-applications view before deciding.

If nothing else in the case references that application, this is a single user who avoided a trap — worth recording in the report as an attempted intrusion, and worth telling the customer about, but not an incident.

Note the corollary: this rule can only see the users who said NO. A tenant where nobody declined is not a tenant nobody targeted.

The rule

Declarative YAML read by the detection engine — data, never executed. Confidence 70%. Source: rules/cloud/entra_consent_declined.yaml, licensed under the Apache License 2.0.

id: cloud.identity.entra_consent_declined
version: 1.0.0
status: stable
severity: medium
confidence: 0.7
platforms: [application]
mitre_techniques: [T1528, T1566.002]
description: |
  A user was shown an OAuth consent prompt for an application and DECLINED it
  (Entra sign-in error `65004` — "User declined to consent to access the app").

  A refusal is not a compromise, and on its own it is the system working. What
  makes it worth an alert is what it proves: **a consent-phishing attempt reached
  a real user in this tenant.** Somebody sent that link, and they did not send it
  to one person.

  Consent phishing is the attack that survives every credential control an MSP
  deploys. The user is never asked for a password, so MFA is irrelevant; they are
  asked to approve an application, and approving it hands over a refresh token
  that keeps working after a password reset. The only reliable place to catch it
  early is the moment somebody notices and says no.

  So the value of this finding is entirely in the pivot, and the rule is written
  for it: correlate on the application, and find out **who else saw the same app**
  — and, crucially, who consented.
match:
  provider: AzureAD
  event_category: authentication
  raw_message_contains_any:
    - "65004"
    - "declined to consent"
correlation_keys: [user_name, source_ip]
false_positive_guidance: |
  A user can decline a perfectly legitimate application — they clicked a link
  from a colleague, did not recognise the publisher, and backed out. That is
  common and it is the correct instinct.

  Triage is about the app, not the user:

    * **Resolve the `appDisplayName` and `appId` in the evidence.** A known
      vendor app the organisation is rolling out is a training matter. A generic
      or plausible-but-wrong name is the consent-phishing shape — the sample this
      rule was written against was called "Super Legit".
    * **Search the case for the same `appId`.** One decline means the campaign is
      live. What matters is whether any `Consent to application.` for that same
      app SUCCEEDED, because that account is the one that is compromised.
    * **Check the publisher's verification status and the requested scopes** in
      the tenant's enterprise-applications view before deciding.

  If nothing else in the case references that application, this is a single user
  who avoided a trap — worth recording in the report as an attempted intrusion,
  and worth telling the customer about, but not an incident.

  Note the corollary: this rule can only see the users who said NO. A tenant
  where nobody declined is not a tenant nobody targeted.

Related detections

Run this rule on your own logs — offline

KIROSEC runs this rule and the rest of the library over Windows, Linux, macOS and cloud audit logs on the analyst's own machine. Every alert links to the events that raised it, and nothing leaves the device.

Browse all detections