Device Code Phishing: A Low-Noise, High-Impact Threat That Demands Your Attention
Introduction
In the ever-evolving landscape of cloud threats, not every adversary kicks down the front door. Some simply wait for you to open a side entrance - one designed for ease, speed, and seemingly harmless interactions. One of the most understated yet increasingly abused mechanisms is the OAuth 2.0 Device Code Flow.
Originally introduced to support input-constrained devices such as smart TVs, printers, and IoT systems, this authentication method has quietly become a high-value target for threat actors. Why? Because it provides legitimate access tokens via a flow that often lacks visibility, oversight, and adequate control mechanisms.
If you’re responsible for defending Microsoft environments, it’s time to examine the risks, detection patterns, and response strategies for device code phishing.
OAuth Device Code Flow
Threat Landscape: How Attackers Abuse Device Code Flow
The OAuth 2.0 Device Authorization Grant (RFC 8628) allows a device to obtain an access token by asking the user to authenticate via a separate device. This interaction typically involves:
- A device_code and user_code pair
- A login URL (https://microsoft.com/devicelogin)
- Polling of the token endpoint until the user completes authentication
This legitimate flow becomes a vector for abuse when:
- An attacker requests a device code using their own client application.
- The attacker sends the user code and login URL to the victim via phishing (e.g., fake Teams meeting invite). In the first example is social engineering used to send a fake Teams meeting invite to the victim. The Teams information “Join the meeting” is redirecting to the device code login page and the ID is the device code. The second example is faking a sharing of a document.
3. The victim, unaware, completes the authentication on the real Microsoft login page.
4. Upon successful authentication, the access token and refresh token are issued to the attacker’s app, not the victim’s device.
Once obtained, the attacker can:
- Access Microsoft Graph API, Outlook, Teams, OneDrive, SharePoint
- Search for sensitive data (e.g., credentials, access links)
- Create inbox rules, delete messages, or exfiltrate documents
- Use Primary Refresh Tokens (PRTs) to register persistent devices
Case in Point: Threat actor Storm-2372 has been actively exploiting this method since 2024, leveraging legitimate Microsoft infrastructure to gain access across sectors including government, energy, education, and IT services.
Technical Visibility & Detection (with KQL)
Monitoring deviceCode authentications requires targeted hunting. Here are key queries and insights to surface abnormal activity:
1. Successful Device Code Sign-ins
SigninLogs
| where TimeGenerated > ago(7d)
| where AuthenticationProtocol == "deviceCode"
| where ResultType == 0 // Successful sign-ins
| project TimeGenerated, UserPrincipalName, AppDisplayName, AppId, IPAddress,
Location, DeviceDetail, RiskLevelDuringSignIn, CorrelationId
Purpose: Establish a baseline or find any usage.
2. Timechart of Device Code Authentications by App
SigninLogs
| where TimeGenerated > ago(90d)
| where AuthenticationProtocol == "deviceCode"
| summarize count() by bin(TimeGenerated, 1d), AppDisplayName
| render timechart
Purpose: Trend analysis and app monitoring over time
3. Top Users by App & Resource
SigninLogs
| where TimeGenerated > ago(90d)
| where AuthenticationProtocol == "deviceCode"
| summarize count() by UserPrincipalName, AppDisplayName, ResourceDisplayName
Purpose: Identify legitimate use and anomalies in volume or application
4. Join Device Code Sign-ins with Device Registration Service Events
SigninLogs
| where TimeGenerated > ago(90d)
| where AuthenticationProtocol == "deviceCode"
| where ResourceDisplayName == "Device Registration Service"
| join AADNonInteractiveUserSignInLogs on $left.CorrelationId == $right.CorrelationId
| extend UserAgentNON = UserAgent1
| project UserPrincipalName, AppDisplayName, ClientAppUsed, ResourceDisplayName, UserAgent, UserAgentNON, IncomingTokenType, IncomingTokenType1
Purpose: Correlate device registrations with potentially malicious sessions
5. Unmanaged/Non-Compliant Device
SigninLogs
| where TimeGenerated > ago(7d)
| where ResultType == 0
| where AuthenticationProtocol == "deviceCode"
| where isempty(DeviceDetail.deviceId) or DeviceDetail.isManaged == false or
DeviceDetail.isCompliant == false
| project TimeGenerated, UserPrincipalName, AppDisplayName, AppId, IPAddress,
Location, DeviceDetail, RiskLevelDuringSignIn, CorrelationId
Purpose: Find successful logins via device code from potentially risky devices. Maybe PRT elevation?
6. Microsoft Authentication Broker
SigninLogs
| where TimeGenerated > ago(7d)
| where AuthenticationProtocol == "deviceCode"
| where AppId == "29d9ed98-a469-4536-ade2-f981bc1d605e" // Microsoft Authentication Broker
| project TimeGenerated, UserPrincipalName, AppDisplayName, IPAddress, Location,
DeviceDetail, RiskLevelDuringSignIn, ResultType, CorrelationId
Purpose: Detect potential PRT theft attempts.
7. User/IP Combination
let lookback = 30d;
let timeframe = 1d;
let knownUserIPs = SigninLogs
| where TimeGenerated between (ago(lookback) .. ago(timeframe))
| where AuthenticationProtocol == "deviceCode" and ResultType == 0
| summarize knownIPs = make_set(IPAddress) by UserPrincipalName;
SigninLogs
| where TimeGenerated > ago(timeframe)
| where AuthenticationProtocol == "deviceCode" and ResultType == 0
| join kind=leftouter knownUserIPs on UserPrincipalName
| where isnull(knownIPs) or array_index_of(knownIPs, IPAddress) == -1
| project
TimeGenerated,
UserPrincipalName,
AppDisplayName,
AppId,
IPAddress,
Location,
knownIPs,
DeviceDetail,
RiskLevelDuringSignIn,
ResultType,
CorrelationId,
UserAgent,
IncomingTokenType
Purpose: Identify the first time a user successfully uses device code flow from a specific IP
8. Find Phishing mail
EmailUrlInfo
| where TimeGenerated >= ago(90d)
| where Url has_any ("aka.ms/devicelogin", "microsoft.com/devicelogin", "login.microsoftonline.com/common/oauth2/deviceauth")
| project TimeGenerated, Url, NetworkMessageId, UrlLocation
| join (EmailEvents) on NetworkMessageId
| project
TimeGenerated,
Url,
UrlLocation,
Subject,
SenderFromAddress,
RecipientEmailAddress,
DeliveryAction,
DeliveryLocation
Purpose: Check if user received mail with device code login page
Indicators of Attack (IoA)
Keep an eye out for the following patterns:
- AuthenticationProtocol == "deviceCode" from unknown or risky IPs
- Sign-ins from unmanaged or non-compliant devices
- Suspicious App IDs (especially generic clients like the Microsoft Authenticator Broker)
- Mail forwarding rules or inbox rule abuse shortly after sign-in
- Sudden deletion of large email volumes
- Repeated login behavior involving Device Registration Service
Note: Device code authentications often bypass traditional redirect URI analysis and are challenging to flag with standard rules. Threat actors exploit this “low friction” design for persistence and stealth.
Mitigation Strategies
Control Area | Recommendation |
Conditional Access | Block or restrict device code flow to approved users and applications |
Token Hygiene | Regularly revoke refresh tokens for inactive or compromised sessions |
App Governance | Monitor and track App IDs allowed to use device flow |
User Training | Teach users to verify login prompts, avoid unsolicited meeting invites, and recognize abuse |
Behavioral Analytics | Leverage Microsoft Sentinel, UEBA, and Defender XDR for anomaly detection |
Warning: Blocking the flow outright may disrupt services that depend on it (e.g., some printers or compliance devices). Test and phase deployment carefully.
Action Checklist for Defender Teams
✔ | Task |
☐ | Investigate use of deviceCode over the past 90 days in Sentinel and Entra logs |
☐ | Correlate with suspicious App IDs and unrecognized user agents |
☐ | Restrict device code flow with Conditional Access |
☐ | Review token issuance and implement automated token revocation policies |
☐ | Integrate custom Sentinel rules for anomalous behavior following deviceCode sign-ins |
☐ | Educate your team about this attack vector and how to identify it in logs |
☐ | Regularly review permissions and the registration of new devices |
☐ | Bring out user information or a training to rise the awareness |
Conclusion
Device Code Phishing is not speculative — it's active, effective, and well-documented in the wild. Unlike traditional phishing or token theft, it operates entirely within legitimate authentication flows, leveraging your existing trust in Microsoft’s infrastructure.
That’s what makes it insidious.
With the right combination of detection, conditional access, user awareness, and token management, organizations can drastically reduce their risk exposure.
Let’s not be passive observers. As defenders, it’s on us to identify, adapt, and act.
Do you have any insights or queries to share? Let's learn from each other.
References
• OAuth 2.0 device authorization grant - Microsoft identity platform | Microsoft Learn
• RFC 8628 - OAuth 2.0 Device Authorization Grant
• Device Code Phishing in Google Cloud and Azure | Huntress
• Storm-2372 conducts device code phishing campaign | Microsoft Security Blog
• Phishing for Primary Refresh Tokens and Windows Hello keys - dirkjanm.io
• Introducing a new phishing technique for compromising Office 365 accounts
• How to Detect Malicious OAuth Device Code Phishing
• Multiple Russian Threat Actors Targeting Microsoft Device Code Authentication | Volexity
• The Art of the Device Code Phish – Boku