Azure AD / Entra ID Token Theft and Abuse

Azure AD / Entra ID Token Theft and Abuse - article cover image Cloud Security
Time it takes to read this article 6 minutes.

Disclaimer: This article is provided strictly for educational purposes and authorized security testing. Only run these techniques against systems you own or have explicit written permission to assess. Unauthorized access to computer systems is illegal in virtually every jurisdiction and can carry severe penalties.

Introduction

Microsoft Entra ID (formerly Azure AD) is the identity backbone behind Microsoft 365, Azure, and a huge share of federated SaaS logins, which makes its OAuth 2.0 / OpenID Connect token model a prime target once an attacker has any kind of foothold on a victim’s device or in their browser. Access tokens, refresh tokens, and the device-bound Primary Refresh Token (PRT) are all bearer credentials: whoever presents a valid token *is* the user, as far as the relying application or Microsoft Graph is concerned. Stealing one is functionally equivalent to stealing a password, except the token is often longer-lived, harder for the user to notice being used, and — critically — frequently bypasses interactive MFA entirely because the MFA challenge was already satisfied when the token was originally issued.

This makes token theft one of the highest-value techniques against modern, MFA-hardened environments: rather than fighting through conditional access and multi-factor prompts at logon time, the attacker steals a credential that already carries a satisfied authentication context. Illicit OAuth consent grants extend the same problem into persistence — a malicious app that a user (or an admin) consents to keeps working long after a password reset, because it authenticates with its own client credentials, not the victim’s.

Attack Prerequisites

Different token-theft techniques share a common shape: some interaction with the victim or their device that yields a token or an OAuth grant, without necessarily needing the victim’s password:

  • Endpoint access (malware, an infostealer, or interactive access to a hybrid/Entra-joined device) to extract a PRT or session cookies from browser/OS token caches.
  • A phishing channel capable of delivering a device-code or OAuth consent prompt — email, Teams, or any messaging the target will act on.
  • No Conditional Access enforcement of token binding — device compliance or token-protection policies that would otherwise invalidate a token replayed from an unmanaged device or IP.
  • For consent phishing, user consent enabled for third-party apps, or a social-engineered admin who can grant tenant-wide admin consent.

How It Works

Entra ID’s OAuth 2.0 implementation issues short-lived access tokens (roughly an hour) alongside long-lived refresh tokens; a client silently redeems the refresh token for a new access token when the old one expires, so a session’s practical lifetime is however long the refresh token remains valid — often 90 days, effectively indefinite under continuous use. On a Windows device that is Azure AD-joined or hybrid-joined, this is elevated into a Primary Refresh Token (PRT): a device-bound artifact created by the Cloud AP provider representing the user’s SSO state for *all* Microsoft endpoints on that device. The PRT is protected by the device’s TPM-backed session key, but tools like Mimikatz’s sekurlsa::cloudap module have demonstrated extraction against it when an attacker already has SYSTEM/admin access on the device — at which point they mint fresh access tokens for the user across every Microsoft 365 service without touching a password.

Device code phishing abuses the OAuth 2.0 device authorization grant, a flow designed for input-constrained devices: the attacker requests a device code from Entra ID, then sends the victim a legitimate-looking link to https://microsoft.com/devicelogin with the code, framed as a Teams meeting join or MFA re-registration. When the victim enters the code and completes their normal sign-in (including MFA, since it really is Microsoft’s own login page), the attacker’s polling client — not the victim’s browser — receives the resulting tokens. Because the login page is genuine Microsoft infrastructure, this defeats most anti-phishing training and domain-based controls.

Illicit consent grants exploit OAuth’s delegated-permission model directly: an attacker registers a multi-tenant application requesting broad Graph scopes (Mail.Read, Files.ReadWrite.All, offline_access), then phishes the victim into visiting the app’s consent URL. If user consent for third-party apps is permitted, clicking “Accept” grants the attacker’s app a refresh token for those scopes — persistence that survives a password reset, since the trust relationship is between the tenant and the app registration, not the victim’s password.

Vulnerable Code / Configuration

The core enabling misconfiguration for consent phishing is tenant-wide user consent left in its permissive default state, allowing any user to grant any registered application access to their data without admin review. Retrieved via Graph, the relevant tenant setting looks like this when it is dangerously open:

{
  "defaultUserRolePermissions": {
    "allowedToCreateApps": true,
    "permissionGrantPoliciesAssigned": [
      "ManagePermissionGrantsForSelf.microsoft-user-default-legacy"
    ]
  }
}
JSON

The microsoft-user-default-legacy policy allows end users to consent to *any* app requesting *any* non-admin-restricted permission, with no risk-based check on publisher verification or requested scope. Combined with allowedToCreateApps: true, a single phished click establishes a persistent, admin-invisible OAuth grant. The fix is to replace this policy with a restricted one, or disable user consent entirely and route requests through an admin consent workflow.

The complementary gap on the Conditional Access side is a policy that requires MFA but does not also require a compliant/managed device or token protection, which does nothing to stop a *replayed* token that already carries a satisfied MFA claim:

