Hacking your way around Modern authentication and the PowerShell modules for Office 365

Most of the Office 365 PowerShell modules now support Modern authentication and that’s a very good thing. However, the implementation across the different modules leaves a lot to be desired because of the different approach taken by each team. For example, some of the modules do not support the Credentials parameter, other support it but automatically fallback to using legacy authentication when this parameter is invoked and so on. The table below summarizes the current landscape:

MFA status Pass credentials Pass token Bypass MFA on trusted location
Azure AD Supported Supported Supported Supported
Exchange Online (legacy) Not supported N/A N/A Not supported
Exchange Online (MFA module) Supported Not supported Not supported* Supported
Security and Compliance Center Not supported N/A N/A Not supported
SharePoint Online Supported Supported*** Not supported Not supported
SharePoint Online PnP Supported Supported*** Not supported Supported
Skype for Business Online Supported Supported*** Not supported* Supported
AIP/AADRM Supported Supported Supported Supported
Azure Supported Supported Supported Supported

The option to pass credentials is an important one, as you can combine it with different methods to bypass the need to perform second-factor authentication. For example, you can modify your claims rules to ensure that when the request is coming from a particular user, IP or application, no additional authentication will be required. Similarly, if you have configured second-factor authentication via Azure MFA, you can use the trusted locations functionality. This enables you to use the account to automate scripts or execute scheduled tasks, while at the same time still making sure it’s protected by additional authentication factors for generic requests.

(The asterisks in the Pass credentials column designate the modules which use legacy authentication when the Credentials parameter is invoked)

An alternative to this approach is to completely bypass the PowerShell modules and get an access token programmatically, then pass it directly, which is what we will discuss in the current article. Some of the modules do have support for passing a token as noted in the above table. The asterisks in the Pass token column indicate modules that do not have a parameter to pass the access token to, but for which certain workarounds exist.

Anyway, in order to get the token programmatically, one can use the ADAL binaries that come with the install of any of the above modules. For example, if you have the 2.0.0.98 version of the Azure AD PowerShell module installed, you can load the necessary DLL via:

Add-Type -Path 'C:\Program Files\WindowsPowerShell\Modules\AzureAD\2.0.0.98\Microsoft.IdentityModel.Clients.ActiveDirectory.dll'

The same DLL is shipped with each of the ADAL-enabled modules, however the version of the DLL might be different! In turn, this results in different methods exposed and even different authentication flows! This is one of the examples of the different ways modern authentication support has been implemented by different teams at Microsoft and one can only hope in the future things will change for the better.

Once the DLL is loaded, one can use the AcquireTokenAsync method to acquire a new access token. Some information is required beforehand though, such as the authority from which to request the token, the clientID of the application (Exchange Online for example), the resource you want access to. Unfortunately, there is no easy way to get the clientID, as Microsoft does not publish a list of the “server-side” applications. However, we can simply “hack” into what the ExO module does for example, and get all the needed information from a Fiddler trace. Or better yet, simply get it from the token cache:

$cache = [Microsoft.IdentityModel.Clients.ActiveDirectory.TokenCache]::DefaultShared
$cache.ReadItems() | select DisplayableId, Authority, ClientId, Resource

The screenshot above is taken after connecting to the Azure AD, ExO and SfBO PowerShell modules with Modern authentication enabled. For each of these, an access token was obtained and the token cache gives us information about the authority, clientID and Resource for which the token is valid. In effect, now we have all the needed information to get a token programmatically for each of these. Here’s how to get the token for ExO:

$authContext = New-Object "Microsoft.IdentityModel.Clients.ActiveDirectory.AuthenticationContext" -ArgumentList https://login.microsoftonline.com/michev.onmicrosoft.com/
$client_id = "a0c73c16-a7e3-4564-9a95-2bdf47383716"
$Credential = Get-Credential huku@michev.onmicrosoft.com
$AADcredential = New-Object "Microsoft.IdentityModel.Clients.ActiveDirectory.UserPasswordCredential" -ArgumentList $Credential.UserName,$Credential.Password
$authResult = [Microsoft.IdentityModel.Clients.ActiveDirectory.AuthenticationContextIntegratedAuthExtensions]::AcquireTokenAsync($authContext,"https://outlook.office365.com",$client_Id,$AADcredential)

If everything went OK, the access token will be contained in the $authResult.Result.AccessToken output. Or, you can simply look at the token cache as we did above. And once you have the access token, you can then connect to ExO Remote PowerShell by using:

$Authorization = "Bearer {0}" -f $authResult.Result.AccessToken
$Password = ConvertTo-SecureString -AsPlainText $Authorization -Force
$Ctoken = New-Object System.Management.Automation.PSCredential -ArgumentList "huku@michev.onmicrosoft.com", $Password
$Session = New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionUri https://outlook.office365.com/PowerShell-LiveId?BasicAuthToOAuthConversion=true -Credential $Ctoken -Authentication Basic -AllowRedirection
Import-PSSession $Session

