Configure OAuth authentication in Exchange 2016

As long as I can remember the Hybrid Configuration Wizard finishes successfully, and itgenerates the error about the OAuth portion of the hybrid configuration.

Configure Intra-Organization Connector

HCW8064 – The HCW has completed, but was not able to perform the OAuth portion of your Hybrid configuration. If you need features that rely on OAuth, you can try running the HCW again or manually configure OAuth using these manual steps.

The Learn more option redirects to the Microsoft page Configure OAuth authentication between Exchange and Exchange Online organizations. I used that article for the PowerShell commands in this blogpost.

OAuth is used cross-premises to logon to other services, on behalf of the user. So, if you are logged on to some Microsoft service, this service can use OAuth to access services in Exchange on-premises and vice versa.

Example of these cross-premises services are:

  • Message Records Management (MRM).
  • Exchange in-place eDiscovery.
  • Exchange in-place Archiving.
  • Teams calendaring.

The HCW can configure Azure Active Directory for OAuth authentication, it can create the IntraOrganizationConnectors, but it cannot export and import the (self-signed) certificate on the Exchange server, nor can it (or does it) create the authorization server objects in Active Directory. So, time to test, guided by the Microsoft article and write down my experiences.

Note. This only works for Exchange 2013 and higher, I have been working on this in a mixed Exchange 2016 and Exchange 2019 environment.

Configuring OAuth between Office 365 and Exchange Online involve a number of steps.

Create Authorization server objects in Exchange on-premises

To create the authorization server objects in your on-premises environment enter the following commands in the Exchange Management Shell.

New-AuthServer -Name "WindowsAzureACS" -AuthMetadataUrl "https://accounts.accesscontrol.windows.net/contoso.com/metadata/json/1"
New-AuthServer -Name "evoSTS" -Type AzureAD -AuthMetadataUrl https://login.windows.net/contoso.com/federationmetadata/2007-06/federationmetadata.xml

Your verified domain contoso.com (in the command) should be something like exchangelabs.nl, and not <your tenant name> as outlined in the Microsoft article.

New-AuthServer

Enable the partner application for use with Exchange Online

The partner application was created in the previous step (the first command) and this should be enabled. Do this using the following command in Exchange Management Shell (on-premises):

Get-PartnerApplication | ?{$_.ApplicationIdentifier -eq "00000002-0000-0ff1-ce00-000000000000" -and $_.Realm -eq ""} | Set-PartnerApplication -Enabled $true

Export the Exchange authorization certificate

Authentication cross-premises is using certificates, so the on-premises certificate needs to be exported to Azure Active Directory. In case you were wondering where the CN=Microsoft Exchange Server Auth Certificate certificate was coming from when running the Get-ExchangeCertificate command in Exchange Management Shell, here you go.

Use the following PowerShell commands and store them in a PowerShell script called ExportAuthCert.ps1 or something and run it. This should export the OAuth certificate to a file called OAuthCert.cer.

$ThumbPrint = (Get-AuthConfig).CurrentCertificateThumbprint
If((Test-Path $ENV:SYSTEMDRIVE\OAuthConfig) -eq $false)
{
md $ENV:SYSTEMDRIVE\OAuthConfig
}
CD $ENV:SYSTEMDRIVE\OAuthConfig
$oAuthCert = (dir Cert:\LocalMachine\My) | ?{$_.ThumbPrint -Match $ThumbPrint}
$CertType = [System.Security.Cryptography.X509Certificates.X509ContentType]::Cert
$CertBytes = $oAuthCert.Export($CertType)
$CertFile = "$env:SYSTEMDRIVE\OAuthConfig\OAuthCert.cer"
[System.IO.File]::WriteAllBytes($CertFile, $CertBytes)

ExportAuthCert

Note. The Export-ExchangeCertificate command doesn’t work in this scenario since the self-signed certificate isn’t exportable.

Import the Exchange authorization certificate into Azure AD

The next step is to import the OAuthCert.cer certificate into Azure AD. Connect to the Microsoft Online service (Connect-MSOLService, if you don’t have this installed you can use the Install-Module MSOnline command) and run the following commands when connected:

$Cred = Get-Credential
Connect-MSOLService -Credential $Cred
$CertFile = "$ENV:SYSTEMDRIVE\OAuthConfig\OAuthCert.cer"
$objFSO = New-Object -ComObject Scripting.FileSystemObject
$CertFile = $objFSO.GetAbsolutePathName($CertFile)
$CER = New-Object System.Security.Cryptography.X509Certificates.X509Certificate
$CER.Import($CertFile)
$binCert = $cer.GetRawCertData()
$CredValue = [System.Convert]::ToBase64String($binCert)
$ServiceName = "00000002-0000-0ff1-ce00-000000000000"
$P = Get-MsolServicePrincipal -ServicePrincipalName $ServiceName
New-MsolServicePrincipalCredential -AppPrincipalId $P.AppPrincipalId -Type asymmetric -Usage Verify -Value $credValue

