Monthly Archives: July 2016

Common questions using Office 365 with ADFS and Azure MFA

Azure Multi Factor Authentication (MFA) is a great service that has been included in Office 365 for almost 2,5 years. The adoption has really been great – at least from an admin user perspective where 99% of my customers admins have it enabled (I usually force them).
From an end user perspective we have more technical and informational challenges, which means that the adoption has not been as great as on the admin side. Hopefully the new shiny Conditional access policies for specific workloads will boost the adoption a bit.

The purpose of this post is to share the most common questions I get from customers about using Azure MFA included in Office 365 (in most cases in combination with ADFS).

Q: Can we pre-stage the MFA authentication methods so the end user doesn’t have to enroll after being enabled for MFA?
A: As of now, unfortunately no – I tried to build a PowerShell function to pre-populate the authentication methods if the user already had a mobile phone number. I was fooled and thought it worked, but when I tried on a user that never had enrolled MFA before, it failed. Troubleshooting further, the required MFA property “StrongAuthenticationUserDetails” is not possible to pre-populate programmaticly, yet. Maybe the new AzureAD module can help here in the future.
Conclusion – we have to instruct our users to enroll for MFA.

Q: Can we prevent MFA from kicking in when authenticating from our internal network?
A: Absolutely – There are some options depending on if you have Azure AD Premium or not.

With Azure AD Premium
Here you can choose to “white list” your external IP addresses (which of course works with or without ADFS), or check the “Skip multi-factor authentication for requests from federated users on my intranet” checkbox. This will make Azure AD decide about MFA based on the insidecorporatenetwork claims issued by your own ADFS.
The following PowerShell rows will add the required Issuance Transform Rules to your Azure AD RP.

$ByPassMFAClaims = @"
@RuleName = "Passtrough - InsideCorporateNetwork"
c:[Type == ""]
 => issue(claim = c);

@RuleName = "Passtrough - PSSO"
c:[Type == ""]
 => issue(claim = c);
$AzureADRP = Get-AdfsRelyingPartyTrust -Name "Microsoft Office 365 Identity Platform" 
Set-AdfsRelyingPartyTrust -TargetName $AzureADRP.Name `
                          -IssuanceTransformRules ($AzureADRP.IssuanceTransformRules + $ByPassMFAClaims)

Without Azure AD Premium
Without Azure AD Premium we don’t have the same choices in service settings.
We can however achieve the same result, but instead of passing through the insidecorporatenetwork claims, we use it in ADFS and “tell” Azure AD that MFA is already taken care of. This can be done with the claim rules as below.

$ByPassMFAClaims = @"
@RuleName = "Bypass MFA from inside - Without Azure AD Premium"
EXISTS([Type == "", Value == "true"])
 => issue(Type = "", Value = "");

@RuleName = "Passtrough - PSSO"
c:[Type == ""]
 => issue(claim = c);
$AzureADRP = Get-AdfsRelyingPartyTrust -Name "Microsoft Office 365 Identity Platform" 
Set-AdfsRelyingPartyTrust -TargetName $AzureADRP.Name `
                          -IssuanceTransformRules ($AzureADRP.IssuanceTransformRules + $ByPassMFAClaims)

Q: Do we really need to use the f****** app passwords?
A: Not really anymore, at least not if you are using ADFS. I usually turn it off.
First of all most rich clients (Including Outlook/SfB on mobile devices) do now support Modern Authentication (ADAL), which means they can handle MFA out of the box. So as long as you have updated clients, you most often only need to handle ActiveSync (native mail clients in all kinds of devices). My approach here is usually to exclude them from MFA to get rid of the app password need, but enable conditional access in order to control the devices.

Below you find a claims rule for the ActiveSync protocol that issues the multipleauthn claim which Azure AD will honor by skipping MFA for the request.

