Multi-factor authentication – Office 365 for IT Pros https://office365itpros.com Mastering Office 365 and Microsoft 365 Mon, 24 Jun 2024 22:00:35 +0000 en-US hourly 1 https://i0.wp.com/office365itpros.com/wp-content/uploads/2024/06/cropped-Office-365-for-IT-Pros-2025-Edition-500-px.jpg?fit=32%2C32&ssl=1 Multi-factor authentication – Office 365 for IT Pros https://office365itpros.com 32 32 150103932 Adding Details of Authentication Methods to the Tenant Passwords and MFA Report https://office365itpros.com/2024/06/25/authentication-methods-v13/?utm_source=rss&utm_medium=rss&utm_campaign=authentication-methods-v13 https://office365itpros.com/2024/06/25/authentication-methods-v13/#comments Tue, 25 Jun 2024 07:00:00 +0000 https://office365itpros.com/?p=65312

Revealing Full Details of Authentication Methods and Why This Might Be a Privacy Issue

Soon after releasing V1.2 of the Tenant Passwords and MFA Report (to add details about per-user MFA states), I was asked if it was possible to add more information for authentication methods, like the phone number used for SMS responses. My response was that I had covered the topic of reporting the details of authentication methods in a previous article and it was simply a matter of using the code from that article, updating it slightly to deal with the device-based passkeys recently introduced for Entra ID.

Not everyone likes cracking open a PowerShell script to insert code that they didn’t write. I don’t like messing with other peoples’ code either and will usually write my own version when necessary. In any case, I found some time and upgraded the script to include the expanded details, available in V1.3 of the script in GitHub.

Reporting Authentication Methods

Figure 1 shows the information about authentication methods registered for a user account in V1.2 of the report. The information given use the names from the MethodsRegistered property returned by the Get-MgBetaReportAuthenticationMethodUserRegistrationDetail cmdlet from the Microsoft Graph PowerShell SDK.

 Reporting the authentication methods registered for a user account.
Figure 1: Reporting the authentication methods registered for a user account

The problem is that the names aren’t very user-friendly. If you’re used to working with authentication methods, you probably recognize the values and understand what they mean. If not, this information might be useless.

More detail about the methods is available by running the Get-MgUserAuthenticationMethod cmdlet. Even so, some manipulation is necessary to generate human-friendly output. I’d done most of the work before, so it was easy to generate more information for each method. For instance, in Figure 2 you can see the mobile phone number used for SMS challenges and the version of the Authenticator app used for push notifications.

Expanded details of a user account's registered authentication methods.
Figure 2: Expanded details of a user account’s registered authentication methods

Because the script captures details in a PowerShell list, it’s also possible to query the list to find information like who uses a YubiKey FIDO2 key with a command like:

$Report | Where-Object {$_.'Authentication Methods' -like "*Yubikey*"}

The Privacy Issue

All was going well when I realized that the information generated about authentication methods might include some PII data, like the mobile phone number used for SMS responses. In most instances, I don’t think this will be a problem because details like mobile phone numbers are often included in the properties of Entra ID user accounts. The email addresses used to recover passwords via the Self-Service Password Reset (SSPR) feature are often personal accounts, so they might be more of an issue.

However, the regulations covering access to PII differs from country to country and it’s a good idea to cover all bases. The script now has a PrivacyFlag parameter. It’s a switch parameter, so the value is false by default. If set to true by including the parameter when running the script or by setting the flag explicitly, the script generates the names of the authentication methods without any details.

$PrivacyFlag = $true

On to The Next Version

I am sure that many other good ideas about how to add value to a report like this exist within the community. If you do, suggest the change through the Office 365 for IT Pros GitHub repository (for this script or any of our other scripts). Many people create a fork of our repository and work on updates that way. Whatever’s easier for you…


