Exchange Online is denying the connection, but the permissions are correct. The reason why this may happen are shown in this article.
The Exchange Online PowerShell Module is a great way to administer Exchange Online by not using a GUI. Especially if you are a PowerShell lover like I am. So in this case I started connecting to Exchange Online with the ExoV2 module ExchangeOnlineManagement:
For whatever reasons, I was not able to connect. So I started investigating and learned, there is a number of possible issues that may cause the following error:
New-ExoPSSession : Connecting to remote server outlook.office365.com failed with the following error message : Access is denied. For more information, see the about_Remote_Troubleshooting Help topic. At C:\Users\Andreas\Documents\WindowsPowerShell\Modules\ExchangeOnlineManagement\2.0 .5\netFramework\ExchangeOnlineManagement.psm1:475 char:30 … PSSession = New-ExoPSSession -ExchangeEnvironmentName $ExchangeEnviro …
~~~~~~~~~~~~~ CategoryInfo : ResourceUnavailable: (:) [New-ExoPSSession], PSRemotingTransportException FullyQualifiedErrorId : System.Management.Automation.Remoting.PSRemotingDataStructureException,Microsoft.Exchang e.Management.ExoPowershellSnapin.NewExoPSSession
The investigation can take quite a large amount of time. I show you all things I’ve found and tried and how I finally solved the connection problem.
Solution Approach by Microsoft
One of the first research results in the web is this website owned by Microsoft: Access is denied when you connect to Exchange Online with Windows PowerShell – Exchange | Microsoft Docs. The connection account was Global Admin (assigned via Priviledged Identity Management more than 1 hour ago and still active). Additionally I also tried adding the account explicitly to the Organization Admins and the AAD RBAC role Exchange Admins. Nothing led to success.
The account is of course active, the password not expired. Security Defaults are not active in the tenant, because it uses Conditional Access.
So the Microsoft solution approaches did not help. Let’s try another one.
Sometimes you can read in the internet on some sites, that there is a registry key that needs to be set on a Windows Machine. I didn’t believe that it will help (because already the name sounds dangerous), but I gave it a try. The key is the following:
HKEY_LOCAL_MACHINE\SOFTWARE\Policies\Microsoft\Windows\WinRM\Client DWORD32 "AllowBasic" Value: 1
This didn’t help, even after PowerShell- and PC-restart. Because that key was initially not present on my Windows 11 computer, I deleted it.
To make sure the error is not related to a specific client, I tried sign in with the same account from another computer that is joined and managed (and compliant) in this Azure Active Directory. The result was the same error -> it must be caused somewhere in the cloud. Usually that should be checked at the beginning 😉
PowerShell 7 makes the difference
Now comes PowerShell 7 into the game. I read in the documentation of Connect-ExchangeOnline, that module version 2.0.4 introduced a new parameter named “-Device” that can only be used with PowerShell 7. Sounds good to finally eliminate possible issues with the account. So here is what happens when signing in with that new parameter:
Navigating to that website asks for the code that is displayed on the screen. I did this in an Edge Browser window where I am currently signed in the admin account I am trying to use when authenticating in the Shell:
After entering the code, Microsoft asks me with which account I want to sign in to ExoV2. Here I choose my admin account:
What happened then, is really interesting – this error is not only “Access Denied” like in the PowerShell error (you remember the error message from the beginning of that post?), it is actually Conditional Access! Look:
This is really weird, because the first thoughts were:
- my PC is compliant
- I did MFA sucessfully
- I have satisfied all rules that may block access
So the journey continues. Thank you PowerShell 7, without that hint, it would have taken many many hours to figure that out!
Investigating Conditional Access
Inside Conditional Access the best point to start are the sign in logs. These can easily be opened in a browser with the admin that is not able to sign in via Shell. And it doesn’t take long time to find the Failure Events and the reasons why Conditional Access blocked:
What I saw then knocked me off my chair. Of course it was Conditional Access. But the guilty rule was strange:
I swear I am coming from a Windows 11 computer, I do not have (and currently don’t need) Linux in my environment, that is why this rule exists. The rule is simple. It blocks all access for all users for all Cloud Apps on Windows Phone and Linux. My assumption: Because PowerShell 7 presents itself as “Core”, it is not recognized as Windows, Android or iOS and (technically correct) blocked in my case.
To solve that, there are multiple solution approaches. Choose the one that fits best into your environment:
- Exclude your office IP from that rule. Use the IP (named location) from where you do administrative tasks
- Exclude your tenant admin account from that rule
- Exclude the app “Office 365 Exchange Online” from that rule (and all other products like Teams as well if you run into an issue)
Funnily, after adding the exclusion or performing the deletion of that rule, the sign in window looked slightly different in my case:
This is followed by a confirmation prompt to close that window after successful authentication. I thought that’s it, but —- the error was still there. So, Conditional Access is not the reason. That meant for me: revert all changes to the ruleset to how it was before.
The end of the journey – use the ExoV2 module V2.0.6
To be honest: I didn’t finish the research until the last bit & byte. After several hours of investigation I saw somwhere in the PowerShell window a message that said that some commands may be deprecated soon, I should install a preview version. Well, at the time of writing, the current GA release is 2.0.5, 2.0.6 is available only as preview. But it’s worth a try. So I deleted the “old” 2.0.5 module and installed the newer version:
Install-Module ExchangeOnlineManagement -AllowPrerelease
Believe it or not – that fixed it for me. I removed all my test configuration, resetted everything back to default and the result was a successful connection:
Life can be so easy.. And the conclusion is: Keep your modules always up 2 date!