Force password change for all users in Office 365

​Forcing password change seems to be a frequent request, so here’s how to do it in Office 365. To force a user to change his password on next login, without actually changing the password on his behalf:

Set-MsolUserPassword -UserPrincipalName user@domain.com -ForceChangePasswordOnly $true -ForceChangePassword $true

To force all users to change their password:

Get-MsolUser -All | Set-MsolUserPassword -ForceChangePasswordOnly $true -ForceChangePassword $true

To force a group of users to change their passwords:

Get-MsolUser -All | ? {$_.Country -eq "USA"} | Set-MsolUserPassword -ForceChangePasswordOnly $true -ForceChangePassword $true

Or use any other criteria, as appropriate. Note that you have to use both the ForceChangePassword and ForceChangePasswordOnly parameters. If you skip the ForceChangePasswordOnly, a new password will be generated for the user and you will need to distribute it.

Speaking of this scenario, here’s an old script I used to reset passwords in the format used by Office 365 (i.e. 8 char password, starting with a Capital letter, three lowercase letters and four numbers):

$users = Get-MsolUser –All
$arrMsolUserData = @()

foreach ($user in $users) {

if ($user.UserPrincipalName -eq "user@tenant.onmicrosoft.com") { continue; }
$objProperties = New-Object PSObject

$Password = ""
$Password += ([char[]]"ABCDEFGHIJKLMNOPQRSTUVWXYZ" | Get-Random)
$Password += $(1..3 | % { [char[]]"abcdefghijklmnopqrstuvwxyz" | Get-Random }) -join ""
$Password += $(1..4 | % { [char[]]"0123456789" | Get-Random }) -join ""

Set-MsolUserPassword -UserPrincipalName $user.UserPrincipalName -NewPassword $Password -ForceChangePassword $false

Add-Member -InputObject $objProperties -MemberType NoteProperty -Name "UserPrincipalName" -Value $user.UserPrincipalName
Add-Member -InputObject $objProperties -MemberType NoteProperty -Name "Password" -Value $Password

$arrMsolUserData += $objProperties
}

$arrMsolUserData
$arrMsolUserData | Export-Csv -Path "C:\passwords.csv" –NoTypeInformation

You can exclude the admin account or just filter out the users you need instead of using All. The list of users and new passwords will be exported to CSV, which you can use to redistribute them. Have fun 🙂

P.S. An updated version of the script that uses the Graph SDK for PowerShell can be found here.

