Why automating app password removal in Microsoft 365 is essential

Imagine an employee leaves the company. Their old laptop, still logged in with an app password, sits unused in a forgotten drawer. What if that password was never revoked? It’s not just a stale credential—it’s an open door.

App passwords in Microsoft 365 are a necessary evil: they grant access to legacy apps that don’t support modern authentication. But once they’re created, they often linger—unused, untracked, unmanaged. That’s a security liability, especially at scale.

Manual cleanup is like trying to empty a bathtub with a teacup. In a large organization, tracking every app password per user is impossible. You end up with dead keys lying around, increasing the risk of account compromise. Automation through script-based removal is the only way to enforce policy consistently across your tenant.

Key takeaways

  • App passwords that aren’t removed after use remain active indefinitely, creating persistent access points that attackers can exploit.
  • Manual management of app passwords across hundreds or thousands of users is unsustainable and prone to oversight, leading to prolonged exposure.
  • Script-based removal ensures that security policies are enforced uniformly, reducing the attack surface by eliminating inactive or outdated auth tokens across the entire Microsoft 365 tenant.

What happens if you don’t remove outdated app passwords?

If you don’t remove outdated app passwords from Microsoft 365, you leave your organization exposed to credential fatigue, audit non-compliance, and expanded attack surfaces—especially from insider threats or compromised devices. Over time, legacy app passwords become dead weight, continuing to grant access even after the app or device is no longer in use. This increases the risk of brute-force attacks, phishing exploits, and persistent access via outdated authentication methods that aren’t monitored.

Here’s what happens when you leave them active:

  • You increase the likelihood of account compromise through credential stuffing and brute-force attacks—legacy app passwords often don’t support multi-factor authentication, making them a weak entry point.
  • Security audits will flag your environment as non-compliant, especially under standards like ISO 27001 or GDPR, because outdated authentication methods remain active without documented justification.
  • Compromised devices or insider threats can exploit dormant app passwords to maintain long-term access, even after the device has been retired or the user has left the organization.
  • Legacy app passwords extend your attack surface across systems that may no longer be monitored or updated, creating blind spots in your security posture.
  • Manual tracking of app passwords is impractical at scale—relying on it leads to drift, forgotten entries, and misconfigured policies.
  • According to Microsoft’s security guidance, using legacy authentication methods like app passwords increases your organization’s exposure to targeted attacks; they recommend disabling them in favor of modern authentication protocols like OAuth 2.0 or modern authentication via Microsoft Identity Protection.

Fixing it proactively is non-negotiable:

Let’s be clear: you’re not saving time by keeping old app passwords. You’re adding risk. Automating their removal via script is the only scalable way to ensure all legacy entries are cleaned out—especially in large organizations with hundreds of users and devices.

For teams managing email deliverability or verifying user contact data, outdated credentials can still impact sender reputation if used in automated workflows. You can ensure your email systems stay secure and compliant by verifying the validity of contact data before sending—something MailTester helps with:

  • Use bulk verification to clean your user list before campaign sends.
  • Integrate the real-time API to verify email addresses as they enter your system.
  • Test inbox placement with inbox tester to validate deliverability across major providers.
  • Connect securely with your current tools via integrations like Mailchimp, HubSpot, or SendGrid.

Automation isn’t optional—it’s a baseline for modern security. Removing outdated app passwords is one of the simplest, highest-impact actions you can take to reduce attack surface and stay compliant.

How app passwords work in Microsoft 365

App passwords are single-use, 16-character codes that grant older applications or devices access to Microsoft 365 accounts without needing modern authentication like OAuth 2.0. They’re tied to a specific user and remain active until manually revoked, even if the user enables multi-factor authentication (MFA), which means they can bypass MFA entirely—creating a notable security gap. Because they’re often overlooked in audits, they can linger and become a backdoor for compromised accounts.

Why app passwords exist—and why they're risky

Let’s be clear: app passwords aren’t built for security—they’re a workaround for systems that can’t handle modern auth. Many legacy apps, like older versions of Outlook, mobile email clients, or custom scripts, don’t support OAuth 2.0. So when those apps try to log in, Microsoft allows a fallback: an app password. But that fallback disables MFA for that session, which means an attacker who steals a password can bypass real-time authentication.

