Blog · Deliverability

How Device-Code Phishing Grants Persistent Mailbox Access in Microsoft 365

How does device-code phishing work in Microsoft 365?

Device-code phishing exploits an OAuth 2.0 authentication flow designed for devices that cannot run a browser. Smart TVs, CLIs, and kiosk machines use it to sign users into Microsoft 365 without a keyboard-friendly login page. The flow works like this:

  1. The device asks Microsoft's identity platform for a user code and a device code.
  2. Microsoft returns a short-lived code pair with an interval and expiry.
  3. The user is instructed to visit a URL (like microsoft.com/devicelogin) and enter the user code.
  4. Meanwhile, the device polls Microsoft's token endpoint at the given interval.
  5. Once the user enters the code in the browser and completes authentication, the device receives a valid access token and refresh token.

The problem is that the phishing page sits between the attacker and the token endpoint. The attacker initiates the flow on their own device, gets the code pair, and plants it on a page that asks the victim to "verify your identity" or "sign in to continue." When the victim enters the code, the attacker absorbs the tokens. No email link clicked. No password entered. No browser redirect that raises suspicion.

The attack chain step by step

Here is the full sequence:

Step 1: Attacker initiates device code flow. Using a tool or a script, the attacker requests a device code and user code from login.microsoftonline.com/common/oauth2/devicecode. The response includes the device_code, user_code, interval, and expires_in (typically 300 seconds for the code itself).

Step 2: Attacker serves the code to the victim. The attacker embeds the user code and instructions on a convincing phishing page, often styled as a Microsoft login or a "verify your account" prompt. The page tells the victim to visit microsoft.com/devicelogin and enter the code.

Step 3: Victim completes the flow. The victim opens the real Microsoft portal, signs in with their credentials, and enters the code. Microsoft delivers tokens to the attacker's polling endpoint.

Step 4: Attacker receives tokens. The attacker's device receives an access_token, a refresh_token, and an id_token. The access token may be short-lived (1 hour by default). The refresh token can live for 90 days or longer depending on tenant configuration.

Step 5: Attacker maintains persistence. The attacker uses the refresh token to request new access tokens indefinitely. They read emails, set up inbox rules to forward copies to an external address, access SharePoint files, and query the Graph API. The victim's password can be changed repeatedly. The attacker stays in.

Why password resets and MFA rotation do not stop this attack

Microsoft's token architecture decouples credentials from sessions. When you change your password or rotate your MFA, Entra ID issues a new credential to the account. It does not automatically revoke every outstanding refresh token unless a conditional access policy specifically requires re-authentication or the token has been flagged for reuse.

Default behavior: refresh tokens remain valid until they expire, the user hard-signs out, or an administrator revokes sessions. In practice, this means an attacker who obtained a refresh token before the password reset can continue using it afterward unless your tenant has specific policies in place to prevent this.

Microsoft deprecated configurable token lifetimes in 2021. However, certain legacy application configurations and migrated tenants may still carry older token lifetime settings. For most modern tenants, the primary control is conditional access rather than token lifetime policies.

How to detect device-code phishing in your tenant

Look for these signals in Entra ID sign-in logs:

Device code flow indicators:

  1. Client app type: "Other" with an OAuth grant type of urn:ietf:wg:oauth:2.0:oob or device_code
  2. Many successful device code grants from a single IP in a short window
  3. User codes entered from IPs that differ from the victim's normal sign-in locations
  4. OAuth applications that rarely use device code flow suddenly appearing in sign-in logs

The urn:ietf:wg:oauth:2.0:oob redirect URI is a special case used when an application cannot listen on a loopback address. Microsoft uses it for the Authenticator app enrollment flow. Attack tools also commonly produce this URI. If you see it in sign-in logs for apps that should not be using it, that is worth investigating.

Microsoft Sentinel has a detection rule called "Device code phishing" under the IdentityThreatDetection solution. Defender for Identity also surfaces alerts for suspicious device code authentication patterns. If you have E5-tier licensing, these are worth enabling.

How to block or limit device-code authentication in Entra ID