Learn more about how Microsoft 365 applications and Entra ID work on an ongoing basis by subscribing to the Office 365 for IT Pros eBook. Our monthly updates keep subscribers informed about what’s important across the Office 365 ecosystem.

]]>
https://office365itpros.com/2024/06/25/authentication-methods-v13/feed/ 1 65312
How to Find Unprotected Azure Active Directory Administrative Accounts https://office365itpros.com/2019/07/15/find-unprotected-azure-ad-accounts/?utm_source=rss&utm_medium=rss&utm_campaign=find-unprotected-azure-ad-accounts https://office365itpros.com/2019/07/15/find-unprotected-azure-ad-accounts/#comments Mon, 15 Jul 2019 02:18:40 +0000 https://office365itpros.com/?p=3466

Multi-Factor Authentication Should Be Enabled for Privileged Accounts

Update: This article describes a script using Graph APIs to generate a report showing the MFA status for accounts and highlights administrative accounts that aren’t MFA-enabled. Given the deprecation of the MSOL module, you should switch to the Graph version.

If, like me, you were impressed by the case laid out in the July 10 2019 blog entitled Your Pa$$word doesn’t matter by Alex Weinert (Microsoft), you might wonder how to take his advice to “turn on MFA” for accounts. The process can take some time and user education because you can’t really enable MFA for “average users” if you don’t prepare them to deal with the resulting challenges, roll out the Microsoft Authenticator app, and so on. And then there’s the ongoing need to find unprotected Azure AD accounts to coach their owners about the wonders of MFA.

Reporting Accounts with Administrative Roles

One immediate step you can take is to clamp down on accounts holding one or more Azure Active Directory administrative roles that are not MFA-enabled. Microsoft has an Azure Active Directory usage and insights report about authentication methods to inform tenants about the accounts that are/are not enabled for MFA and self-service password reset (Figure 1), but it doesn’t highlight accounts holding administrative roles.

Azure Active Directory Usage and Insights Report about MFA and SSPR

Find unprotected Azure AD accounts
Figure 1: Azure Active Directory Usage and Insights Report about MFA and SSPR

We discussed how to create a report of Azure AD accounts and their MFA status in a previous post and we can build on the techniques explored there to construct a PowerShell script to report accounts holding an administrative role that need to be protected with MFA. You can grab a copy of the script from GitHub.

What the Script Does

The script is imperfect and could do with improvement in terms of optimization and error handling, but it works. Here’s what it does.

Azure Active Directory defines directory roles which can be assigned to accounts to allow those accounts to perform specific tasks. In this case, we’re interested in some of the more highly-permissioned roles like Exchange Admin, so we use the Get-AzureADDirectoryRole cmdlet to grab the GUIDs identifying these roles and put them in variables. We then call the Get-AzureADDirectoryRoleMember cmdlet to populate another set of variables with details of the accounts that hold each role.

Write-Host "Finding Azure Active Directory administrative roles..."
$UserAccountAdmin = Get-AzureADDirectoryRole | Where-Object {$_.DisplayName -eq ‘User Account Administrator’} | Select ObjectId
$TenantAdmin = Get-AzureADDirectoryRole | Where-Object {$_.DisplayName -eq ‘Global Administrator’} | Select ObjectId
$TeamsAdmin = Get-AzureADDirectoryRole | Where-Object {$_.DisplayName -eq ‘Teams Service Administrator’} | Select ObjectId
$ExchangeAdmin = Get-AzureADDirectoryRole | Where-Object {$_.DisplayName -eq ‘Exchange Service Administrator’} | Select ObjectId
$SharePointAdmin = Get-AzureADDirectoryRole | Where-Object {$_.DisplayName -eq ‘Sharepoint Service Administrator’} | Select ObjectId