{
  "displayName": "Require MFA for all users",
  "conditions": { "users": { "includeUsers": ["All"] } },
  "grantControls": {
    "operator": "OR",
    "builtInControls": ["mfa"]
  },
  "sessionControls": null
}
JSON

Because sessionControls is null, there is no sign-in frequency re-authentication requirement and no token protection binding the token to the issuing device — a refresh token exfiltrated from the victim’s machine remains fully usable from the attacker’s own infrastructure until it naturally expires or is explicitly revoked.

Walkthrough / Exploitation

A minimal device-code phishing flow starts by requesting a device code for a legitimate, commonly-consented first-party client ID (public clients such as the Azure CLI’s work well, being already trusted tenant-wide), then sending the victim the verification URL and code:

curl -X POST https://login.microsoftonline.com/organizations/oauth2/v2.0/devicecode \
  -d 'client_id=04b07795-8ddb-461a-bbee-02f9e1bf7b46' \
  -d 'scope=https://graph.microsoft.com/.default offline_access'
# Response includes device_code, user_code, verification_uri
# Attacker sends the victim: "Sign in at microsoft.com/devicelogin, code: ABCD-EFGH"
Bash

While the victim completes their real sign-in (including MFA), the attacker’s client polls the token endpoint and receives tokens directly:

curl -X POST https://login.microsoftonline.com/organizations/oauth2/v2.0/token \
  -d 'grant_type=urn:ietf:params:oauth:grant-type:device_code' \
  -d 'client_id=04b07795-8ddb-461a-bbee-02f9e1bf7b46' \
  -d 'device_code=<device_code_from_above>'
Bash

Once tokens are in hand — from device-code phishing, a consent-grant refresh token, or a PRT-derived access token — they are used exactly like a normal authenticated session against Graph or Azure APIs:

az account get-access-token --resource https://graph.microsoft.com
curl -H "Authorization: Bearer <access_token>" \
  https://graph.microsoft.com/v1.0/me/messages
Bash

For deeper tenant enumeration, ROADtools performs a full Graph/AAD-Graph crawl into a queryable local database — mapping users, groups, app registrations, and role assignments:

roadrecon auth -u victim@tenant.onmicrosoft.com -p '<password-or-token>'
roadrecon gather
roadrecon dump
Bash

AADInternals covers the offensive PowerShell side of the same ecosystem — PRT extraction/forging against a compromised device:

Get-AADIntUserPRTToken
New-AADIntUserPRTToken -Settings $prtSettings
PowerShell

Note: PRT theft requires local admin/SYSTEM on the target device — a post-exploitation technique, not a remote one. That is why endpoint detection and response, not just Entra ID logging, is a necessary layer: by the time a PRT is extracted, the attacker already has significant device access.

Opsec: Sign-ins with a stolen token still generate an Entra ID sign-in log entry, but device-code and refresh-token replay often show a *different* client app, device ID, or geolocation than the victim’s normal pattern — that discrepancy, not the sign-in itself, is what most detection rules and Identity Protection risk scoring key on.

Detection and Defense

Token theft is best countered by shrinking the value and lifetime of a stolen token and by binding tokens to the device/session they were issued to, rather than trying to prevent theft outright:

  • Conditional Access requiring compliant or hybrid-joined devices, so a token replayed from an attacker-controlled machine fails device-trust evaluation even if the token itself is valid.
  • Token protection (token binding) for Exchange Online and SharePoint Online sign-in flows, which cryptographically ties refresh tokens to the device’s TPM so a copied token cannot be replayed elsewhere.
  • Continuous Access Evaluation (CAE) to react in near-real-time to user disable, password reset, or location/risk changes instead of waiting for token expiry.
  • Restrict or disable the device code flow via Conditional Access (authenticationFlows condition) unless specific input-constrained scenarios genuinely require it — most tenants have no legitimate use for it at scale.
  • Disable end-user consent to third-party apps and route all OAuth consent through an admin review/workflow; regularly audit Enterprise Applications for over-scoped or unfamiliar app grants.
  • Monitor Entra ID sign-in and audit logs for anomalous client app IDs, impossible-travel sign-ins, new OAuth grants (Consent to application events), and PRT-related indicators from Identity Protection risk detections.

Real-World Impact

Token theft and OAuth consent phishing have been widely reported as primary access techniques by nation-state and financially motivated groups targeting Microsoft 365 tenants, precisely because they route around password-based defenses and interactive MFA. Microsoft’s own threat intelligence has repeatedly flagged device-code phishing and illicit consent grants as active, in-the-wild campaigns rather than theoretical research, prompting Microsoft to progressively harden default consent settings and expand Conditional Access session controls in recent years.

Conclusion

Cloud identity tokens are bearer credentials with a long shelf life, and attackers have adapted accordingly: rather than fighting MFA at the front door, they steal a session that already walked through it. Defending against this means treating tokens as protectable assets — bound to compliant devices, evaluated continuously, short-lived for sensitive roles — alongside tightly governed OAuth consent, since a stolen token or malicious app grant can outlive any password reset.

You Might Also Like

If you found this useful, these related deep-dives cover adjacent techniques and their defenses:

Comments

Copied title and URL