There’s one last piece of information that we needed in order to perform the above action, namely the ConnectionURI. You can see that it’s very similar to the “regular” one we’ve been using for years, however there is one additional parameter added at the end. Where do we get this information you ask? Simply look at the parameters of any ExO Remote PowerShell session you have created via the new, MFA-enabled module:

The procedure outlined above can be used to “reverse engineer” connecting to other Office 365 services via access token. Getting the access token itself can be performed by various means, using the different ADAL methods. For the purposes of automation, a solution that does not require any user interaction is preferred, so my recommended method is to configure the bypass, however you can also invoke the generic ADAL prompt and perform the login process interactively if needed.

Now, one important thing that needs to be made clear ‚Äď this only covers the access token! Depending on the ADAL binaries used, a refresh token might not even be returned, so the session you establish using this method will be a short-lived one ūüôā

Posted in Exchange Online, Office 365, PowerShell | Leave a comment

Improved handling for Modern Attachments in OWA

Modern attachments are one of the features that can have significant positive impact on your productivity and collaboration with others. Instead of emailing document copies all day long just to compare a few edited paragraphs, they allow you to centrally store the document and co-author it, while the mundane task of granting the necessary permissions is taken care of by the client (and the backend).

However, there are some rough edges around the feature. First of all, the experience for external users can be impaired, as some of them might find it harder to actually access the document, compared to just double-clicking the attached copy. It’s also not that uncommon for permissions to fail to apply correctly, leaving you with a useless link instead of the document you urgently needed. Another concert expressed by some organizations was the fact that attachments were shared with Edit permissions by default, while they would have preferred to have them set as Read-only.

Now, Microsoft is rolling out an update to the service that will take care of this. In a nutshell, the client will now respect the Sharing settings configured under the SharePoint Online Admin Center and will present you with different options depending on the level of permissions allowed there. This includes the Anonymous/Guest links, the Organization-wide links or sharing with specific people only. Moreover, the default permissions will also be set in accordance to the settings configured in the SPO Admin center.

The steps to use Modern attachments are the same as before: start composing a new message, press the Attach button, select a file either by uploading it or directly selecting it from your OneDrive for Business folder. Then, to adjust the permissions on the file, press the small arrow on the right-side of the attachment. The below screenshot shows how the newly introduced controls look like with the default tenant settings – external sharing and guest links enabled, with the permission level for guest links set to Edit:

And here’s how the same settings look like after changing the External sharing settings in the SPO Admin Center to Disabled:

Note the absence of the two “Anyone” checkboxes. In addition, the default permission level is now set to “anyone in my organization”.¬†Switching the Sharing¬†settings¬†back will once again make the “Anyone” option available. Exchange Online will query those setting on the backend asynchronously, so you don’t even have to close the message window to have them reflected (although you have to re-attach the file).

Personally, I think these changes are a great step forward, as they should take care of most of the permission-related issues that plagued Modern attachments. In addition, the granular control administrators now have over this feature will surely help put some minds at ease.

Posted in Exchange Online, Office 365, OneDrive for Business, OWA | Leave a comment

“Office 365 for IT Pros” gets its 4th edition

The best book on Office 365 just got better. Edited by yours truly, the 4th edition reached 1000 pages and almost half a million words! It features 840 PowerShell examples and gazillion of pictures. On top of this, you can get 6 bonus PDFs with extra content that had to be removed from the book to keep the size manageable.

The 4th edition introduces a fourth author, Ståle Hansen, who took on the task of expanding the Skype for Business chapter. A lot of content on Security and Compliance was added too, as well as other areas such as Intune, Teams, and so on.

As usual, you can get an upgrade at great discount, and for a limited time, a 20% discount on new purchases. Head over to https://practical365.com/ebooks/office-365-for-it-pros/ to get your copy!

Posted in Office 365 | Leave a comment

Controlling resource delegates for User mailboxes

I can swear I’ve blogged about this already, but I cannot seem to find it, so here we go again.

Configuring resource delegates via PowerShell¬†is no longer possible for User mailboxes in Exchange Online. The –ResourceDelegates parameter of the Set-CalendarProcessing cmdlet designates recipients to which calendar requests will be forwarded, in scenarios where you have chosen to delegate calendar access. In Outlook, you can do this by accessing the Delegate Access dialog, adding a user and select the “Delegate receives copies of meeting-related messages sent to me” checkbox.

Previously, it was possible to control these settings via PowerShell as well, but if you try to use the Set-CalendarProcessing cmdlet now to add/remove resource delegates, you will run into the following error:

