In this section
5.2 Session Revocation Automation
Scenario
Tom revokes the compromised user's sessions at 14:33. The Graph API returns success. He marks containment complete and moves to the next incident. At 15:10, Priya notices the attacker is still downloading SharePoint files: a third-party sync client cached the access token before revocation and kept working for 37 minutes. The API said success. The attacker said otherwise.
How session revocation works
Microsoft's session model has two token types that matter for revocation:
Refresh tokens are long-lived tokens (default 90 days for M365, configurable) that the client uses to obtain new access tokens without re-authenticating. When an AiTM attack steals a session, it steals the refresh token. The attacker uses this token to generate new access tokens for hours or days after the initial compromise.
Access tokens are short-lived tokens (default 1 hour for Entra ID) that grant access to specific resources. They are issued using the refresh token. When the access token expires, the client presents the refresh token to get a new one.
The revokeSignInSessions API call invalidates all refresh tokens. Existing access tokens remain valid until they expire (up to 1 hour). After the refresh token is revoked, the attacker cannot obtain new access tokens, their access terminates when the current access token expires.
The 1-hour gap. This is the most misunderstood aspect of session revocation. The attacker retains access for up to 1 hour after revocation because active access tokens are not immediately invalidated. For most AiTM scenarios, this is acceptable: the attacker's access degrades over the hour as individual service tokens expire. For active data exfiltration or persistence establishment, the 1-hour gap may be too long.
The mitigation for the gap is Continuous Access Evaluation (CAE). If the target application supports CAE (Exchange Online, SharePoint, Teams do), the service validates the session status in near-real-time. CAE-enabled services detect the revocation within minutes, not hours. Check your tenant's CAE status: navigate to Entra admin center → Conditional Access → Continuous access evaluation.
Building the Logic App action
In the containment playbook, after the decision tree (SA5.1) approves containment:
Action: HTTP POST to Graph API.
Method: POST
URI: https://graph.microsoft.com/v1.0/users/@{variables('CompromisedUserUPN')}/revokeSignInSessions
Authentication: Managed Identity
Audience: https://graph.microsoft.com
Headers: Content-Type: application/json
Body: (empty)
The CompromisedUserUPN variable is populated from the Account entity extraction (SA1.6). If the entity provides AadUserId instead of UPN, use the userId in the URI: /users/{AadUserId}/revokeSignInSessions.
Expected response. HTTP 200 with body {"value": true}. Any other response indicates failure: the error handler (SA1.7 pattern) captures the error and routes to manual containment.
Error handling. For session revocation specifically: if the API returns 403 (insufficient permissions), the managed identity is missing User.RevokeSessions.All. If it returns 404 (user not found), the UPN extraction is incorrect or the user does not exist. If it returns 500 (internal error), retry once: the action is idempotent (revoking already-revoked sessions returns success).
The token lifecycle, what revocation actually invalidates
Understanding what revokeSignInSessions does and does not do is critical for assessing whether revocation alone is sufficient containment.
The API invalidates all refresh tokens and session cookies for the user. Refresh tokens are the long-lived credentials (default lifetime 90 days, configurable in Entra) that clients present to the token endpoint to obtain new access tokens. When the attacker steals a session via AiTM, they capture the refresh token, which is why they can access the account for days without re-authenticating. Revoking the refresh token means the attacker cannot obtain new access tokens. Their access dies when the current access token expires.
Access tokens are short-lived (default 60-75 minutes for Entra ID, configurable). After revocation, the attacker's current access token remains valid until it naturally expires. During this window, the attacker can continue to read email, access SharePoint, and use any application where they already have an active access token. This is the "revocation gap", and its practical impact depends on whether the target application supports Continuous Access Evaluation (CAE).
Applications that support CAE (Exchange Online, SharePoint Online, Teams, Graph API) perform near-real-time validation of the session status. When you revoke sessions, CAE-enabled applications detect the revocation within 1-5 minutes, dramatically shorter than the full access token lifetime. The attacker's access to Exchange and SharePoint is typically terminated within 5 minutes of revocation, even if the access token would otherwise be valid for another 55 minutes.
Applications that do NOT support CAE (third-party SaaS apps, on-premises apps using Entra authentication, some legacy Office apps, apps using cached tokens) continue to honor the access token until it expires. For these applications, the revocation gap is the full token lifetime, up to 75 minutes. If the attacker is using a third-party app that received an access token before revocation, they retain access until the token expires.
Practical implication for the containment playbook: session revocation is effective within 5 minutes for the Microsoft 365 applications where AiTM attacks primarily operate (Exchange, SharePoint, Teams). For comprehensive containment across all applications, the CA emergency policy (SA5.4) provides the defense-in-depth that blocks re-authentication even for non-CAE applications: the attacker's access token expires and they cannot obtain a new one because the CA policy blocks their non-compliant device.
To check your tenant's CAE status: navigate to Entra admin center → Protection → Conditional Access → Continuous access evaluation. Verify that CAE is enabled and not overridden by any CA policy settings. The "Strictly enforce location policies" option in CAE provides the tightest enforcement but may cause legitimate disruptions for users on VPNs with changing IP addresses.
Verification, did the revocation actually work?
The Graph API returning {"value": true} means the API accepted the request. It does not guarantee that all services have propagated the revocation. Add a verification step:
Wait 60 seconds (using a Delay action), then query the user's current sign-in sessions:
SigninLogs
| where TimeGenerated > ago(5m)
| where UserPrincipalName =~ "{CompromisedUserUPN}"
| where ResultType == 0
| project TimeGenerated, IPAddress, AppDisplayName, ClientAppUsed
If this query returns successful sign-ins after the revocation timestamp: the revocation has not fully propagated, or the attacker has obtained a new token through a different mechanism (e.g., they also have the password, not just the session token). If the query returns no successful sign-ins or only failures: the revocation is working.
The verification result is added to the incident comment: "Session revocation executed at 14:33:12 UTC. Verification at 14:34:12 UTC: no successful sign-ins detected post-revocation. Status: CONTAINED."
Anti-Pattern
Revoking sessions without verifying revocation succeeded
The playbook calls revokeSignInSessions and marks containment complete. But the Graph API returns 204 (success) even when the revocation does not immediately invalidate all active tokens. Refresh tokens cached by client applications may survive for minutes. The playbook must verify: query SigninLogs for new sign-ins from the attacker IP after revocation. If sign-ins continue, the session token is still valid, escalate to account disable.
Documentation: the incident comment
Every containment action must be documented in the incident with: the action taken, the timestamp, the result (success/failure), and the verification outcome. The playbook adds a structured comment:
🔒 CONTAINMENT ACTION: Session Revocation
━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Target: d.chen@northgateeng.com
Executed: 2026-04-08 14:33:12 UTC
Method: Graph API revokeSignInSessions
Result: SUCCESS (HTTP 200, value: true)
Verification: No sign-ins from attacker IP (203.0.113.45) post-revocation
CAE Status: Enabled (near-real-time propagation)
━━━━━━━━━━━━━━━━━━━━━━━━━━━━
⚠ Note: Access tokens valid up to 1h. CAE accelerates propagation for
Exchange, SharePoint, and Teams. Other applications may retain access
until token expiry.
Next action: MFA method removal (SA5.3)
Compliance Context
Revoking sessions is disruptive. The analyst should monitor the compromised account for 15-30 minutes to confirm the attack before taking containment actions.
Monitoring a confirmed AiTM for 15-30 minutes gives the attacker 15-30 minutes to: create inbox forwarding rules, download mailbox data, register new MFA methods, consent to malicious OAuth applications, and move laterally to other systems. Session revocation is the LOWEST impact containment action, it forces one re-authentication. The user continues working after re-authenticating (5-minute disruption). Compare this to the alternative: the attacker exfiltrates 3GB of email data during the 30-minute monitoring window. Revoke first, investigate second. The revocation does not destroy any evidence: all sign-in logs, audit logs, and activity logs are preserved.