3 min read
Handling user password change and expiration issues with Office365 and ADFS - Part 1
Recently I’ve setup a Office365 Service with ADFS (Active Directory Federation Service) and a DirSync Server.
Sadly I forgot about a huge disadvantage in this architecture, due to using ADFS as an authentication provider, it’s not possible to change a users password. The communication form the local ActiveDirectory environment to the cloud based Office365 services is only one directional.
That’s why there are only 2 options yet to handle the user password change and expiration:
- Disable the users password expiration or
- Set up a enterprise connected platform to deal with the password change and expiration.
At this time option 1 is active in my environment and option 2 is my goal.
In this post series want to show you the solution I’ve developed.
Let’s start with password expiration. Because Office365 doesn’t handle password expiration, that’s why I have to use another channel to show the users on which date their passwords expire: Let’s do it with an bulk e-mail job.
Password Expiration E-Mail Job
This part isn’t a lot of effort. There are 2 requirements, one is a must and the other is optional:
- Active Directory Module for PowerShell
- To create scheduled job on your windows server I've built the function `Add-SheduledTask` which is part of my PowerShell Profile project, you can either download the function or install this project on your windows server.
Now the script:
<#
$Metadata = @{
Title = "Send Password Expiration Reminder"
Filename = "Send-PasswordExpirationReminder.ps1"
Description = ""
Tags = "powershell, script, jobs"
Project = ""
Author = "Janik von Rotz"
AuthorContact = "http://.janikvonrotz.ch"
CreateDate = "2013-08-08"
LastEditDate = "2013-11-25"
Version = "2.1.0"
License = @'
This work is licensed under the Creative Commons Attribution-NonCommercial-NoDerivs 3.0 Unported License.
To view a copy of this license, visit http://creativecommons.org/licenses/by-nc-nd/3.0/ or
send a letter to Creative Commons, 444 Castro Street, Suite 900, Mountain View, California, 94041, USA.
'@
}
#>
try{
#--------------------------------------------------#
# modules
#--------------------------------------------------#
Import-Module ActiveDirectory
#--------------------------------------------------#
# settings
#--------------------------------------------------#
$TriggerDays = 25, 10, 5, 1
$SendLinkOnDays = 25,10, 5, 1
$DaysBeforeDisablingUsersWithPasswordNeverExpires = 180
$ADGroup = "S-1-5-21-1744926098-708661255-2033415169-36648" # Memberof GroupName should be "SPO_PasswordNotification"
#--------------------------------------------------#
# main
#--------------------------------------------------#
# get mail config
$Mail = Get-PPConfiguration $PSconfigs.Mail.Filter | %{$_.Content.Mail | where{$_.Name -eq "PasswordReminder"}} | select -first 1
# get days until password expires
$MaxDays = (Get-ADDefaultDomainPasswordPolicy).MaxPasswordAge.Days
if($MaxDays -le 0){throw "Domain 'MaximumPasswordAge' password policy is not configured."}
# Set days when an email should be sent to inform the users
$TriggerDays = 25, 10, 5, 1
$SendLinkOnDays = 25,10, 5, 1
foreach($TriggerDay in $TriggerDays){
# Memberof GroupName should be "SPO_PasswordNotification"
Get-ADGroupMember $ADGroup -Recursive |
Get-ADUser -Properties Enabled, lastLogonTimestamp, PasswordNeverExpires, PasswordLastSet, Mail, DisplayName |
Select *, @{L = "PasswordExpires";E = {
if($_.PasswordNeverExpires){
$DaysBeforeDisablingUsersWithPasswordNeverExpires - ((Get-Date) - ($_.PasswordLastSet)).Days
}else{
$MaxDays - ((Get-Date) - ($_.PasswordLastSet)).Days
}
}} |
where{($_.Enabled -eq $true) -and ($_.PasswordExpires -eq $TriggerDay)} | %{
# set subject
$Subject = "Passwort Erinnerung: $($_.DisplayName) ihr Passwort läuft in $($_.PasswordExpires) Tagen ab"
$BodyFont = "font-size: 11pt; font-family: Calibri"
# create mail message
$Body = "<p style = ""$BodyFont"">Guten Tag $($_.DisplayName) <br/> <br/> Ihr Passwort läuft am $(Get-Date (Get-Date).AddDays($_.PasswordExpires) -Format D) ab.</b></p>"
if($SendLinkOnDays -contains $TriggerDay){
$Body += "<p style = ""$BodyFont"">Bitte ändern Sie das Passwort bevor es abläuft. Rufen Sie dazu die folgende Seite auf: <a href=""https://vbluzern.sharepoint.com/Support/_layouts/15/start.aspx#/SitePages/Passwortwechsel.aspx"" target=""_blank"">Link</a></p>"
}
$Body += "<p style = ""$BodyFont"">ACHTUNG! Dieses E-Mail wurde von einem unbeaufsichtigtem Konto verschickt, Antworten an den Sender dieser E-Mail werden nicht bearbeitet.</p>"
# send mail
Write-PPEventLog "$($MyInvocation.InvocationName)`n`nSend password reminder to $($_.Mail)" -WriteMessage -Source "Send Password Expiration Reminder"
Send-MailMessage -To $_.Mail -From $mail.FromAddress -Subject $Subject -Body $Body -SmtpServer $Mail.OutSmtpServer -BodyAsHtml -Priority High -Encoding ([System.Text.Encoding]::UTF8)
}
}
}catch{
Write-PPErrorEventLog -Source "Send Password Expiration Reminder" -ClearErrorVariable
}
https://gist.github.com/6184059
For the memberof Group I recommend to use the SID instead of the DN. I’ll show you how the get the SID:
PS C:Userssa-spadmin> (Get-QADGroup "SPO_PasswordNotification").Sid
BinaryLength AccountDomainSid Value
------------ ---------------- -----
28 S-1-5-21-1744926098-708661255-2033415169 S-1-5-21-1744926098-708661255-2033415169-36648
PS C:Userssa-spadmin> Get-QADUser -MemberOf "S-1-5-21-1744926098-708661255-2033415169-36648"
Update
Categories: Office 365 , scriptingTags: activedirectory , expiration , federation , mail , office365 , password , service
Edit this page
Show statistic for this page