Office 365 – Export Email Addresses and UPN of O365 users with PowerShell

I will go over steps on how to export the list of users with their UPN, Object ID, primary SMTP address and Alias email address.

The Get-AzureADUser cmdlet comes in handy to pull all the user details in this scenario. The Mail attribute contains the Primary SMTP address of the user and the Primary SMTP address and Alias email address are stored in the ProxyAddresses attribute in Azure AD. The ProxyAddresses attribute is a multi-value property. The Primary SMTP address can be easily identified as it is in this format, SMTP:user@emaple.com The upper-case SMTP denotes that it the primary email address.

When an object is synced from on-premise Active Directory to Azure AD, the values in the proxyAddresses attribute in AD are compared with Azure AD rules and then populated in Azure AD. So, the values of the proxyAddresses attribute in AD may not match the ProxyAddresses attribute in AzureAD.

Export all users to csv file

The below script will pull all Azure AD users,

Connect-AzureAD

$Output = @() #create an empty array

$AzureADUsers = Get-AzureADUser -All $true | Select DisplayName,UserprincipalName,ObjectId,Mail,ProxyAddresses #Get all Azure AD users

ForEach ($User in $AzureADUsers)
{
	$Output += New-Object PSObject -property $([ordered]@{ #fetch user detail and add to $output
		UserName = $User.DisplayName
		UserprincipalName = $User.UserprincipalName
		UserId = $User.objectId
		SMTPAddress = $User.Mail
		AliasSMTPAddresses = ($User.ProxyAddresses | Where-object {$_ -clike 'smtp:*'} | ForEach-Object {$_ -replace 'smtp:',''}) -join ','
		
	})
}
$Output | Export-csv "C:\tmp\O365Users_$((Get-Date).ToString("MMddyyyy_HHmmss")).csv" -NoTypeInformation -Encoding UTF8 #Export users to csv file

Output file,

csv output

Thank you for stopping by.✌

Office 365 – Block Basic Authentication

Microsoft recently announced they will disable basic authentication for all M365 tenants. This deadline has been pushed postponed due to the impact of COVID-19 across the globe.

Latest update: The latest from Microsoft is, effective October 1, 2022 Basic authentication will be disabled in all tenants.

The following components of Exchange Online will be affected,

  • Exchange Web Services(EWS)
  • POP
  • IMAP
  • Exchange ActiveSync
  • Remote PowerShell

Why is this a big deal?

Basic authentication uses username and password for client access requests. This used to be the industry standard during the time which organizations didn’t understand the cost of security breaches. It poses a significant security risk as Business Email Compromise (BEC) scams have exposed organizations to billions of dollars in potential losses. Check out this 2019 report from ProofPoint that goes into details.

Disabling Basic Authentication will help protect Exchange Online from brute force or password spray attacks. As the above mentioned report goes into, IMAP-based password-spraying campaigns are very effective in particular.

Beyond all this, Basic Authentication doesn’t enforce MFA and this should be the biggest driver for organizations to move away from it.

Is Basic Authentication enabled in your tenant?

Here is how to check if Basic Authentication is enabled in your tenant,

Screenshot above shows how to check if ‘Basic Auth’ is enabled in tenant

Determine who is using Basic Authentication in your tenant

Before you turn off basic authentication for protocols, view your sign-in reports in the ‎Azure AD‎ portal to determine who is using it in your organization.

This can be determined using sign-in logs in Azure AD.

In your Azure AD admin center, Click the ‘Sign-in logs’ blade.,

  • Select ‘Last 1 month‘ in the Date
  • Add a ‘Client app‘ as a second filter, choose all options under the ‘Legacy Authentication Clients‘ and click ‘Apply
Azure AD sign-ins | Basic Auth filter

With this report information, you can contact the application and account owners to determine why Basic Authentication is still in use. This information will also come in handy later if you are planning to allow exceptions to these accounts/applications. I’ve covered it later in this post.

Disable Basic Authentication