Set-CalendarProcessing vasil -ResourceDelegates pesho
ResourceDelegates can only be enabled on resource mailboxes.
+ CategoryInfo          : InvalidData: (vasil:ADObjectId) [Set-CalendarProcessing], ResourceOnlyException
+ FullyQualifiedErrorId : [Server=AM5PR03MB3027,RequestId=68f34b77-37b3-4783-830e-e78186874768,TimeStamp=5/18/2017 3:30:02 PM] [FailureCategory=Cmdlet-ResourceOnlyException] 5491BFF2,Microsoft.Exchange.Management.StoreTasks.SetCalendarProcessing
+ PSComputerName        : outlook.office365.com

If you need to control these settings, you will have to use Outlook or EWS-based script.

As to when this change occurred, I’m pretty sure it was around the time I blogged about a similar change with the –AddNewRequestsTentatively¬†parameter.

Posted in Exchange Online, Office 365, PowerShell | Leave a comment

Accessing Supervisory mailboxes in Outlook

The new, improved Supervision feature in Office 365 was made available a week ago. If differs from the old version is several key areas, but the idea is the same ‚Äď it gives you the ability to monitor some percentage (or all) of employee communication. Details on how to setup the feature can be found for example here: https://support.office.com/en-us/article/Configure-supervision-policies-for-your-organization-d14ae7c3-fcb0-4a03-967b-cbed861bb086

As you might know already from the documentation, the new version relies on SupervisoryReview mailboxes to store the messages for review. The actual recipient type is SupervisoryReviewPolicyMailbox, however knowing this will not help you a lot, as the mailboxes are well hidden in both the UI and PowerShell. The only method you can use to get the name of the mailbox is via the Get-SupervisoryReviewPolicyV2, for example:

Get-CSupervisoryReviewPolicyV2 | select Name,ReviewMailbox

Name ReviewMailbox
---- -------------
Supervision SupervisoryReview{feea04e6-3ae2-4edc-8526-7d758192d7d7}@michev.onmicrosoft.com

Now, when it comes to actually accessing the mailbox, things should be taken care of thanks to the Supervisory Review add-in that is automatically installed for users designated as Reviewers.

The add-in will make sure that the Supervisory Review mailbox is added as additional mailbox in OWA and exposes the relevant actions as well. When it comes to accessing the Supervisory mailbox in Outlook though, things are a bit trickier. Microsoft has published an article detailing how you can add the mailbox in Outlook, however if you follow the steps there you will find out that the process does not actually work.

The thing is, the steps in the article details the process of adding a mailbox as additional account in Outlook. In order to do this, you must have Full Access permissions on said mailbox, which is not the case here. Permissions on the Supervisory mailbox are granted on the Folder level, namely each Reviewer will get the “reviewer” level of permissions on the Root folder and the “Supervision” folder tree. In other words, this is what you will see via PowerShell:

Get-MailboxPermission "SupervisoryReview{feea04e6-3ae2-4edc-8526-7d758192d7d7}@michev.onmicrosoft.com" -User vasil

Get-MailboxFolderPermission "SupervisoryReview{feea04e6-3ae2-4edc-8526-7d758192d7d7}@michev.onmicrosoft.com" -User vasil

FolderName User AccessRights
---------- ---- ------------
Top of Informatio... Vasil Michev {Reviewer}

Get-MailboxFolderPermission "SupervisoryReview{feea04e6-3ae2-4edc-8526-7d758192d7d7}@michev.onmicrosoft.com:\Supervision" -User vasil

FolderName User AccessRights
---------- ---- ------------
Supervision Vasil Michev {Reviewer}

Yes, while the Get-Mailbox or Get-Recipient cmdlets does not recognize Supervisory Mailboxes, some other cmdlets will work just fine. This includes the Add-MailboxPermission cmdlet, which you can use to grant Full Access permissions to the mailbox (with Automapping enabled) and the Set-Mailbox cmdlet which you can use to un-hide it from the GAL:

Add-MailboxPermission "SupervisoryReview{feea04e6-3ae2-4edc-8526-7d758192d7d7}@michev.onmicrosoft.com" -User vasil -AccessRights FullAccess

Identity User AccessRights IsInherited Deny
-------- ---- ------------ ----------- ----
SupervisoryReview... EURPR03A001\vasil... {FullAccess} False False

Set-Mailbox "SupervisoryReview{feea04e6-3ae2-4edc-8526-7d758192d7d7}@michev.onmicrosoft.com" -HiddenFromAddressListsEnabled $false

After doing this, it’s just a matter of waiting for autodiscover refresh and you will get the mailbox added to your Outlook profile:

Now, Microsoft has acknowledged the issue and is working on providing a solution, in the meantime you can use the steps here as a workaround.

Posted in Exchange Online, Office 365, PowerShell | Leave a comment