Azure Cloud Shell now supports connecting to Exchange Online PowerShell for MFA-enabled accounts

In a recent article published over at, I covered Azure Cloud Shell and its use for managing Office 365 services. At the time of writing, there were some issues, such as being unable to connect to Exchange Online PowerShell if your account is protected by MFA, or in general using any module with dependency on ADAL as the library didn’t have support for .Net Core. Even back then we knew that Microsoft was working on bringing the ExO MFA module to ACS, as indicated by the following code snippet:

PowerShell code snippet

Well, this has now been released and you can start using your MFA-enabled accounts. As the ACS environment is managed by Microsoft, you don’t need to do anything in order to get this new functionality. Simply connect to ACS, then execute the Connect-ExOPSSession cmdlet, and voila:

Azure Cloud Shell

At no point doing this process I was asked to provide credentials or perform MFA, yet I managed to connect just fine to ExO PowerShell. Moreover, I connected by using Modern authentication, and this is how I know that for a fact:

Azure Cloud Shell

Of course, being the curious type I just had to know how exactly Microsoft enabled this. One possibility was that the ExO MFA module finally supports running on PowerShell Core, which is the impression you might get by examining the Connect-ExOPSSession cmdlet:

ACsPS3Alas this doesn’t seem to be the case and connecting via MFA-enabled accounts is for the time limited to “regular” PowerShell and ACS. Moreover, this doesn’t explain why I wasn’t prompted for credentials, which leaves the impression of using some form of seamless SSO experience. While we can have (sort of) seamless SSO experience with the ExO MFA module on Azure AD joined machines, this certainly doesn’t apply to ACS environments, which run on a Linux VM in Azure.

So how does it work then? When you login to ACS, the service presents you with an access token/cookie and an ID token. ACS however cannot just reuse this to connect to Exchange Online, as those artifacts were issued for a different resource. In order to facilitate access to Exchange Online, once you issue the Connect-ExOPSSession cmdlet, ACS triggers a request to the /api/DelegationToken endpoint, presenting the cookie it obtained from the initial login process. In return, an access token is presented, which is then passed to Exchange Online via the standard “BasicAuthToOAuthConversion” flow, described for example in this article.

Fiddler traffic captureThe access token itself will look a bit different compared to what you might be used to, as illustrated below. While the username, tenantID and the resource being accessed have the expected values, the application for which the token is requested/issued is different – “AzurePortal Console App” with identifier “b677c290-cf4b-4a8e-a60e-91ba650a4abe“. We can also see that a client certificate authentication was used, and that the scope (permissions) included in the token are limited to just “RemotePowerShell.AccessAsUser.All“, compared to the “AdminApi.AccessAsUser.All FfoPowerShell.AccessAsUser.All RemotePowerShell.AccessAsUser.All” value we get with the regular “Microsoft Exchange Online Remote PowerShell” application (with id “a0c73c16-a7e3-4564-9a95-2bdf47383716“).

Decoded JWT tokenPutting those differences aside, once a token is obtained and passed to the Exchange Online Remote PowerShell endpoint, you can expect to connect and work with the familiar cmdlets as you would do on your desktop machine. All the familiar controls will work as expected, including RBAC, Conditional Access policies, Client Access Rules (example of ACS being blocked by a CAR is shown below). The only difference is with how the token was obtained, and as we’ve shown in previous articles you have several options for doing this and connecting to ExO PowerShell “manually”.

ACSPS CARThe only remark I have is about the lack of any events related to obtaining the Access token and/or the actual connection to Exchange Online PowerShell. While you can certainly use the application identifier (“b677c290-cf4b-4a8e-a60e-91ba650a4abe”) to filter out the logs for any events related to Azure Cloud Shell, getting information about any Exchange Online Remote PowerShell sessions initiated via ACS proved fruitless. Hopefully this will be addressed in the future.

Also check out the official announcement here:

1 thought on “Azure Cloud Shell now supports connecting to Exchange Online PowerShell for MFA-enabled accounts

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.