Depends on the level of automation/sophistication you are aiming for. Simply generating the TAPs is quite easily done via PowerShell or the Graph API. Distributing them is the tricky part, as you need to have a channel to communicate with the user outside of M365. What are you planning for on that front?
Automate TAP Passwords in Bulk and Email them out
I am looking for feedback on how other have handle generating TAP codes for users in bulk then sending the code to the user. I have been reading about this and it looks like I need an automation account etc..Are they any products that hook into Entra that could help with this process?
Microsoft Security | Microsoft Entra | Microsoft Entra ID
1 answer
Sort by: Most helpful
-
Vasil Michev • 121.4K Reputation points • MVP • Volunteer Moderator
2025-08-18T16:28:03.22+00:00 -
rr-4098 • 2,076 Reputation points
2025-08-18T17:54:32.8133333+00:00 Now I am not a Powershell expert and the people who will be using this have even less PowerShell experience. To send the TAP password to the user I was thinking it could read the value from the CSV then insert it into a email body and send it via PowerShell using o365 secure mail with a specific key work in the subject line. This is why I was looking for a App etc... with a GUI interface that could help users with this since I will not be the main one using it. Please note, when generating a TAP password in bulk it could be up to 200+ users at a time.
-
Vasil Michev • 121.4K Reputation points • MVP • Volunteer Moderator
2025-08-19T06:19:54.9733333+00:00 That part is also doable, but if you are looking for a ready-to-use solution, I don't believe there's any free one out there. Most of the M365 management/governance suites will do, but they come at a cost.
-
rr-4098 • 2,076 Reputation points
2025-08-20T14:24:40.02+00:00 I am going to see if our department already has any 365 plans that offer the enhanced governance (probably not). In the meantime, any suggestions on how to setup the scripts to generate TAP passwords in bulk then email the information to the user? I have been using Google but didn't know if others had a better way to approach this using scripts.
-
Vasil Michev • 121.4K Reputation points • MVP • Volunteer Moderator
2025-08-21T07:30:06.6166667+00:00 You can use the
New-MgUserAuthenticationTemporaryAccessPassMethod
cmdlet to generate the TAP, the example below takes input from CSV file and generates TAP for each user:Connect-MgGraph $users = Import-CSV blabla.csv foreach ($user in $users) { $uTap = New-MgUserAuthenticationTemporaryAccessPassMethod -UserId $user.ID }
The CSV file must have a column ID to designate the user, either by its objectID or the UPN value. You can modify the TAP settings via the
-LifetimeInMinutes
parameter (to change it from the default 60 minutes) and/or the-IsUsableOnce
parameter (if you want it to be reusable).For the sending email part, you can use a number of methods, see for example this article by Tony: https://practical365.com/send-email-powershell-graph/
The issue, as alluded to in my previous comments, is that you need to have the address for the user beforehand, as the assumption is that they cannot use their work email for that (i.e. we cannot just send it to the UPN value you provided within the CSV). One possible solution is to add an
Email
column to the CSV, designating the "correct" email address for each user. We can then update the sample above to something like:Connect-MgGraph -Scopes "UserAuthenticationMethod.ReadWrite.All","Mail.Send" $users = Import-CSV blabla.csv foreach ($user in $users) { $uTap = New-MgUserAuthenticationTemporaryAccessPassMethod -UserId $user.ID #Email code goes here, stupid forum messes up the formatting so check the link in the comment below Send-MgUserMail -UserId ******@domain.com -BodyParameter $emailParams }
The example is of course very basic, with zero error handling, no logging capabilities, no report being generated, etc. It also makes use of the admin's account for sending the emails, which is probably not something you'd want in real life...
-
Vasil Michev • 121.4K Reputation points • MVP • Volunteer Moderator
2025-08-21T07:31:51.5833333+00:00 Pfft, I hate this forum... half the code above was lost. Please check this gist instead: https://gist.github.com/michevnew/1babff817c792b938b35ec9434212d2c
-
rr-4098 • 2,076 Reputation points
2025-08-22T17:59:34.5733333+00:00 Thank you for the great feedback. As for the users email address we do populate new users auth methods field with their home email address. Mainly used for SSRS right now.
-
Vasil Michev • 121.4K Reputation points • MVP • Volunteer Moderator
2025-08-23T06:38:32.85+00:00 You can certainly leverage those bits as well, here's an example:
$userEmail = Get-MgUser -UserId ******@domain.com -Property otherMails | select -ExpandProperty OtherMails
or if you plug it into the "full" code:
Connect-MgGraph -Scopes "UserAuthenticationMethod.ReadWrite.All","Mail.Send" $users = Import-CSV blabla.csv foreach ($user in $users) { $uTap = New-MgUserAuthenticationTemporaryAccessPassMethod -UserId $user.ID $userEmail = Get-MgUser -UserId $user.Id -Property otherMails | select -ExpandProperty OtherMails #Email code goes here, leverage $userEmail for the user's address Send-MgUserMail -UserId ******@domain.com -BodyParameter $emailParams }
-
rr-4098 • 2,076 Reputation points
2025-08-26T18:08:48.2066667+00:00 Thanks for the other email the user home email address is listed under auth methods not otheremail
-
rr-4098 • 2,076 Reputation points
2025-08-26T19:27:46.5533333+00:00 Ok I am making . Progress when I use the code from Git I keeping access denied for send-mguser and yes I did update the values to reflect my csv
Connect-MgGraph -Scopes "UserAuthenticationMethod.ReadWrite.All","Mail.Send" $users = Import-CSV blabla.csv foreach ($user in $users) { $uTap = New-MgUserAuthenticationTemporaryAccessPassMethod -UserId $user.ID $emailBody = @" <html> <body> <p>Here is your new TAP</p> <p>$($uTap.TemporaryAccessPass)</p> </body> </html> "@ $emailParams = @{ Message = @{ Subject = "Your new Temporary Access Pass" Body = @{ ContentType = "HTML" Content = $emailBody } ToRecipients = @( @{ EmailAddress = @{ Address = $user.Email } } ) } SaveToSentItems = $false } Send-MgUserMail -UserId ******@domain.com -BodyParameter $emailParams }
-
Vasil Michev • 121.4K Reputation points • MVP • Volunteer Moderator
2025-08-27T06:17:27.5966667+00:00 You need to have permissions to send as the ******@domain.com address. If this is the same user you are running the script with, the Mail.Send scope we have listed above should be sufficient. If it is a different user/mailbox, you need to be granted Send As permissions, and we need to change the scope to Mail.Send.Shared.
Lastly, we will have to add the from field to the JSON:
"from": { "emailAddress": { "address": "******@domain.com" } }
Here's a reference article with more detail: https://learn.microsoft.com/en-us/graph/outlook-send-mail-from-other-user
-
rr-4098 • 2,076 Reputation points
2025-08-27T20:22:07.83+00:00 Ok this may be a stupid question but so one user would need to have send as permissions on all mailbox recreated in order for this to work. I know send-mailmessage is old but could it work here?
-
Vasil Michev • 121.4K Reputation points • MVP • Volunteer Moderator
2025-08-28T05:08:24.2133333+00:00 You only need permissions on the mailbox you intend to send from. Not each user's mailbox.
-
rr-4098 • 2,076 Reputation points
2025-08-28T16:31:05.19+00:00 Thanks!!!!
Well my script ran and did sent the TAP code so this is progress!!! I did notice the TAP code sent though did now work when I tried to use it.
Trying to look into why...
-
Vasil Michev • 121.4K Reputation points • MVP • Volunteer Moderator
2025-08-29T05:56:24.81+00:00 The examples above use the default lifetime for TAP, which is 60 minutes. If you want to extend that, use the
-LifetimeInMinutes
parameter:$users = Import-CSV blabla.csv foreach ($user in $users) { $uTap = New-MgUserAuthenticationTemporaryAccessPassMethod -UserId $user.ID -LifetimeInMinutes 43200 }
30 days is the maximum value you can configure.
-
rr-4098 • 2,076 Reputation points
2025-08-29T12:42:22.51+00:00 I have a TAP policy in place to make the code valid for 4 hours. Also when I tested the TAP code sent I tried it as soon as I received it.
-
rr-4098 • 2,076 Reputation points
2025-08-29T18:50:24.0233333+00:00 I figured out my issue. The policy is set so the minum lifetime is 1 hour and I tried to change the code again to soon. I was able to login with the new TAP. Should it force users to change password as soon as they login or am I mistaken? I did come across this site: https://passwordreset.microsoftonline.com
Sign in to comment -