# Find out the set of accounts that hold these admin roles in the tenant
$UserAccountAdmins = Get-AzureADDirectoryRoleMember -ObjectId $UserAccountAdmin.ObjectID | Select ObjectId, UserPrincipalName
$TenantAdmins = Get-AzureADDirectoryRoleMember -ObjectId $TenantAdmin.ObjectID | Select ObjectId, UserPrincipalName
$TeamsAdmins = Get-AzureADDirectoryRoleMember -ObjectId $TeamsAdmin.ObjectID | Select ObjectId, UserPrincipalName
$ExchangeAdmins = Get-AzureADDirectoryRoleMember -ObjectId $ExchangeAdmin.ObjectID | Select ObjectId, UserPrincipalName
$SharePointAdmins = Get-AzureADDirectoryRoleMember -ObjectId $SharePointAdmin.ObjectID | Select ObjectId, UserPrincipalName

The script then calls the Get-MsolUser cmdlet to create a collection of Azure Active Directory licensed accounts (yes, there’s an odd mix of the Azure AD V1 and V2 cmdlets in the script; that’s because I can’t work out how to get MFA information using the V2 cmdlets). Using the MFA report code described here, each account is checked to see if it is MFA-enabled. We then create an array of accounts which are not MFA-enabled. These accounts are checked to see if they hold one of the administrative roles we’re interested in. If an account holds one or more of those roles, we capture its details.

# Extract users whose accounts don't have MFA
$MFAUsers = $MFAReport | ? {$_.MFAUsed -ne "Enforced"}
If (!($MFAUsers)) { Write-Host "No privileged accounts found without MFA protection" ; break}

Write-Host "Checking MFA status for accounts holding admin roles..."
$i = 0
$Report = [System.Collections.Generic.List[Object]]::new() # Create output file 
# Check Admin Roles if MFA not enabled
ForEach ($User in $MFAUsers) {
  $Roles = $Null
  If ($UserAccountAdmins.ObjectId -Contains $User.ObjectId) {
         Write-Host $User.DisplayName "Account holds the User Account Admin role" -ForegroundColor Red 
         $Roles = "Account Admin" }
  If ($TenantAdmins.ObjectId -Contains $User.ObjectId) {
         Write-Host $User.DisplayName "Account holds the Tenant Admin role" -ForegroundColor Red 
         If ($Roles -eq $Null) { $Roles = "Tenant Admin" } Else { $Roles = $Roles + "; Tenant Admin" } }
  If ($TeamsAdmins.ObjectId -Contains $User.ObjectId) {
         Write-Host $User.DisplayName "Account holds the Teams Admin role" -ForegroundColor Red 
         If ($Roles -eq $Null) { $Roles = "Teams Admin" } Else { $Roles = $Roles + "; Teams Admin" } }
  If ($ExchangeAdmins.ObjectId -Contains $User.ObjectId) {
         Write-Host $User.DisplayName "Account holds the Exchange Admin role" -ForegroundColor Red
         If ($Roles -eq $Null) { $Roles = "Exchange Admin" } Else { $Roles = $Roles + "; Exchange Admin" } }
  If ($SharePointAdmins.ObjectId -Contains $User.ObjectId) {
         Write-Host $User.DisplayName "Account holds the SharePoint Admin role" -ForegroundColor Red 
         If ($Roles -eq $Null) { $Roles = "SharePoint Admin" } Else { $Roles = $Roles + "; SharePoint Admin" } }      
 If ($Roles -ne $Null) {Write-Host "User" $User.DisplayName "is assigned the following roles:" $Roles -ForeGroundColor Yellow;  $i++ 
    $ReportLine = [PSCustomObject]@{
       User      = $User.DisplayName
       UPN       = $User.UserPrincipalName
       Roles     = $Roles
       MFA       = $User.MFAUsed }   
   $Report.Add($ReportLine) } #End if
}

Reporting Unprotected Azure AD Administrative Accounts

As the code runs, it generates information about accounts which are not MFA-enabled but hold administrative roles (Figure 2). Apart from anything else, this is a good way to see what accounts hold administrative roles and ask whether they need to hold those roles.

Viewing details of Azure AD accounts with administrative roles which are not MFA-protected
Figure 2: Viewing details of Azure AD accounts with administrative roles which are not MFA-protected