This will import the self-signed certificate from the Exchange server into Azure AD so it can be used for mutual authentication.

I did not run the commands mentioned above on my Exchange server but on my Azure AD Connect server since the MSOL module was loaded on that server. For importing the certificate file I had to use the following command accessing the certificate file (instead of the $ENV:System variable):

$CertFile = "\\AMS-EXCH01\C$\OAuthConfig\OAuthCert.cer"

Register endpoints in Azure Active Directory

The last step is to register the endpoints of your on-premises Exchange environment into Azure Active Directory. You can use the following commands to register the endpoints:

$ServiceName = "00000002-0000-0ff1-ce00-000000000000";
$x = Get-MsolServicePrincipal -AppPrincipalId $ServiceName;
$x.ServicePrincipalnames.Add("https://webmail.exchangeserver.com/");
$x.ServicePrincipalnames.Add("https://autodiscover.exchangeserver.com/");
Set-MSOLServicePrincipal -AppPrincipalId $ServiceName -ServicePrincipalNames $x.ServicePrincipalNames;

Instead of webmail.exchangeserver.com and Autodiscover.exchangeserver.com you must use your own local FQDNs of the Exchange server (shown below in the verification screenshot).

You can use the the following command to check if this was configured correctly.

Get-MsolServicePrincipal -AppPrincipalId 00000002-0000-0ff1-ce00-000000000000 | select -ExpandProperty ServicePrincipalNames

As shown in the following screenshot:

Register Endpoints

Note. Over the years I have run the HCW several times. Domains have been added, but not (automatically) deleted in Azure Active Directory.

IntraOrganizationConnectors and AvailabilityAddressSpace

The Hybrid Configuration Wizard created the IntraOrganizationConnectors (both in Exchange 2016 as well as Exchange Online) and configured the AvailabilityAddressSpace. There’s no need to create these, but you have to check them using the Get-IntraOrganizationConnector and the Get-AvailabilityAddressSpace commands)

Verify the OAuth configuration

To verify the OAuth configuration you can use the Test-OAuthConnectivity command. You must do this on the on-premises Exchange server and in Exchange Online.

On the on-premises Exchange server use the Exchange Online Uri and a mailbox on-premises:

Test-OAuthConnectivity -Service EWS -TargetUri https://outlook.office365.com/ews/exchange.asmx -Mailbox onprem-user@exchangeserver.com -Verbose | Format-List

In Exchange Online, use the Exchange on-premises Uri with a mailbox in Exchange Online:

Test-OAuthConnectivity -Service EWS -TargetUri https://webmail.exchangeserver.com/metadata/json/1 -Mailbox Online-User@exchangeserver.com -Verbose | Format-List

The output is an extended list, but in the end you should see ResultType: Success and IsValid:True on your console:

Test-OAuthConnectivity

You have now configured the OAuth between Exchange Online and Exchange On-Premises.

 

