PowerShell Function to Connect to All Office 365 Services With Support for MFA
Table of Contents
I usually have to connect to Office 365 via PowerShell at least once per day. I had the following function stored in my PowerShell Profile:
function Connect-O365 { $UserCredential = Get-Credential $Session = New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionUri "https://ps.outlook.com/powershell/" -Credential $UserCredential -Authentication Basic -AllowRedirection Import-PSSession $Session Connect-MsolService -Credential $UserCredential }
This allowed me to just open PowerShell and type Connect-O365 to connect to Office 365 instead of looking up the Session information and all of the cmdlets needed. One of the issues I faced was the lack of multi-factor authentication support. To connect to Exchange Online or Security and Compliance Center using multi-factor authentication you must use another module that is found in your tenant. Also, when you install this module it gets buried in your local app data folder.
So I decided to just re-do the entire function, allowing it to connect to the following Office 365 services:
- Exchange Online
- Skype for Business
- SharePoint Online
- Security and Compliance Center
- Azure AD v2
- Azure AD v1 (MSOnline)
- Microsoft Teams
By calling the MFA switch we can also connect to all of the above services while utilizing multi-factor authentication. The function also allows us to connect to multiple services at once by calling the parameter. If I wanted to connect to Azure AD v1 (MSOnline), Exchange Online and Teams without using multi-factor authentication I can type:
Connect-Office365 -Service Teams, Exchange, MSOnline
If I wanted to use multi-factor authentication I could type:
Connect-Office365 -Service Exchange, MSOnline, Teams -MFA
Modules
The following modules are used and will be needed if you plan on connecting to the relevant Office 365 service. You do not need to have every module installed if you are not going to connect to its service.
Exchange
- EXOPSSession (Only needed if you use multi-factor authentication)
Skype for Business
SharePoint
Security and Compliance Center
- EXOPSSession (Only needed if you use multi-factor authentication)
Azure AD V2
Azure AD V1 (MSOnline)
Microsoft Teams
Features
Credential Pass Through
If you do not utilize multi-factor authentication then you will only be prompted once for credentials. The function will store the credential object in a variable and pass it to each service you connect to. This allows you to connect to multiple services without having to enter in your credentials for each individual one. Due to how multi-factor authentication works in regards to the token, this is not possible if you use MFA.
Auto Import MFA Module
As I mentioned earlier the Exchange MFA module hides itself deep inside your Local App Data folder. The function will parse your app data folder and find the full path to the module and then load it into memory.
$getChildItemSplat = @{ Path = "$Env:LOCALAPPDATA\Apps\2.0\*\CreateExoPSSession.ps1" Recurse = $true ErrorAction = 'SilentlyContinue' Verbose = $false } $MFAExchangeModule = ((Get-ChildItem @getChildItemSplat | Select-Object -ExpandProperty Target -First 1).Replace("CreateExoPSSession.ps1", ""))
Once we store the path in a variable we can dot source the script to import the module
. "$MFAExchangeModule\CreateExoPSSession.ps1"
Service Connection Status
The host title bar will append which services you are connected to. It will do a quick connection verification prior to appending the title bar text. If unable to connect it will not appear in the title bar.
Download
function Connect-Office365 { <# .NOTES =========================================================================== Created on: 2/4/2019 10:42 PM Created by: Bradley Wyatt E-Mail: [email protected] GitHub: https://github.com/bwya77 Website: https://www.thelazyadministrator.com Organization: Porcaro Stolarek Mete Partners; The Lazy Administrator Filename: Connect-Office365.ps1 Version: 1.0.4 Contributors: /u/Sheppard_Ra Changelog: 1.0.4 - Host title will add a service or services you are connected to. If unable to connect it will not display connection status until connection is valid =========================================================================== .SYNOPSIS Connect to Office 365 Services .DESCRIPTION Connect to different Office 365 Services using PowerShell function. Supports MFA. .PARAMETER MFA Description: Specifies MFA requirement to sign into Office 365 services. If set to $True it will use the Office 365 ExoPSSession Module to sign into Exchange & Compliance Center using MFA. Other modules support MFA without needing another external module .PARAMETER Exchange Description: Connect to Exchange Online .PARAMETER SkypeForBusiness Description: Connect to Skype for Business .PARAMETER SharePoint Description: Connect to SharePoint Online .PARAMETER SecurityandCompliance Description: Connect to Security and Compliance Center .PARAMETER AzureAD Description: Connect to Azure AD V2 .PARAMETER MSOnline Type: Switch Description: Connect to Azure AD V1 .PARAMETER Teams Type: Switch Description: Connect to Teams .EXAMPLE Description: Connect to SharePoint Online C:\PS> Connect-Office365 -SharePoint .EXAMPLE Description: Connect to Exchange Online and Azure AD V1 (MSOnline) C:\PS> Connect-Office365 -Service Exchange, MSOnline .EXAMPLE Description: Connect to Exchange Online and Azure AD V2 using Multi-Factor Authentication C:\PS> Connect-Office365 -Service Exchange, MSOnline -MFA .EXAMPLE Description: Connect to Teams and Skype for Business C:\PS> Connect-Office365 -Service Teams, SkypeForBusiness .EXAMPLE Description: Connect to SharePoint Online C:\PS> Connect-Office365 -Service SharePoint -SharePointOrganizationName bwya77 -MFA .LINK Online version: https://www.thelazyadministrator.com/2019/02/05/powershell-function-to-connect-to-all-office-365-services #> [OutputType()] [CmdletBinding(DefaultParameterSetName)] Param ( [Parameter(Mandatory = $True, Position = 1)] [ValidateSet('AzureAD', 'Exchange', 'MSOnline', 'SecurityAndCompliance', 'SharePoint', 'SkypeForBusiness', 'Teams')] [string[]]$Service, [Parameter(Mandatory = $False, Position = 2)] [Alias('SPOrgName')] [string]$SharePointOrganizationName, [Parameter(Mandatory = $False, Position = 3, ParameterSetName = 'Credential')] [PSCredential]$Credential, [Parameter(Mandatory = $False, Position = 3, ParameterSetName = 'MFA')] [Switch]$MFA ) $getModuleSplat = @{ ListAvailable = $True Verbose = $False } If ($MFA -ne $True) { Write-Verbose "Gathering PSCredentials object for non MFA sign on" $Credential = Get-Credential -Message "Please enter your Office 365 credentials" } ForEach ($Item in $PSBoundParameters.Service) { Write-Verbose "Attempting connection to $Item" Switch ($Item) { AzureAD { If ($null -eq (Get-Module @getModuleSplat -Name "AzureAD")) { Write-Error "SkypeOnlineConnector Module is not present!" continue } Else { If ($MFA -eq $True) { $Connect = Connect-AzureAD If ($Connect -ne $Null) { If (($host.ui.RawUI.WindowTitle) -notlike "*Connected To:*") { $host.ui.RawUI.WindowTitle += " - Connected To: AzureAD" } Else { $host.ui.RawUI.WindowTitle += " - AzureAD" } } } Else { $Connect = Connect-AzureAD -Credential $Credential If ($Connect -ne $Null) { If (($host.ui.RawUI.WindowTitle) -notlike "*Connected To:*") { $host.ui.RawUI.WindowTitle += " - Connected To: AzureAD" } Else { $host.ui.RawUI.WindowTitle += " - AzureAD" } } } } continue } Exchange { If ($MFA -eq $True) { $getChildItemSplat = @{ Path = "$Env:LOCALAPPDATA\Apps\2.0\*\CreateExoPSSession.ps1" Recurse = $true ErrorAction = 'SilentlyContinue' Verbose = $false } $MFAExchangeModule = ((Get-ChildItem @getChildItemSplat | Select-Object -ExpandProperty Target -First 1).Replace("CreateExoPSSession.ps1", "")) If ($null -eq $MFAExchangeModule) { Write-Error "The Exchange Online MFA Module was not found! https://docs.microsoft.com/en-us/powershell/exchange/exchange-online/connect-to-exchange-online-powershell/mfa-connect-to-exchange-online-powershell?view=exchange-ps" continue } Else { Write-Verbose "Importing Exchange MFA Module" . "$MFAExchangeModule\CreateExoPSSession.ps1" Write-Verbose "Connecting to Exchange Online" Connect-EXOPSSession If ($Null -ne (Get-PSSession | Where-Object { $_.ConfigurationName -like "*Exchange*" })) { If (($host.ui.RawUI.WindowTitle) -notlike "*Connected To:*") { $host.ui.RawUI.WindowTitle += " - Connected To: Exchange" } Else { $host.ui.RawUI.WindowTitle += " - Exchange" } } } } Else { $newPSSessionSplat = @{ ConfigurationName = 'Microsoft.Exchange' ConnectionUri = "https://ps.outlook.com/powershell/" Authentication = 'Basic' Credential = $Credential AllowRedirection = $true } $Session = New-PSSession @newPSSessionSplat Write-Verbose "Connecting to Exchange Online" Import-PSSession $Session -AllowClobber If ($Null -ne (Get-PSSession | Where-Object { $_.ConfigurationName -like "*Exchange*" })) { If (($host.ui.RawUI.WindowTitle) -notlike "*Connected To:*") { $host.ui.RawUI.WindowTitle += " - Connected To: Exchange" } Else { $host.ui.RawUI.WindowTitle += " - Exchange" } } } continue } MSOnline { If ($null -eq (Get-Module @getModuleSplat -Name "MSOnline")) { Write-Error "MSOnline Module is not present!" continue } Else { Write-Verbose "Connecting to MSOnline" If ($MFA -eq $True) { Connect-MsolService If ($Null -ne (Get-MsolCompanyInformation -ErrorAction SilentlyContinue)) { If (($host.ui.RawUI.WindowTitle) -notlike "*Connected To:*") { $host.ui.RawUI.WindowTitle += " - Connected To: MSOnline" } Else { $host.ui.RawUI.WindowTitle += " - MSOnline" } } } Else { Connect-MsolService -Credential $Credential If ($Null -ne (Get-MsolCompanyInformation -ErrorAction SilentlyContinue)) { If (($host.ui.RawUI.WindowTitle) -notlike "*Connected To:*") { $host.ui.RawUI.WindowTitle += " - Connected To: MSOnline" } Else { $host.ui.RawUI.WindowTitle += " - MSOnline" } } } } continue } SecurityAndCompliance { If ($MFA -eq $True) { $getChildItemSplat = @{ Path = "$Env:LOCALAPPDATA\Apps\2.0\*\CreateExoPSSession.ps1" Recurse = $true ErrorAction = 'SilentlyContinue' Verbose = $false } $MFAExchangeModule = ((Get-ChildItem @getChildItemSplat | Select-Object -ExpandProperty Target -First 1).Replace("CreateExoPSSession.ps1", "")) If ($null -eq $MFAExchangeModule) { Write-Error "The Exchange Online MFA Module was not found! https://docs.microsoft.com/en-us/powershell/exchange/exchange-online/connect-to-exchange-online-powershell/mfa-connect-to-exchange-online-powershell?view=exchange-ps" continue } Else { Write-Verbose "Importing Exchange MFA Module (Required)" . "$MFAExchangeModule\CreateExoPSSession.ps1" Write-Verbose "Connecting to Security and Compliance Center" Connect-IPPSSession If ($Null -ne (Get-PSSession | Where-Object { $_.ConfigurationName -like "*Exchange*" })) { If (($host.ui.RawUI.WindowTitle) -notlike "*Connected To:*") { $host.ui.RawUI.WindowTitle += " - Connected To: Security and Compliance Center" } Else { $host.ui.RawUI.WindowTitle += " - Security and Compliance Center" } } } } Else { $newPSSessionSplat = @{ ConfigurationName = 'Microsoft.SecurityAndCompliance' ConnectionUri = 'https://ps.compliance.protection.outlook.com/powershell-liveid/' Authentication = 'Basic' Credential = $Credential AllowRedirection = $true } $Session = New-PSSession @newPSSessionSplat Write-Verbose "Connecting to SecurityAndCompliance" Import-PSSession $Session -DisableNameChecking If ($Null -ne (Get-PSSession | Where-Object { $_.ConfigurationName -like "*Exchange*" })) { If (($host.ui.RawUI.WindowTitle) -notlike "*Connected To:*") { $host.ui.RawUI.WindowTitle += " - Connected To: Security and Compliance Center" } Else { $host.ui.RawUI.WindowTitle += " - Security and Compliance Center" } } } continue } SharePoint { If ($null -eq (Get-Module @getModuleSplat -Name Microsoft.Online.SharePoint.PowerShell)) { Write-Error "Microsoft.Online.SharePoint.PowerShell Module is not present!" continue } Else { If (-not ($PSBoundParameters.ContainsKey('SharePointOrganizationName'))) { Write-Error 'Please provide a valid SharePoint organization name with the -SharePointOrganizationName parameter.' continue } $SharePointURL = "https://{0}-admin.sharepoint.com" -f $SharePointOrganizationName Write-Verbose "Connecting to SharePoint at $SharePointURL" If ($MFA -eq $True) { $SPOSession = Connect-SPOService -Url $SharePointURL If ($Null -ne (Get-SPOTenant)) { If (($host.ui.RawUI.WindowTitle) -notlike "*Connected To:*") { $host.ui.RawUI.WindowTitle += " - Connected To: SharePoint Online" } Else { $host.ui.RawUI.WindowTitle += " - SharePoint Online" } } } Else { $SPOSession = Connect-SPOService -Url $SharePointURL -Credential $Credential If ($Null -ne (Get-SPOTenant)) { If (($host.ui.RawUI.WindowTitle) -notlike "*Connected To:*") { $host.ui.RawUI.WindowTitle += " - Connected To: SharePoint Online" } Else { $host.ui.RawUI.WindowTitle += " - SharePoint Online" } } } } continue } SkypeForBusiness { Write-Verbose "Connecting to SkypeForBusiness" If ($null -eq (Get-Module @getModuleSplat -Name "SkypeOnlineConnector")) { Write-Error "SkypeOnlineConnector Module is not present!" } Else { # Skype for Business module Import-Module SkypeOnlineConnector If ($MFA -eq $True) { $CSSession = New-CsOnlineSession Import-PSSession $CSSession -AllowClobber If ($Null -ne (Get-CsOnlineDirectoryTenant)) { If (($host.ui.RawUI.WindowTitle) -notlike "*Connected To:*") { $host.ui.RawUI.WindowTitle += " - Connected To: Skype for Business" } Else { $host.ui.RawUI.WindowTitle += " - Skype for Business" } } } Else { $CSSession = New-CsOnlineSession -Credential $Credential Import-PSSession $CSSession -AllowClobber If ($Null -ne (Get-CsOnlineDirectoryTenant)) { If (($host.ui.RawUI.WindowTitle) -notlike "*Connected To:*") { $host.ui.RawUI.WindowTitle += " - Connected To: Skype for Business" } Else { $host.ui.RawUI.WindowTitle += " - Skype for Business" } } } } continue } Teams { If ($null -eq (Get-Module @getModuleSplat -Name "MicrosoftTeams")) { Write-Error "MicrosoftTeams Module is not present!" } Else { Write-Verbose "Connecting to Teams" If ($MFA -eq $True) { $TeamsConnect = Connect-MicrosoftTeams If ($Null -ne ($TeamsConnect)) { If (($host.ui.RawUI.WindowTitle) -notlike "*Connected To:*") { $host.ui.RawUI.WindowTitle += " - Connected To: Microsoft Teams" } Else { $host.ui.RawUI.WindowTitle += " - Microsoft Teams" } } } Else { $TeamsConnect = Connect-MicrosoftTeams -Credential $Credential If ($Null -ne ($TeamsConnect)) { If (($host.ui.RawUI.WindowTitle) -notlike "*Connected To:*") { $host.ui.RawUI.WindowTitle += " - Connected To: Microsoft Teams" } Else { $host.ui.RawUI.WindowTitle += " - Microsoft Teams" } } } } continue } Default { } } } }
My name is Bradley Wyatt; I am a 4x Microsoft Most Valuable Professional in Cloud and Datacenter Management. I have given talks at many different conferences, user groups, and companies throughout the United States ranging from PowerShell to DevOps Security best practices and am the 2022 North American Outstanding Contribution to the Microsoft Community winner.
41 thoughts on “PowerShell Function to Connect to All Office 365 Services With Support for MFA”
Good work!
The page you link to for the Skype Online Connector module says that the module has been de-listed. Looking at MS docs, it appears that the powershell module for skype online which is currently recommended is this one:
https://www.microsoft.com/en-us/download/details.aspx?id=39366
I’m not sure if this is simply a newer version with an updated name, or if they are significantly different.
Is there a reason you went with the de-listed module over the current module?
I always try to find the module on the gallery first, so I saw the module named and linked the gallery version from here: https://docs.microsoft.com/en-us/skypeforbusiness/set-up-your-computer-for-windows-powershell/download-and-install-the-skype-for-business-online-connector
I changed it on the blog link so it links correctly. thanks
Will this work in VS Code, MFA has not been a friend of VS Code and PowerShell so far?
yeah just a function, IDE doesnt matter
Thank you! Looks Great!
Will this code get upgraded to include the Disconnect Sessions that should be done when using certain connections?
you mean removing your PSSessions? Run Get-PSSession | Remove-PSsession
This is magic, thank you for sharing.
Also, tiny typo on the AzureAD switch (line 113) in your module check condition.
Write-Error “SkypeOnlineConnector Module is not present!”
I assume this should be the ‘AzureAD Module’.
thanks, fixed
If I run Connect-Office365 -Service MSOnline, Exchange -MFA, does it right to input credential twice? In my case I should input id, password, code all twice?
yes because they are separate services which require a login and their own MFA code.
Hey I need some help I downloaded the script and when I am trying to run the ps I receive the following error:
I want to mention that I am not good with PowerShell I need some guidance on what I am doing wrong?
PS C:\Users\administrator> Connect-Office365 -Service Teams, Exchange, MSOnline
Connect-Office365 : The term ‘Connect-Office365’ is not recognized as the name of a cmdlet, function, script file, or
operable program. Check the spelling of the name, or if a path was included, verify that the path is correct and try
again.
At line:1 char:1
+ Connect-Office365 -Service Teams, Exchange, MSOnline
+ ~~~~~~~~~~~~~~~~~
+ CategoryInfo : ObjectNotFound: (Connect-Office365:String) [], CommandNotFoundException
+ FullyQualifiedErrorId : CommandNotFoundException
you need to load the function into memory. you can open powershell ISE, paste it and press the play button and then you will have it but I recommend creating a powershell profile and copying, pasting and saving the function in the profile file.
I did what you suggested still doesn’t want to work.
Nothing happened I want to mention that I installed the modules.
I tried to open like this but I receive the following error.
Suggestion [3,General]: The command Connect-Office365.ps1 was not found, but does exist in the current location. Windows PowerShell does not load commands from the current location by default. If you trust this command, instead type: “.\Connect-Office365.ps1”. See “get-help about_Command_Precedence” for more details.
PS C:\Users\administrator\Desktop\PowerShell-master\Office 365>
set you execution policy by launching an admin powershell (set-executionpolicy unrestricted (or remotesigned) ). when you save the function in your powershell profile you will need to relaunch powershell so powershell can see it.
You are a Rock Star!!!
Thanks for your help and quick reply.
How do you end the session, the reason why I ask is because my PS keeps freezing if I leave o365 connected. I tried Connect-Office365 -Exchange -MFA $false but it returns an error saying failed to connect.
you dont need to specify -MFA $False, only use the mfa param if you require MFA. (changed this from previous behavior)
when you connect youll have a PSSession, you can view your PSSessions by running Get-PSSession and remove all PSSessions by running Get-PSSession | Remove-PSSession
Thank you very much that makes a lot of sense! Now my powershell will stop freezing if I end the PSession wooo!
Wow this is awesome! once I figured out I had to paste it into Microsoft.PowerShell_profile.ps1 and change the sharepoint site name to mine.
Thanks, great script. Question: When I tried to connect with MFA, Here is what I got:
Connect-Office365 -Service exchange -MFA
Select-Object : Property “Target” cannot be found.
At line:137 char:59
+ $MFAExchangeModule = ((Get-ChildItem @getChildItemSplat | Select-Object -ExpandP …
+ ~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidArgument: (C:\Users\cli\Ap…xoPSSession.ps1:PSObject) [Select-Object], PSArgumentException
+ FullyQualifiedErrorId : ExpandPropertyNotFound,Microsoft.PowerShell.Commands.SelectObjectCommand
You cannot call a method on a null-valued expression.
At line:137 char:1
+ $MFAExchangeModule = ((Get-ChildItem @getChildItemSplat | Select-Object -ExpandP …
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (:) [], RuntimeException
+ FullyQualifiedErrorId : InvokeMethodOnNull
Connect-Office365 : The Exchange Online MFA Module was not found!
https://docs.microsoft.com/en-us/powershell/exchange/exchange-online/connect-to-exchange-online-powershell/mfa-connect-to-exchange-online-powershell?view=ex
change-ps
At line:1 char:1
+ Connect-Office365 -Service exchange -MFA
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [Write-Error], WriteErrorException
+ FullyQualifiedErrorId : Microsoft.PowerShell.Commands.WriteErrorException,Connect-Office365
What am I missing?
Did you download the MFA module from your tenant? Looks like it cannot find it
Much thanks for this and the links in the comments to add to profile!
I really hope that we (and I really mean you because I am no where near this) can design a way for one MFA prompt.
This is the most working way for me too… but still looking forward to know how to bypass MFA to enter only one time.
Brad –
Nice work!
Very slick method of importing the MFA module 🙂
I like it!
Wonderful idea, but half the customers I connect with, I need to use -OverrideAdminDomain setting on the New-CsOnlineSession for SFBO.
Great script! Makes it som much easier and slicker to connect to O365 services. Thank you for sharing this.
I think you have a typo(s)
Your first script uses Connect-O365 and you explain that is what you use to connect with, however below that the scripts by the screenshots you instead have Connect-Office365 instead of the Connect-O365.
my old function was Connect-O365 which is referenced but since I re-did the function I re-named it
Just wanted to say thank you for sharing this!
nice script LazyAdmin 😉 Thank you for sharing! One other thing, we are a company who manage multiple tenants as partner. There is a new option now made possible (at least in Exchange) the function -DelegatedOrganization. This allowes you to use EXOP to connect to a partner tenant with MFA through my partner account. How can I implement this in the script? Preferably like “Connect-Office365 -Service Exchange, MSOnline, Teams -MFA -DelegatedOrganization”
This is great! Any way to connect to multiple Office 365 Services with support for MFA without having to be prompted for my credentials each time?
Please delete my last comment, my email address was incorrect. Thanks.
No not as of yet
Thanks for this, works really well.
I have inserted the function into a powershell module I have created (stuff that I use a lot) and when it runs out from the module it all runs without error but the functions loading from exchange are not accessible. If I just include the file in the script it works great.
I hit a bit of a mental block so any assistance would be greatly appreciated.
If you are using MFA, then take a look at the following from The Lazy Administrator.
https://docs.microsoft.com/en-us/powershell/exchange/exchange-online/connect-to-exchange-online-powershell/mfa-connect-to-exchange-online-powershell?view=exchange-ps
Thanks, checked this already and I have that installed. As I say, if I run it as a function in a script it works fine but as soon as I include it in a module it no longer works…..very strange
Beautiful! MS should have had something like this from the start, but I’ll never understand why they don’t at at minimum have a version of something like the MS Teams Powershell module(https://www.powershellgallery.com/packages/MicrosoftTeams/) thats easy to install and lets you connect with a single command, for each service. Why does that exist but for most of the rest we have to do these semi-convoluted multi-line PoSs?
Anyone want to have a crack at updating this for Exchange V2?
https://docs.microsoft.com/en-us/powershell/exchange/exchange-online/exchange-online-powershell-v2/exchange-online-powershell-v2?view=exchange-ps
I’m not an expert but should be able to “power” through it if I ever have the time.
Does this work with CSOM?