Exchange Online module now supports PowerShell 7/Core

Yesterday, Microsoft officially released the 2.0.4 version of the Exchange Online V2 PowerShell module. The biggest improvement this version brings is support for running the module on PowerShell 7+ instances, as announced back at Ignite. In other words, we now have cross-platform support for running Exchange Online PowerShell cmdlets!

Since the announcement at Ignite, quite few public preview versions of the module have been made available, so people that were interested in PowerShell 7 support have most likely already tested it and I will not go over many details here. I do want to point few facts that I personally find interesting though. Let’s start with the new “browser-based SSO” method.

If you have used some of the “cloud” PowerShell modules on a PSCore install, you might have experienced the annoyance of having to go over the device code flow in order to complete the authentication process. While this flow is designed to be used on devices with limited input capabilities, it’s also the default method for some PowerShell modules running in “core” environments, even if the device is capable to use the browser control. The “browser-based SSO” method alleviates some of the annoyances by leveraging a clever workaround of sorts, redirecting the response (and the token) to a local HTTPS listener.

In effect, when you issue the Connect-ExchangeOnline cmdlet without any parameters, the default browser will be launched and the familiar Azure AD login page will be displayed. You can then proceed with typing your credentials, meeting the MFA challenge or performing passwordless authentication, depending on what’s configured for your account/organization. Finally, a new page will be displayed in the browser with a simple message designating either success or failure, as shown below:

If you take a closer look at the URL during the authentication phase however, you will notice some familiar elements as well as few differences compared to the “standard” process. The client_id property is still using the same value of fb78d390-0c51-40cd-8e17-fdbfab77341b or the appID corresponding to the Microsoft Exchange REST API Based PowerShell application. Similarly, the same resource and scopes are utilized. The redirect_uri value will look a bit strange however, for example https://localhost:59618. This is in fact the local “listener”, which is only active during the authentication phase and to which the response will be redirected as the last step of the authentication process. As the response itself contains the token, the PowerShell process now has all the needed building blocks to establish a remote session.

Now, some questions might arise from the above description, such as “is PowerShell really spinning up an HTTP server on my device every time I run the cmdlet”? Well, yeah, and not really. OK, maybe 😀 One can argue on that front I suppose, but the reality is that it will only listed to “local” addresses, only on a specific port (incremental) and only for the validity of the authentication flow. If you close the tab or cancel the flow in any other way, or if you try to access the local address directly, it will immediately shut down.

TCP              LISTENING
TCP    [::]:63670             [::]:0                 LISTENING

The “browser-based SSO” described above is the default method and the one used when you run the Connect-ExchangeOnline cmdlet without any parameters. You can still use the device code flow when needed, by specifying the -Device parameter. Lastly, you can also use the newly introduced -InlineCredential parameter to enter credentials directly in the console:

Remember that there is no way to perform MFA when using this method, so it might inapplicable in most scenarios. Also, there is no –Credential parameter when using the PowerShell 7+ version of the module, meaning you need to use –InlineCredential instead. Last but not least, you can also connect via certificate, which remains the preferred method for automation scenarios, with the added benefit that it now works on core.

Other things worth mentioning about the new version of the module include support for Continuous Access Evaluation, which is one of my favorite new feature on Azure AD side of things, and the fact that it now powers the experience within Azure Cloud Shell (which got support for browser based SSO a while back).

This entry was posted in Exchange Online, Microsoft 365, Office 365, PowerShell. Bookmark the permalink.

3 Responses to Exchange Online module now supports PowerShell 7/Core

  1. bees says:

    Hi Vasil,
    firstly, great blog.
    Secondly, you mentioned here device code flow as a way to log in to Exchange Online which is really annoying. I’m just curious whether you’ve heard of any method to connect to Exchange Online (or other MS entities) via PowerShell using physical security keys (e.g. from yubico) as 2nd factor? Passwordless seems to be a bit neglected here. There is not a simple way out there for me, as an admin, to fully get rid of that MS Authenticator app on admin account just because I cannot use security keys/passwordless while logging through PowerShell. I’ve done some research and probably certificates (?) are the only option left but so far I’ve not dig into it since it’s not my top priority and it wasn’t documented very well then.
    Thirdly, since I’m already writing, as far as I know it’s not possible to “save” the result of MFA authentication process into a variable, just like it is with sth like Get-Credential (and then e.g. export-clixml and use it as -Credential parameter etc)? I’m aware that it kills the whole purpose of setting up MFA. Of course this is loosely connected to the paragraph above, I was just trying to find some workaround.

    • Vasil Michev says:

      Never got a physical token to test with, so I cannot be certain what the experience is. However I see no point why it wouldnt work, at least on a Windows machine. At the very least, you should be able to obtain token and pass it to create the session.
      Passwordless on a Azure AD joined machine works fine btw, just use the -UserPrincipalName switch.

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.