74 thoughts on “Force password change for all users in Office 365

  1. Clayont Amelia says:

    Vasil, thank you for this post!

    Use your second cmdlet to force a password reset for everyone the next time they log in. Is there a way to find users who must change their password on next logon but haven’t run through the process yet?

    Not seeing a property from MsolUser or AzureAdUser jump out as the ‘must change password on next logon’ flag, so looking for something similar to AD that I can use.

    Reply
    1. Vasil Michev says:

      You can get this via the Azure AD Module:

      Get-AzureADUser | fl UserPrincipalName,PasswordProfile

      Or Graph:

      https://graph.microsoft.com/v1.0/users?$top=1&$select=id,passwordprofile
      
          "value": [
              {
                  "id": "5993c2f1-be16-416d-a32c-d3432334f823",
                  "passwordProfile": {
                      "password": null,
                      "forceChangePasswordNextSignIn": true,
                      "forceChangePasswordNextSignInWithMfa": false
                  }
              }
          ]
      
      Reply
  2. Alex says:

    I am not sure if this forum is still active, but is there a way to force a password change for all users of a sub-domain only?

    Could I maybe use this and change the Get-MsolUser -All to only get sub-domain users?

    Get-MsolUser -All | Set-MsolUserPassword -ForceChangePasswordOnly $true -ForceChangePassword $true

    Reply
    1. Vasil Michev says:

      Try using Get-MsolUser -DomainName sub.domain.com. Or filter the users in any other way.

      Reply
      1. Karina Caro says:

        Hello Vasil,
        I know this topic is old but I am trying to see how can I force users in a specific group to change their password at next logon through PowerShell. Would appreciate some guidance.
        Thanks

        Reply
        1. Vasil Michev says:

          Simply replace the first two lines in the sample code, Get-MsolGroupMember should do in your case.

  3. Neil Midlane says:

    I’ve tested this and there seems a 10 minute lag before the force password change kicks in which is weird. Tested using the Set-MsolUserPassword -serprincipalname bob@test.net -ForceChangePassword $true -ForceChangePasswordOnly $True

    Reply
  4. Haitham badarin says:

    Thanks for the post, very helpful.
    I was wondering if there’s a way to force a password reset on users who still use a default password? for example forcing those who use a 12345123 to reset theirs?

    Reply
    1. Haitham says:

      Ignore this comment please as it’s repetitive. just noticed your reply to the last comment.
      ThanksVasil.

      Reply
  5. Haitham Badarin says:

    Hi,
    Thanks for the amazing post, Large number of users in my tenant still use a default password which is related to their upn, i want to warn them by forcing a temporary block of accounts for say 2 or 4 hours on certain day if they keep using the default password. how should i do that? how to get users who are still using the default password and how to block them based on this criteria.

    Thanks

    Reply
    1. Rami Hanani says:

      Good Luck Haitham, I think Force change password is very good now.

      Reply
  6. Silver says:

    Hi,

    We have an issue whereby users are able to access O365 with expired passwords. I investigated and found this explanation from a Microsoft forum: “if a user is in the scope of password synchronization, the cloud account password is set to Never Expire. Which means users can continue to sign in to their cloud services by using a synchronized password that is expired in your on-premises environment. Their cloud passwords are updated the next time you change the password in the on-premises environment –> https://answers.microsoft.com/en-us/msoffice/forum/msoffice_o365admin-mso_password-mso_o365b/office-365-hybrid-log-in-after-password-expired/ac61216d-85fd-44f5-911f-a76c35fb4a94

    My question is: How can we ensure that expired passwords are not able to be used on O365?

    Thanks.

    ST

    Reply
  7. Len Ross says:

    Truly a solution written by a programmer, for a programmer, with no empathy for how a non-programmer will receive. Where does one even go to paste this code? I guess if you’re a programmer you just know.

    Reply
    1. Rich says:

      Without wanting to sound like an a*hole, if you don’t recognise PowerShell commands, and basic understanding of a PowerShell script…. you probably shouldn’t be here, This should be the bread and butter of all System Admins and if you’re not comfortable with it, it’s high time you got comfortable with it cause PowerShell is amazing, and is well worth investing your time in getting your head around it.

      Not a programmer, yet I understand it.

      Great Post

      Reply
      1. josef says:

        Well I am a programmer but work more on the linux side.

        And I am working in a small company that uses o367 so that we don’t have technical hazzles.
        As one of my colleages was breached I would like to reset the passwords of my 15 colleagues.

        I can start powershell. But I wonder already how/where I sign in so that powershell knows which users to list.

        But already entering

        GET-MsolUser

        the shell tells me
        “The term ‘Get-MsolUser’ is not recognized as the name of a cmdlet,”

        Reply
  8. PhilFIT says:

    Just a quick note, if you have “PasswordNeverExpires” set to “True” this won’t do a damn thing.
    In my case I had to first run:
    > Get-MsolUser -All | Set-MsolUser -PasswordNeverExpires $false
    Then run
    > Get-MsolUser -All | Set-MsolUserPassword -ForceChangePasswordOnly $true -ForceChangePassword $true

    Reply
    1. Tom Jan says:

      I’ve had opposite experience.
      Coupled with Revoke-AzureADUserAllRefreshToken it does what is intended. User sessions are disrupted and next sign in forces password change. Worked for my tenant even though Get-MsolUser property PasswordNeverExpires is indeed $True.

      Reply
      1. Krisen Kuppusamy says:

        Hi Tom, did you run the Revoke-AzureADUserAllRefreshToken separately or included it as part of Get-MsolUser -All | Set-MsolUserPassword -ForceChangePasswordOnly $true -ForceChangePassword $true
        thanks,
        Krisen

        Reply
      2. Zidong says:

        Not familiar with all these cmdlet, but Revoke-AzureADSignedInUserAllRefreshToke would be easier than Revoke-AzureADUserAllRefreshToken ? We don’t have to prepare an account CSV list ? Right ?

        Reply
  9. Andrea Palazzi says:

    Could you provide a script that is going to force such change for all the members of a specific groups?

    Get-MsolUser -All | ? {$_.Country -eq “USA”} | Set-MsolUserPassword -ForceChangePasswordOnly $true -ForceChangePassword $true

    if a group is 1234@contoso.org….. how the script should look like

    Reply
  10. Daniel Fuentes says:

    Hey Vasil,

    I’m trying to execute a script that will force a specific Group in Azure to change their passwords upon next login, however, after executing it against a test group that just includes myself, it doesn’t seem to be doing anything.

    Can you assist in identifying what I may be doing wrong?

    $users = Get-MsolGroupMember -GroupObjectID “”xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx””

    foreach ($users in $user) {
    Set-MsolUserPassword -UserPrincipalName “$users@domain.com” -ForceChangePasswordOnly $true -ForceChangePassword $true
    }

    Any & all input would be greatly appreciated!

    Reply
    1. Vasil Michev says:

      Your loop is all wrong, try something like this:

      foreach ($user in $users) {
      Set-MsolUserPassword -UserPrincipalName $user.UserPrincipalName -ForceChangePasswordOnly $true -ForceChangePassword $true
      }

      Reply
      1. Simon Hand says:

        hey there

        trying to get this working but im getting error when running this. Need to force the password change for users in a group. ive copied what you have here but no joy

        cannot bind argument to parameter userprincipalname because it is null

        a powershell virgin meself, ive done just a copy of what you have in your reply to Daniel.

        Reply
        1. Vasil Michev says:

          Did you set the $users variable first?

        2. Simon Hand says:

          The error was saying the upn is null. There is no UPN field being populated when you run the command.
          the group doesnt seem to have this column of upn. i got it working by setting it to use the email

          $users = Get-MsolGroupMember -GroupObjectID “”xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx””

          foreach ($user in $users) {
          Set-MsolUserPassword -UserPrincipalName $user.EmailAddress -ForceChangePasswordOnly $true -ForceChangePassword $true

          Is there a risk in using the email address rather than the UPN for this?

        3. Vasil Michev says:

          Oh you’re right, it should be using EmailAddress. That’s what happens when I try to write some script sample from memory 🙂

        4. Simon Hand says:

          haha all good Vasil, appreciate your help. Last one for ye

          i know upn and email can be different. Could i make a mess by running it with the email, is there a risk using the emailaddress instead of UPN?

        5. Vasil Michev says:

          Should be fine, as they are all unique within the tenant.

  11. Tom Johnson says:

    Hello Vasil, do you know if this will work for a hybrid environment?

    Reply
    1. Vasil Michev says:

      Define Hybrid? If passwords are managed/synced from on-premises, you need to change them there.

      Reply
  12. jjako says:

    You can deactivate the option to require a user to change the password when starting the first time, by powershell and in bulk. ?????

    Reply
    1. Vasil Michev says:

      Yes, just use the -ForceChangePassword $false switch

      Reply
  13. Zack says:

    Is there a way to schedule the force password change in Office 365 to be every six months?

    Reply
      1. Zack says:

        Thanks for the response! If people change their passwords outside of the 6th month interval, will that stagger the forced password changes per user? If so that is my dilemma.

        Reply
        1. Vasil Michev says:

          It’s a rolling window, the period gets reset every time the user changes his password.

        2. jjako says:

          You can deactivate the option to require a user to change the password when starting the first time, by powershell and in bulk. ?????

  14. Erik Sheldon says:

    How can I set the flag for password reset on all users on next logon EXCEPT a few I want to name?

    Reply
    1. Vasil Michev says:

      Simply provide a suitable list of users for the $user variable.

      Reply
  15. Jako says:

    Dave, you have to use Set-MsolUserPassword command, not Set-MsolUser

    Reply
  16. Dave says:

    I’ve got the MSOnline module installed but I’m getting an error message:

    A parameter cannot be found that matches parameter name ‘ForceChangePasswordOnly’

    Reply
  17. Nick says:

    Can this be done in powershell if not using Azure AD? I use powershell to set mailbox permissions, etc. but when I attempt these commands I get an error that states ‘Set-MsolUserPassword’ in is not recognized as the name of a cmdlet… ObjectNotFound, CommandNotFoundException.

    Any help would be appreciated.

    Thank you.

    Reply
    1. Vasil Michev says:

      You need the MSOnline module (Install-Module MSOnline).

      Reply
  18. John says:

    Great work, thank you. Has anyone managed to do this from a CSV file for force password change on next logon?

    Reply
    1. Vasil Michev says:

      Hi John, I see you already got the answer on EE, but for any future enquiries:

      Assuming you have a blabla.csv with a column UPN to designate the users:

      Improt-CSV blabla.csv | % { Set-MsolUserPassword -UserPrincipalName $_.UPN -ForceChangePasswordOnly $true -ForceChangePassword $true }

      Reply
  19. Bob says:

    Vasil,

    can we force notification (standard one like 14 days) for password change for a user or groups?

    thanks

    Reply
  20. Scott C says:

    No password writeback.

    For the three users that were not prompted immediately:
    User1 was prompted about 3 hours later within Outlook. Changed his password on the O365 portal. Outlook accepted the new password. He did not change the password on his phone yet it continued to work with the old password.
    User2’s email stopped working. He logged onto webmail and was prompted to change password. He started his MacBook laptop and the Outlook application. He was not prompted to change the Outlook for MAC password yet mail flowed to and from the application.
    User3 didn’t attempt to access email via Outlook till the next morning at which time he was prompted to reset the password.

    We do not use federation nor do we sync Azure passwords locally but this link enables users to change their own password. https://account.activedirectory.windowsazure.com/ChangePassword.aspx

    I don’t really expect you to troubleshoot my problems, I just wanted to get them out there in case you or someone else had any quick idea why they were happening. The delay in triggering the change is a problem but the inconsistency is the real issue.

    Reply
    1. Vasil Michev says:

      OK, I get it now, and this is pretty much expected. There’s a lot of caching happening on the backend and the middle-tier, so it’s normal that credentials don’t expire immediately. It’s one of the reasons why simply changing the password for a “leaver” is not a complete solution.

      In addition, the applications themselves can store credentials and even cause issues by trying to reuse the old password.

      Reply
      1. me says:

        M$ have blown security right out of the water with 365. Once a user is comprised in your business you are fucked. That user sends out an email to all other users who then may enter their password to what looks like a 365 login screen sent by your ceo. Fucked. Try disabling all users and prompting for password resets “immediately”. User credentials are signed and last for as long as the default 365 setting is, which is generally an hour. In that hour, I can tell you, the hackers run rampant and gather as much of your data as possible before they are finally closed out. Users get comprised left and right in a large organisation long before you can log into mso or other portal where the process of “security” is so obfuscated in the typical M$ garbage that it is impossible to gather what has been done, shut if off by pulling a plug immediately and to take back control. This is a massive fuck around and M$ is to blame. I mean remote powershell active by default for ALL users? Seriously wtf?!?

        Reply
  21. Scott C says:

    An addendum to my question.
    The directions above say that it will force a password change at next login.
    Does that mean Office 365 login or PC login?
    For the two of us who had our passwords expired, it was logoff / login to Office 365 but I can believe that there could be something cached requiring a PC logoff / login.
    The other test subjects couldn’t logoff their PC till the end of the day so I’ll see then.

    Reply
    1. Vasil Michev says:

      It means O365 login. Do you have the password writeback feature enabled?

      Reply
  22. Scott C says:

    This is beating the crap out of me, I’ve tried both:
    Set-MsolUserPassword -UserPrincipalName username@our-domain.com -ForceChangePasswordOnly $true -ForceChangePassword $true
    AND
    Set-MsolUserPassword -ObjectID -ForceChangePasswordOnly $true -ForceChangePassword $true
    It worked for two users (myself included) but not for three others.
    I get no error, it looks like the command was issued.
    When I run:
    Get-MsolUser -userprincipalname username@our-domain.com | select DisplayName, LastPasswordChangeTimeStamp,@{Name=”PasswordAge”;Expression={(Get-Date)-$_.LastPasswordChangeTimeStamp}}
    It returns valid information (user / last changed / pw age) so I’ve got the correct user principal name.
    Get-MsolUser returns the entire user list so it’s not an authentication issue with me.
    I’m stumped… any thoughts would be appreciated.

    Reply
  23. nat c says:

    this can only be done through scripts? why doesn’t microsoft have an easy way to do something so important!

    Reply
    1. Vasil Michev says:

      Which part exactly? Bulk changing passwords is available in the Admin portal. If you just want to toggle the reset password flag, you have to use PowerShell.

      Reply
  24. Hal says:

    Really good post! For a newbie to Exchange administration (forced really), this is very helpful.

    Curious if there is a way to reverse the force all users to reset their password. Replacing True with False creates new passwords.

    Thank you!

    Reply
    1. Vasil Michev says:

      No, once the flag is set, you cannot unset it.

      Reply
  25. Micah Jones says:

    How do you specify all the users of a specific security group? I’ve been reading powershell articles all morning and haven’t found the answer.

    Reply
    1. Vasil Michev says:

      You will have to use the Get-MsolGroupMember or the Get-DistributionGroupMember cmdlets. That’s assuming you are talking about group that exists in O365.

      Reply
    2. John Davies says:

      Did you manage to script this? I know it is going back a while.

      Thanks

      Reply
  26. Ricky says:

    It would be nice if you would show where these scripts are utilized within the Office 365 Admin environment.

    Reply

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.