Blog · Dmarc
Why OAuth App Consent Lets Attackers Keep Access After You Close a M365 Mailbox Incident
The mailbox is closed but the attacker still has access
You get the alert. A user's M365 mailbox shows signs of compromise. You reset their password, force a sign-out on all sessions, and mark the incident closed.
Two weeks later, the same mailbox is compromised again. The attacker did not brute-force a new password. They never needed to.
After the original incident, the user had granted an OAuth application consent to access their mailbox via Microsoft Graph. That consent grant includes a refresh token. That refresh token is still valid after a password reset, because OAuth token validity is not tied to the user's password.
This is not a theoretical edge case. It is a documented persistence mechanism used in real attacks, and most M365 incident response runbooks do not cover it.
This is also where DMARC aggregate report monitoring becomes relevant. If you are watching your DMARC reports across your M365 environment, authentication anomalies from a compromised mailbox -- unexpected sending sources, unusual alignment failures -- can flag OAuth-based persistence that your Entra ID logs might not immediately surface. More on that in the section on using DMARCFlow for OAuth anomaly detection.
Why password reset does not revoke OAuth app consent
OAuth 2.0 operates independently of the resource owner's password. When a user grants an application consent to access their mailbox, the application receives an access token and a refresh token. These tokens are issued by Azure Active Directory, now Microsoft Entra ID.
When you reset the user's password, you invalidate their credentials. You do not invalidate tokens that Entra ID has already issued to third-party applications. Those tokens remain valid until they expire or are explicitly revoked.
The same applies to session revocation. Revoking a session invalidates the user's browser sessions. It does not invalidate the OAuth refresh token that a previously consented application holds.
This design is intentional. OAuth exists so that users can grant access to applications without sharing their password. The tradeoff is that revoking password access does not automatically revoke that access.
What OAuth app consent actually grants
In M365, OAuth app consent comes in two types that matter for mailbox access:
Delegated permissions allow an app to act on behalf of the user. With the right scopes, an application with a valid refresh token can read emails, send emails, access files, and more, using the user's identity.
Application permissions allow an app to access resources directly, without a user context. These are less common for mailbox persistence but appear in more sophisticated attacks.
The attack path for mailbox compromise via OAuth:
1. Attacker gains access to the victim's M365 mailbox through phishing or credential stuffing.
2. Attacker, or the victim unknowingly, grants an OAuth application consent to access the mailbox with delegated permissions. This often looks like a normal SaaS integration prompt.
3. Attacker captures or retains the refresh token issued by Entra ID.
4. SOC resets the user's password and revokes sessions.
5. Attacker uses the OAuth refresh token to obtain a new access token, maintaining mailbox access through Microsoft Graph.
6. SOC believes the incident is resolved. It is not.
Step 3 is the critical part. OAuth consent is often granted through a convincing consent prompt. Users click Accept because they see these prompts in normal workflows. An attacker weaponizes this by crafting a prompt that requests access to email, contacts, and files under the guise of a legitimate integration.
How to audit OAuth app grants for a compromised mailbox
You need to check two places in the Entra admin center and reconcile both.
Place 1: The user's OAuth consent grants
Open the Entra admin center and navigate to Users > All users > [affected user] > Enterprise applications. This shows applications assigned to or accessible by that user.
For a programmatic view, use the Microsoft Graph API. Open Graph Explorer and run:
GET https://graph.microsoft.com/v1.0/users/{userId}/oauth2PermissionGrants
Look for grants where the startDateTime predates the incident and the scope includes Mail.Read, Mail.Send, or offline_access. Any grant meeting those two conditions is worth investigating.
Place 2: The user's sign-in history filtered by application
In Entra ID sign-in logs, filter by the affected user. Then look specifically for applications accessed using token-based authentication after the password reset.
In the sign-in log details, the Authentication method field will show whether the sign-in used an interactive credential or a token. If an application shows successful token-based sign-ins after the password reset date, that application is using OAuth tokens, not user credentials.
This is the fastest way to confirm whether an attacker is using OAuth tokens for persistent access after you believe the incident is closed.
How to revoke OAuth app access in Microsoft Entra ID
Revocation requires two steps. Do both.
Step 1: Revoke the OAuth consent grant for the specific user
In the Entra admin center, find the Enterprise Application and remove the user's assignment. Or use Graph Explorer to delete the grant directly:
DELETE https://graph.microsoft.com/v1.0/users/{userId}/oauth2PermissionGrants/{grantId}
Removing the user's assignment from the Enterprise Application removes the application's ability to act on behalf of that user. This is the primary revocation action.
Step 2: Disable or remove the Enterprise Application
If the application is not a recognized business tool, disable or delete it in the Enterprise Applications blade. If it is a legitimate third-party application that was abused, coordinate with the application owner before removing access.
After revoking the OAuth grant, also reset the user's password again. This is because an attacker with the refresh token could use it once more before revocation fully propagates.
Adding OAuth consent review to your incident response runbook
Most M365 incident response runbooks include these steps after a mailbox compromise:
- Reset user password
- Revoke active sessions
- Enable MFA for the affected user
- Notify relevant stakeholders
Add this sequence after the password reset:
1. Check the user's OAuth consent grants using the Graph API or the Enterprise Applications blade in Entra admin center. Look for grants issued before the incident date.
2. Review the user's sign-in history filtered by application. Identify applications using token-based authentication after the password reset.
3. Revoke access for any unrecognized or suspicious applications. Remove user assignment or delete the Enterprise Application if it is malicious.
4. Document the revoked applications in the incident report.
5. Monitor the user's sign-in logs for the next 30 days, specifically watching for new OAuth application access.
This adds roughly 20 minutes to the incident response process. That is a reasonable tradeoff against an attacker maintaining persistent mailbox access after you believe the incident is closed.
Using DMARCFlow for OAuth anomaly detection
Here is where email authentication data adds a layer that Entra ID sign-in logs do not provide on their own.
When an attacker uses an OAuth token to access a compromised mailbox and sends email from that context, the SMTP transaction shows up in your DMARC aggregate reports. The sending source may not align with your expected mail flow. The authentication results may show failures you would not expect from a legitimate internal sender.
DMARCFlow processes aggregate reports and surfaces authentication anomalies across your domains. If your DMARC reports show unexpected authentication patterns -- a sending source that does not match your normal M365 tenant, or alignment failures on mail coming from a recently compromised mailbox -- DMARCFlow flags that signal.
This does not replace Entra ID sign-in log analysis. But for domains handling high volumes of M365-hosted email, DMARC aggregate monitoring catches OAuth-based persistence that might otherwise go undetected until the next incident. Both layers are needed. Neither is sufficient on its own.
## FAQ
Does resetting the password revoke OAuth app consent in M365?
No. OAuth tokens are issued by Entra ID and are independent of the user's password. Resetting the password does not invalidate existing refresh tokens or access tokens. You must explicitly revoke the OAuth consent grant through the Enterprise Applications blade or the Graph API.
How do I see which OAuth apps have been granted access to a specific user's mailbox?
Use the Microsoft Graph API endpoint GET /users/{userId}/oauth2PermissionGrants, or check the Entra admin center under Enterprise applications and filter by the specific user.
Can I prevent users from granting OAuth consent to risky applications?
Yes. In Entra ID, configure consent settings to require admin approval for all OAuth permission requests, or restrict user consent to verified publisher applications only. These settings are in the Entra admin center under Enterprise applications, Consent and permissions.
What is the difference between revoking a session and revoking an OAuth consent grant?
Revoking a session invalidates the user's active browser or application sessions. Revoking an OAuth consent grant invalidates the application's access tokens and refresh tokens for that user. Both are needed after a compromise. Revoking sessions alone leaves OAuth tokens active.
How does DMARCFlow help detect OAuth-based mailbox compromise?
DMARCFlow monitors aggregate reports for authentication anomalies. If a compromised mailbox is used to send email through your domain, DMARC reports will show authentication failures or unusual sending patterns that can indicate unauthorized OAuth-based access. DMARCFlow correlates these signals across your domains and flags anomalies that warrant investigation in your Entra ID sign-in logs.