AAD Identity Protection – End-user behavior

Microsoft is moving from a “force Multi-Factor Authentication for all users” model to a risk based model where users are requested to do Multi-Factor Authentication when their sign-in has a risk assigned to it. This could happen for example by an impossible travel, the user logging in from an IP address which has been in contact with a botnet or other “signals” as Microsoft calls them.

First of all, with AAD Identity Protection, instead of doing manual or scripted assigning of MFA, this is now done with an MFA registration policy. Here is an example on what this can look like:

snip_20160321095252

This will let organizations start with a group of users and expand to more and more users. What will happen is that the user will be prompted to register for MFA when they log on with a browser (or Office with ADAL etc.), but their next logon will not require MFA.

snip_20160321095400

When we look at StrongAuthenticationRequirements of the user, it will be empty, meaning that MFA is not enforced, but the user is still ready to use MFA whenever Azure AD requires it.

Now let us look at the Sign-in risk policy:

snip_20160321100036

Here I have configured the policy to be invoked when the machine learning system in Azure AD find my sign-in a low or medium risk. If a high risk is detected, it is blocked completely.

When I sign in from my regular computer, nothing happens. No MFA; everything is like it has always been. This is perfect, and exactly how this should work. Azure AD detects that everything is safe, no risk at all, so I am not prompted for MFA.

Now, let us try signing in through a RDP session from a computer about 2 hours away by air.

snip_20160321095306

 

snip_2016032110100

Suddenly my sign-in requires Multi-Factor Authentication, because I made an impossible travel.

 

PowerShell and EWS Managed API

Here is a script that lets you download mail objects with attachments from an Exchange mailbox (works with Office 365). First, install Exchange Web Services Managed API 2.2.

# Destination folder
$destinationFolder = "C:\Users\marius\Downloads\Attachment Downloader"

# replace with your email address
$email    = "username@mytenant.onmicrosoft.com"
$username = "username@mytenant.onmicrosoft.com"
$password = "Password123!"

# File extensions to download
$extensions = "pdf","pdfa","doc","docx","dot","dotx","xls","xlsx","ppt","pptx"

# load the assembly
Add-Type -Path "C:\Program Files\Microsoft\Exchange\Web Services\2.2\Microsoft.Exchange.WebServices.dll"

# Create Exchange Service object
$s = New-Object Microsoft.Exchange.WebServices.Data.ExchangeService([Microsoft.Exchange.WebServices.Data.ExchangeVersion]::Exchange2013_SP1)
$s.Credentials = New-Object Net.NetworkCredential($username, $password)
# $s.TraceEnabled = $true
Write-Host "Trying AutoDiscover... "
$s.AutodiscoverUrl($email, {$true})

if(!$s.Url) {
    Write-Error "AutoDiscover failed"
    return;
} else {
    Write-Host -ForegroundColor Green "AutoDiscover succeeded - $($s.Url)"
}

# Create destination folder
$destinationFolder = "{0}\{1}" -f $destinationFolder, (Get-Date -Format "yyyyMMdd HHmmss")
mkdir $destinationFolder | Out-Null

# get a handle to the inbox
$inbox = [Microsoft.Exchange.WebServices.Data.Folder]::Bind($s,[Microsoft.Exchange.WebServices.Data.WellKnownFolderName]::Inbox)

#create a property set (to let us access the body & other details not available from the FindItems call)
$psPropertySet = new-object Microsoft.Exchange.WebServices.Data.PropertySet([Microsoft.Exchange.WebServices.Data.BasePropertySet]::FirstClassProperties)
$psPropertySet.RequestedBodyType = [Microsoft.Exchange.WebServices.Data.BodyType]::Text;

# Find the items
$inc = 0;
$maxRepeat = 50;
do {
    $maxRepeat -= 1;

    Write-Host "Searching for items in mailbox... " -NoNewline
    $items = $inbox.FindItems(100)
    Write-Host -ForegroundColor Green "found $($items.items.Count)"

    foreach ($item in $items.Items)
    {
        # Create mail folder
        $inc += 1
        $mailFolder = "{0}\{1}" -f $destinationFolder, $inc;
        mkdir $mailFolder | Out-Null

        # load the property set to allow us to get to the body
        try {
            $item.load($psPropertySet)
            Write-Host ("$inc - $($item.Subject)") -ForegroundColor Yellow

            # save the metadata to a file
            $item | Export-Clixml ("{0}\metadata.xml" -f $mailFolder)

            # save all attachments
            foreach($attachment in $item.Attachments) {
                if(($attachment.Name -split "\." | select -last 1) -in $extensions) {
                    Write-Host " - $($attachment.Name) - $([Math]::Round($attachment.Size / 1024))KB"
                    $fileName = ("{0}\{1}" -f $mailFolder, $attachment.Name) -replace "/",""
                    $attachment.Load($fileName)
                }
            }

            # delete the mail item
            $item.Delete([Microsoft.Exchange.WebServices.Data.DeleteMode]::HardDelete, $true)
        } catch [Exception] {
            Write-Error "Unable to load item: $($_)"
        }
    }
} while($items.MoreAvailable -and $maxRepeat -ge 0)

Outlook AutoDiscover redirect limit (0x800c8206)

Today I encountered something I’ve not seen before, and I am sure more people will encounter this. If a client is in an Active Directory site without an AutoDiscover serviceConnectionPoint (SCP), it will try to connect to all AutoDiscover instances in the organization simultaneously. If the user have been cross-forest migrated, a redirect response will come from each server, and if there are more than 8 of them, Outlook reaches a redirect limit and fails to AutoDiscover.

After a cross-forest migration, the targetAddress of the source Active Directory object will be set to an address in the routing domain. For example when you do migrate to Office 365 / Exchange Online, your user will get a tenant.mail.onmicrosoft.com address, in my case mailNickname@gwrnd.mail.onmicrosoft.com. After the migration, when requesting details from AutoDiscover On-Premise, the response will be a redirect to the Exchange Online autodiscover. The problem is that when SCP is enabled in Outlook, it will count each response On-Premise as a redirect. This means that if it requests from all of your AutoDiscover instances, it will fail (the limit is 10).

If you believe this is your issue, you can look for error code 0x800c8206 in “Test E-mail Autoconfiguration” in Outlook. If you find this error code, here is your solution.

Disable SCP on the client

Instead of having Outlook look for SCPs in AD, you can disable this feature by adding the following to the registry on the client.


[HKEY_CURRENT_USER\Software\Microsoft\Office\14.0\Outlook\AutoDiscover]
"ExcludeScpLookup"=dword:00000001

With this disabled, Outlook will work more like on the internet. It will look at the UserPrincipalName (UPN), and try autodiscover.goodworkaround.com if your UPN ends with @goodworkaround.com. The reason this helps is that it will only get one response On-premise, not one per AutoDiscover virtual directory.

Configure AutoDiscoverSiteScope

By default a CAS only serves its own site. You can use the cmdlet Set-ClientAccessServer -identity -AutodiscoverSiteScope Oslo,Beijing,Boston,Seattle to configure it to serve more sites. This can help if you for example have 4 datacenters with 3 AutoDiscover instances in each, and some sites in AD does not have an Exchange server. The sites with the Exchange server will try all of the 12 AutoDiscover instances, and fail because it reaches the limit. If you configure the site to only try one of the sites, it will succeed because it will only try 3 servers.

Reduce the number of AutoDiscover instances

Do you really need 12? Remember that this is a lightweight service, and you can have a CAS without AutoDiscover. If you can manage to have 8 or less AutoDiscover instances you are safe.

Hope this helps someone.