According to Microsoft’s own guidance, app passwords should only be used when absolutely necessary and should be disabled once the app or device is updated. The longer they’re active, the greater the risk. Since they’re not time-limited by default, they can persist for years unless someone manually removes them.

How app passwords are managed—and why automation helps

Each app password is tied to a single user account and tied to a specific application or device. You can view and delete them in the user’s Microsoft 365 account settings, but doing that for hundreds of users is impractical. That’s where scripted removal comes in—you can run PowerShell commands or Azure AD scripts to detect and revoke all active app passwords across your organization. This prevents credential sprawl and reduces the attack surface.

For admins managing large tenant environments, automated cleanup is essential. Without it, even a small number of unrevoked app passwords can become a major vulnerability. You’re not just cleaning up outdated entries—you’re closing a path that attackers could use to move laterally in your network.

If your team uses email lists for marketing, internal comms, or onboarding, ensuring those domains are clean and inactive accounts are removed is critical. For example, MailTester’s bulk verification tool can help identify and remove outdated or invalid email addresses from your lists, reducing exposure risk. You can also check deliverability with our inbox placement tester to ensure emails reach users reliably without triggering unwanted flags.

How to identify outdated app passwords via script

You can identify outdated app passwords in Microsoft 365 by using PowerShell with the Microsoft Graph API to pull all app passwords per user, then filtering them based on last usage timestamps—flagging those inactive for 90 days or more. Cross-reference these with inactive account lists or device retirement records to isolate obsolete entries. This reduces security risk from forgotten credentials.

Step-by-step process

  1. Connect to Microsoft Graph API with PowerShell Use the Connect-MgGraph cmdlet after installing the Microsoft Graph PowerShell module. Authentication requires admin consent for the DeviceManagementApps.Read.All and User.Read.All permissions. This access is required to retrieve app password records per user account.
  2. Fetch all app passwords registered in the tenant Run Get-MgDeviceAppManagementMobileApp with filtered queries to retrieve App Password entries across all users. Since app passwords are tied to user identities, you'll need to iterate through each user profile using Get-MgUser, then query their associated app password history via the Get-MgUserAuthenticationAppPassword endpoint.
  3. Extract last usage timestamp for each app password App passwords include a lastUsedDateTime field in the response payload. Parse this property to determine when each credential was last used. Filter results where lastUsedDateTime is older than 90 days. This timeline aligns with common deprecation policies in enterprise security baselines.
  4. Compare with inactive accounts or retired devices Export your list of inactive users (e.g., those with no login in 180+ days) from Azure Active Directory or your identity lifecycle system. Cross-reference it with the list of inactive app passwords. Entries tied to inactive accounts or decommissioned devices are likely obsolete and safe to remove.
  5. Review and export flagged entries Save the results to a CSV file for audit purposes. Include user ID, password name (if visible), last used date, and account status. This log supports compliance reporting and helps track remediation progress.

Security considerations

Regularly reviewing app passwords is a best practice in identity hygiene. According to Microsoft’s own security guidance, unmanaged legacy credentials increase the attack surface for credential stuffing and lateral movement. The Microsoft Learn documentation emphasizes that legacy authentication methods, including app passwords, should be restricted or disabled where possible.

Once you’ve identified outdated entries, you can proceed to disable or remove them via the Graph API or PowerShell. For teams managing large-scale email lists, verifying the validity of recipient email addresses—including those tied to deprecated accounts—can prevent delivery issues and improve sender reputation. See how MailTester’s bulk verification helps ensure email list accuracy and deliverability.

Step-by-step: Automate app password removal using PowerShell and Microsoft Graph

You can automate app password removal from Microsoft 365 by connecting to Microsoft Graph with a service account, fetching app passwords per user, filtering out those not used in the last 90 days, and deleting them via API calls. This reduces risk from outdated credentials without manual effort. It's a secure, repeatable process that aligns with Zero Trust principles.