Before you begin,

  • Verify Modern Authentication is enabled
  • Verify your email clients are Modern Authentication capable

In this post, I’ve elaborated how to block Basic Authentication using Azure AD conditional access.

IMO, the easiest method to disable Basic Authentication is to use authentication policies.

With Authentication policies you can,

  • Apply a default organization level policy that blocks Basic Authentication
  • Apply a per user policy to allow certain protocols. Example: ActiveSync

Create Authentication Policy

This creates an authentication policy named ‘Block Basic Auth’

New-AuthenticationPolicy -Name "Block Basic Auth"

When you create a new authentication policy without specifying any protocols, Basic Authentication is blocked for all client protocols in Exchange Online.

The default value of the AllowBasicAuth* parameters (switches) is False for all protocols.

Set Default Authentication Policy

The default policy is assigned to all users in the tenant who don’t have a specific policy assigned to them. To configure the default authentication policy for the organization, use this:

Set-OrganizationConfig -DefaultAuthenticationPolicy "Block Basic Auth"

To verify that a default authentication policy is configured,

Get-OrganizationConfig | Format-Table DefaultAuthenticationPolicy

Create user specific authentication policies

Authentication policies assigned to users take precedence over the default organization policy.

  • To enable Basic authentication for a specific protocol that’s disabled, specify the switch without a value
  • To disable Basic authentication for a specific protocol that’s enabled, use the value :$false

In this scenario, I’m creating an authentication policy to allow ActiveSync. This is sometimes typical in organizations where users will have Intune managed devices but would like to add second O365 email from a different tenant. The Outlook app prevents this but the built-in mail app can be used with ActiveSync to fetch email.

New-AuthenticationPolicy -Name "Allow ActiveSync" -AllowBasicAuthActiveSync
New policy to allow ActiveSync

This example assigns the policy named ‘Allow ActiveSync’ to the user account ‘JoniS’

$Id = Read-Host "Enter user's email address"
Set-User -Identity $Id -AuthenticationPolicy "Allow ActiveSync"

To confirm the policy is assigned,

Get-User -Identity $Id | fl AuthenticationPolicy
Assign policy to user and confirm assignment

To assign a policy to a list of users, fill text file with the user’s UPN one per line.,

$LM = Get-Content "C:\Scripts\AllowAuthActiveSync.txt"
$LM | foreach {Set-User -Identity $_ -AuthenticationPolicy "Allow ActiveSync"}

To get all users assigned to a policy you need to get the policy’s DN using the cmdlet Get-AuthenticationPolicy,

$PolicyId = Read-Host "Enter policy ID in distinguished name format"
Get-User -Filter "AuthenticationPolicy -eq '$PolicyId'"
Assign policy to user, confirm and get all users assigned to a policy
Determine policy DN using ‘Get-AuthenticationPolicy’

By default, when you create or change the authentication policy assignment on users or update the policy, the changes take effect within 24 hours. If you want the policy to take effect within 30 minutes, use the following syntax:

$Id = Read-Host "Enter user's email address"
Set-User -Identity $Id -STSRefreshTokensValidFrom $([System.DateTime]::UtcNow)

This example below immediately applies the authentication policy to multiple users. As I’m in the same PowerShell session and haven’t changed the variables you used to identify the users,

$LM | foreach {Set-User -Identity $_ -STSRefreshTokensValidFrom $([System.DateTime]::UtcNow)}

Depending on your organizational requirement, you can create additional authentication policies allowing other protocols and assigning it to users.

And it’s highly recommended to keep track of these users and eventually remove these exceptions.

Thank you for stopping by. ✌

Teams – How to mask phone numbers in meetings

The default setting for all organizations using Teams is the phone numbers are masked from the participants outside of the organization. The phone numbers are fully displayed to internal participants.

Based on certain uses cases and added privacy, Teams administrators have the ability to choose how the participants’ phone numbers appear in meetings. Options available,

  • Phone numbers are not masked, which makes it visible to everyone in the meeting
  • Phone numbers are masked for everyone except the organizer
  • Phone numbers are masked only from external participants

