Microsoft Graph API for Incident Response: Top Actions and Safe Usage Patterns
A practical guide to the most impactful Graph API actions for security incident response, with safe usage patterns, permission requirements, and automation guardrails.
Microsoft Graph API provides powerful capabilities for automated incident response across Microsoft 365 environments. When a security incident occurs, the ability to programmatically revoke sessions, disable accounts, and contain threats can mean the difference between a contained incident and a full-scale breach.
However, these same capabilities carry significant risk if misused. Automating destructive actions without proper guardrails can disrupt business operations, lock out legitimate users, or create compliance issues.
This guide covers the top Graph API actions for incident response, organized by impact level, with practical patterns for safe automation.
Top Graph API Actions for Incident Response
Session Management
Revoke All Sign-In Sessions
Medium ImpactInvalidates all refresh tokens and session cookies, forcing re-authentication across all applications. As of October 2025, this also invalidates MFA-protected sessions regardless of enforcement method.
POST https://graph.microsoft.com/v1.0/users/{userId}/revokeSignInSessions
// Response
{
"value": true
}Required Permissions
User.ReadWrite.All, Directory.ReadWrite.All
Required Role
User Administrator, Privileged Authentication Admin
Invalidate Specific Refresh Tokens
Low ImpactTarget specific application tokens without disrupting all sessions. Useful for containing compromised OAuth apps without full session revocation.
// Get user's OAuth2 permission grants
GET https://graph.microsoft.com/v1.0/users/{userId}/oauth2PermissionGrants
// Delete specific grant
DELETE https://graph.microsoft.com/v1.0/oauth2PermissionGrants/{id}Account Actions
Disable User Account
High ImpactPrevents all sign-ins without deleting data. Reversible action ideal for containment during investigation.
PATCH https://graph.microsoft.com/v1.0/users/{userId}
Content-Type: application/json
{
"accountEnabled": false
}Disabling an account does not immediately terminate active sessions. Combine with revokeSignInSessions for immediate effect.
Force Password Reset
High ImpactForces password change on next sign-in. Essential for credential compromise scenarios.
PATCH https://graph.microsoft.com/v1.0/users/{userId}
Content-Type: application/json
{
"passwordProfile": {
"forceChangePasswordNextSignIn": true,
"forceChangePasswordNextSignInWithMfa": true
}
}Reset MFA Methods
Critical ImpactRemoves all registered authentication methods. Use only when MFA is confirmed compromised (e.g., SIM swap, authenticator app takeover).
// List authentication methods
GET https://graph.microsoft.com/v1.0/users/{userId}/authentication/methods
// Delete specific method
DELETE https://graph.microsoft.com/v1.0/users/{userId}/authentication/
phoneMethods/{id}
// Require MFA re-registration
POST https://graph.microsoft.com/v1.0/users/{userId}/authentication/
operationsEmail and Mailbox Actions
Remove Mailbox Forwarding Rules
Medium ImpactDeletes inbox rules that forward or redirect email to external addresses — a common BEC persistence mechanism.
// List inbox rules
GET https://graph.microsoft.com/v1.0/users/{userId}/mailFolders/inbox/
messageRules
// Delete suspicious rule
DELETE https://graph.microsoft.com/v1.0/users/{userId}/mailFolders/inbox/
messageRules/{ruleId}Purge Malicious Emails
High ImpactSoft-delete phishing or malware emails from user mailboxes organization-wide.
// Search for malicious messages
GET https://graph.microsoft.com/v1.0/users/{userId}/messages?$filter=
internetMessageId eq '<malicious-message-id>'
// Move to deleted items (soft delete)
POST https://graph.microsoft.com/v1.0/users/{userId}/messages/{messageId}/move
{
"destinationId": "deleteditems"
}
// Hard delete (permanent)
DELETE https://graph.microsoft.com/v1.0/users/{userId}/messages/{messageId}Revoke Delegate Access
Medium ImpactRemove delegate permissions from a mailbox. Attackers often add delegate access for persistence.
// List mailbox permissions
GET https://graph.microsoft.com/v1.0/users/{userId}/mailboxSettings
// Remove delegate (via Exchange Online PowerShell / EWS)
// Graph API has limited delegate management - use EWS or PowerShell
Remove-MailboxPermission -Identity user@domain.com
-User delegate@domain.com -AccessRights FullAccessSafe Usage Patterns
1. Tiered Approval Based on Impact
Map each action to an approval level based on reversibility and business impact.
| Action | Impact | Approval | Reversible |
|---|---|---|---|
| Revoke OAuth grant | Low | Auto-approve | Yes (user re-consents) |
| Revoke sessions | Medium | Auto-approve | Yes (re-authenticate) |
| Delete inbox rules | Medium | Auto with logging | No (manual recreate) |
| Force password reset | High | Require review | Yes |
| Disable account | High | Require approval | Yes |
| Reset MFA methods | Critical | Manual only | Yes (re-register) |
2. VIP and Service Account Protection
Implement guardrails that prevent automated actions on sensitive accounts.
// Check if user is protected before action
async function canAutomate(userId: string): Promise<boolean> {
const user = await graphClient.api(`/users/${userId}`)
.select('displayName,jobTitle,memberOf')
.expand('memberOf')
.get();
// Check against protected groups
const protectedGroups = [
'VIP-Executives',
'Service-Accounts',
'Break-Glass-Admins'
];
const userGroups = user.memberOf
.filter(m => m['@odata.type'] === '#microsoft.graph.group')
.map(g => g.displayName);
const isProtected = protectedGroups.some(pg =>
userGroups.includes(pg)
);
if (isProtected) {
// Route to manual approval queue
await createApprovalRequest(userId, 'protected-user');
return false;
}
return true;
}3. Rate Limiting and Circuit Breakers
Prevent runaway automation from affecting too many users in a short period.
const RATE_LIMITS = {
sessionRevoke: { max: 50, windowMinutes: 5 },
accountDisable: { max: 10, windowMinutes: 15 },
passwordReset: { max: 20, windowMinutes: 10 },
};
async function checkRateLimit(action: string): Promise<boolean> {
const key = `ratelimit:${action}:${getCurrentWindow()}`;
const count = await redis.incr(key);
if (count === 1) {
await redis.expire(key, RATE_LIMITS[action].windowMinutes * 60);
}
if (count > RATE_LIMITS[action].max) {
await alertSecurityTeam({
type: 'rate-limit-exceeded',
action,
count,
message: 'Automated action rate limit exceeded - manual review required'
});
return false;
}
return true;
}Session Revoke
50 per 5 min
Low impact, high velocity OK
Account Disable
10 per 15 min
High impact, needs review
Password Reset
20 per 10 min
User disruption concern
4. Comprehensive Audit Trail
Log every automated action with context for compliance and rollback capability.
interface ActionAuditLog {
timestamp: string;
action: string;
targetUserId: string;
targetUserPrincipalName: string;
triggeredBy: 'automation' | 'analyst';
triggerSource: string; // Alert ID, playbook name
previousState: object; // For rollback
newState: object;
graphRequestId: string; // Graph API request ID
correlationId: string; // Incident correlation
approvalId?: string; // If approval was required
}
// Always capture previous state before modification
async function disableUserWithAudit(userId: string, trigger: string) {
const previousState = await graphClient.api(`/users/${userId}`)
.select('accountEnabled,signInSessionsValidFromDateTime')
.get();
const response = await graphClient.api(`/users/${userId}`)
.patch({ accountEnabled: false });
await auditLog.write({
timestamp: new Date().toISOString(),
action: 'user.disable',
targetUserId: userId,
previousState: { accountEnabled: previousState.accountEnabled },
newState: { accountEnabled: false },
graphRequestId: response.headers['request-id'],
triggerSource: trigger,
// ... other fields
});
}Permission Requirements Summary
| Action Category | Graph Permissions | Minimum Role |
|---|---|---|
| Session Management | User.ReadWrite.All | User Administrator |
| Account Enable/Disable | User.ReadWrite.All, Directory.ReadWrite.All | User Administrator |
| Password Management | UserAuthenticationMethod.ReadWrite.All | Authentication Administrator |
| MFA Methods | UserAuthenticationMethod.ReadWrite.All | Privileged Authentication Admin |
| Mail Operations | Mail.ReadWrite, MailboxSettings.ReadWrite | Exchange Administrator |
| Risk Detection/Remediation | IdentityRiskyUser.ReadWrite.All | Security Administrator |
Best Practice: Use application permissions with certificate authentication for automation. Avoid delegated permissions that require user context.
Common Mistakes to Avoid
Disabling account without revoking sessions
User remains active until tokens expire (up to 90 days)
Always call revokeSignInSessions immediately after disabling
Not checking group membership before action
Automating on VIPs causes executive escalations
Implement VIP/service account guardrails
Using delegated permissions for automation
Requires user sign-in, breaks unattended scenarios
Use application permissions with certificate auth
No rate limiting on bulk operations
False positive cascades can lock out entire departments
Implement circuit breakers and rate limits
Deleting emails without soft-delete first
Legitimate emails permanently lost, compliance issues
Soft-delete to Deleted Items, hard-delete after review period
Not capturing previous state
Cannot rollback accidental actions
Always log previous state before any modification
Summary
Microsoft Graph API provides powerful capabilities for automated incident response, but power requires responsibility. The most effective implementations combine immediate automated actions for low-impact containment with approval workflows for high-impact remediation.
Auto-Approve
Session revoke, OAuth revoke, inbox rule delete
Require Review
Password reset, account disable, email purge
Manual Only
MFA reset, account delete, tenant-wide blocks
Automate Graph API Response with BitLyft AIR
BitLyft AIR orchestrates Microsoft Graph API actions with built-in guardrails, VIP protection, and audit trails — so you get fast containment without the risk.