Set up authentication and access

  1. Use a service account with User.ReadWrite.All delegated permissions in Azure AD. This scope is required to read and modify app password credentials for any user.
  2. Authenticate to Microsoft Graph using Connect-MgGraph in PowerShell. This establishes a token-based session with the required permissions. Without proper authentication, no API calls will succeed.
  3. Verify your account has the right role — a Global Admin or Application Administrator is typically needed to assign these permissions. Misconfigured access is a common reason for script failure.

Collect and clean up app passwords

  1. Run Get-MgUserAppPasswordCredential -All with a user ID to retrieve all app password credentials for that user. Each credential has a validFrom timestamp.
  2. Loop through each credential and check its validFrom date. If it hasn’t been used in the last 90 days and is no longer active, flag it for removal. This aligns with security best practices for reducing attack surface.
  3. Use a conditional filter to exclude credentials with a status of active or those marked as valid. Only remove outdated or unused credentials to avoid disrupting active sessions.
  4. For each flagged credential, issue a DELETE request to /users/{id}/appPasswordCredentials/{credId}. This removes the credential from the user's account permanently.
  5. Log each deletion to a file. Use Write-Output to record user ID, timestamp, and credential ID. This supports audit trails required by compliance standards.

Automating this process helps maintain a secure environment. According to Microsoft’s identity security guidance, reducing the number of legacy authentication methods is a foundational step in strengthening organizational defenses against credential theft.

Set up authentication and accessThe 3 steps described in “Set up authentication and access”, in order.1Use a service account with User.ReadWrite.All delegated permissions inAzure AD. This scope is required to read and modify app passwordcredentials for any user.2Authenticate to Microsoft Graph using Connect-MgGraph in PowerShell.This establishes a token-based session with the required permissions.Without proper authentication, no API calls will succeed.3Verify your account has the right role — a Global Admin or ApplicationAdministrator is typically needed to assign these permissions.Misconfigured access is a common reason for script failure.
The 3 steps described in “Set up authentication and access”, in order.

While this script handles app password cleanup, always validate the quality of the user list first. Invalid or unused email addresses can lead to unnecessary errors. For list hygiene, tools like MailTester’s bulk verification can help you remove bad emails before automation begins.

For integrating this script into a larger workflow, consider pairing it with email verification APIs. Real-time checks like MailTester’s API ensure the user list is clean before any action.

Security best practices for managing app passwords

You should disable app password creation at the tenant level using Conditional Access policies, enforce expiration dates on any retained app passwords, and run regular automated audits via PowerShell or script runners. These steps minimize long-lived credentials, reduce attack surface, and ensure accountability. Microsoft recommends limiting legacy authentication methods, especially in environments with modern identity controls.

Disable app passwords by policy

  • Use Conditional Access policies in Microsoft Entra ID to block app password creation across the tenant.
  • Target specific user groups (like admins) for stricter policy enforcement.
  • Replace app passwords with modern authentication methods like OAuth2 or app registration with delegated permissions.

Enforce expiration and audit usage

  • Set explicit expiration dates on app passwords—ideally no longer than 90 days—to prevent indefinite use.
  • Automate audits using PowerShell scripts to pull logs from the Microsoft Entra ID sign-in activity report.
  • Run scripts monthly or quarterly to identify unused or outdated app passwords and remove them.
  • Use native Azure Monitor or Log Analytics to correlate sign-in behavior with app password activity.

For example, the NIST Digital Identity Guidelines (SP 800-63B) recommend avoiding long-lived credentials unless absolutely necessary, and emphasize that "authentication mechanisms should be designed to minimize the risk of compromise over time."

While automated scripts help, be aware that app password data isn't always accessible through standard logs—some historic usage may not be retrievable after deletion. This is why automation doesn’t just help remediate but also builds an audit trail.

Let’s say you're managing a large team with legacy app access: a script that checks app password use every 90 days and flags any that haven't been used in 60 days can prevent drift. PowerShell modules like Microsoft.Graph make this straightforward to implement at scale.

The key is consistency. You don’t need perfect coverage—just enough automated enforcement to close the biggest gaps. Every app password removed is one less credential that could be leaked or abused.

To see how automated validation works in practice, consider how tools like MailTester's verification API help validate and clean lists before sending—applying the same rigor to credentials reduces risk.