Finally, a CSV file is generated with details of accounts holding Azure AD administrative roles which are not MFA-enabled and exported to a CSV file. Figure 3 shows details of what the file contains as viewed through the Out-GridView cmdlet. It’s easy to pick out the accounts whose security needs to be improved.

Viewing details of unprotected accounts through Out-GridView
Figure 3: Viewing details of unprotected accounts through Out-GridView

As always, we’re happy to hear about other approaches to the problem. Please post your ideas as a comment to this post.


Need more solutions to common Office 365 Admin problems? The Office 365 for IT Pros eBook is packed full of ideas…

]]>
https://office365itpros.com/2019/07/15/find-unprotected-azure-ad-accounts/feed/ 10 3466
How to Report the MFA Status for Azure AD Accounts https://office365itpros.com/2018/11/21/reporting-mfa-enabled-accounts/?utm_source=rss&utm_medium=rss&utm_campaign=reporting-mfa-enabled-accounts https://office365itpros.com/2018/11/21/reporting-mfa-enabled-accounts/#comments Wed, 21 Nov 2018 08:57:43 +0000 https://office365itpros.com/?p=1015

Knowing Which Accounts Are MFA-Enabled and Those That Don’t

When an issue like the November 19 2018 Azure outage occurs, the first thing that an administrator needs to know is what users are affected. In this case, the problem was that users whose accounts were enabled for multi-factor authentication (MFA) couldn’t complete the sign-in process and therefore weren’t able to access Exchange, SharePoint, and other Office 365 apps.

You can, of course go to the Microsoft 365 Admin Center and manage the MFA status of accounts there (Go to Active Users, click the More drop-down, and select Multifactor Authentication setup). However, the GUI is awful (Figure 1). It’s not part of Office 365 (it comes from Azure), hasn’t been updated in years, is slow, and is painful to navigate when you have a large tenant with many accounts.

Managing the MFA status of Azure AD accounts in an Office 365 tenant
Figure 1: Managing the MFA status of Office 365 Accounts – Just terrible!

Because the GUI is so terrible and slow, I usually turn to PowerShell to manage MFA for Office 365 accounts. The cmdlets you need are in the MSOnline module.

PowerShell Report

To start, let’s find out what accounts are MFA-enabled. Here’s a script to find and report the MFA status of all user accounts. The output is a CSV file. In a situation where an MFA outage is happening and you can’t access your normal administrative account, you’ll need to sign into Office 365 with a breakglass account.

CLS
Write-Host "Finding Azure Active Directory Accounts..."
$Users = Get-MsolUser -All | ? {$_.IsLicensed -eq $True}
$Report = [System.Collections.Generic.List[Object]]::new() # Create output file
Write-Host "Processing" $Users.Count "accounts..." 
ForEach ($User in $Users) {
   $MFAMethods = $User.StrongAuthenticationMethods.MethodType
   $MFAEnforced = $User.StrongAuthenticationRequirements.State
   $DefaultMFAMethod = ($User.StrongAuthenticationMethods | ? {$_.IsDefault -eq "True"}).MethodType
   If (($MFAEnforced -eq "Enforced") -or ($MFAEnforced -eq "Enabled")) {
      Switch ($DefaultMFAMethod) {
        "OneWaySMS"             { $MethodUsed = "One-way SMS" }
        "TwoWayVoiceMobile"     { $MethodUsed = "Phone call verification" }
        "PhoneAppOTP"           { $MethodUsed = "Hardware token or authenticator app" }
        "PhoneAppNotification"  { $MethodUsed = "Authenticator app" }
      } #End Switch
    }
    Else {
          $MFAEnforced= "Not Enabled"
          $MethodUsed = "MFA Not Used" }
  
   $ReportLine = [PSCustomObject] @{
           User        = $User.UserPrincipalName
           Name        = $User.DisplayName
           MFAUsed     = $MFAEnforced
           MFAMethod   = $MethodUsed }
                 
    $Report.Add($ReportLine) 
} # End For