39 thoughts on “Configure OAuth authentication in Exchange 2016”

    1. Hoi,

      I’m not sure. When I tried it failed, and it works with the primary SMTP domain. I submitted feedback but except for a receive notification I haven’t heard back. Since you are a trusted resource I will ask within the MVP community and get back on this.

      Like

      1. I knew these changes were coming 😉
        Yesterday I ran the HCW after upgrading an environment from Exchange 2010 to Exchange 2016 and I did not see the OAuth portion warnings, so I’ll have a closer look soon.

        Like

  1. So we should see more news from the MVP summit, something like removing the lat Exchange server 😀 ?
    Well with the first v17.x release i had to change the server timezone to at least UTC or it would fail (i was not alone in this bug). Yesterday i ran the ‘latest’ HCW v17.x and it did not configure the oauth portion, so i had to do it manually and eventually got the Teams Calendar. So lets say there is still room for improvement 🙂

    Like

    1. Hello there, How does one remove this when it is no longer wanted? Especially how to return the ServicePrincipalNames to the default values?

      Like

      1. Officially it is not supported to remove the last Exchange server, even when all mailboxes are in Office 365. This is for management purposes. I always recommend keeping one (or two) Exchange servers on-premises for management, but also for on-premises SMTP relaying. It is possible to work without an Exchange server, but it has some sharp edges. I also wrote some blogs on this: https://jaapwesselius.com/2016/06/09/office-365-directory-synchronization-without-exchange-server/

        Like

      1. Great so how do I get rid of an old setup from then I did have some of those things. PS love your blogs, they are so helpful

        Like

      2. I have an issue where the HCW completes but never creates the Migration Endpoint.
        I can’t create Migration Endpoints manually in EAC or powershell.
        What I have found it that I have some old domains and various strange endpoints which I think might be part of the problem.

        Get-MsolServicePrincipal -AppPrincipalId 00000002-0000-0ff1-ce00-000000000000 | select -ExpandProperty ServicePrincipalNames
        https://outlook-tdf.office.com/
        00000002-0000-0ff1-ce00-000000000000
        00000002-0000-0ff1-ce00-000000000000/*.outlook.com
        00000002-0000-0ff1-ce00-000000000000/outlook.com
        00000002-0000-0ff1-ce00-000000000000/mail.office365.com
        00000002-0000-0ff1-ce00-000000000000/outlook.office365.com
        00000002-0000-0ff1-ce00-000000000000/mydomain.ch
        00000002-0000-0ff1-ce00-000000000000/autodiscover.mydomain.ch
        00000002-0000-0ff1-ce00-000000000000/rossignols19.ch
        00000002-0000-0ff1-ce00-000000000000/autodiscover.rossignols19.ch
        00000002-0000-0ff1-ce00-000000000000/mydom.pri
        00000002-0000-0ff1-ce00-000000000000/autodiscover.mydom.pri
        00000002-0000-0ff1-ce00-000000000000/mydomain.mail.onmicrosoft.com
        00000002-0000-0ff1-ce00-000000000000/autodiscover.mydomain.mail.onmicrosoft.com
        00000002-0000-0ff1-ce00-000000000000/owa.mydomain.ch
        https://owa.mydomain.ch
        00000002-0000-0ff1-ce00-000000000000/mail.mydomain.ch
        https://mail.mydomain.ch
        https://webmail.apps.mil/
        https://ps.protection.outlook.com/
        https://outlook-dod.office365.us/
        https://outlook.com/
        https://outlook.office365.com/
        https://outlook.office.com/
        https://outlook.office365.com:443/
        https://outlook-sdf.office365.com/
        https://outlook-sdf.office.com/
        https://outlook.office365.us/
        https://autodiscover-s.office365.us/
        https://ps.compliance.protection.outlook.com

        These are left over from way back in 2013, and I want to remove them so I can create a migration endpoint and migrate some mailboxes.

        Your procedure is an updated version of what I did in 2013, I am looking to reverse it since I have simplified and got rid of ADFS, S4B and would like to get rid of Exchange too, but at a minimum I want to move the mailboxes online.

        Looking for the default settings and how to update that array in powershell (not my strong point)

        Like

  2. If we enable hma what is the end user impact if there are using legacy outlook clients like outlook 2010 and other mail apps and legacy protocols imap and pop3

    Like

  3. hi thanks for the info.
    i am keen to setup OAuth, especially for teams. i am running exchange 2016 with minimal hybrid configured.
    i am in the process in changing this to full hybrid configuration. is it best to complete the OAuth configuration before or after i run HCW in order to setup Oauth or does it even matter.

    Like

    1. Hi, you can configure OAuth anytime to get it working with Exchange 2016. You don’t even need Exchange 2016 hybrid for Teams integration, when you have Azure AD Connect up-and-running and configured OAuth you can use Exchange 2016 and Teams.

      Liked by 1 person

      1. ok that’s brilliant! i already have Azure AD Connect setup and running, we all all good with that. our company have not committed either way to mirgating to the cloud or not so i will have to change setup to full hybrid to get all features as we will probably need it indefinitely. but keen to get a better
        integration with teams as we are using it extensively now with the current situation.

        thanks a lot for the info

        Like

  4. Hi! I am definitely missing something here…thankful for any input! Running a Exchange Server 2019, set up an AD Connect (authorization through ADFS server), HCW (17.0.4544.0) – full hybrid configuration, Exchange Classic Hybrid Topology.
    Moving the mailboxes online is unfortunately not an option.

    I’ve followed the steps above but the Calendar tab/button is still missing in Teams – while the other features are OK – and I can create a Teams meeting through Outlook and join it.

    Is there a “most common error”/reason for this?

    Like

    1. That’s weird. Exchange 2019 does support this, you only need Azure AD Connect (hybrid is for Teams not needed, it’s just authentication) and in my lab i am using ADFS as well. I think somewhere your authentication process is a bit broken, but I haven’t the slightest idea where.

      Like

  5. Hi Jaap, thanks for taking your time to reply.
    Alright, so the problem might be somewhere in the AD Connect setup perhaps…Could it be something in the federation? Do you know what the requirements are for the AD Connect setup for it to function properly? (attributes etc).
    Cheers

    Like

  6. Running Exchange 2019 Classic Hybrid Configuration with Oauth configured, but only for one of SMTP Domains Calendar is working in Teams. Maybe you have a hint 🙂

    Like

  7. hi jaap,

    just one more thing. just want to confirm if i can configure OAuth ok but i dont have to enable modern authentication for my on premise exchange environment ?
    i am not in a position to enable on prem modern authentication yet

    Like

  8. Hi,

    My Microsoft Exchange Server Auth Certificate certificate is due to expire on in ealry Jan. due i need to renew this cert onprem exchange server and run the Export/Import of the new Exchange authorization certificate part of the process again ?

    Like

  9. Thank you so much for doing this guide. My biggest problem at the moment though is getting the “Connect-MSOLService” command to work! In PowerShell I used the command “Install-Module MSOnline”, it has a think then looks like it did something however it doesn’t confirm anything. I then try “Connect-MSOLService” and it just says it’s not a recognized cmdlet. I bounced around Microsoft for hours figuring out what to do but getting no where! Any ideas?

    Like

  10. Thank you for the above. We do get success resultson both sites (on prem and online)

    when we run Get-AuthServer | where {$_.Name -eq “EvoSts”}. it dispays nothing. If we run Get-AuthServer | FL it shows the evosts server as well as domaincontroller as the originating server
    so we ran the HWB again as per microsoft instructions but still do not get results with Get-AuthServer | where {$_.Name -eq “EvoSts”}

    And if we run Set-AuthServer -Identity EvoSTS -IsDefaultAuthorizationEndpoint $true it cannot find the object on the domain controller. We have checked in the setup logs that the service was setup and no 8064 errors were given. is there anything we have missed?

    Like

    1. Did you get an error when running New-AuthServer? Or some other warning?
      Can you see the object in AD with ADSI Edit? It should be here (change org name and domain name of course)
      CN=evoSTS,CN=Auth Servers,CN=Auth Configuration,CN=,CN=Microsoft Exchange,CN=Services,CN=Configuration,DC=domain,DC=local

      Like

  11. Jaap – I’ve run into this today and MS Support is having difficulty helping me resolve it even after following all of the steps outlined above. When rerunning the hybrid tool, it still continues to give us the same error message HCW8064. Support though did confirm testing both directions was successful using Test-OAuthConnectivity … any suggestions/recommendations? If the tests are successful, is the tool wrong?

    Like

      1. Same here. Powershell commands are stating everything’s fine, the wizard complains (HCW8064).

        Like

    1. Free/Busy was indeed not working…the value in the Get-IntraOrganizationConnector Enabled status was set to false. I ran this from an Exchange Online PS session as well as an on-prem Exchange shell. In both cases, the Enabled status was set to False. So…from each PS session: > Get-IntraOrganizationConnector | Set-IntraOrganizationConnector -Enabled $true.

      After that, Free/Busy started displaying normally almost immediately. I opened up a support ticket with Microsoft to verify what else the HCW might have missed or otherwise. They indicated that the HCW having shut the IntraOrgConnector setting down, it didn’t turn it back on – which led to the error. But otherwise if I turned it back on and everything else checks out with verification – I should be all set. Sloppy.

      Like

  12. Hi Jaap, I too am encountering the HCW8064 error after running the latest HCW on an Exc2016 CU21. The powershell commands say everything is fine but re-running the HCW always returns this error and I can’t find anything significant in the logs. The only thing I noticed is that when I run
    Get-AuthServer | where {$_.Name -like “EvoSts*”} | fl Name,DomainName,IssuerIdentifier,Realm,TokenIssuingEndpoint,Enabled,IsDefault*
    the “DomainName” field is unpopulated {} which I think shouldn’t be the case. Also, as this is an Exc 2016, it should have as name “evoSTS – ” but it only displays “evoSTS”.
    Maybe this is because previously I had configured the Teams hybrid environment allowing the calendar info be read from the onprem server (a couple of years ago) so I beilee an endpoint had to be created. Maybe in such a case the HCW finds some inconsistencies and reports such warning as it’s a non standard scenario. What are your thoughts on this? Thanks for the insightful blog!

    Like

Leave a comment