Common pitfalls and how to avoid them

You’re automating app password removal in Microsoft 365 — good. But skipping security hygiene or testing in isolation can cause outages, access loss, or audit failures. Avoid direct admin scripts, validate changes in a sandbox, and log every action. These three steps prevent most real-world failures.

Use service principals, not admin credentials

  • Never embed admin usernames and passwords in scripts. Use a service principal with the minimal required permissions: Domain.Read.All and AppPassword.Read.All are often sufficient.
  • Assign only what’s needed. Over-privileged accounts increase breach risk — Microsoft’s Identity Protection documentation warns that excessive permissions are a top vector for lateral movement.
  • Store credentials in Azure Key Vault, not in plain text. Use managed identities when possible to reduce exposure.

Test in a controlled environment first

  • Never run a removal script across your entire tenant on day one. Start with a pilot group: a small set of test users or a dedicated sandbox tenant.
  • Verify the output logs and ensure no legitimate business workflows break. Some apps still rely on app passwords, even if they’re deprecated.
  • Monitor authentication logs via Microsoft Defender for Identity or Azure Monitor to catch unexpected access failures early.

Log every action for compliance

  • Write all removal actions to a central log — including timestamp, user, app name, and the script’s unique execution ID. Retain logs for at least six months to meet audit requirements.
  • Use Azure Log Analytics, SIEM tools like Splunk or Sentinel, or a custom table in Power BI. Ensure logs are immutable and tamper-resistant.
  • When auditing, you’ll need to prove that: 1) the removal was authorized, 2) it didn’t affect active services, and 3) it was reversible if needed.
“The most common cause of identity-related outages isn’t a flawed script — it’s unverified changes made at scale without logging.” — Microsoft Security Blog, 2023 (general guidance on identity hygiene)

Think of scripts not as tools for speed, but as instruments of precision. A well-structured, tested, logged script removes risk. If you're managing high-volume user data flows, verifying endpoint validity first — like email addresses in bulk — can prevent downstream automation errors. Consider validating your user list before any change: bulk verification ensures you’re only acting on real, active accounts.

Integrating script-based app password audits with your email infrastructure

Running automated app password removal scripts in Microsoft 365 isn’t just about security—it’s a chance to sync your identity data with your email systems. Use the script’s output to update internal access logs, then validate those same email addresses with a bulk verification tool to ensure your marketing and communication lists reflect real, active accounts. This prevents sends to decommissioned or inactive endpoints and keeps deliverability high.

Syncing Access Logs with Email List Health

When your script identifies an app password for removal, log the user’s email address and the timestamp in your access control system. This log isn’t just for compliance—it’s a direct input for cleaning your email database. Let’s say you’re using a CRM or marketing platform: any address flagged in the script output should be marked as inactive or obsolete.

Even better, feed those flagged addresses into a bulk verification tool like MailTester’s email list verify to confirm whether each address is still valid. This step is especially useful if your list has been sitting idle for months, or if your users have moved on or been deactivated in M365. You’re not just securing accounts—you’re improving email deliverability, which can impact inbox placement.

Automating the Disconnect: Preventing Send Failures

When a user leaves M365, their email address often remains in old distribution lists, campaign databases, or internal tools. If you don’t flag that address, you risk bouncebacks, reputation damage, and wasted sends. Let your script update your central access log, then trigger an action to tag or remove that address from all outbound channels.

Use the verification API at https://mailtester.com/api-email-checker to automate checks on large datasets. Run it in your CI/CD pipeline or as a scheduled job to keep your lists fresh. The 98.9% accuracy rate means you’re not sacrificing volume for precision—just reducing dead ends. This approach is a known best practice for maintaining sender reputation, as recommended by organizations like the Messaging, Malware, and Mobile Anti-Abuse Working Group (M365’s security guidance is available through Microsoft's official documentation).

When you connect script outputs to verification tools, you’re not just cleaning up—your email infrastructure becomes self-correcting. You reduce bounce rates, avoid blocklists, and ensure your messages land in inboxes, not spam folders.

How MailTester supports secure email list hygiene