Write-Host "Report is in c:\temp\MFAUsers.CSV"
$Report | Select Name, MFAUsed, MFAMethod | Out-GridView
$Report | Export-CSV -NoTypeInformation c:\temp\MFAUsers.CSV

Figure 2 shows the contents of the report as viewed through the Out-GridView cmdlet.

Reporting MFA status for accounts in an Office 365 tenant
Figure 2: Reporting MFA status for accounts in an Office 365 tenant

Update: The script described in this post uses the Microsoft Services Online module (MSOL). Microsoft will deprecate the module at the end of 2022. You should upgrade scripts to use Graph API queries or cmdlets from the Microsoft Graph PowerShell SDK. See this post for information about how to extract and report details of authentication methods used by Azure AD accounts.

Azure Active Directory Sign-in Log

Because the refresh token of MFA-enabled accounts don’t necessarily expire during an outage, a more nuanced approach is to check the Azure Active Directory sign-in logs for events with error codes 50076, 50074, or 50058, all of which flag problems signing in with an MFA-enabled account. You can review sign-ins interactively or download events to a CSV file. You can then use Excel to look through the failed sign-ins or import the CSV file into Power BI to analyze it there. In either case, you’ll end up with a set of accounts who are experiencing problems signing into Office 365.

Disabling MFA for Accounts

When a cloud outage happens, there’s no guarantee when normal service will resume. As everyone discovered on November 18, the process to figure out the root cause of a problem, come up with a fix, test it, and then deploy into production across a massive multi-tenant infrastructure can take many hours. While this process was in going on, the only workaround administrators had was to disable MFA for user accounts. This is easily done for a specific user:

$MFAOptions = @()
Set-MsolUser -UserPrincipalName Kim.Akers@Office365itpros.com -StrongAuthenticationRequirements $MFAOptions

To disable a batch of users, simply form a collection and call the Set-MsolUser cmdlet for each account. In this case, we disable MFA for all members of the Marketing department. If you extract failed sign-in data from Azure Active Directory, you can create a CSV file holding the set of accounts to process and use it as the input.

$MFAOptions = @()
$Accounts = Get-MsolUser -Department Marketing | ? {$_.StrongAuthenticationMethods -ne $Null}
ForEach ($A in $Accounts) {
Set-MsolUser -UserPrincipalName $A.UserPrincipalName -StrongAuthenticationRequirements $MFAOptions}

Enabling MFA for Accounts

Later on when the outage is over, we need to re-enable MFA for the same set of accounts (we’ll assume that you have saved details of the accounts and populated those names in the $Accounts variable). The PowerShell snippet shown below sets up MFA based on one-way SMS (text) messages containing 6-digit codes.

$MFA = New-Object –TypeName Microsoft.Online.Administration.StrongAuthenticationRequirement
$MFA.RelyingParty = "*"
$MFA.State = "Enabled"
$MFAOptions = @($MFA)
$MFAMethod = New-Object –TypeName Microsoft.Online.Administration.StrongAuthenticationMethod
$MFAMethod.IsDefault = $True
$MFAMethod.MethodType = "OneWaySMS"
$MFAMethods = @($MFAMethod)

ForEach ($A in $Accounts) {
    Set-MsolUser –UserPrincipalName $A.UserPrincipalName –StrongAuthenticationRequirements $MFAOptions –StrongAuthenticationMethods $MFAMethods }

These examples aren’t a complete solution. Instead, they’re intended to give administrators a start to figure out how to manage MFA settings with PowerShell.

For more details about Office 365 MFA, see the online documentation.


We cover multi-factor authentication for Office 365 in Chapter 3 of the Office 365 for IT Pros eBook.

]]>
https://office365itpros.com/2018/11/21/reporting-mfa-enabled-accounts/feed/ 15 1015