The Exchange Team announced in this blog post a while ago they are offering support for Hybrid Modern Authentication (HMA) for Exchange On-Premises, this includes a new set of updates for Exchange 2013 (CU19) and 2016 (CU8). With this you are now able to use Azure AD issued tokens to authenticate your Exchange servers on-premises, this is a step in the right direction to eliminate any weak legacy authentication methods. Currently this is hard to achieve and not (yet) supported to turn off completely.
Why not Hybrid Modern Authentication?
There are several good reasons for not turning on HMA. Firstly, you really must know all your clients and often, you need to prioritize resolving any issues associated with this before you’re able to turn on HMA. I’m currently going through this challenge in a larger environment, here are a few examples of the issues I have encountered:
- LOB applications can’t perform OAuth
- Applications need to be rewritten to perform HMA, which is time consuming
- Skype for Business dependencies
Note: When you have Skype for Business deployed, you need to be careful and double-check for your clients. The main reason here is that there are vendors, which can’t perform HMA, therefore meaning they would be locked out.
On the other hand, you may want to give your users the option to use this authentication for the following reasons:
- Increase security as you now can use Conditional Access
- Increase end-user experience in terms of authentication as you have the same as in EXO
- State-of-the-art authentication mechanism of applications
- Reduce complexity for application development due to different authentication
In this this post, I will be predominantly focusing on how to make OAuth authentication without enabling Hybrid Modern Authentication.
There are some essential requirements you must meet before you make OAuth available without having HMA enabled:
- Executing your Exchange Hybrid Deployment (you can read more on Paul’s post here)
- Ensure you have read this article on Docs about Hybrid Modern Authentication overview and prerequisites for using it with on-premises Skype for Business and Exchange servers.
- Add all your on-premises namespaces to your Exchange ServicePrincipal in your tenant. You don’t have to enable HMA for this step, you can stop after verifying your virtual directories.
- You have registered two applications in AD. This is because you can’t add the required values to the property identifierUris when using Native application type, which is the preferred one. You can learn more about the types of applications here.
Register an application
When you have completed all the prerequisites, you need to start by registering two applications in Azure AD. For our example, the application needs access to both environments. One will be a Web App/API for Exchange on-premises and a Native one, which includes Exchange online and Exchange on-premises.
First, you need to register the application for the on-premises environment, follow the below steps to do so:
- Create a new app: Azure AD portal > App registrations > New application registration
Note: I usually use https://localhost/ plus a GUID as Sign-On/Redirect ULR/URI. Make sure this is unique! Create a GUID in PowerShell with this command: [System.Guid]::NewGuid()
2. Add EWS permissions: API permissions > Add a permission > on Microsoft APIs scroll down to Exchange > Delegated permission > on EWS check EWS.AccessAsUser.
3. Make this app visible to other apps by exposing an API:
- Expose an API > next to Application ID URI click on Set
- AAD will auto-generate an ID
- Save > Add a scope
Note: The Scope name is the only field, which requires the specific value: user_impersonate. The other fields can be filled as you want to describe the scope.
Now we can register the second Native app:
5. Create a new app Azure AD portal > App registrations > New application registration
5. Add EWS permissions: the steps for Exchange online is exactly as described for the first app. But in this app we also add the previously registered one: API permissions > Add a permission > APIs my organization uses > search for the previously registered app > select Delegated permissions and check user_impersonation
Note: don’t forget to check the permission.
6. To avoid the prompt for consent twice, we now copy the Application ID of the second app and edit the Manifest of the first app again. Add the Application ID to the property knownClientApplications and add the namespace of the on-premises hosts to the property identifierUris:
Note: You can add multiple namespaces. Make sure you have added all also to Exchange SPN as described in the pre-requisites:
Add all your on-premises namespaces to your Exchange ServicePrincipal in your tenant
If you missed this on the SPN or in the attribute identifierUris, you will receive an error, when acquiring a token:
AADSTS500011: The resource principal named <resource> was not found in the tenant named <your tenant>. This can happen if the application has not been installed by the administrator of the tenant or consented to by any user in the tenant. You might have sent your authentication request to the wrong tenant.
Accessing the mailbox
Now that we have configured our applications, we can start using it directly.
Here, I’m using the EWSEditor to complete the testing for retrieving an Accesstoken and accessing a mailbox. I’ll be using my script on Github for retrieving and decrypting an AccessToken:
Again, you’ll need to ensure you consent:
After consenting you can see the scope in your retrieved AccessToken:
When you have everything configured correctly, you can access your mailbox via EWSEditor using OAuth:
This also works for other protocol like REST. In this case, you need to select the appropriate claims in the permissions.
If you’ve fulfilled all the requirements and followed the above steps, you will now be able to provide your developers and application owners an additional authentication mechanism. The outcome of this is that it increases security and end-user experience at the same time. You can see this as an effective temporary resolution prior to HMA, where you are currently blocked by the reasons discussed in this article.
If I want to use oAuth, with or without HMA, will I still be able to certificate-based auth besides for Exch 2016/19?
afaik, there shouldn’t be an issue.
What version of Exchange did you use in your test?
May I know if it is possible to only enable HMA of part of the user in my organisation?
Would like to implement it by phases.
Thanks for the blog, if i am having Exchange 2013 (CU19) how can i enable OAUTH for my clients. Is the HMA feature in Exchange 2013 (CU19) automatically accepts OAUTH tokens? or i need to run any scripts?
you can check your VDirs by the steps outlined here:
OAuth should be listed.
I think I have this partly implemented and would like to remove it. Any instructions or should I just work backwards?
I think it’s going to be hard to remove the Hybrid config. But what you can do is removing the on-premises namespaces from the config.
Whats is the end user impact if we enable HMA. IF organisations have legacy mail clients like outlook 2010,2007 and legacy protocols imap and pop3 configurations?
these clients doesn’t understand that the server is offering Modern Auth and will ignore it as they don’t understand. That’s why you need to enable MA on 2013 clients.
Nothing for these clients.
This solution is it able to apply for on-premises Exchange MAPI user and only for group of user instead global setting like HMA. As we have some of user restricted internet access so wanna to know this solution is it can as workaround solution.
updated document was submitted. Not sure how long it takes for publishing.
Has the updated document been published yet? if yes, can you share the link?
yes, the article was already updated to reflect the latest changes in the AAD UI, when registering an app. Also better screenshots of the URIs.
What do you think is missing?
Thanks for this. I assume this works only for OWA or web-based applications only? The advantage of enabling HMA is that it supports rich clients, like Outlook, SfB (2013 and above)
it works for all web based clients. Outlook for instance needs to be switched to MAPI over Http, SfB clients using EWS for connecting to Exchange and these request will use OAuth as soon as you turn on HMA. This post is about not turning on HMA as there might be some blocking reasons.
When you compare HMA and this scenario, the only difference is that when you enable HMA, the server sends back some more information, which will be the trigger for OAuth capable clients to use OAuth.
Any chance of a couple of items of clarification here…
1.) Updated walk through on creating the app registrations given the new interface…
2.) at a minimum some higher resolution screenshots available. For example the one showing what the identifierUris should look like in the Manifest is so small I can’t actually make out what it has there…
noticed and already working on this. For now:
The identifierUris needs your Exchange endpoints. By default Azure AD adds one (e.g.: https://.onmicrosoft.com/ ). You can use the existing GUID and append it to your endpoints, which looks like this:
The key is that the URIs are unique and therefore a GUID is the best approach.
Thanks Ingo for this insight.
Can you clarify what GUID is being used in the “identifierUris” for the first app manifest?
sorry for the delay. By default Azure AD will create a identifireURI specific to your tenant. I usually take the GUID from the created one and append it to the local names.
Sorry if I am asking the same question seun about identfireURI. So the GUID you use is a random generated GUID with our onprepem exchange name space?
It would be helpful if you can give the identifierURI you have mentioned in your screen shot in text or a bigger screen shot.
I’m currently updating the article as there were 2 major changes in the UI (and this seems not to be the last ones). For now:
The property identifierUris contains all the on-premises resources for which you want to have OAuth enabled. In this example you can either generate a new GUID or use the one from the default generated URI. Either way it looks like this:
I hope this helps.
Can you please share the updated instructions..?