Using PowerShell to define phone-number masking

Use the MaskPstnNumbersType parameter of the Set-CsOnlineDialInConferencingTenantSettings cmdlet to change PSTN masking setting,

To disable phone masking,

Set-CsOnlineDialInConferencingTenantSettings -MaskPstnNumbersType "NoMasking"

To mask phone numbers from all participants in the meeting, except the organizer,

Set-CsOnlineDialInConferencingTenantSettings -MaskPstnNumbersType "MaskedForAllUsers"

To mask phone numbers from external participants only, will be visible to all internal participants,

Set-CsOnlineDialInConferencingTenantSettings -MaskPstnNumbersType "MaskedForExternalUsers"

Thank you for stopping by. ✌

Azure AD – Conditional Access – Block Legacy Authentication

Many organizations implement MFA as a common requirement for security and to address identity theft. Legacy authentication doesn’t support MFA. Blocking legacy authentication will improve your tenant’s protection.

I have detailed on how to disable protocols using basic authentication using authentication policies in a different post here. I’ll go into detail on how to block legacy authentication using Azure AD Conditional Access.

Remember: Conditional Access policies take effect after the first-factor authentication is completed. In a scenario where a user's credentials were leaked, then attackers use it to gain access but signal generated from these events like location of the request, sign-in risk level can be used to block access.

Clients using legacy authentication cannot enforce MFA. Examples of such applications,

  • Microsoft Office 2013 or older
  • Apps using mail protocols like IMAP, POP

Block legacy authentication

There are two ways Conditional Access policies can be used to block legacy authentication,

  • Direct Method
  • Indirect Method