Conditional access policy (recommended):

  1. In Entra ID > Protection > Conditional Access, create a new policy.
  2. Under Assignments > Users and groups, select your target population (or All users to start).
  3. Under Assignments > Cloud apps or actions, choose All cloud apps (or scope to high-value apps like Exchange Online and Graph API).
  4. Under Conditions > Client apps, check "Other client" and enable "Mobile apps and desktop clients" -- or look for "Device code flow" if it appears as a separate option in your tenant UI.
  5. Under Access controls > Grant, choose Block. Alternatively, require Compliant device + MFA for a less aggressive posture.
  6. Enable the policy and test with a pilot group first.

This blocks the device code grant at the conditional access layer. Legitimate uses like Azure CLI and PowerShell device enrollment will also be blocked unless you scope the policy to exclude service accounts or create an exception group.

Restrict app permissions:

Review which third-party applications have device code permissions in your tenant. In Entra ID > Enterprise applications, look for apps with "Device code" in their grant type. Remove unnecessary permissions. Require admin consent for high-privilege scopes like Mail.Read or Files.Read.

Enable Continuous Access Evaluation:

CAE forces token revocations to take effect within minutes rather than waiting for token expiry. When an access token is revoked via CAE, any attempt to use it against Microsoft Graph or Exchange Online returns a 401 immediately. Enable CAE for all supported applications in Entra ID > Protection > Continuous Access Evaluation.

Revoke all active sessions after a suspected compromise:

Even with conditional access in place, if you suspect a device code compromise, go to Entra ID > Users > select the user > Sign-in sessions > Revoke all. This invalidates all refresh tokens for that user. Combine with a password reset and MFA re-registration to force a clean credential state.

FAQ

Does DMARC or email authentication prevent device-code phishing?

No. DMARC, DKIM, and SPF operate at the mail transport layer. They verify that an email came from an authorized sender, not that the person signing into Microsoft 365 is legitimate. Device-code phishing is an identity layer attack. It bypasses your email security entirely because the attacker authenticates as the real user through Microsoft's legitimate OAuth flow. Email authentication cannot stop a valid token from being issued to an attacker.

Can DMARCFlow help with device-code phishing?

DMARCFlow cannot prevent token theft at the identity layer. However, if a compromised account is used to send outbound email, DMARCFlow will surface those failures in aggregate reports. An unusual forwarding rule set via Graph API may show up as external-forwarding anomalies in DMARC forensic reports if the compromised account sends mail through your MX. Think of DMARCFlow as a post-compromise signal for your email channel, not a prevention control for identity attacks.

Does changing my password revoke refresh tokens?

Not automatically in most Entra ID configurations. You need a conditional access policy that enforces re-authentication or a session revocation event. To be thorough, change the password, revoke all sessions in the Entra ID user portal, and re-register MFA. Then monitor sign-in logs for any residual activity from the old session tokens.

What is the urn:ietf:wg:oauth:2.0:oob redirect URI?

It stands for "OAuth 2.0 out-of-band." Microsoft uses it for flows where the device cannot listen on a loopback port, such as enrolling the Microsoft Authenticator app. Attackers also use it because it does not require the attacker to operate a web server. If you see this URI in sign-in logs for applications that should be using standard redirect URIs, that is a high-fidelity signal of tooling abuse.

Practical next steps

  1. Check your Entra ID sign-in logs now for device code grants from the past 30 days. In the Azure portal, filter by Client app = "Other" and look for Grant type = "device_code." If you see spikes from IPs you do not recognize, investigate.
  2. Scope your conditional access policy to block device code flow for non-service accounts. Start with a pilot group. Monitor for helpdesk tickets from users who legitimately use Azure CLI or PowerShell.
  3. Enable Continuous Access Evaluation if it is not already active. It is available for Exchange Online, SharePoint Online, Teams, and Microsoft Graph.
  4. If you use DMARCFlow, check your aggregate reports for any sudden spikes in external-forwarding failures or unusual auth results. A compromised account forwarding mail externally will show up as forwarding anomalies before the account owner notices.