§ AC

Device Code Phishing and Persistent OAuth Consent: 2026 APT Tradecraft in Entra ID

Throughout 2025 and into 2026, the cluster of activity Microsoft tracks as Storm-2372, along with APT29-aligned operators (Midnight Blizzard / Cozy Bear), has shifted decisively away from password-spray and adversary-in-the-middle MFA capture toward two cheaper, quieter primitives: the OAuth 2.0 device authorization grant (RFC 8628) and durable application consent in Entra ID. Both abuse documented protocol behavior rather than software vulnerabilities, both survive password resets, and both produce telemetry that looks indistinguishable from a legitimate user signing into Teams on a TV until you know what to filter for. For tenants that still treat “MFA enforced” as the end of the identity conversation, this is the gap.

Why this tradecraft, why now

The device code flow exists because input-constrained devices — smart TVs, IoT controllers, CLI tools on headless servers — cannot reasonably host a browser. The user is shown a short code and a URL, authenticates on a separate device, and the original client polls the token endpoint until a token is issued. Nothing about that exchange requires the polling client and the authenticating user to be on the same network, the same continent, or even the same organization. Entra ID issues the token to whichever client is polling with the matching device_code.

The operational appeal for an APT is straightforward. There is no credential to phish, no MFA prompt to intercept, no fake login page to host and burn. The victim sees a real microsoft.com URL, a real Microsoft sign-in, and a real consent screen. Conditional Access policies that key on “unmanaged device” or “untrusted location” frequently evaluate the user’s browser session, not the polling client that ultimately receives the token. Refresh tokens issued to public clients then provide weeks of access, and where the operator can also induce consent to a multi-tenant OAuth application — particularly one requesting Mail.Read, Files.Read.All, or offline_access against Microsoft Graph — the persistence outlives any password rotation, MFA re-enrollment, or session revocation that does not also touch the service principal.

What changed in 2026

Three shifts are worth calling out for SOC leads.

Consent laundering through compromised partner tenants. Rather than registering a fresh malicious multi-tenant app, operators are compromising a low-value tenant, registering the OAuth app there, and using the publisher-verified appearance of that tenant to request consent in the target. Defenders looking for newly registered apps in their own directory will not see it; the service principal materializes only when a user grants consent.

Long-tail refresh token abuse. Public-client refresh tokens in Entra ID can be redeemed for new access tokens well past the initial intrusion window, and family-of-client-IDs (FOCI) behavior allows a refresh token issued to one Microsoft first-party client to be redeemed for tokens scoped to another. Operators are deliberately seeding FOCI-eligible clients to retain access even when one client family is revoked.

Targeting of M365 Copilot and Graph connectors. Where tenants have enabled Copilot, Graph-scoped access is a force multiplier — a single compromised identity with Files.Read.All plus Copilot grounding can be queried in natural language across SharePoint, OneDrive, and Exchange Online without ever touching the file system. Treat Copilot semantic index access as a sensitive data path, not a productivity feature.

Detection: where the signal actually lives

The Entra ID sign-in logs distinguish the device code grant explicitly. Hunt on AADSignInEventsBeta (or the equivalent in your SIEM ingestion of SigninLogs) for AuthenticationProtocol == "deviceCode" and pivot on the following tells:

  • Sign-ins where the user originates from a corporate egress but the resulting token is redeemed by a client IP in a hosting ASN (DigitalOcean, Hetzner, M247, residential proxy ranges) within minutes.
  • Device code authentications against client IDs the tenant has no operational reason to use — Microsoft Azure CLI, Microsoft Azure PowerShell, or Visual Studio Code from accounts that do not develop.
  • Consent grants to multi-tenant applications where the publisher tenant has fewer than ~50 service principals registered globally, or where verifiedPublisher is null and the requested permissions include offline_access plus any *.Read.All Graph scope.
  • Token issuance events with ResourceDisplayName == "Microsoft Graph" from a service principal that was first consented to within the last 30 days and has zero interactive sign-ins from any other identity.

Enable MicrosoftGraphActivityLogs (GA in 2024, broadly deployed by 2026) and join on SignInActivityId. The Graph activity log is where exfiltration actually appears — the sign-in log only tells you a token was issued.

Remediation that actually breaks persistence

Revoking sessions is not enough. The full sequence:

  1. Disable the user account and run Revoke-MgUserSignInSession, then rotate the credential.
  2. Identify every service principal the user consented to in the last 90 days via the audit log Consent to application events. For each, evaluate whether other users in the tenant also granted consent.
  3. Remove the application’s user assignments and, where the app is not business-critical, delete the service principal outright. Deleting the app registration in the publisher tenant does not remove the service principal in yours.
  4. Where FOCI clients are implicated, treat all family members as compromised and revoke refresh tokens across the family, not just the originating client ID.
  5. Restrict the device code flow via Conditional Access (authenticationFlows filter, transferMethod = deviceCodeFlow) to a named group of users with documented need. For everyone else, block it.
  6. Move user consent for applications to admin-approval workflows. The operational cost is real; the alternative is worse.

800-53 mapping

Control Application
IA-2, IA-5, IA-8 Phishing-resistant authenticators (FIDO2, certificate-based) for the populations operators target — executives, IT, finance
AC-2(12), AC-6(9) Account monitoring for atypical usage; least privilege on Graph-scoped delegated permissions
AC-4, SC-7 Conditional Access as policy enforcement, including authentication flow restrictions
AU-2, AU-6, AU-12 Ingestion of SigninLogs, AuditLogs, and MicrosoftGraphActivityLogs with correlation, not just retention
CA-7 Continuous monitoring of consented applications and service principal inventory
CM-7 Disable the device code flow as a default-deny capability
SI-4 Anomaly detection on token redemption locations and refresh token reuse
RA-5, SR-3 Risk-rate third-party multi-tenant applications as a supply chain surface

Bottom line

Device code phishing is not novel — it has been documented since at least 2021 — but the 2026 variant has matured into a quiet, durable persistence mechanism that bypasses most of the controls organizations actually invested in. Treat the consented service principal, not the user account, as the primary unit of compromise. If your incident response runbook ends at password reset and session revocation, it ends too early.