Direct Method

  1. In Azure AD admin center, click on the Security tab(https://aad.portal.azure.com/)
  2. Click Conditional Access and Create a new policy

I typically prefix Conditional Access policies with ‘Grant Access’ or ‘Block Access’ in the tenants I manage.

Under Users

  • Include : ‘All users’
  • I’ll exclude ‘Global administrator’ role just to be on the safe side of things
Include and Exclude in Conditional Access policy

Under ‘Cloud apps or actions

  • Include : All cloud apps
  • Exclude : None
cloud apps and actions

In Conditions –> Client Apps,

  • Select ‘Yes‘ to configure policy
  • Uncheck ‘Browser‘ and ‘Mobile apps and desktop clients‘ which are checked by default
  • Exchange ActiveSync clients‘ and ‘Other clients‘ needs to be left checked
  • Click ‘Done
client apps

Grant: Select ‘Block access

Block access

While taking this approach, it is better to set the policy to ‘Report Only‘. This way, you can get some insights on what is using legacy authentication and hopefully you won’t break business critical applications in a production environment. Or if you like living life on the edge, go for it and set it to ‘On

Indirect Method

In this method, the policy creation steps are same as the ‘Direct method’.

  • When it comes to choosing the ‘Client apps‘, Configure ‘No
  • In ‘Grant‘, select ‘Grant Access‘ and ‘Require multi-factor authentication‘ and ‘Require Hybrid Azure AD joined device

During authentication, legacy authentication clients don’t support sending MFA, Azure AD join state or device compliance. When we apply policies with grant controls to all client applications, the legacy authentication based sign-ins that cannot satisfy these required grant controls are blocked.

Client apps – No
Grant access – MFA, Azure AD joined

Conditional Access policies can take up 24 hours to take effect. Please keep this in mind while rolling out changes in a production environment. What seems to be working immediately after you put the policy in place might not work when you wake up the next day as the policy is just taking effect or even worse while you are on a camping weekend with no cell coverage..Live and learn.. I guess.😁

Thank you for stopping by. ✌

Automatically Roll Over Kerberos Decryption Key with Azure AD SSO

In Azure AD, Seamless Single Sign-on can be configured when Password Hash Sync or Pass through authentication is configured. Azure AD Seamless SSO automatically signs in users when they are in their corporate owned devices and one the corporate network. This helps save a lot of time without repeatedly typing credentials in to Azure AD and other Azure AD integrated applications.

When we enable Azure AD Seamless SSO, a computer account named AZUREADSSOACC is created in on-premises AD in each AD forest. This computer account represent Azure AD in the on-premises AD. Considering how important this computer object is, it is better to take the following steps to protect it,

  • Move it into a OU,
    • Where they are safe from accidental deletions
    • Where only domain admins have access
  • Ensure that Kerberos delegation on the computer account is disabled
  • No other accounts in AD have delegation permissions
    • This can be easy to miss if you have permissions sprawl

The Kerberos decryption key for this computer account is securely shared with Azure AD. Microsoft recommends to roll over the Kerberos decryption Key at least every30 days. You will notice a warning when the key has not been updated in the past 30 days.

Azure AD warning
Kerberos decryption key

As I mentioned earlier, Microsoft recommends to roll over the keys at least every 30 days. Obviously, I can remember it promptly or even put a meeting invite in Outlook to recur 30 days, keep snoozing it to eventually dismiss the alert because I’m stuck doing something else on that day. I’m sure this feels very familiar to most of you reading this. 😂

This is a great scenario where automation can come in handy and I’ll go through the steps on how I implemented this.

Prerequisites

Below are the requirements for implementing this solution.

  • Global admin account
    • With MFA exception (preferably by origin IP)
  • Administrator account on AD Connect server with logon as a batch job
  • On-Premises AD domain admin account
  • Domain account that has permissions to ‘login as batch service’ on the Azure AD connect server

I covered in later half of another post about securely storing credentials using PowerShell into a file. Run these below lines to store encrypted credentials into a text file. This is far better than storing the password in plain text.

Remember, this method is secure but not 100% safe.

$ADCred = Get-Credential
$ADCred.Password | ConvertFrom-SecureString | Out-File "C:\temp\ADCred_sec.txt"
$AzureAD = Get-Credential
$AzureAD.Password | ConvertFrom-SecureString | Out-File "C:\temp\AzureAD_sec.txt"

Enter the domain user and Azure AD user which has necessary permissions in this below script and save it.

$ADUser = 'domain.com\user' #Must be entered in the SAM account name format contoso.com\jdoe
$ADUserEncrypted = Get-Content "C:\temp\ADCred_sec.txt" | ConvertTo-SecureString
$OnPremADCred = New-Object System.Management.Automation.PsCredential($ADUser,$OnPremADCred)

$AzureADUser = 'admin@tenant.onmicrosoft.com'
$AzureADUserEncrypted = Get-Content "C:\temp\AzureAD_sec.txt" | ConvertTo-SecureString
$AzureADCred = New-Object System.Management.Automation.PsCredential($AzureADUser,$AzureADUserEncrypted)

Import-Module 'C:\Program Files\Microsoft Azure Active Directory Connect\AzureADSSO.psd1'
New-AzureADSSOAuthenticationContext -CloudCredentials $AzureADCred
Update-AzureADSSOForest -OnPremCredentials $OnPremADCred

Schedule to automate

Once the script is stored, create a basic scheduled task to run it every month. Below are my settings,

Scheduled Task – General
Scheduled Task – Trigger
Scheduled Task – Actions

After making sure all the setting, Click OK and you will be prompted for credentials. If you receive the below error,

Task Scheduler Error “A specified logon session does not exist” - Microsoft  Tech Community
  1. Run gpedit.msc
  2. Look in Computer Configuration | Windows Settings | Security Settings | Local Policies | Security Options
  3. Double-click Network access: Do not allow storage of passwords and credentials for network authentication
  4. Set the policy to Disabled
  5. Go back to scheduled task to enter your credentials and click OK

Hope this helped you out in automating the Kerberos decrypting key roll over for the AZUREADSSOACC computer account.

Thank you for stopping by. ✌