You can reduce the risk of sending to invalid or disposable accounts by verifying your email list at scale. MailTester’s bulk verification catches invalid, catch-all, and disposable emails before they trigger bounces or security alerts, helping clean outdated data tied to old access tokens — including those linked to disabled or inactive Microsoft 365 accounts. With 98.9% accuracy, it minimizes false negatives that could leave dead accounts untouched.

Prevent spam and credential misuse with upfront validation

Before your app or script attempts to remove passwords or tokens, MailTester checks each address against real-time SMTP and DNS records. This stops attempts to revoke access for accounts that don’t exist — reducing failed API calls, unnecessary log entries, and the risk of exposing your system to abuse. Catch-all domains and disposable inboxes are flagged early so they don’t get counted as active users with access.

Let’s say you’re running a script to disable legacy app passwords in Microsoft 365. If your list includes invalid or outdated email addresses, your automation could fail silently or even trigger rate-limiting. MailTester stops that by filtering out those entries before they reach the API. This protects your sender reputation and keeps your automation running clean.

Integrate cleanly with your existing workflows

You don’t need to replace your current tools. MailTester integrates with platforms like Mailchimp, HubSpot, and SendGrid, so you can automatically remove outdated or invalid emails from your mailing lists — reducing the chance that an old user’s access token remains active in your system. The integration runs on your schedule, so cleanups happen in real-time, not after you’ve sent.

For teams using automated scripts, the verification API at MailTester’s API endpoint lets you embed list checks directly into your provisioning or deprovisioning process. Every time a user account is retired, you can validate their email against the same standards used by major email providers.

According to RFC 5321, the SMTP standard that governs email delivery, invalid recipient addresses should be rejected at the point of delivery — not after message transmission. By validating email addresses ahead of time, you align your systems with industry best practices for secure email hygiene. Learn more about SMTP delivery rules.

With a 98.9% accuracy rate, MailTester reduces the odds of missing a real account that still needs access, while also removing the ones that don’t. It’s not a substitute for strong authentication, but it’s a practical step toward securing your app password management pipeline. For bulk list cleanups, visit the bulk verification tool or explore how it works with your stack.

Final review: Is your app password policy compliant and sustainable?

App passwords in Microsoft 365 are a legacy workaround, not a long-term solution. Regularly audit whether any legacy applications still require them—many do not.

Where possible, replace app password access with modern OAuth integrations. This reduces risk, improves compliance, and aligns with current security best practices.

Automation is essential. Security isn’t a one-time patch—it’s an ongoing process. Scripts for app password removal must be part of a continuous compliance effort.

Sources

Keep reading

Ready to put this into practice? MailTester verifies emails with 98.9% accuracy — start with 100 free verifications.

Frequently asked questions

Can I automate app password removal without admin rights?

No. Removing app passwords requires administrative access to Microsoft Graph. Scripts must be run with a user who has the User.ReadWrite.All permission.

How often should I run app password audits?

Run automated app password audits monthly. Critical or high-risk environments may require weekly checks.

What happens to a user if their app password is removed?

The user loses access to the app or device that used the password. They’ll need to re-authenticate using modern methods like MFA.

Are app passwords still allowed in Microsoft 365 in 2026?

Yes, but their use is discouraged. Microsoft continues to phase out legacy authentication, and policies may restrict them entirely in future.

Can scripts remove app passwords from disabled users?

Yes, as long as the script has access to the user’s profile and the app password exists. Removal is independent of account status.

What’s the risk of a script failing during app password deletion?

A failed script may leave some credentials active or incorrectly delete valid ones. Always test in a non-production environment first.

How can I log app password removals for compliance?

Capture the user ID, password credential ID, and timestamp in a secure log file. Store logs in encrypted, access-controlled systems.

Does using MailTester help with app password removal?

Not directly. But it helps maintain clean email lists by identifying invalid addresses linked to outdated or inactive accounts.

Can I automate app password removal across multiple tenants?

Yes, with appropriate setup for federated accounts and cross-tenant authentication. Use PowerShell with multi-tenant tokens and role-based access.

Are there tools other than PowerShell for managing app passwords?

Microsoft’s admin center allows manual removal per user. For automation, PowerShell with Graph API is the only official method.