OAuth Device Code Phishing: Why "Secondary Auth" is Failing Us
Has anyone else noticed the massive spike in OAuth 2.0 Device Authorization Grant abuse lately? The Hacker News article this morning hit the nail on the head—what used to be a niche technique for red teams targeting input-constrained devices (smart TVs, printers) has turned into a full-blown phishing epidemic in just a few months.
The mechanics are simple but devastating: attackers automate the device code request, present the user with a code via a fake "verification" portal, and then poll the token endpoint until the user unwittingly authenticates on a legitimate page. Since the user enters their creds and MFA on the real site, standard email gateway defenses often miss it.
We've started hunting for this in our Entra ID logs. The key is correlating the DeviceCode login events with the user's standard interactive sessions. If you see a device code initiation followed immediately by a successful login from a geo-impossible location, that's your smoking gun.
Here is a basic KQL query we are using to baseline normal device code activity to spot anomalies:
SigninLogs
| where AuthenticationProtocol == "DeviceCodeFlow"
| summarize count() by AppId, UserPrincipalName, bin(TimeGenerated, 1h)
| order by count_ desc
How is everyone else approaching detection? Are you blocking device code flows entirely via Conditional Access, or just relying on anomaly detection?
We moved to blocking Device Code Flow entirely for most users via Conditional Access. Unless someone has a legitimate legacy hardware need (like those IoT printers mentioned), it's just too large of an attack surface. You can configure this in the 'Grant' controls of your CA policies by filtering client types. It saves a lot of headache compared to trying to detect the polling behavior.
From a pentester's perspective, this is the holy grail of bypasses right now. Tools like TokenTactics have made it incredibly easy to automate. The scary part is how effectively it bypasses MFA because the victim performs the MFA challenge themselves. We recommend organizations enforce 'Hybrid Joined' or 'Compliant Device' requirements, so even if the token is stolen, the attacker can't use it on an unmanaged device.
Detection is tough because the login looks legitimate. We've had luck looking at the ResourceDisplayName in the token request. If a user is initiating a device code flow for an app they haven't used in months, or if the User-Agent string on the polling device looks suspicious (generic python-requests), we flag it for SOC review.
Building on Ivan's point about detection, we've found success monitoring polling frequency. Attackers using automated scripts often poll significantly faster than a legitimate IoT device. You can catch this by flagging multiple polling attempts from the same user within a short window.
SigninLogs
| where AuthenticationProtocol == "DeviceCode"
| summarize Count = count() by UserPrincipalName, bin(TimeGenerated, 5m)
| where Count > 10
Training users is vital, but technical controls need to catch what they miss. A reliable indicator we've seen is Device Code Flow completions originating from standard web browsers—legitimate IoT flows shouldn't come from Chrome or Edge. You can hunt for this behavior with the following KQL query:
kusto
SigninLogs
| where AuthenticationDetails has "Device Code"
| where DeviceDetail Browser in ("Chrome", "Safari", "Edge")
| project UserPrincipalName, AppDisplayName, TimeGenerated
If you see a browser user agent here, it's almost certainly phishing.
Verified Access Required
To maintain the integrity of our intelligence feeds, only verified partners and security professionals can post replies.
Request Access