$Claims = @"
@Claims= "Bypass MFA for ActiveSync"
EXISTS([Type == "", Value=="/adfs/services/trust/2005/usernamemixed"]) && 
EXISTS([Type == "", Value =~"^(Microsoft.Exchange.(Autodiscover|ActiveSync))$"]) 
=> Issue(Type = "", Value = ""); 
$AzureADRP = Get-AdfsRelyingPartyTrust -Name "Microsoft Office 365 Identity Platform" 
Set-AdfsRelyingPartyTrust -TargetName $AzureADRP.Name `
                          -IssuanceTransformRules ($AzureADRP.IssuanceTransformRules + $Claims)

Please note that additional rules may be needed depending on if you have an Exchange or Skype for Business Hybrid environment.

Q: Can we combine Azure MFA with our already implemented on-premises MFA solution?
A: It works fine to combine Azure MFA with any MFA solution that integrates with ADFS. The only thing you need to do is issue the authnmethodsreferences on the Azure AD RP to prevent users from getting “Double MFA” like SmartCard + Azure MFA. 🙂 For example, if I have Cert Auth as an enabled MFA provider as below, I only have to authenticate with my VSM/SmartCard even if MFA is enabled on the user.
The needed claims rule looks like this:

$Claims= @"
@RuleName = "Passthrough - MFA"
c:[Type == ""]
 => issue(claim = c);
$AzureADRP = Get-AdfsRelyingPartyTrust -Name "Microsoft Office 365 Identity Platform" 
Set-AdfsRelyingPartyTrust -TargetName $AzureADRP.Name `
                          -IssuanceTransformRules ($AzureADRP.IssuanceTransformRules + $Claims)

The above also works with the new Conditional Access policies for Exchange and SharePoint online.

Wrap up
Hopefully this post has given you some good insights what to think about implementing Azure MFA for Office 365. It is not a complete walk in the park, but it’s definately doable for most organizations.
As always, there are lots of if’s and but’s in all different environments. If I have missed something or if you have other, more specific questions, let me know!



How to resolve “We’ve run into a problem with your Office 365 subscription” with PowerShell

A colleague of mine performed a tenant to tenant migration a while ago. After the switchover to the new tenant, almost all users Office 365 ProPlus installations started to complain with the error message “We’ve run into a problem with your Office 365 subscription”. 2016-07-13_21-29-33
Signing out/in trying to activate the installation again didn’t help and after a while he found a solution at Jaap Wesselius blog.

The solution was to run the OSPP.vbs script located in the Office installation folder as in the screenshot below. Running the script with the /unpkey parameter removes the existing license and forces the user/client to re-register.

So – all good? The only challenge now was that he had over 200 clients to run the script on.

To help him automate this, I wrote a simple PowerShell script as a wrapper around OSPP.vbs to automate the key deactivation. It simply locates OSPP.vbs from the installation folder(s), fetches the key(s) and last removes all existing activations. Please note that it needs to run elevated and that it removes ALL activations on the machine.

    This script locates OSPP.vbs and removes all product keys to trigger O365 reactivation. It will remove ALL product keys.
    File Name: 
    Author   : Johan Dahlbom, johan[at]
    Blog     :
    The script is provided “AS IS” with no guarantees, no warranties, and they confer no rights.
#Check that the script runs with privileged rights
if (-not([Security.Principal.WindowsPrincipal] [Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole] "Administrator")) {
    Write-Warning "You need to have Administrator rights to run this script!`nPlease re-run this script as an Administrator in an elevated powershell prompt!"
#Find OSPP.vbs path and run the command with the dstatus option (Last 1...)
$OSPP = Resolve-Path -Path "C:\Program Files*\Microsoft Offic*\Office*\ospp.vbs" | Select-Object -ExpandProperty Path -Last 1
Write-Output -InputObject "OSPP Location is: $OSPP"
$Command = "cscript.exe '$OSPP' /dstatus"
$DStatus = Invoke-Expression -Command $Command

#Get product keys from OSPP.vbs output.
$ProductKeys = $DStatus | Select-String -SimpleMatch "Last 5" | ForEach-Object -Process { $_.tostring().split(" ")[-1]}

if ($ProductKeys) {
    Write-Output -InputObject "Found $(($ProductKeys | Measure-Object).Count) productkeys, proceeding with deactivation..."
    #Run OSPP.vbs per key with /unpkey option.
    foreach ($ProductKey in $ProductKeys) {
        Write-Output -InputObject "Processing productkey $ProductKey"
        $Command = "cscript.exe '$OSPP' /unpkey:$ProductKey"
        Invoke-Expression -Command $Command
} else {
    Write-Output -InputObject "Found no keys to remove... "

Hope this helps you if running in to this issue and as always – let me know if you have any questions!